Update setup wizard for missing media codecs

This commit is contained in:
Dan Paulat 2023-12-08 09:56:01 -06:00
parent d760641770
commit f143186ea5
7 changed files with 268 additions and 11 deletions

View file

@ -252,12 +252,14 @@ set(UI_UI source/scwx/qt/ui/about_dialog.ui
source/scwx/qt/ui/radar_site_dialog.ui source/scwx/qt/ui/radar_site_dialog.ui
source/scwx/qt/ui/settings_dialog.ui source/scwx/qt/ui/settings_dialog.ui
source/scwx/qt/ui/update_dialog.ui) source/scwx/qt/ui/update_dialog.ui)
set(HDR_UI_SETUP source/scwx/qt/ui/setup/finish_page.hpp set(HDR_UI_SETUP source/scwx/qt/ui/setup/audio_codec_page.hpp
source/scwx/qt/ui/setup/finish_page.hpp
source/scwx/qt/ui/setup/map_layout_page.hpp source/scwx/qt/ui/setup/map_layout_page.hpp
source/scwx/qt/ui/setup/map_provider_page.hpp source/scwx/qt/ui/setup/map_provider_page.hpp
source/scwx/qt/ui/setup/setup_wizard.hpp source/scwx/qt/ui/setup/setup_wizard.hpp
source/scwx/qt/ui/setup/welcome_page.hpp) source/scwx/qt/ui/setup/welcome_page.hpp)
set(SRC_UI_SETUP source/scwx/qt/ui/setup/finish_page.cpp set(SRC_UI_SETUP source/scwx/qt/ui/setup/audio_codec_page.cpp
source/scwx/qt/ui/setup/finish_page.cpp
source/scwx/qt/ui/setup/map_layout_page.cpp source/scwx/qt/ui/setup/map_layout_page.cpp
source/scwx/qt/ui/setup/map_provider_page.cpp source/scwx/qt/ui/setup/map_provider_page.cpp
source/scwx/qt/ui/setup/setup_wizard.cpp source/scwx/qt/ui/setup/setup_wizard.cpp

View file

@ -0,0 +1,176 @@
#include <scwx/qt/ui/setup/audio_codec_page.hpp>
#include <scwx/qt/manager/settings_manager.hpp>
#include <scwx/qt/settings/audio_settings.hpp>
#include <scwx/qt/settings/settings_interface.hpp>
#include <QCheckBox>
#include <QDesktopServices>
#include <QLabel>
#include <QMediaFormat>
#include <QScrollArea>
#include <QSpacerItem>
#include <QVBoxLayout>
namespace scwx
{
namespace qt
{
namespace ui
{
namespace setup
{
class AudioCodecPage::Impl
{
public:
explicit Impl(AudioCodecPage* self) : self_ {self} {};
~Impl() = default;
void SetupSettingsInterface();
void SetInstructionsLabelText();
AudioCodecPage* self_;
QLayout* layout_ {};
QLayout* topLayout_ {};
QScrollArea* scrollArea_ {};
QWidget* contents_ {};
QLabel* descriptionLabel_ {};
QLabel* instructionsLabel_ {};
QCheckBox* ignoreMissingCodecsCheckBox_ {};
QSpacerItem* spacer_ {};
settings::SettingsInterface<bool> ignoreMissingCodecs_ {};
};
AudioCodecPage::AudioCodecPage(QWidget* parent) :
QWizardPage(parent), p {std::make_shared<Impl>(this)}
{
setTitle(tr("Media Codecs"));
setSubTitle(tr("Configure system media settings for Supercell Wx."));
p->descriptionLabel_ = new QLabel(this);
p->instructionsLabel_ = new QLabel(this);
p->ignoreMissingCodecsCheckBox_ = new QCheckBox(this);
// Description
p->descriptionLabel_->setText(
tr("Your system does not have the proper codecs installed in order to "
"play the default audio. You may either install the proper codecs, or "
"update Supercell Wx audio settings to change from the default audio "
"files. After installing the proper codecs, you must restart "
"Supercell Wx."));
p->descriptionLabel_->setWordWrap(true);
p->SetInstructionsLabelText();
p->instructionsLabel_->setWordWrap(true);
p->ignoreMissingCodecsCheckBox_->setText(tr("Ignore missing codecs"));
p->spacer_ =
new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Expanding);
// Overall layout
p->layout_ = new QVBoxLayout(this);
p->layout_->addWidget(p->descriptionLabel_);
p->layout_->addWidget(p->instructionsLabel_);
p->layout_->addWidget(p->ignoreMissingCodecsCheckBox_);
p->layout_->addItem(p->spacer_);
p->contents_ = new QWidget(this);
p->contents_->setLayout(p->layout_);
p->scrollArea_ = new QScrollArea(this);
p->scrollArea_->setHorizontalScrollBarPolicy(
Qt::ScrollBarPolicy::ScrollBarAlwaysOff);
p->scrollArea_->setFrameShape(QFrame::Shape::NoFrame);
p->scrollArea_->setWidgetResizable(true);
p->scrollArea_->setWidget(p->contents_);
p->topLayout_ = new QVBoxLayout(this);
p->topLayout_->setContentsMargins(0, 0, 0, 0);
p->topLayout_->addWidget(p->scrollArea_);
setLayout(p->topLayout_);
// Configure settings interface
p->SetupSettingsInterface();
}
AudioCodecPage::~AudioCodecPage() = default;
void AudioCodecPage::Impl::SetInstructionsLabelText()
{
#if defined(_WIN32)
instructionsLabel_->setText(tr(
"<p><b>Option 1</b></p>" //
"<p>Update your Windows installation. The required media codecs may "
"be available with the latest operating system updates.</p>" //
"<p><b>Option 2</b></p>" //
"<p>Install the <a "
"href=\"https://www.microsoft.com/store/productId/9N5TDP8VCMHS\">Web "
"Media Extensions</a> package from the Windows Store.</p>" //
"<p><b>Option 3</b></p>" //
"<p>Install <a "
"href=\"https://www.codecguide.com/"
"download_k-lite_codec_pack_basic.htm\">K-Lite Codec Pack "
"Basic</a>. This is a 3rd party application, and no support or warranty "
"is provided.</p>"));
instructionsLabel_->setTextInteractionFlags(
Qt::TextInteractionFlag::TextBrowserInteraction);
QObject::connect(instructionsLabel_,
&QLabel::linkActivated,
self_,
[](const QString& link)
{ QDesktopServices::openUrl(QUrl {link}); });
#else
instructionsLabel_->setText(
tr("Please see the instructions for your Linux distribution for "
"installing media codecs."));
#endif
}
void AudioCodecPage::Impl::SetupSettingsInterface()
{
auto& audioSettings = settings::AudioSettings::Instance();
ignoreMissingCodecs_.SetSettingsVariable(
audioSettings.ignore_missing_codecs());
ignoreMissingCodecs_.SetEditWidget(ignoreMissingCodecsCheckBox_);
}
bool AudioCodecPage::validatePage()
{
bool committed = false;
committed |= p->ignoreMissingCodecs_.Commit();
if (committed)
{
manager::SettingsManager::Instance().SaveSettings();
}
return true;
}
bool AudioCodecPage::IsRequired()
{
auto& audioSettings = settings::AudioSettings::Instance();
bool ignoreCodecErrors = audioSettings.ignore_missing_codecs().GetValue();
QMediaFormat oggFormat {QMediaFormat::FileFormat::Ogg};
auto oggCodecs =
oggFormat.supportedAudioCodecs(QMediaFormat::ConversionMode::Decode);
// Setup is required if codec errors are not ignored, and the default codecs
// are not supported
return (!ignoreCodecErrors &&
oggCodecs.contains(QMediaFormat::AudioCodec::Vorbis));
}
} // namespace setup
} // namespace ui
} // namespace qt
} // namespace scwx

View file

@ -0,0 +1,34 @@
#pragma once
#include <QWizardPage>
namespace scwx
{
namespace qt
{
namespace ui
{
namespace setup
{
class AudioCodecPage : public QWizardPage
{
Q_DISABLE_COPY_MOVE(AudioCodecPage)
public:
explicit AudioCodecPage(QWidget* parent = nullptr);
~AudioCodecPage();
bool validatePage() override;
static bool IsRequired();
private:
class Impl;
std::shared_ptr<Impl> p;
};
} // namespace setup
} // namespace ui
} // namespace qt
} // namespace scwx

View file

@ -278,6 +278,18 @@ bool MapProviderPage::validatePage()
return true; return true;
} }
bool MapProviderPage::IsRequired()
{
auto& generalSettings = settings::GeneralSettings::Instance();
std::string mapboxApiKey = generalSettings.mapbox_api_key().GetValue();
std::string maptilerApiKey = generalSettings.maptiler_api_key().GetValue();
// Setup is required if either API key is empty, or contains a single
// character ("?")
return (mapboxApiKey.size() <= 1 && maptilerApiKey.size() <= 1);
}
} // namespace setup } // namespace setup
} // namespace ui } // namespace ui
} // namespace qt } // namespace qt

