Implement completion of wizard

Applying settings is still only implemented for one of the cases.
This commit is contained in:
Martchus 2022-10-01 22:25:33 +02:00
parent 442aee992a
commit bd5b93d311
5 changed files with 105 additions and 14 deletions

View File

@ -87,6 +87,7 @@ TrayWidget::TrayWidget(TrayMenu *parent)
, m_selectedConnection(nullptr)
, m_startStopButtonTarget(StartStopButtonTarget::None)
, m_tabTextsShown(true)
, m_applyingSettingsForWizard(false)
{
// don't show connection status within connection settings if there are multiple tray widgets/icons (would be ambiguous)
if (!s_instances.empty() && s_settingsDlg) {
@ -273,10 +274,51 @@ void TrayWidget::showWizard()
s_wizard = Wizard::instance();
connect(s_wizard, &Wizard::destroyed, this, [] { s_wizard = nullptr; });
connect(s_wizard, &Wizard::settingsDialogRequested, this, &TrayWidget::showSettingsDialog);
connect(s_wizard, &Wizard::openSyncthingRequested, this, &TrayWidget::showWebUi);
connect(s_wizard, &Wizard::settingsChanged, this, &TrayWidget::applySettingsChangesFromWizard);
}
showDialog(s_wizard, centerWidgetAvoidingOverflow(s_wizard));
}
void TrayWidget::applySettingsChangesFromWizard()
{
// reset possibly opened settings dialog to be consistent with new configuration
if (s_settingsDlg) {
s_settingsDlg->reset();
}
// consider the settings applied instantly if there's no tray widget instance
if (s_instances.empty()) {
if (s_wizard) {
s_wizard->handleConfigurationApplied();
}
return;
}
// apply settings on all tray widgets using the normal re-connect logic
// note: Ensure at least one tray widget has the primary config selected as this is the config changed
// by the wizard we need to keep track of.
const auto &primaryConnectionName = Settings::values().connection.primary.label;
TrayWidget *relevantInstance = nullptr;
for (auto *const instance : s_instances) {
auto index = instance->m_connectionsMenu->actions().indexOf(instance->m_connectionsActionGroup->checkedAction());
if (index == 0) {
instance->m_applyingSettingsForWizard = true;
relevantInstance = instance;
break;
}
}
for (auto *const instance : s_instances) {
if (!relevantInstance) {
instance->m_applyingSettingsForWizard = true;
instance->applySettings(primaryConnectionName);
relevantInstance = instance;
} else {
instance->applySettings();
}
}
}
void TrayWidget::showAboutDialog()
{
if (!s_dialogParent) {
@ -413,10 +455,13 @@ void TrayWidget::handleStatusChanged(SyncthingStatus status)
m_ui->statusPushButton->setIcon(QIcon(QStringLiteral("refresh.fa")));
m_ui->statusPushButton->setHidden(false);
updateTraffic(); // ensure previous traffic statistics are no longer shown
break;
if (m_applyingSettingsForWizard) {
concludeWizard(tr("Unable to establish connection to Syncthing."));
}
return;
case SyncthingStatus::Reconnecting:
m_ui->statusPushButton->setHidden(true);
break;
return;
case SyncthingStatus::Idle:
case SyncthingStatus::Scanning:
case SyncthingStatus::Synchronizing:
@ -434,6 +479,9 @@ void TrayWidget::handleStatusChanged(SyncthingStatus status)
break;
default:;
}
if (m_applyingSettingsForWizard) {
concludeWizard();
}
}
void TrayWidget::applySettings(const QString &connectionConfig)
@ -551,6 +599,11 @@ void TrayWidget::applySettings(const QString &connectionConfig)
msgBox->setAttribute(Qt::WA_DeleteOnClose);
msgBox->show();
}
// conclude wizard immediately if no re-connect was required anyways
if (!reconnectRequired) {
concludeWizard();
}
}
bool TrayWidget::event(QEvent *event)
@ -857,6 +910,17 @@ void TrayWidget::handleConnectionSelected(QAction *connectionAction)
}
}
void TrayWidget::concludeWizard(const QString &errorMessage)
{
if (!m_applyingSettingsForWizard) {
return;
}
m_applyingSettingsForWizard = false;
if (s_wizard) {
s_wizard->handleConfigurationApplied(errorMessage);
}
}
void TrayWidget::showDialog(QWidget *dlg, bool maximized)
{
if (m_menu) {

View File

@ -76,6 +76,7 @@ public Q_SLOTS:
void restartSyncthing();
void quitTray();
void applySettings(const QString &connectionConfig = QString());
void applySettingsChangesFromWizard();
protected:
bool event(QEvent *event) override;
@ -106,6 +107,7 @@ private Q_SLOTS:
#endif
void handleNewNotification(CppUtilities::DateTime when, const QString &msg);
void handleConnectionSelected(QAction *connectionAction);
void concludeWizard(const QString &errorMessage = QString());
void showDialog(QWidget *dlg, bool maximized = false);
void setBrightColorsOfModelsAccordingToPalette();
@ -137,6 +139,7 @@ private:
enum class StartStopButtonTarget { None, Service, Launcher } m_startStopButtonTarget;
QStringList m_tabTexts;
bool m_tabTextsShown;
bool m_applyingSettingsForWizard;
static std::vector<TrayWidget *> s_instances;
};

View File

@ -87,7 +87,7 @@ find_package(${PACKAGE_NAMESPACE_PREFIX}c++utilities${CONFIGURATION_PACKAGE_SUFF
use_cpp_utilities(VISIBILITY PUBLIC)
# find qtutilities
find_package(${PACKAGE_NAMESPACE_PREFIX}qtutilities${CONFIGURATION_PACKAGE_SUFFIX_QTUTILITIES} 6.8.0 REQUIRED)
find_package(${PACKAGE_NAMESPACE_PREFIX}qtutilities${CONFIGURATION_PACKAGE_SUFFIX_QTUTILITIES} 6.9.0 REQUIRED)
use_qt_utilities()
# find backend libraries

View File

@ -92,7 +92,7 @@ SetupDetection &Wizard::setupDetection()
return *m_setupDetection;
}
bool Wizard::applyConfig()
bool Wizard::changeSettings()
{
const auto &detection = setupDetection();
auto &settings = Settings::values();
@ -108,7 +108,8 @@ bool Wizard::applyConfig()
if (url != primary.syncthingUrl || detection.config.guiUser != primary.userName || detection.config.guiApiKey != primary.apiKey) {
if (!primary.syncthingUrl.isEmpty() || !primary.userName.isEmpty() || !primary.password.isEmpty() || !primary.apiKey.isEmpty()) {
// backup previous primary config unless fields going to be overridden are empty anyways
settings.connection.secondary.emplace_back(primary);
auto &backup = settings.connection.secondary.emplace_back(primary);
backup.label = tr("Backup of %1 (created by wizard)").arg(backup.label);
}
primary.syncthingUrl = url;
primary.userName = detection.config.guiUser;
@ -130,12 +131,9 @@ bool Wizard::applyConfig()
break;
}
// TODO: invoke resetAllPages() on possibly opened settings dialog in slot connected to that signal
// TODO: let tray widget / plasmoid re-connect on that signal
// let the tray widget / plasmoid apply the settings
// note: The tray widget / plasmoid is expected to call handleConfigurationApplied().
emit settingsChanged();
// TODO: wait for successful connection instead of just invoking handleConfigurationApplied()
handleConfigurationApplied(QStringLiteral("not implemented yet"));
return true;
}
@ -739,7 +737,7 @@ void ApplyWizardPage::initializePage()
bool ApplyWizardPage::validatePage()
{
auto *const wizard = qobject_cast<Wizard *>(this->wizard());
return wizard ? wizard->applyConfig() : false;
return wizard ? wizard->changeSettings() : false;
}
FinalWizardPage::FinalWizardPage(QWidget *parent)
@ -750,10 +748,12 @@ FinalWizardPage::FinalWizardPage(QWidget *parent)
layout->addWidget(m_label = new QLabel());
setLayout(layout);
m_label->setWordWrap(true);
m_progressBar->setMaximum(0);
auto *const wizard = qobject_cast<Wizard *>(this->wizard());
connect(wizard, &Wizard::configApplied, this, &QWizardPage::completeChanged);
connect(m_label, &QLabel::linkActivated, this, &FinalWizardPage::handleLinkActivated);
}
FinalWizardPage::~FinalWizardPage()
@ -771,6 +771,13 @@ void FinalWizardPage::initializePage()
showResults();
}
bool FinalWizardPage::validatePage()
{
// keep config file on disk in-sync with new settings
Settings::save();
return true;
}
void QtGui::FinalWizardPage::showResults()
{
auto *const wizard = qobject_cast<Wizard *>(this->wizard());
@ -791,7 +798,9 @@ void QtGui::FinalWizardPage::showResults()
m_progressBar->hide();
if (wizard->configError().isEmpty()) {
setSubTitle(tr("All changes have been applied"));
m_label->setText(tr("You can close the wizard. It may take shortly until Syncthing is up and running."));
m_label->setText(tr("The configuration has been changed successfully. You can close the wizard and <a href=\"openSyncthing\">open "
"Syncthing</a> to pair remote devices and add folders for sharing. If you need further help, read the "
"<a href=\"openDocs\">documentation to get started</a>."));
} else {
setSubTitle(tr("Not all changes could be applied"));
m_label->setText(
@ -801,4 +810,14 @@ void QtGui::FinalWizardPage::showResults()
}
}
void FinalWizardPage::handleLinkActivated(const QString &href)
{
auto *const wizard = qobject_cast<Wizard *>(this->wizard());
if (wizard && href == QLatin1String("openSyncthing")) {
emit wizard->openSyncthingRequested();
} else if (href == QLatin1String("openDocs")) {
QDesktopServices::openUrl(QStringLiteral("https://docs.syncthing.net/intro/getting-started.html#configuring"));
}
}
} // namespace QtGui

View File

@ -53,10 +53,12 @@ public:
const QString &configError() const;
public Q_SLOTS:
bool applyConfig();
bool changeSettings();
void handleConfigurationApplied(const QString &configError = QString());
Q_SIGNALS:
void settingsDialogRequested();
void openSyncthingRequested();
void settingsChanged();
void configApplied();
@ -64,7 +66,6 @@ private Q_SLOTS:
void showDetailsFromSetupDetection();
void handleConfigurationSelected(MainConfiguration mainConfig, ExtraConfiguration extraConfig);
void handleAutostartSelected(bool autostartEnabled);
void handleConfigurationApplied(const QString &configError);
private:
static Wizard *s_instance;
@ -199,10 +200,14 @@ public:
bool isComplete() const override;
void initializePage() override;
bool validatePage() override;
public Q_SLOTS:
void showResults();
private Q_SLOTS:
void handleLinkActivated(const QString &href);
private:
QLabel *m_label;
QProgressBar *m_progressBar;