View file

@ -22,6 +22,8 @@ public:
bool isComplete() const override; bool isComplete() const override;
bool validatePage() override; bool validatePage() override;
static bool IsRequired();
private: private:
class Impl; class Impl;
std::shared_ptr<Impl> p; std::shared_ptr<Impl> p;

View file

@ -1,9 +1,9 @@
#include <scwx/qt/ui/setup/setup_wizard.hpp> #include <scwx/qt/ui/setup/setup_wizard.hpp>
#include <scwx/qt/ui/setup/audio_codec_page.hpp>
#include <scwx/qt/ui/setup/finish_page.hpp> #include <scwx/qt/ui/setup/finish_page.hpp>
#include <scwx/qt/ui/setup/map_layout_page.hpp> #include <scwx/qt/ui/setup/map_layout_page.hpp>
#include <scwx/qt/ui/setup/map_provider_page.hpp> #include <scwx/qt/ui/setup/map_provider_page.hpp>
#include <scwx/qt/ui/setup/welcome_page.hpp> #include <scwx/qt/ui/setup/welcome_page.hpp>
#include <scwx/qt/settings/general_settings.hpp>
#include <QDesktopServices> #include <QDesktopServices>
#include <QUrl> #include <QUrl>
@ -38,6 +38,7 @@ SetupWizard::SetupWizard(QWidget* parent) :
setPage(static_cast<int>(Page::Welcome), new WelcomePage(this)); setPage(static_cast<int>(Page::Welcome), new WelcomePage(this));
setPage(static_cast<int>(Page::MapProvider), new MapProviderPage(this)); setPage(static_cast<int>(Page::MapProvider), new MapProviderPage(this));
setPage(static_cast<int>(Page::MapLayout), new MapLayoutPage(this)); setPage(static_cast<int>(Page::MapLayout), new MapLayoutPage(this));
setPage(static_cast<int>(Page::AudioCodec), new AudioCodecPage(this));
setPage(static_cast<int>(Page::Finish), new FinishPage(this)); setPage(static_cast<int>(Page::Finish), new FinishPage(this));
#if !defined(Q_OS_MAC) #if !defined(Q_OS_MAC)
@ -55,16 +56,43 @@ SetupWizard::SetupWizard(QWidget* parent) :
SetupWizard::~SetupWizard() = default; SetupWizard::~SetupWizard() = default;
int SetupWizard::nextId() const
{
int nextId = currentId();
while (true)
{
switch (++nextId)
{
case static_cast<int>(Page::MapProvider):
case static_cast<int>(Page::MapLayout):
if (MapProviderPage::IsRequired())
{
return nextId;
}
break;
case static_cast<int>(Page::AudioCodec):
if (AudioCodecPage::IsRequired())
{
return nextId;
}
break;
case static_cast<int>(Page::Finish):
return nextId;
default:
return -1;
}
}
return -1;
}
bool SetupWizard::IsSetupRequired() bool SetupWizard::IsSetupRequired()
{ {
auto& generalSettings = settings::GeneralSettings::Instance(); return (MapProviderPage::IsRequired() || AudioCodecPage::IsRequired());
std::string mapboxApiKey = generalSettings.mapbox_api_key().GetValue();
std::string maptilerApiKey = generalSettings.maptiler_api_key().GetValue();
// Setup is required if either API key is empty, or contains a single
// character ("?")
return (mapboxApiKey.size() <= 1 && maptilerApiKey.size() <= 1);
} }
} // namespace setup } // namespace setup

View file

@ -19,12 +19,15 @@ public:
Welcome = 0, Welcome = 0,
MapProvider, MapProvider,
MapLayout, MapLayout,
AudioCodec,
Finish Finish
}; };
explicit SetupWizard(QWidget* parent = nullptr); explicit SetupWizard(QWidget* parent = nullptr);
~SetupWizard(); ~SetupWizard();
int nextId() const override;
static bool IsSetupRequired(); static bool IsSetupRequired();
private: private: