diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt
index ae91f802dc5..705c677319e 100644
--- a/src/gui/CMakeLists.txt
+++ b/src/gui/CMakeLists.txt
@@ -3,25 +3,17 @@ include(ECMAddAppIcon)
find_package(KDSingleApplication-qt6 1.0.0 REQUIRED)
set(client_UI_SRCS
- aboutdialog.ui
- generalsettings.ui
ignorelisteditor.ui
networksettings.ui
localactivitywidget.ui
syncerrorwidget.ui
- settingsdialog.ui
tlserrordialog.ui
logbrowser.ui
- accountsgui/accountview.ui
)
set(client_SRCS
- aboutdialog.cpp
accountmanager.cpp
- accountmodalwidget.cpp
- accountmodalwidget.ui
-
application.cpp
fetchserversettings.cpp
clientproxy.cpp
@@ -30,20 +22,18 @@ set(client_SRCS
folder.cpp
folderman.cpp
folderwatcher.cpp
- generalsettings.cpp
ignorelisteditor.cpp
lockwatcher.cpp
logbrowser.cpp
networkinformation.cpp
networksettings.cpp
openfilemanager.cpp
- owncloudgui.cpp
+ traymenucontroller.cpp
localactivitywidget.cpp
protocolitem.cpp
syncerrorwidget.cpp
activitysettings.cpp
selectivesyncwidget.cpp
- settingsdialog.cpp
tlserrordialog.cpp
syncrunfilelog.cpp
accountstate.cpp
diff --git a/src/gui/FoldersGui/accountfolderscontroller.cpp b/src/gui/FoldersGui/accountfolderscontroller.cpp
index 893ba230caf..2803481f4e8 100644
--- a/src/gui/FoldersGui/accountfolderscontroller.cpp
+++ b/src/gui/FoldersGui/accountfolderscontroller.cpp
@@ -20,9 +20,7 @@
#include "commonstrings.h"
#include "configfile.h"
#include "foldermodelcontroller.h"
-#include "folderwizard.h"
#include "selectivesyncwidget.h"
-#include "settingsdialog.h"
#include "guiutility.h"
#include "networkjobs.h"
@@ -85,27 +83,7 @@ void AccountFoldersController::onFolderChanged(OCC::Folder *folder)
void AccountFoldersController::onAddFolder()
{
- if (!_accountState || !_accountState->account()) {
- return;
- }
-
- emit requestAddFolder();
-}
-
-void AccountFoldersController::onFolderWizardAccepted(OCC::FolderMan::SyncConnectionDescription result)
-{
- if (!_accountState) {
- return;
- }
-
- // The gui should not allow users to selectively choose any sync lists if vfs is enabled, but this kind of check was
- // originally in play here so...keep it just in case.
- if (result.useVirtualFiles && !result.selectiveSyncBlackList.empty()) {
- result.selectiveSyncBlackList.clear();
- }
-
- // Refactoring todo: turn this into a signal
- FolderMan::instance()->addFolderFromGui(_accountState, result);
+ emit requestAddFolder(_accountId);
}
void AccountFoldersController::buildMenuActions()
@@ -196,7 +174,7 @@ void AccountFoldersController::onEnableVfs()
"will become available again."
"\n\n"
"This action will abort any currently running synchronization."),
- QMessageBox::Yes | QMessageBox::No, ocApp()->gui()->settingsDialog());
+ QMessageBox::Yes | QMessageBox::No, ocApp()->mainWindow());
msgBox.setObjectName("confirmDisableVfsDialog");
msgBox.button(QMessageBox::Yes)->setText(tr("Disable support"));
msgBox.button(QMessageBox::Yes)->setObjectName("disableVfsButton");
@@ -278,7 +256,7 @@ void AccountFoldersController::onForceSync()
QMessageBox messageBox(QMessageBox::Question, tr("Internet connection is metered"),
tr("Synchronization is paused because the Internet connection is a metered connection"
"
Do you really want to force a Synchronization now?"),
- QMessageBox::Yes | QMessageBox::No, ocApp()->gui()->settingsDialog());
+ QMessageBox::Yes | QMessageBox::No, ocApp()->mainWindow());
messageBox.setObjectName("confirmForceSyncWhenMeteredDialog");
messageBox.button(QMessageBox::No)->setObjectName("cancelForceSyncWhenMeteredButton");
messageBox.button(QMessageBox::Yes)->setObjectName("forceSyncWhenMeteredButton");
@@ -300,7 +278,7 @@ void AccountFoldersController::onTogglePauseSync()
if (!currentlyPaused) {
if (_currentFolder->isSyncRunning()) {
QMessageBox msgbox(QMessageBox::Question, tr("Sync Running"), tr("The sync operation is running.
Do you want to stop it?"),
- QMessageBox::Yes | QMessageBox::No, ocApp()->gui()->settingsDialog());
+ QMessageBox::Yes | QMessageBox::No, ocApp()->mainWindow());
msgbox.setDefaultButton(QMessageBox::No);
msgbox.setObjectName("confirmPauseRunningSyncDialog");
msgbox.button(QMessageBox::Yes)->setObjectName("pauseRunningSyncButton");
@@ -330,7 +308,7 @@ void AccountFoldersController::onRemoveSync()
tr("
Do you really want to stop syncing the folder %1?
"
"Note: This will not delete any files.
")
.arg(shortGuiLocalPath),
- QMessageBox::Yes | QMessageBox::No, ocApp()->gui()->settingsDialog());
+ QMessageBox::Yes | QMessageBox::No, ocApp()->mainWindow());
msgBox.button(QMessageBox::Yes)->setText(tr("Remove Folder Sync Connection"));
msgBox.button(QMessageBox::No)->setText(tr("Cancel"));
msgBox.setObjectName("confirmRemoveFolderSyncDialog");
diff --git a/src/gui/FoldersGui/accountfolderscontroller.h b/src/gui/FoldersGui/accountfolderscontroller.h
index 1d8c8c67dda..88ccfa9a1db 100644
--- a/src/gui/FoldersGui/accountfolderscontroller.h
+++ b/src/gui/FoldersGui/accountfolderscontroller.h
@@ -38,17 +38,16 @@ class AccountFoldersController : public QObject
signals:
void removeFolderFromGui(OCC::Folder *f);
- void requestAddFolder();
+ void requestAddFolder(QUuid accountId);
void requestAccountModalWidget(OCC::AccountModalWidget *widget);
protected:
void onUnsyncedSpaceCountChanged(const QUuid &accountId, int unsyncedSpaceCount, int totalSpaceCount);
void onAddFolder();
- void onFolderWizardAccepted(OCC::FolderMan::SyncConnectionDescription result);
private:
- AccountState *_accountState = nullptr;
+ QPointer _accountState;
QUuid _accountId;
QPointer _currentFolder = nullptr;
AccountFoldersView *_view = nullptr;
diff --git a/src/gui/aboutdialog.cpp b/src/gui/aboutdialog.cpp
deleted file mode 100644
index db723001b53..00000000000
--- a/src/gui/aboutdialog.cpp
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (C) by Hannah von Reth
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-#include "aboutdialog.h"
-#include "ui_aboutdialog.h"
-
-#include "gui/guiutility.h"
-#include "libsync/theme.h"
-
-#include
-
-#ifdef WITH_AUTO_UPDATER
-#include "config/appconfig.h"
-#include "libsync/configfile.h"
-#include "updater/ocupdater.h"
-#ifdef Q_OS_MAC
-// FIXME We should unify those, but Sparkle does everything behind the scene transparently
-#include "updater/sparkleupdater.h"
-#endif
-#endif
-
-namespace {
-#ifdef WITH_AUTO_UPDATER
-bool isTestPilotCloudTheme()
-{
- return OCC::Theme::instance()->appName() == QLatin1String("testpilotcloud");
-}
-#endif
-}
-
-namespace OCC {
-
-AboutDialog::AboutDialog(QWidget *parent)
- : QDialog(parent)
- , ui(new Ui::AboutDialog)
-{
- ui->setupUi(this);
- ui->aboutText->setText(Theme::instance()->about());
- ui->icon->setPixmap(Theme::instance()->aboutIcon().pixmap(256));
- ui->versionInfo->setText(Theme::instance()->aboutVersions(Theme::VersionFormat::RichText));
-
- connect(ui->versionInfo, &QTextBrowser::anchorClicked, this, &AboutDialog::openBrowserFromUrl);
- connect(ui->aboutText, &QLabel::linkActivated, this, &AboutDialog::openBrowser);
-
- setupUpdaterWidget();
-}
-
-AboutDialog::~AboutDialog()
-{
- delete ui;
-}
-
-void AboutDialog::openBrowser(const QString &s)
-{
- Utility::openBrowser(QUrl(s), this);
-}
-
-void AboutDialog::openBrowserFromUrl(const QUrl &s)
-{
- return openBrowser(s.toString());
-}
-
-void AboutDialog::setupUpdaterWidget()
-{
-#ifdef WITH_AUTO_UPDATER
- // non-standard update channels are only supported by the vanilla theme and the testpilotcloud theme
- if (!Resources::isVanillaTheme() && !isTestPilotCloudTheme()) {
- if (Utility::isMac()) {
- // Because we don't have any statusString from the SparkleUpdater anyway we can hide the whole thing
- ui->updaterWidget->hide();
- }
- }
-
- ConfigFile().makeQSettings().remove("skipUpdateCheck"); // remove old config key
-
- if (!AppConfig().skipUpdateCheck() && Updater::instance()) {
- // Note: the sparkle-updater is not an OCUpdater
- if (auto *ocupdater = qobject_cast(Updater::instance())) {
- auto updateInfo = [ocupdater, this] {
- QString statusString = ocupdater->statusString();
- switch (ocupdater->downloadState()) {
- case OCUpdater::Unknown:
- [[fallthrough]];
- case OCUpdater::CheckingServer:
- [[fallthrough]];
- case OCUpdater::UpToDate:
- // No update, leave the status string as is.
- break;
- case OCUpdater::Downloading:
- [[fallthrough]];
- case OCUpdater::DownloadComplete:
- [[fallthrough]];
- case OCUpdater::DownloadFailed:
- [[fallthrough]];
- case OCUpdater::DownloadTimedOut:
- [[fallthrough]];
- case OCUpdater::UpdateOnlyAvailableThroughSystem:
- statusString = QStringLiteral("Version %1 is available. %2").arg(ocupdater->availableVersionString(), statusString);
- break;
- }
-
- ui->updateStateLabel->setText(statusString);
- ui->restartButton->setVisible(ocupdater->downloadState() == OCUpdater::DownloadComplete);
- };
- connect(ocupdater, &OCUpdater::downloadStateChanged, this, updateInfo);
- connect(ui->restartButton, &QAbstractButton::clicked, ocupdater, &Updater::applyUpdateAndRestart);
- updateInfo();
- }
-#ifdef HAVE_SPARKLE
- if (SparkleUpdater *sparkleUpdater = qobject_cast(Updater::instance())) {
- ui->updateStateLabel->setText(sparkleUpdater->statusString());
- ui->restartButton->setVisible(false);
- }
-#endif
- } else {
- ui->updaterWidget->hide();
- }
-#else
- ui->updaterWidget->hide();
-#endif
-}
-
-} // OCC namespace
diff --git a/src/gui/aboutdialog.h b/src/gui/aboutdialog.h
deleted file mode 100644
index e252a8ce639..00000000000
--- a/src/gui/aboutdialog.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) by Hannah von Reth
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-#pragma once
-
-#include
-
-
-namespace OCC {
-
-namespace Ui {
- class AboutDialog;
-}
-
-class AboutDialog : public QDialog
-{
- Q_OBJECT
-
-public:
- explicit AboutDialog(QWidget *parent = nullptr);
- ~AboutDialog();
-
-private:
- void openBrowser(const QString &s);
- void openBrowserFromUrl(const QUrl &s);
- void setupUpdaterWidget();
-
-private:
- Ui::AboutDialog *ui;
-};
-
-}
diff --git a/src/gui/aboutdialog.ui b/src/gui/aboutdialog.ui
deleted file mode 100644
index 14955a8804e..00000000000
--- a/src/gui/aboutdialog.ui
+++ /dev/null
@@ -1,191 +0,0 @@
-
-
- OCC::AboutDialog
-
-
-
- 0
- 0
- 751
- 391
-
-
-
- About
-
-
- -
-
-
- 0
-
-
-
- About
-
-
-
-
-
-
-
-
-
-
-
-
- Qt::Orientation::Vertical
-
-
-
- 20
- 40
-
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 256
- 256
-
-
-
-
-
-
- :/client/ownCloud/theme/colored/owncloud-icon.svg
-
-
-
- -
-
-
- Qt::Orientation::Vertical
-
-
-
- 20
- 40
-
-
-
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- &Restart && Update
-
-
-
-
-
-
-
-
-
-
- Versions
-
-
- -
-
-
- false
-
-
- false
-
-
-
-
-
-
-
- -
-
-
- Qt::Orientation::Horizontal
-
-
- QDialogButtonBox::StandardButton::Ok
-
-
-
-
-
-
- tabWidget
- versionInfo
- restartButton
-
-
-
-
- buttonBox
- accepted()
- OCC::AboutDialog
- accept()
-
-
- 248
- 254
-
-
- 157
- 274
-
-
-
-
- buttonBox
- rejected()
- OCC::AboutDialog
- reject()
-
-
- 316
- 260
-
-
- 286
- 274
-
-
-
-
-
diff --git a/src/gui/accountsgui/CMakeLists.txt b/src/gui/accountsgui/CMakeLists.txt
index 4475959344e..fb018b30aee 100644
--- a/src/gui/accountsgui/CMakeLists.txt
+++ b/src/gui/accountsgui/CMakeLists.txt
@@ -3,9 +3,13 @@ target_sources(owncloudGui PRIVATE
accountsguicontroller.h
accountview.cpp
accountview.h
+ accountview.ui
accountviewcontroller.cpp
accountviewcontroller.h
accountplaceholderwidget.h
accountplaceholderwidget.cpp
+ accountmodalwidget.cpp
+ accountmodalwidget.h
+ accountmodalwidget.ui
)
diff --git a/src/gui/accountsgui/accountmodalwidget.cpp b/src/gui/accountsgui/accountmodalwidget.cpp
new file mode 100644
index 00000000000..c4b922d0160
--- /dev/null
+++ b/src/gui/accountsgui/accountmodalwidget.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) Lisa Reese
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "accountmodalwidget.h"
+#include "ui_accountmodalwidget.h"
+
+#include "gui/qmlutils.h"
+
+#include
+
+namespace OCC {
+
+AccountModalWidget::AccountModalWidget(const QString &title, QWidget *widget, QWidget *parent)
+ : QWidget(parent)
+ , ui(new Ui::AccountModalWidget)
+{
+ ui->setupUi(this);
+ ui->groupBox->setTitle(title);
+ ui->groupBox->layout()->addWidget(widget);
+
+ // the internal widget may be a dialog, in which case we want to block adding "standard buttons" and
+ // connect to the dialog accept/reject signals instead
+ QDialog *dialog = qobject_cast(widget);
+ if (dialog) {
+ _widgetHasButtons = true;
+ connect(dialog, &QDialog::accepted, this, &AccountModalWidget::accept);
+ connect(dialog, &QDialog::rejected, this, &AccountModalWidget::reject);
+ } else {
+ _widgetHasButtons = false;
+ connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &AccountModalWidget::accept);
+ connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &AccountModalWidget::reject);
+ }
+}
+
+
+AccountModalWidget::AccountModalWidget(const QString &title, const QUrl &qmlSource, QObject *qmlContext, QWidget *parent)
+ : AccountModalWidget(
+ title,
+ [&] {
+ auto *out = new QmlUtils::OCQuickWidget;
+ out->setOCContext(qmlSource, parent, qmlContext, QJSEngine::JavaScriptOwnership);
+ return out;
+ }(),
+ parent)
+{
+}
+void AccountModalWidget::setStandardButtons(QDialogButtonBox::StandardButtons buttons)
+{
+ if (!_widgetHasButtons)
+ ui->buttonBox->setStandardButtons(buttons);
+}
+
+QPushButton *AccountModalWidget::addButton(const QString &text, QDialogButtonBox::ButtonRole role)
+{
+ if (!_widgetHasButtons)
+ return ui->buttonBox->addButton(text, role);
+ return nullptr;
+}
+
+void AccountModalWidget::accept()
+{
+ Q_EMIT accepted();
+ Q_EMIT finished(this);
+}
+
+void AccountModalWidget::reject()
+{
+ Q_EMIT rejected();
+ Q_EMIT finished(this);
+}
+
+} // OCC
diff --git a/src/gui/accountsgui/accountmodalwidget.h b/src/gui/accountsgui/accountmodalwidget.h
new file mode 100644
index 00000000000..aedbabc7f02
--- /dev/null
+++ b/src/gui/accountsgui/accountmodalwidget.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) Lisa Reese
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#pragma once
+
+#include "gui/qmlutils.h"
+
+#include
+
+namespace OCC {
+
+namespace Ui {
+ class AccountModalWidget;
+}
+
+// this class is basically a "wrapper" that hosts a widget/panel that we want to run in a modal concept.
+// basically it adds a title to the given widget, and provides buttons (normally ok/cancel) that control the lifetime of
+// the "modality"
+// the class is used in the AccountView with account related stuff
+// it's basically a reproduction of a modal dialog but it's embedded in the account view of the main window.
+// it's also possible to use it to wrap a QDialog, such as the FolderWizard, in which case the dialog's accept/reject
+// signals are taken over for the modal widget result
+class AccountModalWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ AccountModalWidget(const QString &title, QWidget *widget, QWidget *parent);
+ AccountModalWidget(const QString &title, const QUrl &qmlSource, QObject *qmlContext, QWidget *parent);
+
+ // if the widget is a QDialog, these functions silently do nothing (because the dialog buttons already exist)
+ void setStandardButtons(QDialogButtonBox::StandardButtons buttons);
+ QPushButton *addButton(const QString &text, QDialogButtonBox::ButtonRole role);
+
+public Q_SLOTS:
+ void accept();
+ void reject();
+
+Q_SIGNALS:
+ void accepted();
+ void rejected();
+ void finished(OCC::AccountModalWidget *widget);
+
+private:
+ Ui::AccountModalWidget *ui;
+
+ bool _widgetHasButtons = false;
+};
+
+} // OCC
diff --git a/src/gui/accountsgui/accountmodalwidget.ui b/src/gui/accountsgui/accountmodalwidget.ui
new file mode 100644
index 00000000000..e5e5aa004ee
--- /dev/null
+++ b/src/gui/accountsgui/accountmodalwidget.ui
@@ -0,0 +1,42 @@
+
+
+ OCC::AccountModalWidget
+
+
+
+ 0
+ 0
+ 400
+ 300
+
+
+
+ Form
+
+
+
+ 25
+
+
+ 25
+
+ -
+
+
+ placeholder
+
+
+
+
+ -
+
+
+ QDialogButtonBox::StandardButton::NoButton
+
+
+
+
+
+
+
+
diff --git a/src/gui/accountsgui/accountsguicontroller.cpp b/src/gui/accountsgui/accountsguicontroller.cpp
index fb1bc93ef81..ece1debbc5d 100644
--- a/src/gui/accountsgui/accountsguicontroller.cpp
+++ b/src/gui/accountsgui/accountsguicontroller.cpp
@@ -21,8 +21,10 @@
#include "accountmanager.h"
#include "accountplaceholderwidget.h"
+#include "accountsgui/accountviewcontroller.h"
#include "accountstate.h"
#include "accountview.h"
+#include "application.h"
#include "creds/abstractcredentials.h"
#include "folderman.h"
#include "mainwindow/mainwindow.h"
@@ -63,22 +65,24 @@ void AccountsGuiController::onAccountAdded(AccountState *state)
{
if (!_window || !state || !state->account())
return;
- // asap we need to create some kind of accountView builder that will instantiate a controller and view + whatever else
- // as currently everything is in the view which is absolutely not ok, especially given the multitude of "heavy lifting"
- // that goes on in there
Account *account = state->account();
QUuid accountId = account->uuid();
+
connect(account, &Account::avatarChanged, this, &AccountsGuiController::onAccountAvatarChanged);
- auto accountView = new AccountView(state, nullptr);
+ auto accountView = new AccountView(nullptr);
// for both the view and the action, we create a unique objectName using the account uuid
// to support squish test object identification
accountView->setObjectName(QString("accountView_%1").arg(accountId.toString()));
- connect(account->credentials(), &AbstractCredentials::requestAccountModal, accountView, &AccountView::onRequestAccountModalWidget);
- connect(accountView, &AccountView::accountBeginModal, this, &AccountsGuiController::startModal);
- connect(accountView, &AccountView::accountEndModal, this, &AccountsGuiController::endModal);
+ AccountViewController *viewController = new AccountViewController(accountView, state, this);
+ _viewControllerForAccount.insert(accountId, viewController);
+
+ connect(account->credentials(), &AbstractCredentials::requestAccountModal, viewController, &AccountViewController::addAccountModalWidget);
+
+ connect(viewController, &AccountViewController::accountBeginModal, this, &AccountsGuiController::startModal);
+ connect(viewController, &AccountViewController::accountEndModal, this, &AccountsGuiController::endModal);
QAction *accountAction = new QAction(this);
accountAction->setObjectName(QString("accountAction_%1").arg(accountId.toString()));
@@ -153,7 +157,7 @@ void AccountsGuiController::runAccountWizard()
NewAccountWizard wizard(_window);
NewAccountModel model(nullptr);
NewAccountWizardController wizardController(&model, &wizard, nullptr);
- ownCloudGui::raise();
+ _window->ensureVisible();
int result = wizard.exec();
if (result == QDialog::Accepted) {
// the builder needs to be a pointer as it has to wait for the connection state to go to connected
@@ -228,19 +232,17 @@ void AccountsGuiController::handleAccountSetupError(const QString &error)
setupAccountPlaceholder();
}
-void AccountsGuiController::runFolderWizard(Account *account)
+void AccountsGuiController::runFolderWizard(QUuid accountId)
{
- if (!account)
- return;
-
- QAction *action = _actionForAccount.value(account->uuid(), nullptr);
+ QAction *action = _actionForAccount.value(accountId, nullptr);
if (!action)
return;
action->setChecked(true);
- AccountView *view = action->data().value();
- if (view)
- view->slotAddFolder();
+
+ AccountViewController *controller = _viewControllerForAccount.value(accountId, nullptr);
+ if (controller)
+ controller->runFolderWizard();
}
void AccountsGuiController::startModal(QUuid accountId)
@@ -251,7 +253,7 @@ void AccountsGuiController::startModal(QUuid accountId)
action->setIcon(Resources::getCoreIcon("states/warning"));
action->setChecked(true);
- ownCloudGui::raise();
+ ocApp()->ensureVisible();
}
void AccountsGuiController::endModal(QUuid accountId)
diff --git a/src/gui/accountsgui/accountsguicontroller.h b/src/gui/accountsgui/accountsguicontroller.h
index 7b85e6842f4..0a8eafcbb9c 100644
--- a/src/gui/accountsgui/accountsguicontroller.h
+++ b/src/gui/accountsgui/accountsguicontroller.h
@@ -30,6 +30,7 @@ class AccountState;
class AccountManager;
class Account;
class MainWindow;
+class AccountViewController;
class AccountsGuiController : public QObject
{
@@ -44,6 +45,7 @@ class AccountsGuiController : public QObject
QPointer _accountMgr;
QPointer _window;
QHash _actionForAccount;
+ QHash _viewControllerForAccount;
void onAccountAdded(AccountState *state);
void onAccountRemoved(AccountState *state);
@@ -51,7 +53,7 @@ class AccountsGuiController : public QObject
void onAccountAvatarChanged();
- void runFolderWizard(Account *account);
+ void runFolderWizard(QUuid accountId);
void handleAccountSetupError(const QString &error);
void startModal(QUuid accountId);
diff --git a/src/gui/accountsgui/accountview.cpp b/src/gui/accountsgui/accountview.cpp
index 867cb9fe411..3d92335e58b 100644
--- a/src/gui/accountsgui/accountview.cpp
+++ b/src/gui/accountsgui/accountview.cpp
@@ -14,359 +14,103 @@
#include "accountview.h"
-#include "FoldersGui/accountfoldersview.h"
-#include "FoldersGui/foldermodelcontroller.h"
#include "ui_accountview.h"
-
-#include "FoldersGui/accountfolderscontroller.h"
-#include "account.h"
-#include "accountmanager.h"
-#include "accountstate.h"
-#include "application.h"
-#include "commonstrings.h"
-#include "configfile.h"
-#include "folderman.h"
-#include "folderwizard/folderwizard.h"
-#include "gui/accountmodalwidget.h"
-#include "gui/models/models.h"
-#include "gui/networkinformation.h"
-#include "gui/qmlutils.h"
-#include "gui/selectivesyncwidget.h"
-#include "libsync/graphapi/spacesmanager.h"
-#include "scheduling/syncscheduler.h"
-#include "settingsdialog.h"
-#include "theme.h"
-
-#include
-#include
-#include
-#include
-#include
-
-namespace {
-constexpr auto modalWidgetStretchedMarginC = 50;
-}
+#include
namespace OCC {
-Q_LOGGING_CATEGORY(lcAccountView, "gui.account.view", QtInfoMsg)
-
-// Refactoring todo: devise a correct handling of null account state in this ctr.
-// also move all this connect stuff to a "connect" method.
-// also ditch the lambdas which should actually be functions (private if necessary)
-// Also refactoring todo: split the controller behavior out into a controller. A widget should NOT contain
-// business or controller logic!
-AccountView::AccountView(AccountState *accountState, QWidget *parent)
+AccountView::AccountView(QWidget *parent)
: QWidget(parent)
- , ui(new Ui::AccountView)
- , _wasDisabledBefore(false)
- , _accountState(accountState)
+ , _ui(new Ui::AccountView)
{
- ui->setupUi(this);
-
- // as usual we do too many things in the ctr and we need to eval all the code paths to make sure they handle
- // the QPointer properly, but as a stopgap to catch null states asap before they trickle down into other areas:
- if (!_accountState || !_accountState->account())
- return;
-
- AccountFoldersController *foldersController = new AccountFoldersController(_accountState, ui->accountFoldersView, this);
- connect(foldersController, &AccountFoldersController::requestAddFolder, this, &AccountView::slotAddFolder);
- connect(foldersController, &AccountFoldersController::requestAccountModalWidget, this, &AccountView::onRequestAccountModalWidget);
-
- ui->connectionStatusLabel->clear();
-
- connect(_accountState, &AccountState::stateChanged, this, &AccountView::slotAccountStateChanged);
- slotAccountStateChanged(_accountState->state());
-
- buildManageAccountMenu();
+ _ui->setupUi(this);
+ _ui->connectionStatusLabel->clear();
- connect(_accountState, &AccountState::isSettingUpChanged, this, &AccountView::accountSettingUpChanged);
-
- connect(ui->stackedWidget, &QStackedWidget::currentChanged, this,
- [this] { ui->manageAccountButton->setEnabled(ui->stackedWidget->currentWidget() == ui->accountFoldersView); });
- ui->stackedWidget->setCurrentWidget(ui->accountFoldersView);
+ connect(_ui->stackedWidget, &QStackedWidget::currentChanged, this,
+ [this] { _ui->manageAccountButton->setEnabled(_ui->stackedWidget->currentWidget() == _ui->accountFoldersView); });
+ _ui->stackedWidget->setCurrentWidget(_ui->accountFoldersView);
}
AccountView::~AccountView()
{
- // this is questionable.
- _goingDown = true;
- delete ui;
+ delete _ui;
}
-void AccountView::accountSettingUpChanged(bool settingUp)
+void AccountView::setAccountMenuActions(QList actions)
{
- if (settingUp) {
- ui->spinner->startAnimation();
- ui->stackedWidget->setCurrentWidget(ui->loadingPage);
+ QMenu *menu = _ui->manageAccountButton->menu();
+ if (!menu) {
+ menu = new QMenu(this);
+ menu->setObjectName("manageAccountMenu");
+ menu->setAccessibleName(tr("Account options menu"));
+ connect(menu, &QMenu::aboutToShow, this, &AccountView::requestMenuActionUpdate);
} else {
- ui->spinner->stopAnimation();
- ui->stackedWidget->setCurrentWidget(ui->accountFoldersView);
- }
-}
-
-void AccountView::slotAddFolder()
-{
- if (!_accountState || !_accountState->account()) {
- return;
+ menu->clear();
}
- FolderWizard *folderWizard = new FolderWizard(_accountState->account(), this);
-
- connect(folderWizard, &QDialog::accepted, this, &AccountView::slotFolderWizardAccepted);
- connect(folderWizard, &QDialog::rejected, this, [] { qCInfo(lcAccountView) << "Folder wizard cancelled"; });
-
- // ignore clang analyzer warning about potential memory leak, please.
- // the modal widget gets reparented to the stacked widget and is automatically deleted when the finished() signal is
- // received
- AccountModalWidget *widget = new AccountModalWidget({}, folderWizard, this);
- addModalAccountWidget(widget);
+ menu->addActions(actions);
+ if (_ui->manageAccountButton->menu() == nullptr)
+ _ui->manageAccountButton->setMenu(menu);
}
-void AccountView::slotFolderWizardAccepted()
+void AccountView::setTopStackWidget(QWidget *widget)
{
- if (!_accountState) {
- return;
- }
+ // should not contain this widget already
+ Q_ASSERT(_ui->stackedWidget->indexOf(widget) < 0);
- FolderWizard *folderWizard = qobject_cast(sender());
- if (!folderWizard)
- return;
-
- qCInfo(lcAccountView) << "Folder wizard completed";
-
- auto config = folderWizard->result();
-
- // The gui should not allow users to selectively choose any sync lists if vfs is enabled, but this kind of check was
- // originally in play here so...keep it just in case.
- if (config.useVirtualFiles && !config.selectiveSyncBlackList.empty()) {
- config.selectiveSyncBlackList.clear();
- }
-
- // Refactoring todo: turn this into a signal/requestAddFolder
- FolderMan::instance()->addFolderFromGui(_accountState, config);
+ _ui->stackedWidget->addWidget(widget);
+ _ui->stackedWidget->setCurrentWidget(widget);
}
-void AccountView::slotOpenAccountInBrowser()
+void AccountView::removeStackWidget(QWidget *widget)
{
- if (!_accountState) {
- return;
- }
-
- QUrl url = _accountState->account()->url();
- if (!Theme::instance()->overrideServerPath().isEmpty()) {
- // There is an override for the WebDAV endpoint. Remove it for normal web browsing.
- url.setPath({});
- }
- QDesktopServices::openUrl(url);
+ _ui->stackedWidget->removeWidget(widget);
}
-void AccountView::slotToggleSignInState()
+AccountFoldersView *AccountView::foldersView()
{
- if (!_accountState) {
- return;
- }
-
- if (_accountState->isSignedOut()) {
- _accountState->signIn();
- } else {
- _accountState->signOutByUi();
- }
+ return _ui->accountFoldersView;
}
-
-
-void AccountView::showConnectionLabel(const QString &message, StatusIcon statusIcon, QStringList errors)
+void AccountView::accountSettingUpChanged(bool settingUp)
{
- if (errors.isEmpty()) {
- ui->connectionStatusLabel->setText(message);
- ui->connectionStatusLabel->setToolTip(QString());
+ if (settingUp) {
+ _ui->spinner->startAnimation();
+ _ui->stackedWidget->setCurrentWidget(_ui->loadingPage);
} else {
- errors.prepend(message);
- const QString msg = errors.join(QLatin1String("\n"));
- qCDebug(lcAccountView) << msg;
- ui->connectionStatusLabel->setText(msg);
- ui->connectionStatusLabel->setToolTip(QString());
+ _ui->spinner->stopAnimation();
+ _ui->stackedWidget->setCurrentWidget(_ui->accountFoldersView);
}
- ui->accountStatus->setVisible(!message.isEmpty());
-
- QIcon icon;
- switch (statusIcon) {
- case StatusIcon::None:
- break;
- case StatusIcon::Connected:
- icon = Resources::getCoreIcon(QStringLiteral("states/ok"));
- break;
- case StatusIcon::Disconnected:
- icon = Resources::getCoreIcon(QStringLiteral("states/offline"));
- break;
- case StatusIcon::Info:
- icon = Resources::getCoreIcon(QStringLiteral("states/information"));
- break;
- case StatusIcon::Warning:
- icon = Resources::getCoreIcon(QStringLiteral("states/warning"));
- break;
- }
-
- if (!icon.isNull()) {
- ui->warningLabel->setPixmap(icon.pixmap(ui->warningLabel->size()));
- }
- ui->warningLabel->setVisible(statusIcon != StatusIcon::None);
-}
-
-
-void AccountView::buildManageAccountMenu()
-{
- QMenu *menu = new QMenu(this);
- menu->setAccessibleName(tr("Account options menu"));
-
- auto *logInOutAction = menu->addAction(tr("Log in"), this, &AccountView::slotToggleSignInState);
- auto *reconnectAction = menu->addAction(tr("Reconnect"), this, [this] { _accountState->checkConnectivity(true); });
- reconnectAction->setEnabled(!_accountState->isConnected() && !_accountState->isSignedOut());
- connect(_accountState, &AccountState::stateChanged, this, [logInOutAction, reconnectAction, this]() {
- logInOutAction->setText(_accountState->isSignedOut() ? tr("Log in") : tr("Log out"));
- reconnectAction->setEnabled(!_accountState->isConnected() && !_accountState->isSignedOut());
- });
-
- menu->addAction(CommonStrings::showInWebBrowser(), this, &AccountView::slotOpenAccountInBrowser);
- menu->addAction(tr("Remove"), this, &AccountView::slotDeleteAccount);
-
- ui->manageAccountButton->setMenu(menu);
}
-void AccountView::slotAccountStateChanged(AccountState::State state)
-{
- if (!_accountState || !_accountState->account()) {
- return;
- }
-
- Account *account = _accountState->account();
- qCDebug(lcAccountView) << "Account state changed to" << state << "for account" << account;
-
- switch (state) {
- case AccountState::Connected: {
- QStringList errors;
- StatusIcon icon = StatusIcon::Connected;
- if (account->serverSupportLevel() != Account::ServerSupportLevel::Supported) {
- errors << tr("The server version %1 is unsupported! Proceed at your own risk.").arg(account->capabilities().status().versionString());
- icon = StatusIcon::Warning;
- }
- showConnectionLabel(tr("Connected"), icon, errors);
- break;
- }
- case AccountState::ServiceUnavailable:
- showConnectionLabel(tr("Server is temporarily unavailable"), StatusIcon::Disconnected);
- break;
- case AccountState::MaintenanceMode:
- showConnectionLabel(tr("Server is currently in maintenance mode"), StatusIcon::Disconnected);
- break;
- case AccountState::SignedOut:
- showConnectionLabel(tr("Signed out"), StatusIcon::Disconnected);
- break;
- case AccountState::AskingCredentials: {
- showConnectionLabel(tr("Updating credentials…"), StatusIcon::Info);
- break;
- }
- case AccountState::Connecting:
- if (NetworkInformation::instance()->isBehindCaptivePortal()) {
- showConnectionLabel(tr("Captive portal prevents connections to the server."), StatusIcon::Disconnected);
- } else if (NetworkInformation::instance()->isMetered() && ConfigFile().pauseSyncWhenMetered()) {
- showConnectionLabel(tr("Sync is paused due to metered internet connection"), StatusIcon::Disconnected);
- } else {
- showConnectionLabel(tr("Connecting…"), StatusIcon::Info);
- }
- break;
- case AccountState::ConfigurationError:
- showConnectionLabel(tr("Server configuration error"), StatusIcon::Warning, _accountState->connectionErrors());
- break;
- case AccountState::NetworkError:
- // don't display the error to the user, https://github.com/owncloud/client/issues/9790
- [[fallthrough]];
- case AccountState::Disconnected:
- showConnectionLabel(tr("Disconnected"), StatusIcon::Disconnected);
- break;
- }
-}
-
void AccountView::showEvent(QShowEvent *ev)
{
Q_UNUSED(ev);
- ui->manageAccountButton->setFocus();
+ _ui->manageAccountButton->setFocus();
}
-void AccountView::onRequestAccountModalWidget(OCC::AccountModalWidget *widget)
+void AccountView::setConnectionLabel(const QString &message, const QIcon &icon, QStringList errors)
{
- addModalAccountWidget(widget);
-}
-
-// notes to self: the "modal" stuff is in this direction: the accountView sometimes wants to show something in a manner
-// that users should finish the activity. The accountview shows the gui the user should interact with, but it has to ask the
-// main window layer to block other user activity in the meantime. I think conceptually it's ok but the impl needs to be
-// simplified, especially to get rid of the legacy vs non legacy impls
-void AccountView::addModalAccountWidget(AccountModalWidget *widget)
-{
- if (!_accountState || !_accountState->account()) {
- return;
+ // I really see no point in these but they existed previously...eval usefulness later
+ // oh wait...the "warning label" is actually the name of the STATUS ICON?!?!
+ // if so this makes more sense. for goodness sake, let's rename that item asap :D
+ _ui->warningLabel->setVisible(!icon.isNull());
+ if (!icon.isNull()) {
+ _ui->warningLabel->setPixmap(icon.pixmap(_ui->warningLabel->size()));
}
- ui->stackedWidget->addWidget(widget);
- ui->stackedWidget->setCurrentWidget(widget);
-
- connect(widget, &AccountModalWidget::finished, this, &AccountView::finishAccountModalWidget);
-#ifdef USE_NEW_MAIN_WINDOW
- emit accountBeginModal(_accountState->account()->uuid());
-#else
- ocApp()->gui()->settingsDialog()->requestModality(_accountState->account());
-#endif
-}
-
-void AccountView::finishAccountModalWidget(AccountModalWidget *widget)
-{
- if (!widget)
- return;
-
- ui->stackedWidget->removeWidget(widget);
- widget->deleteLater();
-
- Q_ASSERT(_accountState && _accountState->account());
+ _ui->accountStatus->setVisible(!message.isEmpty());
-#ifdef USE_NEW_MAIN_WINDOW
- emit accountEndModal(_accountState->account()->uuid());
-#else
- ocApp()->gui()->settingsDialog()->ceaseModality(_accountState->account());
-#endif
-}
-
-void AccountView::slotDeleteAccount()
-{
- if (!_accountState) {
- return;
+ if (errors.isEmpty()) {
+ _ui->connectionStatusLabel->setText(message);
+ _ui->connectionStatusLabel->setToolTip(QString());
+ } else {
+ errors.prepend(message);
+ const QString msg = errors.join(QLatin1String("\n"));
+ _ui->connectionStatusLabel->setText(msg);
+ _ui->connectionStatusLabel->setToolTip(QString());
}
-
- // Deleting the account potentially deletes 'this', so
- // the QMessageBox should be destroyed before that happens.
- // todo: this is an unnecessarily complicated def for the message box and should exec instead of open.
- auto messageBox = new QMessageBox(QMessageBox::Question, tr("Confirm Account Removal"),
- tr("Do you really want to remove the connection to the account %1?
"
- "Note: This will not delete any files.
")
- .arg(_accountState->account()->displayNameWithHost()),
- QMessageBox::NoButton, this);
- messageBox->setObjectName("confirmRemoveAccountDialog");
- auto yesButton = messageBox->addButton(tr("Remove connection"), QMessageBox::YesRole);
- yesButton->setObjectName("removeAccountButton");
- auto noButton = messageBox->addButton(tr("Cancel"), QMessageBox::NoRole);
- noButton->setObjectName("cancelRemoveAccountButton");
-
- messageBox->setAttribute(Qt::WA_DeleteOnClose);
- connect(messageBox, &QMessageBox::finished, this, [this, messageBox, yesButton]{
- if (messageBox->clickedButton() == yesButton) {
- auto manager = AccountManager::instance();
- manager->deleteAccount(_accountState);
- manager->save();
- }
- });
- messageBox->open();
}
} // namespace OCC
diff --git a/src/gui/accountsgui/accountview.h b/src/gui/accountsgui/accountview.h
index 11e8bc62081..ad2903d5e50 100644
--- a/src/gui/accountsgui/accountview.h
+++ b/src/gui/accountsgui/accountview.h
@@ -16,19 +16,8 @@
#include "gui/owncloudguilib.h"
-#include "folder.h"
-#include "gui/qmlutils.h"
-#include "owncloudgui.h"
-#include "progressdispatcher.h"
-
-#include
#include
-class QModelIndex;
-class QNetworkReply;
-class QLabel;
-class QStandardItemModel;
-
namespace OCC {
class AccountModalWidget;
@@ -40,8 +29,7 @@ class FolderMan;
class Account;
class AccountState;
-// class FolderStatusModel;
-class FolderStatusDelegate;
+class AccountFoldersView;
/**
* @brief The AccountView class
@@ -52,57 +40,32 @@ class OWNCLOUDGUI_EXPORT AccountView : public QWidget
Q_OBJECT
public:
- enum class ModalWidgetSizePolicy { Minimum = QSizePolicy::Minimum, Expanding = QSizePolicy::Expanding };
- Q_ENUM(ModalWidgetSizePolicy)
-
- explicit AccountView(AccountState *accountState, QWidget *parent = nullptr);
+ explicit AccountView(QWidget *parent);
~AccountView() override;
- // this is called by SettingsDialog directly but should be corrected to either respond to signal, or just make
- // it a normal function
- void slotAddFolder();
+ void setAccountMenuActions(QList actions);
+ void setConnectionLabel(const QString &message, const QIcon &icon, QStringList errors = QStringList());
+
+ // this is primarily used to run an account "modal" widget
+ void setTopStackWidget(QWidget *widget);
+ void removeStackWidget(QWidget *widget);
+
+ // holding my nose for now - this should not be public, nor should the type be "embedded" in the view's ui.
+ // todo: replace the concrete folders view with a placeholder location so the controller can SET the folders view in the
+ // account view.
+ // open question: would this mess up the squish tests? we'll soon learn the answer
+ AccountFoldersView *foldersView();
+ void accountSettingUpChanged(bool settingUp);
- void onRequestAccountModalWidget(OCC::AccountModalWidget *widget);
- // todo: this should be protected/private but still "needed" by old impl
- void addModalAccountWidget(AccountModalWidget *widget);
signals:
- // these are sent when the account view starts and ends a "modal" operation
- // at the moment I'm not blocking access to main window toolbar actions as there is really no need, imo,
- // just because the account is in the middle of something. At least we will try it this way and see
- // if it's preferred. So long as the account modal widget blocks *account* related activity I think we're good
- void accountEndModal(QUuid accountId);
- void accountBeginModal(QUuid accountId);
-
-protected slots:
- void slotAccountStateChanged(OCC::AccountState::State state);
- void slotDeleteAccount();
- void slotOpenAccountInBrowser();
- void slotToggleSignInState();
- void slotFolderWizardAccepted();
+ void requestMenuActionUpdate();
protected:
- void accountSettingUpChanged(bool settingUp);
void showEvent(QShowEvent *ev) override;
- void finishAccountModalWidget(AccountModalWidget *widget);
private:
- enum class StatusIcon { None, Connected, Disconnected, Info, Warning };
- void showConnectionLabel(const QString &message, StatusIcon statusIcon, QStringList errors = QStringList());
-
-
- void buildManageAccountMenu();
-
- Ui::AccountView *ui;
-
- QStandardItemModel *_model;
- QSortFilterProxyModel *_sortModel;
- bool _wasDisabledBefore;
- QPointer _accountState;
- // are we already in the destructor
- bool _goingDown = false;
- uint _syncedSpaces = 0;
- uint _unsyncedSpaces = 0;
+ Ui::AccountView *_ui;
};
} // namespace OCC
diff --git a/src/gui/accountsgui/accountviewcontroller.cpp b/src/gui/accountsgui/accountviewcontroller.cpp
index cf91766eb5d..864ac9b778a 100644
--- a/src/gui/accountsgui/accountviewcontroller.cpp
+++ b/src/gui/accountsgui/accountviewcontroller.cpp
@@ -14,14 +14,307 @@
#include "accountviewcontroller.h"
+#include "FoldersGui/accountfolderscontroller.h"
+#include "accountmanager.h"
+#include "accountmodalwidget.h"
#include "accountview.h"
+#include "commonstrings.h"
+#include "configfile.h"
+#include "folderman.h"
+#include "folderwizard.h"
+#include "libsync/theme.h"
+
+#include
+#include
+#include
+#include
namespace OCC {
-AccountViewController::AccountViewController(AccountView *view, QObject *parent)
+Q_LOGGING_CATEGORY(lcAccountViewController, "gui.account.viewcontroller", QtInfoMsg)
+
+AccountViewController::AccountViewController(AccountView *view, AccountState *state, QObject *parent)
: QObject{parent}
, _view(view)
+ , _accountState(state)
+{
+ if (!_view || !_accountState || !_accountState->account())
+ return;
+
+ connect(_view, &AccountView::requestMenuActionUpdate, this, &AccountViewController::refreshAccountActions);
+
+ AccountFoldersController *foldersController = new AccountFoldersController(_accountState, _view->foldersView(), this);
+ connect(foldersController, &AccountFoldersController::requestAddFolder, this, &AccountViewController::runFolderWizard);
+ connect(foldersController, &AccountFoldersController::requestAccountModalWidget, this, &AccountViewController::addAccountModalWidget);
+
+ connect(_accountState, &AccountState::stateChanged, this, &AccountViewController::onAccountStateChanged);
+ connect(_accountState, &AccountState::isSettingUpChanged, _view, &AccountView::accountSettingUpChanged);
+
+ buildManageAccountMenu();
+
+ onAccountStateChanged(_accountState->state());
+}
+
+void AccountViewController::onOpenAccountInBrowser()
+{
+ if (!_accountState) {
+ return;
+ }
+
+ QUrl url = _accountState->account()->url();
+ if (!Theme::instance()->overrideServerPath().isEmpty()) {
+ // There is an override for the WebDAV endpoint. Remove it for normal web browsing.
+ url.setPath({});
+ }
+ QDesktopServices::openUrl(url);
+}
+
+void AccountViewController::onToggleSignInState()
+{
+ if (!_accountState) {
+ return;
+ }
+
+ if (_accountState->isSignedOut()) {
+ _accountState->signIn();
+ } else {
+ _accountState->signOutByUi();
+ }
+}
+
+void AccountViewController::buildManageAccountMenu()
+{
+ if (!_view || !_accountState)
+ return;
+
+ QList actions;
+
+ _logInOut = new QAction(tr("Log in"), this);
+ _logInOut->setObjectName("logInOutAction");
+ connect(_logInOut, &QAction::triggered, this, &AccountViewController::onToggleSignInState);
+ actions.push_back(_logInOut);
+
+ _reconnect = new QAction(tr("Reconnect"), this);
+ _reconnect->setObjectName("reconnectAction");
+ connect(_reconnect, &QAction::triggered, this, [this] { _accountState->checkConnectivity(true); });
+ actions.push_back(_reconnect);
+
+ _showInBrowser = new QAction(CommonStrings::showInWebBrowser(), this);
+ _showInBrowser->setObjectName("showInBrowserAction");
+ connect(_showInBrowser, &QAction::triggered, this, &AccountViewController::onOpenAccountInBrowser);
+ actions.push_back(_showInBrowser);
+
+ _remove = new QAction(tr("Remove"), this);
+ _remove->setObjectName("removeAction");
+ connect(_remove, &QAction::triggered, this, &AccountViewController::onDeleteAccount);
+ actions.push_back(_remove);
+
+ _view->setAccountMenuActions(actions);
+}
+
+void AccountViewController::refreshAccountActions()
+{
+ Q_ASSERT(_logInOut && _reconnect && _showInBrowser && _remove);
+
+ // no we don't need to set enabled to match account state existence, if account state is null it's NOT coming back.
+ if (!_accountState) {
+ _logInOut->setEnabled(false);
+ _reconnect->setEnabled(false);
+ _showInBrowser->setEnabled(false);
+ _remove->setEnabled(false);
+ return;
+ }
+
+ _logInOut->setText(_accountState->isSignedOut() ? tr("Log in") : tr("Log out"));
+ _reconnect->setEnabled(!_accountState->isConnected() && !_accountState->isSignedOut());
+}
+
+void AccountViewController::addAccountModalWidget(AccountModalWidget *widget)
+{
+ if (!_accountState || !_accountState->account()) {
+ return;
+ }
+
+ _view->setTopStackWidget(widget);
+
+ connect(widget, &AccountModalWidget::finished, this, &AccountViewController::finishAccountModalWidget);
+
+ emit accountBeginModal(_accountState->account()->uuid());
+}
+
+void AccountViewController::finishAccountModalWidget(AccountModalWidget *widget)
+{
+ if (!widget)
+ return;
+
+ _view->removeStackWidget(widget);
+ widget->deleteLater();
+
+ Q_ASSERT(_accountState && _accountState->account());
+
+ emit accountEndModal(_accountState->account()->uuid());
+}
+
+void AccountViewController::onDeleteAccount()
{
+ if (!_accountState) {
+ return;
+ }
+
+ // Deleting the account potentially deletes 'this', so
+ // the QMessageBox should be destroyed before that happens.
+ // todo: this is an unnecessarily complicated def for the message box and should exec instead of open.
+ auto messageBox = new QMessageBox(QMessageBox::Question, tr("Confirm Account Removal"),
+ tr("Do you really want to remove the connection to the account %1?
"
+ "Note: This will not delete any files.
")
+ .arg(_accountState->account()->displayNameWithHost()),
+ QMessageBox::NoButton, _view);
+ messageBox->setObjectName("confirmRemoveAccountDialog");
+ auto yesButton = messageBox->addButton(tr("Remove connection"), QMessageBox::YesRole);
+ yesButton->setObjectName("removeAccountButton");
+ auto noButton = messageBox->addButton(tr("Cancel"), QMessageBox::NoRole);
+ noButton->setObjectName("cancelRemoveAccountButton");
+
+ messageBox->setAttribute(Qt::WA_DeleteOnClose);
+ connect(messageBox, &QMessageBox::finished, this, [this, messageBox, yesButton] {
+ if (messageBox->clickedButton() == yesButton) {
+ auto manager = AccountManager::instance();
+ manager->deleteAccount(_accountState);
+ manager->save();
+ }
+ });
+ messageBox->open();
+}
+
+QIcon AccountViewController::lookupStatusIcon(StatusIcon status)
+{
+ QIcon icon;
+ switch (status) {
+ case StatusIcon::None:
+ break;
+ case StatusIcon::Connected:
+ icon = Resources::getCoreIcon(QStringLiteral("states/ok"));
+ break;
+ case StatusIcon::Disconnected:
+ icon = Resources::getCoreIcon(QStringLiteral("states/offline"));
+ break;
+ case StatusIcon::Info:
+ icon = Resources::getCoreIcon(QStringLiteral("states/information"));
+ break;
+ case StatusIcon::Warning:
+ icon = Resources::getCoreIcon(QStringLiteral("states/warning"));
+ break;
+ }
+ return icon;
+}
+void AccountViewController::onAccountStateChanged(AccountState::State state)
+{
+ if (!_accountState || !_accountState->account() || !_view) {
+ return;
+ }
+
+ Account *account = _accountState->account();
+ qCDebug(lcAccountViewController()) << "Account state changed to" << state << "for account" << account;
+
+ QStringList errors;
+ QString text;
+ StatusIcon icon;
+
+ switch (state) {
+ case AccountState::Connected: {
+ icon = StatusIcon::Connected;
+ if (account->serverSupportLevel() != Account::ServerSupportLevel::Supported) {
+ errors << tr("The server version %1 is unsupported! Proceed at your own risk.").arg(account->capabilities().status().versionString());
+ icon = StatusIcon::Warning;
+ }
+ text = tr("Connected");
+ break;
+ }
+ case AccountState::ServiceUnavailable:
+ text = tr("Server is temporarily unavailable.");
+ icon = StatusIcon::Disconnected;
+ break;
+ case AccountState::MaintenanceMode:
+ text = tr("Server is currently in maintenance mode.");
+ icon = StatusIcon::Disconnected;
+ break;
+ case AccountState::SignedOut:
+ text = tr("Signed out");
+ icon = StatusIcon::Disconnected;
+ break;
+ case AccountState::AskingCredentials:
+ text = tr("Updating credentials…");
+ icon = StatusIcon::Info;
+ break;
+ case AccountState::Connecting:
+ if (NetworkInformation::instance()->isBehindCaptivePortal()) {
+ text = tr("Captive portal prevents connections to the server.");
+ icon = StatusIcon::Disconnected;
+ } else if (NetworkInformation::instance()->isMetered() && ConfigFile().pauseSyncWhenMetered()) {
+ text = tr("Sync is paused due to metered internet connection.");
+ icon = StatusIcon::Disconnected;
+ } else {
+ text = tr("Connecting…");
+ icon = StatusIcon::Info;
+ }
+ break;
+ case AccountState::ConfigurationError:
+ text = tr("Server configuration error");
+ icon = StatusIcon::Warning;
+ errors = _accountState->connectionErrors();
+ break;
+ case AccountState::NetworkError:
+ // don't display the error to the user, https://github.com/owncloud/client/issues/9790
+ [[fallthrough]];
+ case AccountState::Disconnected:
+ text = tr("Disconnected");
+ icon = StatusIcon::Disconnected;
+ break;
+ default:
+ text = tr("Invalid connection status");
+ icon = StatusIcon::None;
+ }
+
+ _view->setConnectionLabel(text, lookupStatusIcon(icon), errors);
+}
+
+void AccountViewController::runFolderWizard()
+{
+ if (!_accountState || !_accountState->account() || !_view)
+ return;
+
+
+ FolderWizard *folderWizard = new FolderWizard(_accountState->account(), _view);
+
+ connect(folderWizard, &QDialog::accepted, this, &AccountViewController::onFolderWizardAccepted);
+ connect(folderWizard, &QDialog::rejected, this, [] { qCInfo(lcAccountViewController) << "Folder wizard cancelled"; });
+
+ // ignore clang analyzer warning about potential memory leak, please.
+ // the modal widget gets reparented to the stacked widget and is automatically deleted when the finished() signal is
+ // received
+ AccountModalWidget *widget = new AccountModalWidget({}, folderWizard, _view);
+ addAccountModalWidget(widget);
+}
+
+void AccountViewController::onFolderWizardAccepted()
+{
+ if (!_accountState)
+ return;
+
+ FolderWizard *folderWizard = qobject_cast(sender());
+ if (!folderWizard)
+ return;
+
+ auto config = folderWizard->result();
+
+ // The gui should not allow users to selectively choose any sync lists if vfs is enabled, but this kind of check was
+ // originally in play here so...keep it just in case.
+ if (config.useVirtualFiles && !config.selectiveSyncBlackList.empty())
+ config.selectiveSyncBlackList.clear();
+
+
+ // Refactoring todo: turn this into a signal/requestAddFolder
+ FolderMan::instance()->addFolderFromGui(_accountState, config);
}
}
diff --git a/src/gui/accountsgui/accountviewcontroller.h b/src/gui/accountsgui/accountviewcontroller.h
index 61746a0e12b..4f00f507347 100644
--- a/src/gui/accountsgui/accountviewcontroller.h
+++ b/src/gui/accountsgui/accountviewcontroller.h
@@ -14,22 +14,58 @@
#pragma once
+#include "accountstate.h"
#include
+#include
+
+class QAction;
namespace OCC {
class AccountView;
+class AccountModalWidget;
+
+enum class StatusIcon { None, Connected, Disconnected, Info, Warning };
class AccountViewController : public QObject
{
Q_OBJECT
public:
- explicit AccountViewController(AccountView *view, QObject *parent = nullptr);
+ explicit AccountViewController(AccountView *view, AccountState *state, QObject *parent);
+
+ void addAccountModalWidget(AccountModalWidget *widget);
+ void runFolderWizard();
signals:
+ // these are sent when the account view starts and ends a "modal" operation
+ // at the moment I'm not blocking access to main window toolbar actions as there is really no need, imo,
+ // just because the account is in the middle of something. At least we will try it this way and see
+ // if it's preferred. So long as the account modal widget blocks *account* related activity I think we're good
+ void accountEndModal(QUuid accountId);
+ void accountBeginModal(QUuid accountId);
+
+protected:
+ void onAccountStateChanged(OCC::AccountState::State state);
+ void onDeleteAccount();
+ void onOpenAccountInBrowser();
+ void onToggleSignInState();
+
+ void onFolderWizardAccepted();
+
+ void finishAccountModalWidget(AccountModalWidget *widget);
private:
- AccountView *_view = nullptr;
+ QPointer _view = nullptr;
+ QPointer _accountState;
+
+ QAction *_logInOut = nullptr;
+ QAction *_reconnect = nullptr;
+ QAction *_showInBrowser = nullptr;
+ QAction *_remove = nullptr;
+
+ void buildManageAccountMenu();
+ void refreshAccountActions();
+ QIcon lookupStatusIcon(StatusIcon status);
};
}
diff --git a/src/gui/accountstate.cpp b/src/gui/accountstate.cpp
index a865caf8830..096410bf33d 100644
--- a/src/gui/accountstate.cpp
+++ b/src/gui/accountstate.cpp
@@ -20,7 +20,6 @@
#include "libsync/creds/abstractcredentials.h"
-#include "gui/settingsdialog.h"
#include "gui/tlserrordialog.h"
#include "socketapi/socketapi.h"
@@ -101,9 +100,9 @@ void AccountState::connectAccount()
connect(_account.data(), &Account::unknownConnectionState, this, [this] { checkConnectivity(true); });
connect(_account.data(), &Account::appProviderErrorOccured, this, [](const QString &error) {
- QMessageBox *msgBox = new QMessageBox(QMessageBox::Information, Theme::instance()->appNameGUI(), error, {}, ocApp()->gui()->settingsDialog());
+ QMessageBox *msgBox = new QMessageBox(QMessageBox::Information, Theme::instance()->appNameGUI(), error, {}, ocApp()->mainWindow());
msgBox->setAttribute(Qt::WA_DeleteOnClose);
- ownCloudGui::raise();
+ ocApp()->ensureVisible();
msgBox->open();
});
}
@@ -353,8 +352,8 @@ void AccountState::handleSslConnectionErrors(const QList &errors, boo
for (const auto &error : std::as_const(filteredErrors)) {
certs << error.certificate();
}
- TlsErrorDialog tlsDlg(filteredErrors, _account->url().host(), ocApp()->gui()->settingsDialog());
- ownCloudGui::raise();
+ TlsErrorDialog tlsDlg(filteredErrors, _account->url().host(), ocApp()->mainWindow());
+ ocApp()->ensureVisible();
int res = tlsDlg.exec();
if (res == TlsErrorDialog::Accepted) {
_account->addApprovedCerts(certs);
diff --git a/src/gui/application.cpp b/src/gui/application.cpp
index 5681408d9c2..ed9a1ae2329 100644
--- a/src/gui/application.cpp
+++ b/src/gui/application.cpp
@@ -19,6 +19,7 @@
#include "account.h"
#include "accountmanager.h"
+#include "accountsgui/accountsguicontroller.h"
#include "accountstate.h"
#include "common/vfs.h"
#include "configfile.h"
@@ -26,9 +27,9 @@
#include "folderman.h"
#include "mainwindow/mainwindow.h"
#include "mainwindow/mainwindowcontroller.h"
-#include "settingsdialog.h"
#include "socketapi/socketapi.h"
#include "theme.h"
+#include "traymenucontroller.h"
#ifdef WITH_AUTO_UPDATER
#include "updater/ocupdater.h"
@@ -51,9 +52,9 @@ QString Application::displayLanguage() const
return _displayLanguage;
}
-ownCloudGui *Application::gui() const
+TrayMenuController *Application::tray() const
{
- return _gui;
+ return _trayController;
}
Application *Application::_instance = nullptr;
@@ -85,32 +86,10 @@ Application::Application(Platform *platform, const QString &displayLanguage, boo
qApp->setQuitOnLastWindowClosed(false);
+ // todo: dc-307 - there should be no setters and hence no notifications from theme
Theme::instance()->setSystrayUseMonoIcons(cfg.monoIcons());
connect(Theme::instance(), &Theme::systrayUseMonoIconsChanged, this, &Application::slotUseMonoIconsChanged);
- // Setting up the gui class will allow tray notifications for the
- // setup that follows, like folder setup
- _gui = new ownCloudGui(this);
-
-#ifdef USE_NEW_MAIN_WINDOW
- _mainWin = new MainWindow();
- _mainController = new MainWindowController(_mainWin, this);
-#endif
-
- connect(AccountManager::instance(), &AccountManager::accountAdded, this, &Application::slotAccountStateAdded);
- connect(AccountManager::instance(), &AccountManager::lastAccountRemoved, this, &Application::lastAccountStateRemoved);
- for (const auto &ai : AccountManager::instance()->accounts()) {
- slotAccountStateAdded(ai);
- }
-
- connect(FolderMan::instance()->socketApi(), &SocketApi::shareCommandReceived, _gui.data(), &ownCloudGui::slotShowShareInBrowser);
-
- // Refactoring example: this is oversimplified and really belongs in a dedicated app builder impl but the idea is illustrated:
- // don't handling everything "locally" -> request that the best entity for the job do it. Then make the proper connections between
- // requestor and responsible handler in a clearly defined, central location (e.g. an app builder, but for now, this will do)
- connect(_gui, &ownCloudGui::requestSetUpSyncFoldersForAccount, FolderMan::instance(), &FolderMan::setUpInitialSyncFolders);
- connect(_gui, &ownCloudGui::requestLoadSpacesOnly, FolderMan::instance(), &FolderMan::setUpInitialSpaces);
-
#ifdef WITH_AUTO_UPDATER
// Update checks
UpdaterScheduler *updaterScheduler = new UpdaterScheduler(this, this);
@@ -125,26 +104,27 @@ Application::Application(Platform *platform, const QString &displayLanguage, boo
Application::~Application()
{
- // Make sure all folders are gone, otherwise removing the
- // accounts will remove the associated folders from the settings.
- FolderMan::instance()->unloadAndDeleteAllFolders();
+}
- if (_mainWin) {
- _mainWin->disconnect();
- delete _mainWin;
- }
+QMainWindow *Application::mainWindow() const
+{
+ return _mainWin;
}
-void Application::lastAccountStateRemoved() const
+void Application::ensureVisible() const
{
-#ifndef USE_NEW_MAIN_WINDOW
- // auto run the wizard if there are no existing accounts
- if (_gui && AccountManager::instance()->accounts().isEmpty()) {
- gui()->runAccountWizard();
- }
-#endif
+ if (_mainWin)
+ _mainWin->ensureVisible();
+}
+
+void Application::showModalWidget(ModalWrapperWidget *wrapper) const
+{
+ if (_mainWin)
+ _mainWin->showModalWidget(wrapper);
}
+
+// move to owncloudgui or wherever we end up consolidating the tray meny/socketApi management
void Application::slotAccountStateAdded(AccountState *accountState) const
{
if (!accountState || !accountState->account())
@@ -152,9 +132,11 @@ void Application::slotAccountStateAdded(AccountState *accountState) const
// Hook up the GUI slots to the account state's Q_SIGNALS:
Account *account = accountState->account();
- connect(accountState, &AccountState::stateChanged, _gui.data(), &ownCloudGui::slotComputeOverallSyncStatus);
- connect(account, &Account::serverVersionChanged, _gui.data(), [account, this] { _gui->slotTrayMessageIfServerUnsupported(account); });
+ connect(accountState, &AccountState::stateChanged, _trayController, &TrayMenuController::slotComputeOverallSyncStatus);
+ connect(account, &Account::serverVersionChanged, _trayController, &TrayMenuController::slotTrayMessageIfServerUnsupported);
+ // todo: this does not belong here! This can be done in the folder man when it's given a "new" account
+ // (eg in load from config or load from new account). note that FolderMan does not receive accountAdded signals, but maybe it should?
// Hook up the folder manager slots to the account state's Q_SIGNALS:
connect(accountState, &AccountState::isConnectedChanged, FolderMan::instance(), &FolderMan::slotIsConnectedChanged);
connect(account, &Account::serverVersionChanged, FolderMan::instance(), [account] { FolderMan::instance()->slotServerVersionChanged(account); });
@@ -162,10 +144,6 @@ void Application::slotAccountStateAdded(AccountState *accountState) const
void Application::slotCleanup()
{
- // unload the ui to make sure we no longer react to signals
- _gui->slotShutdown();
- delete _gui;
-
// by now the credentials are supposed to be persisted
// don't start async credentials jobs during shutdown
AccountManager::instance()->save();
@@ -195,7 +173,7 @@ void Application::updateAutoRun(bool firstRun)
void Application::slotUseMonoIconsChanged(bool)
{
- _gui->slotComputeOverallSyncStatus();
+ _trayController->slotComputeOverallSyncStatus();
}
bool Application::debugMode()
@@ -203,10 +181,38 @@ bool Application::debugMode()
return _debugMode;
}
+void Application::buildAppGuis()
+{
+ Q_ASSERT(!_mainWin && !_trayController);
+ _mainWin = new MainWindow();
+ _mainController = new MainWindowController(_mainWin, this);
+
+ _accountsGuiController = new AccountsGuiController(AccountManager::instance(), _mainWin, _mainController);
+ connect(_mainController, &MainWindowController::requestAccountWizard, _accountsGuiController, &AccountsGuiController::runAccountWizard);
+
+ // Setting up the gui class will allow tray notifications for the
+ // setup that follows, like folder setup
+ _trayController = new TrayMenuController(this);
+ connect(_trayController, &TrayMenuController::requestShowAbout, _mainController, &MainWindowController::onAbout);
+ connect(_trayController, &TrayMenuController::requestShowHelp, _mainController, &MainWindowController::onHelp);
+
+ connect(FolderMan::instance()->socketApi(), &SocketApi::shareCommandReceived, _trayController, &TrayMenuController::slotShowShareInBrowser);
+}
+
+void Application::setupManagers()
+{
+ connect(AccountManager::instance(), &AccountManager::accountAdded, this, &Application::slotAccountStateAdded);
+ for (const auto &ai : AccountManager::instance()->accounts()) {
+ slotAccountStateAdded(ai);
+ }
+}
+
std::unique_ptr Application::createInstance(Platform *platform, const QString &displayLanguage, bool debugMode)
{
Q_ASSERT(!_instance);
_instance = new Application(platform, displayLanguage, debugMode);
+ _instance->buildAppGuis();
+ _instance->setupManagers();
return std::unique_ptr(_instance);
}
diff --git a/src/gui/application.h b/src/gui/application.h
index 29772b6668d..918c6e3238d 100644
--- a/src/gui/application.h
+++ b/src/gui/application.h
@@ -14,12 +14,12 @@
#pragma once
-#include "gui/owncloudguilib.h"
-
#include "folderman.h"
-#include "owncloudgui.h"
+#include "gui/owncloudguilib.h"
#include "platform.h"
+#include "traymenucontroller.h"
+#include
#include
class QMessageBox;
@@ -38,6 +38,9 @@ class Theme;
class Folder;
class MainWindow;
class MainWindowController;
+class AccountsGuiController;
+class ModalWrapperWidget;
+
/**
* @brief The Application class
@@ -52,10 +55,19 @@ class OWNCLOUDGUI_EXPORT Application : public QObject
bool debugMode();
- ownCloudGui *gui() const;
+ TrayMenuController *tray() const;
+
+ // this is needed primarily to parent message boxes and other temporary views
+ // we return QMainWindow to protect access to public functions of the MainWindow that should only be used by true dependents!
+ // ie, if you need public functions of MainWindow, it should be injected as its concrete type
+ QMainWindow *mainWindow() const;
- // try to get rid of this before the end. currently needed to raise the main window via owncloudgui
- MainWindow *mainWindow() { return _mainWin; }
+ // redirect to MainWindow::ensureVisible -> protect access to main window interface
+ void ensureVisible() const;
+
+ // hopefully temporary - this is only needed in the updater mess which has no reasonable structure I can currently use to pass the MainWindow
+ // again, redirect to MainWindow::showModalWidget to protect access to the rest of the main window interface
+ void showModalWidget(ModalWrapperWidget *wrapper) const;
QString displayLanguage() const;
@@ -75,15 +87,22 @@ protected Q_SLOTS:
void slotUseMonoIconsChanged(bool);
void slotCleanup();
void slotAccountStateAdded(AccountState *accountState) const;
- void lastAccountStateRemoved() const;
private:
- explicit Application(Platform *platform, const QString &displayLanguage, bool debugMode);
+ // important! we can't set up the gui's in the ctr - it needs to be a separate step because owncloudgui depends on ocApp to parent
+ // it's actions
+ void buildAppGuis();
+
+ // this is currently fairly empty, but will be moving other manager init stuff in here.
+ void setupManagers();
- QPointer _gui = {};
+private:
+ explicit Application(Platform *platform, const QString &displayLanguage, bool debugMode);
MainWindow *_mainWin = nullptr;
MainWindowController *_mainController = nullptr;
+ AccountsGuiController *_accountsGuiController = nullptr;
+ TrayMenuController *_trayController = nullptr;
const bool _debugMode = false;
QString _displayLanguage;
diff --git a/src/gui/creds/requestauthenticationcontroller.cpp b/src/gui/creds/requestauthenticationcontroller.cpp
index 4d83c3f72f0..fcdd25b5c92 100644
--- a/src/gui/creds/requestauthenticationcontroller.cpp
+++ b/src/gui/creds/requestauthenticationcontroller.cpp
@@ -18,7 +18,6 @@
#include "requestauthenticationwidget.h"
#include "accountmodalwidget.h"
-#include "settingsdialog.h"
#include
@@ -77,14 +76,8 @@ void RequestAuthenticationController::startAuthentication(Account *account)
connect(_widget, &RequestAuthenticationWidget::connectClicked, this, &RequestAuthenticationController::handleSignIn);
connect(_widget, &RequestAuthenticationWidget::stayLoggedOutClicked, this, &RequestAuthenticationController::handleLogOut);
-#ifdef USE_NEW_MAIN_WINDOW
_modalWidget = new AccountModalWidget(QString(), _widget, nullptr);
emit requestAccountModal(_modalWidget);
-#else
- AccountView *accountView = ocApp()->gui()->settingsDialog()->accountView(_account);
- _modalWidget = new AccountModalWidget(QString(), _widget, accountView);
- accountView->addModalAccountWidget(_modalWidget);
-#endif
}
Q_ASSERT(_widget && _modalWidget);
_oauth->startAuthentication();
@@ -137,6 +130,6 @@ void RequestAuthenticationController::handleOAuthResult(OAuth::Result result, co
Q_EMIT authenticationSucceeded(accessToken, refreshToken);
}
- ownCloudGui::raise();
+ ocApp()->ensureVisible();
}
}
diff --git a/src/gui/folder.cpp b/src/gui/folder.cpp
index 269659bd33d..d14c0e3cb3f 100644
--- a/src/gui/folder.cpp
+++ b/src/gui/folder.cpp
@@ -28,12 +28,10 @@
#include "configfile.h"
#include "filesystem.h"
#include "folderman.h"
-#include "foldermanagement/foldermanagementutils.h"
#include "folderwatcher.h"
#include "libsync/graphapi/spacesmanager.h"
#include "localdiscoverytracker.h"
#include "scheduling/syncscheduler.h"
-#include "settingsdialog.h"
#include "socketapi/socketapi.h"
#include "syncengine.h"
#include "syncresult.h"
@@ -422,7 +420,7 @@ void Folder::createGuiLog(const QString &filename, LogStatus status, int count,
}
if (!text.isEmpty()) {
- ocApp()->gui()->slotShowOptionalTrayMessage(tr("Sync Activity"), text);
+ ocApp()->tray()->slotShowOptionalTrayMessage(tr("Sync Activity"), text);
}
}
}
@@ -1028,7 +1026,7 @@ void Folder::warnOnNewExcludedItem(const SyncJournalFileRecord &record, QStringV
"It will not be synchronized.")
.arg(fi.filePath());
- ocApp()->gui()->slotShowOptionalTrayMessage(Theme::instance()->appNameGUI(), message);
+ ocApp()->tray()->slotShowOptionalTrayMessage(Theme::instance()->appNameGUI(), message);
}
void Folder::slotWatcherUnreliable(const QString &message)
@@ -1044,10 +1042,10 @@ void Folder::slotWatcherUnreliable(const QString &message)
"\n"
"%1")
.arg(message),
- {}, ocApp()->gui()->settingsDialog());
+ {}, ocApp()->mainWindow());
msgBox->setAttribute(Qt::WA_DeleteOnClose);
- ownCloudGui::raise();
+ ocApp()->ensureVisible();
msgBox->open();
}
diff --git a/src/gui/folderwizard/folderwizard.cpp b/src/gui/folderwizard/folderwizard.cpp
index 2dce6412dd5..ba79a5ed36b 100644
--- a/src/gui/folderwizard/folderwizard.cpp
+++ b/src/gui/folderwizard/folderwizard.cpp
@@ -24,7 +24,6 @@
#include "common/asserts.h"
#include "common/vfs.h"
#include "gui/application.h"
-#include "gui/settingsdialog.h"
#include "theme.h"
#include "gui/folderman.h"
@@ -137,7 +136,7 @@ bool FolderWizardPrivate::useVirtualFiles() const
QString vfsSupported = Vfs::pathSupportDetail(initialLocalPath(), mode);
if (!vfsSupported.isEmpty()) {
auto msg = new QMessageBox(QMessageBox::Warning, FolderWizard::tr("Virtual files are not available for the selected folder"), vfsSupported,
- QMessageBox::Ok, ocApp()->gui()->settingsDialog());
+ QMessageBox::Ok, ocApp()->mainWindow());
msg->setAttribute(Qt::WA_DeleteOnClose);
msg->open();
return false;
diff --git a/src/gui/generalsettings.cpp b/src/gui/generalsettings.cpp
deleted file mode 100644
index dbee5941949..00000000000
--- a/src/gui/generalsettings.cpp
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright (C) by Daniel Molkentin
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include "generalsettings.h"
-#include "ui_generalsettings.h"
-
-#include "common/restartmanager.h"
-#include "common/version.h"
-#include "gui/application.h"
-#include "gui/ignorelisteditor.h"
-#include "gui/settingsdialog.h"
-#include "gui/translations.h"
-#include "libsync/configfile.h"
-#include "libsync/theme.h"
-
-#include
-#include
-#include
-
-namespace OCC {
-
-GeneralSettings::GeneralSettings(QWidget *parent)
- : QWidget(parent)
- , _ui(new Ui::GeneralSettings)
- , _currentlyLoading(false)
-{
- _ui->setupUi(this);
-
- connect(_ui->desktopNotificationsCheckBox, &QAbstractButton::toggled, this, &GeneralSettings::slotToggleOptionalDesktopNotifications);
-
- reloadConfig();
- loadMiscSettings();
-
- // misc
- connect(_ui->monoIconsCheckBox, &QAbstractButton::toggled, this, &GeneralSettings::saveMiscSettings);
- connect(_ui->crashreporterCheckBox, &QAbstractButton::toggled, this, &GeneralSettings::saveMiscSettings);
-
- connect(_ui->languageDropdown, QOverload::of(&QComboBox::activated), this, [this]() {
- // first, store selected language in config file
- saveMiscSettings();
-
- // warn user that a language change requires a restart to take effect
- QMessageBox::warning(this, tr("Warning"), tr("Language changes require a restart of this application to take effect."), QMessageBox::Ok);
- });
-
- /* handle the hidden file checkbox */
-
- /* the ignoreHiddenFiles flag is a folder specific setting, but for now, it is
- * handled globally. Save it to every folder that is defined.
- */
- connect(_ui->syncHiddenFilesCheckBox, &QCheckBox::toggled, this, [](bool checked) { FolderMan::instance()->setIgnoreHiddenFiles(!checked); });
-
- _ui->crashreporterCheckBox->setVisible(Theme::instance()->withCrashReporter());
-
- _ui->moveToTrashCheckBox->setVisible(true);
- connect(_ui->moveToTrashCheckBox, &QCheckBox::toggled, this, &GeneralSettings::moveToTrashChanged); /*[this](bool checked) {
- ConfigFile().setMoveToTrash(checked);
- Q_EMIT moveToTrashChanged(checked);
- });*/
-
- // OEM themes are not obliged to ship mono icons, so there
- // is no point in offering an option
- _ui->monoIconsCheckBox->setVisible(Resources::hasMonoTheme());
-
- connect(_ui->ignoredFilesButton, &QAbstractButton::clicked, this, &GeneralSettings::slotIgnoreFilesEditor);
- connect(_ui->logSettingsButton, &QPushButton::clicked, this, [] {
- // only access occApp after things are set up
- ocApp()->gui()->slotToggleLogBrowser();
- });
-
- connect(_ui->about_pushButton, &QPushButton::clicked, this, &GeneralSettings::showAbout);
-
- if (!Theme::instance()->aboutShowCopyright()) {
- _ui->copyrightLabel->hide();
- }
-}
-
-GeneralSettings::~GeneralSettings()
-{
- delete _ui;
-}
-
-void GeneralSettings::loadMiscSettings()
-{
- QScopedValueRollback scope(_currentlyLoading, true);
- ConfigFile cfgFile;
- _ui->monoIconsCheckBox->setChecked(cfgFile.monoIcons());
- _ui->desktopNotificationsCheckBox->setChecked(cfgFile.optionalDesktopNotifications());
- _ui->crashreporterCheckBox->setChecked(cfgFile.crashReporter());
- _ui->monoIconsCheckBox->setChecked(cfgFile.monoIcons());
-
- // the dropdown has to be populated before we can can pick an entry below based on the stored setting
- loadLanguageNamesIntoDropdown();
-
- const auto &locale = cfgFile.uiLanguage();
- const auto index = _ui->languageDropdown->findData(locale);
- _ui->languageDropdown->setCurrentIndex(index < 0 ? 0 : index);
-}
-
-void GeneralSettings::showEvent(QShowEvent *)
-{
- reloadConfig();
-}
-
-void GeneralSettings::saveMiscSettings()
-{
- if (_currentlyLoading)
- return;
- ConfigFile cfgFile;
- bool isChecked = _ui->monoIconsCheckBox->isChecked();
- cfgFile.setMonoIcons(isChecked);
- Theme::instance()->setSystrayUseMonoIcons(isChecked);
- cfgFile.setCrashReporter(_ui->crashreporterCheckBox->isChecked());
-
- // the first entry, identified by index 0, means "use default", which is a special case handled below
- const QString pickedLocale = _ui->languageDropdown->currentData().toString();
- cfgFile.setUiLanguage(pickedLocale);
-}
-
-void GeneralSettings::slotToggleLaunchOnStartup(bool enable)
-{
- Theme *theme = Theme::instance();
- Utility::setLaunchOnStartup(theme->appName(), theme->appNameGUI(), enable);
-}
-
-void GeneralSettings::slotToggleOptionalDesktopNotifications(bool enable)
-{
- ConfigFile cfgFile;
- cfgFile.setOptionalDesktopNotifications(enable);
-}
-
-void GeneralSettings::slotIgnoreFilesEditor()
-{
- if (_ignoreEditor.isNull()) {
- _ignoreEditor = new IgnoreListEditor(ocApp()->gui()->settingsDialog());
- _ignoreEditor->setAttribute(Qt::WA_DeleteOnClose, true);
- ownCloudGui::raise();
- _ignoreEditor->open();
- }
-}
-
-void GeneralSettings::reloadConfig()
-{
- _ui->syncHiddenFilesCheckBox->setChecked(!FolderMan::instance()->ignoreHiddenFiles());
- _ui->moveToTrashCheckBox->setChecked(FolderMan::instance()->moveToTrash());
- if (Utility::hasSystemLaunchOnStartup(Theme::instance()->appName())) {
- _ui->autostartCheckBox->setChecked(true);
- _ui->autostartCheckBox->setDisabled(true);
- _ui->autostartCheckBox->setToolTip(tr("You cannot disable autostart because system-wide autostart is enabled."));
- } else {
- const bool hasAutoStart = Utility::hasLaunchOnStartup(Theme::instance()->appName());
- // make sure the binary location is correctly set
- slotToggleLaunchOnStartup(hasAutoStart);
- _ui->autostartCheckBox->setChecked(hasAutoStart);
- connect(_ui->autostartCheckBox, &QAbstractButton::toggled, this, &GeneralSettings::slotToggleLaunchOnStartup);
- }
-}
-
-void GeneralSettings::loadLanguageNamesIntoDropdown()
-{
- // allow method to be called more than once
- _ui->languageDropdown->clear();
-
- // if no option has been chosen explicitly by the user, the first entry shall be used
- _ui->languageDropdown->addItem(tr("(use default)"));
-
- // initialize map of locales to language names
- const auto availableLocales = []() {
- auto rv = Translations::listAvailableTranslations().values();
- rv.sort(Qt::CaseInsensitive);
- return rv;
- }();
-
- for (const auto &availableLocale : availableLocales) {
- auto nativeLanguageName = QLocale(availableLocale).nativeLanguageName();
-
- // fallback if there's a locale whose name Qt doesn't know
- // this indicates a broken filename
- if (nativeLanguageName.isEmpty()) {
- qCDebug(lcApplication()) << "Warning: could not find native language name for locale" << availableLocale;
- nativeLanguageName = tr("unknown (%1)").arg(availableLocale);
- }
-
- QString entryText = QStringLiteral("%1 (%2)").arg(nativeLanguageName, availableLocale);
- _ui->languageDropdown->addItem(entryText, availableLocale);
- }
-}
-
-} // namespace OCC
diff --git a/src/gui/generalsettings.h b/src/gui/generalsettings.h
deleted file mode 100644
index d3bec7ff33c..00000000000
--- a/src/gui/generalsettings.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) by Daniel Molkentin
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#ifndef MIRALL_GENERALSETTINGS_H
-#define MIRALL_GENERALSETTINGS_H
-
-#include
-#include
-#include
-
-namespace OCC {
-class IgnoreListEditor;
-class SyncLogDialog;
-
-namespace Ui {
- class GeneralSettings;
-}
-
-/**
- * @brief The GeneralSettings class
- * @ingroup gui
- */
-class GeneralSettings : public QWidget
-{
- Q_OBJECT
-
-public:
- explicit GeneralSettings(QWidget *parent = nullptr);
- ~GeneralSettings() override;
-
-Q_SIGNALS:
- void showAbout();
- void moveToTrashChanged(bool trashIt);
-
-private Q_SLOTS:
- void saveMiscSettings();
- void slotToggleLaunchOnStartup(bool);
- void slotToggleOptionalDesktopNotifications(bool);
- void slotIgnoreFilesEditor();
- void loadMiscSettings();
-
-protected:
- void showEvent(QShowEvent *event) override;
-
-private:
- void reloadConfig();
- void loadLanguageNamesIntoDropdown();
-
- Ui::GeneralSettings *_ui;
- QPointer _ignoreEditor;
- bool _currentlyLoading;
-};
-
-
-} // namespace OCC
-#endif // MIRALL_GENERALSETTINGS_H
diff --git a/src/gui/generalsettings.ui b/src/gui/generalsettings.ui
deleted file mode 100644
index f4c1f1e4cf6..00000000000
--- a/src/gui/generalsettings.ui
+++ /dev/null
@@ -1,282 +0,0 @@
-
-
- OCC::GeneralSettings
-
-
-
- 0
- 0
- 791
- 686
-
-
-
- Form
-
-
- -
-
-
- true
-
-
-
-
- 0
- 0
- 765
- 618
-
-
-
-
-
-
-
- General Settings
-
-
-
-
-
-
- Use Monochrome Icons in the system tray
-
-
-
- -
-
-
- Show Desktop Notifications
-
-
-
- -
-
-
- Start on Login
-
-
-
- -
-
-
-
-
-
-
- 0
- 0
-
-
-
-
-
-
- Language
-
-
- languageDropdown
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- Language selector
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
- Advanced
-
-
-
-
-
-
-
-
-
- Sync hidden files
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- Show crash reporter
-
-
-
- -
-
-
- Move remotely deleted files to the local trash bin instead of deleting them
-
-
-
- -
-
-
-
-
-
- Edit Ignored Files
-
-
-
- -
-
-
- Log Settings
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 555
- 20
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
- Network
-
-
-
-
-
-
- Qt::StrongFocus
-
-
-
-
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
-
-
-
-
- -
-
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
-
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
- ArrowCursor
-
-
- Copyright ownCloud GmbH (A Kiteworks Company)
-
-
- Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse
-
-
-
- -
-
-
- About
-
-
-
-
-
-
-
-
-
-
- NetworkSettings
- QWidget
-
- 1
-
-
-
- autostartCheckBox
- desktopNotificationsCheckBox
- monoIconsCheckBox
- languageDropdown
- syncHiddenFilesCheckBox
- crashreporterCheckBox
- moveToTrashCheckBox
- ignoredFilesButton
- logSettingsButton
- widget
- scrollArea
- about_pushButton
-
-
-
-
diff --git a/src/gui/guiutility.cpp b/src/gui/guiutility.cpp
index e995b68c95e..b92e105bde9 100644
--- a/src/gui/guiutility.cpp
+++ b/src/gui/guiutility.cpp
@@ -14,7 +14,6 @@
#include "guiutility.h"
#include "gui/application.h"
-#include "gui/settingsdialog.h"
#include "libsync/filesystem.h"
#include "libsync/theme.h"
diff --git a/src/gui/localactivitywidget.cpp b/src/gui/localactivitywidget.cpp
index 4c656dce2e9..44ff4d2a6c9 100644
--- a/src/gui/localactivitywidget.cpp
+++ b/src/gui/localactivitywidget.cpp
@@ -26,6 +26,7 @@
#include
#include
+#include
#include "ui_localactivitywidget.h"
diff --git a/src/gui/localactivitywidget.h b/src/gui/localactivitywidget.h
index d755bd16bc8..ea22f284552 100644
--- a/src/gui/localactivitywidget.h
+++ b/src/gui/localactivitywidget.h
@@ -17,7 +17,7 @@
#include
#include
-#include "owncloudgui.h"
+// #include "owncloudgui.h"
#include "models/protocolitemmodel.h"
#include "models/models.h"
diff --git a/src/gui/main.cpp b/src/gui/main.cpp
index f82a7e91fc7..63ecf028865 100644
--- a/src/gui/main.cpp
+++ b/src/gui/main.cpp
@@ -437,15 +437,10 @@ int main(int argc, char **argv)
return -1;
}
- // I think this could/should just be a local instance that just naturally goes out of scope. this will take some time though,
- // as it's a singleton :/
- // good news is that it's mostly used to handle the main window "modal" impls which will likely change or even go away soon-ish
- auto ocApp = Application::createInstance(platform.get(), displayLanguage, options.debugMode);
+ std::unique_ptr ocApp = Application::createInstance(platform.get(), displayLanguage, options.debugMode);
ocApp->updateAutoRun(firstRun);
+ QObject::connect(platform.get(), &Platform::requestAttention, ocApp.get(), &Application::ensureVisible);
- QObject::connect(platform.get(), &Platform::requestAttention, ocApp->gui(), &ownCloudGui::slotShowSettings);
-
- // Refactoring todo: convert lambda to function
QObject::connect(&singleApplication, &KDSingleApplication::messageReceived, ocApp.get(), [&](const QByteArray &message) {
const QString msg = QString::fromUtf8(message);
qCInfo(lcMain) << Q_FUNC_INFO << msg;
@@ -453,7 +448,7 @@ int main(int argc, char **argv)
const QStringList optionsStrings = msg.mid(msgParseOptionsC().size()).split(QLatin1Char('|'));
CommandLineOptions options = parseOptions(optionsStrings);
if (options.show) {
- ocApp->gui()->slotShowSettings();
+ ocApp->ensureVisible();
}
if (options.quitInstance) {
qApp->quit();
@@ -484,16 +479,8 @@ int main(int argc, char **argv)
}
if (options.show) {
- ocApp->gui()->slotShowSettings();
- // The user explicitly requested the settings dialog, so don't start the new-account wizard.
- }
-
-#ifndef USE_NEW_MAIN_WINDOW
- // Display the wizard if we don't have an account yet, and no other UI is showing.
- if (AccountManager::instance()->accounts().isEmpty()) {
- QTimer::singleShot(0, ocApp->gui(), &ownCloudGui::runAccountWizard);
+ ocApp->ensureVisible();
}
-#endif
// Now that everything is up and running, start accepting connections/requests from the shell integration.
folderManager->socketApi()->startShellIntegration();
diff --git a/src/gui/mainwindow/mainwindow.cpp b/src/gui/mainwindow/mainwindow.cpp
index 183fd122e6b..6fa8e9f7965 100644
--- a/src/gui/mainwindow/mainwindow.cpp
+++ b/src/gui/mainwindow/mainwindow.cpp
@@ -27,6 +27,10 @@
#include "modalwrapperwidget.h"
#include "theme.h"
+#ifdef Q_OS_WIN
+#include
+#endif
+
#ifdef Q_OS_MAC
#include "settingsdialog_mac.h"
void setActivationPolicy(ActivationPolicy policy);
@@ -174,7 +178,7 @@ void MainWindow::endModalWidget()
_actionGroup->checkedAction()->toggled(true);
}
-void MainWindow::addGeneralAction(QAction *action)
+void MainWindow::addViewAction(QAction *action)
{
_toolbar->insertAction(_separatorAction, action);
configureAction(action);
@@ -273,6 +277,30 @@ QSize MainWindow::minimumSizeHint() const
return min;
}
+void MainWindow::ensureVisible()
+{
+ show();
+ raise();
+ activateWindow();
+
+#if defined(Q_OS_WIN)
+ // Windows disallows raising a Window when you're not the active application.
+ // Use a common hack to attach to the active application
+ const auto activeProcessId = GetWindowThreadProcessId(GetForegroundWindow(), nullptr);
+ if (activeProcessId != qApp->applicationPid()) {
+ const auto threadId = GetCurrentThreadId();
+ // don't step here with a debugger...
+ if (AttachThreadInput(threadId, activeProcessId, true)) {
+ const auto hwnd = reinterpret_cast(winId());
+ SetForegroundWindow(hwnd);
+ SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
+ AttachThreadInput(threadId, activeProcessId, false);
+ }
+ }
+
+#endif
+}
+
void MainWindow::setVisible(bool visible)
{
if (!visible) {
diff --git a/src/gui/mainwindow/mainwindow.h b/src/gui/mainwindow/mainwindow.h
index 92736646cda..153a59bf7ee 100644
--- a/src/gui/mainwindow/mainwindow.h
+++ b/src/gui/mainwindow/mainwindow.h
@@ -14,6 +14,7 @@
#pragma once
+#include "gui/owncloudguilib.h"
#include
class QAction;
@@ -26,7 +27,7 @@ namespace OCC {
class ModalWrapperWidget;
-class MainWindow : public QMainWindow
+class OWNCLOUDGUI_EXPORT MainWindow : public QMainWindow
{
Q_OBJECT
public:
@@ -34,6 +35,8 @@ class MainWindow : public QMainWindow
QSize minimumSizeHint() const override;
+ void ensureVisible();
+
void setVisible(bool visible) override;
void setMoreMenuActions(const QList &actions);
@@ -43,7 +46,7 @@ class MainWindow : public QMainWindow
void addAccountAction(QAction *action);
void removeAction(QAction *action);
- void addGeneralAction(QAction *action);
+ void addViewAction(QAction *action);
private slots:
void endModalWidget();
diff --git a/src/gui/mainwindow/mainwindowcontroller.cpp b/src/gui/mainwindow/mainwindowcontroller.cpp
index 6badfad36db..c66103177b1 100644
--- a/src/gui/mainwindow/mainwindowcontroller.cpp
+++ b/src/gui/mainwindow/mainwindowcontroller.cpp
@@ -15,8 +15,7 @@
#include "mainwindowcontroller.h"
#include "aboutview.h"
-#include "accountmanager.h"
-#include "accountsgui/accountsguicontroller.h"
+#include "application.h"
#include "localactivitywidget.h"
#include "mainwindow.h"
#include "modalwrapperwidget.h"
@@ -25,8 +24,8 @@
#include "theme.h"
#include
+#include
#include
-#include
namespace OCC {
@@ -42,8 +41,6 @@ void MainWindowController::setup()
createSyncErrorsAction();
createActivityAction();
buildMenuActions();
-
- _accountsController = new AccountsGuiController(AccountManager::instance(), _window, this);
}
void MainWindowController::buildMenuActions()
@@ -52,7 +49,7 @@ void MainWindowController::buildMenuActions()
QAction *addAccountAction = new QAction(tr("Add account..."), this);
addAccountAction->setObjectName("addAcountAction");
- connect(addAccountAction, &QAction::triggered, this, &MainWindowController::onAddAccount);
+ connect(addAccountAction, &QAction::triggered, this, &MainWindowController::requestAccountWizard);
menuActions.push_back(addAccountAction);
QAction *settingsAction = new QAction(tr("Settings..."), this);
@@ -88,7 +85,7 @@ void MainWindowController::createSyncErrorsAction()
syncErrorWidget, &SyncErrorWidget::issueCountUpdated, this, [syncErrorsAction](int count) { syncErrorsAction->setText(tr("Errors: %1").arg(count)); });
syncErrorsAction->setData(QVariant::fromValue(syncErrorWidget));
- _window->addGeneralAction(syncErrorsAction);
+ _window->addViewAction(syncErrorsAction);
}
void MainWindowController::createActivityAction()
@@ -99,12 +96,7 @@ void MainWindowController::createActivityAction()
activityAction->setCheckable(true);
auto localActivityWidget = new LocalActivityWidget(_window);
activityAction->setData(QVariant::fromValue(localActivityWidget));
- _window->addGeneralAction(activityAction);
-}
-
-void MainWindowController::onAddAccount()
-{
- _accountsController->runAccountWizard();
+ _window->addViewAction(activityAction);
}
void MainWindowController::onSettings()
@@ -116,11 +108,17 @@ void MainWindowController::onSettings()
void MainWindowController::onAbout()
{
+ _window->ensureVisible();
AboutView *aboutPanel = new AboutView(_window);
ModalWrapperWidget *wrapper = new ModalWrapperWidget(aboutPanel, _window);
_window->showModalWidget(wrapper);
}
+void MainWindowController::onHelp()
+{
+ QDesktopServices::openUrl(QUrl(Theme::instance()->helpUrl()));
+}
+
void MainWindowController::onQuit()
{
// this is just copied/pasted from the original - most likely will change this to a simple dialog exec, then we
diff --git a/src/gui/mainwindow/mainwindowcontroller.h b/src/gui/mainwindow/mainwindowcontroller.h
index 7dc20c0a67d..e34a0806323 100644
--- a/src/gui/mainwindow/mainwindowcontroller.h
+++ b/src/gui/mainwindow/mainwindowcontroller.h
@@ -29,18 +29,21 @@ class MainWindowController : public QObject
// public for now
void setup();
+ // called from tray menu, too. make this a signal/slot connection between the tray menu controller and main window controller
+ void onAbout();
+ void onHelp();
+
+signals:
+ void requestAccountWizard();
private:
void buildMenuActions();
void createSyncErrorsAction();
void createActivityAction();
- void onAddAccount();
void onSettings();
- void onAbout();
void onQuit();
MainWindow *_window = nullptr;
- AccountsGuiController *_accountsController = nullptr;
};
}
diff --git a/src/gui/mainwindow/modalwrapperwidget.cpp b/src/gui/mainwindow/modalwrapperwidget.cpp
index 22a12e06e46..46a20362dd0 100644
--- a/src/gui/mainwindow/modalwrapperwidget.cpp
+++ b/src/gui/mainwindow/modalwrapperwidget.cpp
@@ -14,6 +14,7 @@
#include "modalwrapperwidget.h"
+#include
#include
#include
#include
@@ -30,15 +31,19 @@ ModalWrapperWidget::ModalWrapperWidget(QWidget *content, QWidget *parent)
QVBoxLayout *layout = new QVBoxLayout(this);
layout->addWidget(content);
- QDialogButtonBox *buttons = new QDialogButtonBox(QDialogButtonBox::Ok, Qt::Horizontal, this);
- connect(buttons, &QDialogButtonBox::accepted, this, &ModalWrapperWidget::finished);
- // yes I know there is a default "close" button, but it emits rejected which can have consequences
- // I'm choosing close for the naming here because it doesn't imply any sort of "save" action, which will be important
- // wrt the settings view, which updates values "live" as they are changed, not committed on "ok" or "save"
- QPushButton *okButton = buttons->button(QDialogButtonBox::Ok);
- okButton->setObjectName("closeButton");
- okButton->setText(tr("Close"));
- layout->addWidget(buttons);
+ if (QDialog *asDialog = qobject_cast(content)) {
+ connect(asDialog, &QDialog::finished, this, &ModalWrapperWidget::finished);
+ } else {
+ QDialogButtonBox *buttons = new QDialogButtonBox(QDialogButtonBox::Ok, Qt::Horizontal, this);
+ connect(buttons, &QDialogButtonBox::accepted, this, &ModalWrapperWidget::finished);
+ // yes I know there is a default "close" button, but it emits rejected which can have consequences
+ // I'm choosing close for the naming here because it doesn't imply any sort of "save" action, which will be important
+ // wrt the settings view, which updates values "live" as they are changed, not committed on "ok" or "save"
+ QPushButton *okButton = buttons->button(QDialogButtonBox::Ok);
+ okButton->setObjectName("closeButton");
+ okButton->setText(tr("Close"));
+ layout->addWidget(buttons);
+ }
setLayout(layout);
}
diff --git a/src/gui/mainwindow/modalwrapperwidget.h b/src/gui/mainwindow/modalwrapperwidget.h
index 50d008d1f40..932cf97301a 100644
--- a/src/gui/mainwindow/modalwrapperwidget.h
+++ b/src/gui/mainwindow/modalwrapperwidget.h
@@ -18,6 +18,20 @@
namespace OCC {
+/**
+ * @brief The ModalWrapperWidget class is used to show "child" widgets in the main window, in a quasi modal fashion, ie
+ * the toolbar is disabled and you can't do anything in the main window until you finish interacting with the content.
+ *
+ * This impl eliminates the need for caller to manage the lifetime of the widget they want to run as the content widget is reparented
+ * to the ModalWrapperWidget and the main window closes and deletes the wrapper when it receives the finished signal. It also eliminates
+ * the need for the content widget to create and manage its own buttons. In short, this class ordinarily expects a simple "panel" widget,
+ * and it adds a single "close" button below the content widget to dismiss the modal view.
+ *
+ * However, to support the updater, it is now also possible to pass a QDialog to the ctr in which case the dialog is used as-is
+ * with its own buttons in place. In this case the dialog's finished signal is forwarded to ModalWrapperWidget::finished.
+ *
+ * You *must* use a wrapper widget if you want to use MainWindow::showModalWidget
+ */
class ModalWrapperWidget : public QWidget
{
Q_OBJECT
diff --git a/src/gui/mainwindow/settingsview.cpp b/src/gui/mainwindow/settingsview.cpp
index ec2569bf264..b9fb3ae8119 100644
--- a/src/gui/mainwindow/settingsview.cpp
+++ b/src/gui/mainwindow/settingsview.cpp
@@ -15,14 +15,12 @@
#include "settingsview.h"
#include "ui_settingsview.h"
-#include "common/restartmanager.h"
-#include "common/version.h"
-#include "gui/application.h"
-#include "gui/ignorelisteditor.h"
-#include "gui/settingsdialog.h"
-#include "gui/translations.h"
+#include "application.h"
+#include "ignorelisteditor.h"
#include "libsync/configfile.h"
#include "libsync/theme.h"
+#include "logbrowser.h"
+#include "translations.h"
#include
#include
@@ -74,10 +72,7 @@ SettingsView::SettingsView(QWidget *parent)
_ui->monoIconsCheckBox->setVisible(Resources::hasMonoTheme());
connect(_ui->ignoredFilesButton, &QAbstractButton::clicked, this, &SettingsView::slotIgnoreFilesEditor);
- connect(_ui->logSettingsButton, &QPushButton::clicked, this, [] {
- // only access occApp after things are set up
- ocApp()->gui()->slotToggleLogBrowser();
- });
+ connect(_ui->logSettingsButton, &QPushButton::clicked, this, &SettingsView::slotShowLogSettings);
if (!Theme::instance()->aboutShowCopyright()) {
_ui->copyrightLabel->hide();
@@ -141,9 +136,9 @@ void SettingsView::slotToggleOptionalDesktopNotifications(bool enable)
void SettingsView::slotIgnoreFilesEditor()
{
if (_ignoreEditor.isNull()) {
- _ignoreEditor = new IgnoreListEditor(ocApp()->gui()->settingsDialog());
+ _ignoreEditor = new IgnoreListEditor(ocApp()->mainWindow());
_ignoreEditor->setAttribute(Qt::WA_DeleteOnClose, true);
- ownCloudGui::raise();
+ ocApp()->ensureVisible();
_ignoreEditor->open();
}
}
@@ -195,4 +190,12 @@ void SettingsView::loadLanguageNamesIntoDropdown()
}
}
+void SettingsView::slotShowLogSettings()
+{
+ auto logBrowser = new LogBrowser(ocApp()->mainWindow());
+ logBrowser->setAttribute(Qt::WA_DeleteOnClose);
+ ocApp()->ensureVisible();
+ logBrowser->open();
+}
+
} // namespace OCC
diff --git a/src/gui/mainwindow/settingsview.h b/src/gui/mainwindow/settingsview.h
index 0f4888ee2a8..10f94aa0c07 100644
--- a/src/gui/mainwindow/settingsview.h
+++ b/src/gui/mainwindow/settingsview.h
@@ -43,10 +43,11 @@ class SettingsView : public QWidget
private Q_SLOTS:
void saveMiscSettings();
+ void loadMiscSettings();
void slotToggleLaunchOnStartup(bool);
void slotToggleOptionalDesktopNotifications(bool);
void slotIgnoreFilesEditor();
- void loadMiscSettings();
+ void slotShowLogSettings();
protected:
void showEvent(QShowEvent *event) override;
diff --git a/src/gui/networkadapters/resolveurladapter.cpp b/src/gui/networkadapters/resolveurladapter.cpp
index 49b1fe18d45..07dffd43733 100644
--- a/src/gui/networkadapters/resolveurladapter.cpp
+++ b/src/gui/networkadapters/resolveurladapter.cpp
@@ -17,8 +17,6 @@
#include "abstractcorejob.h"
#include "common/utility.h"
#include "gui/application.h"
-#include "gui/owncloudgui.h"
-#include "gui/settingsdialog.h"
#include "gui/tlserrordialog.h"
#include
@@ -95,7 +93,7 @@ void ResolveUrlAdapter::handleSslErrors(const QList &errors)
} else {
auto *tlsErrorDialog = new TlsErrorDialog(filtered, reply->url().host(), _tlsDialogParent);
- ownCloudGui::raise();
+ ocApp()->ensureVisible();
// we have to exec here or the request finishes too fast
int res = tlsErrorDialog->exec();
if (res == QDialog::DialogCode::Accepted) {
diff --git a/src/gui/newaccountwizard/newaccountbuilder.cpp b/src/gui/newaccountwizard/newaccountbuilder.cpp
index 1ffdfb09fc9..4f46e96414e 100644
--- a/src/gui/newaccountwizard/newaccountbuilder.cpp
+++ b/src/gui/newaccountwizard/newaccountbuilder.cpp
@@ -88,7 +88,7 @@ void NewAccountBuilder::completeAccountSetup()
// if selective sync is selected, we need to run the folder wizard asap.
if (_syncType == NewAccount::SyncType::SELECTIVE_SYNC)
- Q_EMIT requestFolderWizard(_account);
+ Q_EMIT requestFolderWizard(_account->uuid());
deleteLater();
}
diff --git a/src/gui/newaccountwizard/newaccountbuilder.h b/src/gui/newaccountwizard/newaccountbuilder.h
index 0dedd692106..4c63ba84dfb 100644
--- a/src/gui/newaccountwizard/newaccountbuilder.h
+++ b/src/gui/newaccountwizard/newaccountbuilder.h
@@ -35,7 +35,7 @@ class NewAccountBuilder : public QObject
Q_SIGNALS:
void requestSetUpSyncFoldersForAccount(OCC::AccountState *, bool useVfs);
void requestLoadSpacesOnly(OCC::AccountState *);
- void requestFolderWizard(OCC::Account *account);
+ void requestFolderWizard(QUuid accountId);
void unableToCompleteAccountCreation(const QString &error);
private:
diff --git a/src/gui/newaccountwizard/newaccountwizardcontroller.cpp b/src/gui/newaccountwizard/newaccountwizardcontroller.cpp
index ec8a486fe1f..0cc4acdeabc 100644
--- a/src/gui/newaccountwizard/newaccountwizardcontroller.cpp
+++ b/src/gui/newaccountwizard/newaccountwizardcontroller.cpp
@@ -16,13 +16,12 @@
#include "accessmanager.h"
#include "advancedsettingspagecontroller.h"
+#include "application.h"
#include "authsuccesspagecontroller.h"
#include "common/utility.h"
#include "newaccountmodel.h"
#include "newaccountwizard.h"
#include "oauthpagecontroller.h"
-#include "owncloudgui.h"
-#include "resources/template.h"
#include "theme.h"
#include "urlpagecontroller.h"
@@ -177,7 +176,7 @@ void NewAccountWizardController::onOAuthValidationCompleted(const OCC::OAuthPage
_model->setWebfingerUserInfoUrl(results.webfingerUserUrl);
_wizard->setCurrentId(_authSuccessPageIndex);
- ownCloudGui::raise();
+ ocApp()->ensureVisible();
// on mac, for unknown reasons, the main window is active after raise
_wizard->activateWindow();
}
@@ -187,7 +186,7 @@ void NewAccountWizardController::onOauthValidationFailed(const OCC::OAuthPageRes
if (!_wizard)
return;
Q_UNUSED(results);
- ownCloudGui::raise();
+ ocApp()->ensureVisible();
_wizard->activateWindow();
}
diff --git a/src/gui/owncloudgui.cpp b/src/gui/owncloudgui.cpp
deleted file mode 100644
index ecebf2f27cd..00000000000
--- a/src/gui/owncloudgui.cpp
+++ /dev/null
@@ -1,357 +0,0 @@
-/*
- * Copyright (C) by Klaas Freitag
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include "owncloudgui.h"
-#include "aboutdialog.h"
-#include "account.h"
-#include "accountmanager.h"
-#include "accountstate.h"
-#include "application.h"
-#include "common/restartmanager.h"
-#include "common/syncjournalfilerecord.h"
-#include "configfile.h"
-#include "folderman.h"
-#include "gui/networkinformation.h"
-#include "guiutility.h"
-#include "libsync/theme.h"
-#include "logbrowser.h"
-#include "mainwindow/mainwindow.h"
-#include "progressdispatcher.h"
-#include "settingsdialog.h"
-
-#include "newaccountwizard/newaccountbuilder.h"
-#include "newaccountwizard/newaccountmodel.h"
-#include "newaccountwizard/newaccountwizard.h"
-#include "newaccountwizard/newaccountwizardcontroller.h"
-
-#include "resources/resources.h"
-
-#include
-#include
-#include
-#include
-
-#ifdef Q_OS_WIN
-#include
-#endif
-
-using namespace std::chrono_literals;
-
-namespace OCC {
-
-// simple helper to compute the overall status for the tray icon
-SyncResult::Status trayOverallStatus()
-{
- TrayOverallStatusResult result;
- for (auto *folder : FolderMan::instance()->folders()) {
- result.addResult(folder);
- }
- if (result.overallStatus().status() == SyncResult::Undefined) {
- return SyncResult::Offline;
- }
- return result.overallStatus().status();
-}
-
-ownCloudGui::ownCloudGui(Application *parent)
- : QObject(parent)
- , _tray(new QSystemTrayIcon(this))
- // , _settingsDialog(new SettingsDialog(this))
- , _app(parent)
-{
-#ifndef USE_NEW_MAIN_WINDOW
- _settingsDialog = new SettingsDialog(this);
-#endif
-
- connect(_tray, &QSystemTrayIcon::activated, this, &ownCloudGui::slotTrayClicked);
-
- setupTrayContextMenu();
-
- // init systray
- slotComputeOverallSyncStatus();
- _tray->show();
-
- // Refactoring todo: we have a very nasty habit of connecting to globally available managers, etc inside constructors or similar.
- // this should only happen when we are dealing with a formal dependency: eg a dep passed by injection and kept as member,
- // or a dep that is instantiated inside the class (also with a member kept)
- // in cases like this one, the external deps should be instantiated externally and connected externally. This is normally part
- // of an app building routine. The global singletons have to go and this is an important step to achieving that.
- FolderMan *folderMan = FolderMan::instance();
- connect(folderMan, &FolderMan::folderSyncStateChange, this, &ownCloudGui::slotSyncStateChange);
-}
-
-ownCloudGui::~ownCloudGui()
-{
- delete _settingsDialog;
-}
-
-// This should rather be in application.... or rather in ConfigFile?
-void ownCloudGui::slotOpenSettingsDialog()
-{
- // if account is set up, start the configuration wizard.
- if (!AccountManager::instance()->accounts().isEmpty()) {
- if (QApplication::activeWindow() != _settingsDialog) {
- slotShowSettings();
- } else {
- // ????!!!!?????????
- _settingsDialog->close();
- }
- } else {
-#ifndef USE_NEW_MAIN_WINDOW
- qCInfo(lcApplication) << "No configured folders yet, starting setup wizard";
- runAccountWizard();
-#endif
- }
-}
-
-void ownCloudGui::slotTrayClicked(QSystemTrayIcon::ActivationReason reason)
-{
- // Left click
- if (reason == QSystemTrayIcon::Trigger) {
-#ifdef Q_OS_MAC
- // on macOS, a left click always opens menu.
- // However if the settings dialog is already visible but hidden
- // by other applications, this will bring it to the front.
- if (_settingsDialog->isVisible()) {
- raise();
- }
-#else
- slotOpenSettingsDialog();
-#endif
- }
-}
-
-void ownCloudGui::slotSyncStateChange(Folder *folder)
-{
- slotComputeOverallSyncStatus();
-
- if (!folder) {
- return; // Valid, just a general GUI redraw was needed.
- }
-
- auto result = folder->syncResult();
-
- qCInfo(lcApplication) << "Sync state changed for folder " << folder->remoteUrl().toString() << ": " << Utility::enumToDisplayName(result.status());
-}
-
-void ownCloudGui::slotTrayMessageIfServerUnsupported(Account *account)
-{
- if (account->serverSupportLevel() != Account::ServerSupportLevel::Supported) {
- slotShowTrayMessage(tr("Unsupported Server Version"),
- tr("The server on account %1 runs an unsupported version %2. "
- "Using this client with unsupported server versions is untested and "
- "potentially dangerous. Proceed at your own risk.")
- .arg(account->displayNameWithHost(), account->capabilities().status().versionString()));
- }
-}
-
-QIcon ownCloudGui::getTrayStatusIcon(const SyncResult::Status &status) const
-{
- auto contextMenuVisible = _tray->contextMenu() && _tray->contextMenu()->isVisible();
- return Theme::instance()->themeTrayIcon(SyncResult{status}, contextMenuVisible);
-}
-
-void ownCloudGui::slotComputeOverallSyncStatus()
-{
- auto status = trayOverallStatus();
- const QIcon statusIcon = getTrayStatusIcon(status);
- _tray->setIcon(statusIcon);
-}
-
-SettingsDialog *ownCloudGui::settingsDialog() const
-{
- return _settingsDialog;
-}
-
-void ownCloudGui::setupTrayContextMenu()
-{
- // using the main windows (_settingsDialog) as parent for memory management
- auto menu = new QMenu(_settingsDialog);
- menu->setTitle(Theme::instance()->appNameGUI());
-
- _tray->setContextMenu(menu);
-
- // Populate the context menu now.
- menu->addAction(Theme::instance()->applicationIcon(), tr("Show %1").arg(Theme::instance()->appNameGUI()), this, &ownCloudGui::slotShowSettings);
- menu->addSeparator();
-
- if (_app->debugMode()) {
- auto *debugMenu = menu->addMenu(QStringLiteral("Debug actions"));
- debugMenu->addAction(QStringLiteral("Crash if asserts enabled - OC_ENSURE"), _app, [] {
- if (OC_ENSURE(false)) {
- Q_UNREACHABLE();
- }
- });
- debugMenu->addAction(QStringLiteral("Crash if asserts enabled - Q_ASSERT"), _app, [] { Q_ASSERT(false); });
- debugMenu->addAction(QStringLiteral("Crash now - Utility::crash()"), _app, [] { Utility::crash(); });
- debugMenu->addAction(QStringLiteral("Crash now - OC_ENFORCE()"), _app, [] { OC_ENFORCE(false); });
- debugMenu->addAction(QStringLiteral("Crash now - qFatal"), _app, [] { qFatal("la Qt fatale"); });
- debugMenu->addAction(QStringLiteral("Restart now"), _app, [] { RestartManager::requestRestart(); });
- debugMenu->addSeparator();
- auto captivePortalCheckbox = debugMenu->addAction(QStringLiteral("Behind Captive Portal"));
- captivePortalCheckbox->setCheckable(true);
- captivePortalCheckbox->setChecked(NetworkInformation::instance()->isForcedCaptivePortal());
- connect(captivePortalCheckbox, &QAction::triggered, [](bool checked) { NetworkInformation::instance()->setForcedCaptivePortal(checked); });
-
- menu->addSeparator();
- }
-
- if (!Theme::instance()->helpUrl().isEmpty()) {
- menu->addAction(tr("Help"), this, &ownCloudGui::slotHelp);
- }
-
- if (! Theme::instance()->about().isEmpty()) {
- menu->addAction(tr("About %1").arg(Theme::instance()->appNameGUI()), this, &ownCloudGui::slotAbout);
- }
-
- menu->addAction(tr("Quit %1").arg(Theme::instance()->appNameGUI()), _app, &QApplication::quit);
-}
-
-void ownCloudGui::slotShowTrayMessage(const QString &title, const QString &msg, const QIcon &icon)
-{
- _tray->showMessage(title, msg, icon.isNull() ? Resources::getCoreIcon(QStringLiteral("states/information")) : icon);
-}
-
-void ownCloudGui::slotShowOptionalTrayMessage(const QString &title, const QString &msg, const QIcon &icon)
-{
- ConfigFile cfg;
- if (cfg.optionalDesktopNotifications()) {
- slotShowTrayMessage(title, msg, icon);
- }
-}
-
-void ownCloudGui::runAccountWizard()
-{
- NewAccountWizard wizard(settingsDialog());
- NewAccountModel model(nullptr);
- NewAccountWizardController wizardController(&model, &wizard, nullptr);
- ownCloudGui::raise();
- int result = wizard.exec();
- if (result == QDialog::Accepted) {
- // the builder needs to be a pointer as it has to wait for the connection state to go to connected
- // it will delete itself once it has completed its mission.
- // pass this as parent only as a safeguard.
- if (!model.isComplete()) {
- QMessageBox::warning(
- _settingsDialog, tr("New account failure"), tr("The information required to create a new account is incomplete. Please run the wizard again."));
- } else {
- NewAccountBuilder *builder = new NewAccountBuilder(model, this);
- connect(builder, &NewAccountBuilder::requestSetUpSyncFoldersForAccount, this, &ownCloudGui::requestSetUpSyncFoldersForAccount);
- connect(builder, &NewAccountBuilder::requestLoadSpacesOnly, this, &ownCloudGui::requestLoadSpacesOnly);
- connect(builder, &NewAccountBuilder::requestFolderWizard, _settingsDialog, &SettingsDialog::runFolderWizard);
- connect(builder, &NewAccountBuilder::unableToCompleteAccountCreation, this, &ownCloudGui::handleAccountSetupError);
- builder->buildAccount();
- }
- } else
- qDebug() << "wizard rejected";
-}
-
-void ownCloudGui::handleAccountSetupError(const QString &error)
-{
- QMessageBox::warning(_settingsDialog, tr("New account failure"),
- tr("The account could not be created due to an error:\n%1\nPlease check the server's availability then run the wizard again.").arg(error));
-}
-
-void ownCloudGui::slotShowSettings()
-{
- raise();
-}
-
-void ownCloudGui::slotShutdown()
-{
- // with the new mainWindow the geometry is autosaved without this shutdown routine
- // todo: dc-300 or soon after, get rid of this whole function
-
- // explicitly close windows. This is somewhat of a hack to ensure
- // that saving the geometries happens ASAP during an OS shutdown
-
- // those do delete on close
- if (_settingsDialog)
- _settingsDialog->close();
-}
-
-void ownCloudGui::slotToggleLogBrowser()
-{
- auto logBrowser = new LogBrowser(settingsDialog());
- logBrowser->setAttribute(Qt::WA_DeleteOnClose);
- ownCloudGui::raise();
- logBrowser->open();
-}
-
-void ownCloudGui::slotHelp()
-{
- QDesktopServices::openUrl(QUrl(Theme::instance()->helpUrl()));
-}
-
-void ownCloudGui::raise()
-{
- // auto window = ocApp()->gui()->settingsDialog();
- QMainWindow *window;
-#ifdef USE_NEW_MAIN_WINDOW
- window = ocApp()->mainWindow();
-#else
- // no we can't just use the member because this function apparently "has" to be static?
- // if this is the case it would make more sense to move it to Application since it should own the main window
- window = ocApp()->gui()->settingsDialog();
-#endif
- window->show();
- window->raise();
- window->activateWindow();
-
-#if defined(Q_OS_WIN)
- // Windows disallows raising a Window when you're not the active application.
- // Use a common hack to attach to the active application
- const auto activeProcessId = GetWindowThreadProcessId(GetForegroundWindow(), nullptr);
- if (activeProcessId != qApp->applicationPid()) {
- const auto threadId = GetCurrentThreadId();
- // don't step here with a debugger...
- if (AttachThreadInput(threadId, activeProcessId, true))
- {
- const auto hwnd = reinterpret_cast(window->winId());
- SetForegroundWindow(hwnd);
- SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
- AttachThreadInput(threadId, activeProcessId, false);
- }
- }
-#endif
-}
-
-
-void ownCloudGui::slotShowShareInBrowser(const QString &sharePath, const QString &localPath)
-{
- QString file;
- const auto folder = FolderMan::instance()->folderForPath(localPath, &file);
- if (!folder) {
- qCWarning(lcApplication) << "Could not open browser share page for" << localPath << "no responsible folder found";
- return;
- }
-
- if (folder->accountState()->account()->capabilities().filesSharing().sharing_roles) {
- fetchPrivateLinkUrl(folder->accountState()->account(), folder->webDavUrl(), sharePath, this, [](const QUrl &url) {
- const auto queryUrl = Utility::concatUrlPath(url, QString(), {{QStringLiteral("details"), QStringLiteral("sharing")}});
- Utility::openBrowser(queryUrl, nullptr);
- });
- }
-}
-
-void ownCloudGui::slotAbout()
-{
- if(!_aboutDialog) {
- _aboutDialog = new AboutDialog(_settingsDialog);
- _aboutDialog->setAttribute(Qt::WA_DeleteOnClose);
- ocApp()->gui()->settingsDialog()->addModalWidget(_aboutDialog);
- }
-}
-
-
-} // end namespace
diff --git a/src/gui/settingsdialog.cpp b/src/gui/settingsdialog.cpp
deleted file mode 100644
index 448b2045e34..00000000000
--- a/src/gui/settingsdialog.cpp
+++ /dev/null
@@ -1,313 +0,0 @@
-/*
- * Copyright (C) by Daniel Molkentin
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include "settingsdialog.h"
-#include "ui_settingsdialog.h"
-
-#include "accountmanager.h"
-#include "accountsgui/accountview.h"
-#include "activitysettings.h"
-#include "application.h"
-#include "configfile.h"
-#include "generalsettings.h"
-#include "gui/qmlutils.h"
-#include "owncloudgui.h"
-#include "resources/qmlresources.h"
-#include "theme.h"
-
-#include
-#include
-#include
-
-#ifdef Q_OS_MAC
-#include "settingsdialog_mac.h"
-
-void setActivationPolicy(ActivationPolicy policy);
-#endif
-
-Q_LOGGING_CATEGORY(lcSettingsDialog, "gui.settingsdialog", QtInfoMsg);
-
-namespace {
-auto minimumSizeHint(const QWidget *w)
-{
- const QSize min { 800, 700 }; // When changing this, please check macOS: widgets there have larger insets, so they take up more space.
- const auto screen = w->windowHandle() ? w->windowHandle()->screen() : QApplication::screenAt(QCursor::pos());
- if (screen) {
- const auto availableSize = screen->availableSize();
- if (availableSize.isValid()) {
- // Assume we can use at least 90% of the screen, if the screen is smaller than 800x700 pixels.
- //
- // Note: this means that the wizards have even less space: with the style we use, the
- // wizard tries to fit inside the window. So, if this is a common case that users have
- // such small screens, and the contents of the wizard screen are squashed together (or
- // not shown due to lack of space), we should consider putting that content in a
- // scroll-view.
- return min.boundedTo(availableSize * 0.9);
- }
- }
- return min;
-}
-
-
-class AvatarImageProvider : public QQuickImageProvider
-{
- Q_OBJECT
-public:
- AvatarImageProvider()
- : QQuickImageProvider(QQuickImageProvider::Pixmap, QQuickImageProvider::ForceAsynchronousImageLoading)
- {
- }
-
- QPixmap requestPixmap(const QString &id, QSize *size, const QSize &requestedSize)
- {
- const auto qmlIcon = OCC::Resources::QMLResources::parseIcon(id);
- const auto accountState = OCC::AccountManager::instance()->accountState(QUuid::fromString(qmlIcon.iconName));
- if (!accountState || !accountState->account())
- return {};
- return OCC::Resources::pixmap(requestedSize, accountState->account()->avatar(), qmlIcon.enabled ? QIcon::Normal : QIcon::Disabled, size);
- }
-};
-}
-
-
-namespace OCC {
-
-SettingsDialog::SettingsDialog(ownCloudGui *gui, QWidget *parent)
- : QMainWindow(parent)
- , _ui(new Ui::SettingsDialog)
- , _gui(gui)
-{
- setObjectName(QStringLiteral("Settings")); // required as group for saveGeometry call
- setWindowTitle(Theme::instance()->appNameGUI());
- _ui->setupUi(this);
-
- setMinimumSize(::minimumSizeHint(this));
-
- // People perceive this as a Window, so also make Ctrl+W work
- addAction(tr("Hide"), Qt::CTRL | Qt::Key_W, this, &SettingsDialog::hide);
-
- // TODO: fix sizing
- _ui->quickWidget->setFixedHeight(minimumHeight() * 0.13);
- _ui->quickWidget->engine()->addImageProvider(QStringLiteral("avatar"), new AvatarImageProvider);
- _ui->quickWidget->setOCContext(QUrl(QStringLiteral("qrc:/qt/qml/org/ownCloud/gui/qml/AccountBar.qml")), this);
- connect(
- _ui->quickWidget->engine(), &QQmlEngine::quit, QApplication::instance(),
- [this] {
- auto box = new QMessageBox(QMessageBox::Question, tr("Quit %1").arg(Theme::instance()->appNameGUI()),
- tr("Are you sure you want to quit %1?").arg(Theme::instance()->appNameGUI()), QMessageBox::Yes | QMessageBox::No, this);
- box->setAttribute(Qt::WA_DeleteOnClose);
- connect(box, &QMessageBox::accepted, this, [] {
- // delay quit to prevent a Qt 6.6 crash in the destructor of the dialog
- QTimer::singleShot(0, qApp, &QCoreApplication::quit);
- });
- box->open();
- },
- Qt::QueuedConnection);
-
- _activitySettings = new ActivitySettings;
- _ui->stack->addWidget(_activitySettings);
-
- _generalSettings = new GeneralSettings;
- _ui->stack->addWidget(_generalSettings);
- connect(_generalSettings, &GeneralSettings::showAbout, gui, &ownCloudGui::slotAbout);
- connect(_generalSettings, &GeneralSettings::moveToTrashChanged, FolderMan::instance(), &FolderMan::updateMoveToTrash);
-
- ConfigFile().restoreGeometry(this);
-#ifdef Q_OS_MAC
- setActivationPolicy(ActivationPolicy::Accessory);
-#endif
-
- // todo
- // I don't see the point here insofar as I can't find any panels that change the app title
- connect(_ui->dialogStack, &QStackedWidget::currentChanged, this, [this] {
- auto *w = _ui->dialogStack->currentWidget();
- if (!w->windowTitle().isEmpty()) {
- setWindowTitle(tr("%1 - %2").arg(Theme::instance()->appNameGUI(), w->windowTitle()));
- } else {
- setWindowTitle(Theme::instance()->appNameGUI());
- }
- });
-
- setCurrentPage(SettingsPage::Settings);
-
- // load any existing accounts from the manager.
- const auto accounts = AccountManager::instance()->accounts();
- for (const auto &accountState : accounts) {
- onAccountAdded(accountState);
- }
- if (!_viewForAccount.isEmpty()) {
- setCurrentAccount(accounts.first()->account());
- }
-
- connect(AccountManager::instance(), &AccountManager::accountAdded, this, &SettingsDialog::onAccountAdded);
- connect(AccountManager::instance(), &AccountManager::accountRemoved, this, &SettingsDialog::onAccountRemoved);
-}
-
-SettingsDialog::~SettingsDialog()
-{
- delete _ui;
-}
-
-void SettingsDialog::onAccountAdded(AccountState *state)
-{
- if (!state || !state->account())
- return;
- // asap we need to create some kind of accountView builder that will instantiate a controller and view + whatever else
- // as currently everything is in the view which is absolutely not ok, especially given the multitude of "heavy lifting"
- // that goes on in there
-
- auto accountView = new AccountView(state, this);
- _ui->stack->addWidget(accountView);
- _viewForAccount.insert(state->account()->uuid(), accountView);
-
- setCurrentAccount(state->account());
-}
-
-void SettingsDialog::onAccountRemoved(AccountState *state)
-{
- if (!state || !state->account())
- return;
- // todo: #37. using the account after we know it's been removed is not ok.
- Account *acc = state->account();
-
- if (AccountView *asw = _viewForAccount.value(acc->uuid(), nullptr)) {
- _viewForAccount.remove(acc->uuid());
- _ui->stack->removeWidget(asw);
- asw->deleteLater();
- // go to the settings page if the last account was removed
- if (_viewForAccount.isEmpty()) {
- _ui->stack->setCurrentWidget(_generalSettings);
- }
- }
-}
-
-void SettingsDialog::addModalWidget(QWidget *w)
-{
- ownCloudGui::raise();
- if (_ui->dialogStack->indexOf(w) == -1) {
- _ui->dialogStack->addWidget(w);
- _ui->dialogStack->setCurrentWidget(w);
- }
-}
-
-void SettingsDialog::requestModality(Account *account)
-{
- if (!account)
- return;
-
- _ui->quickWidget->setEnabled(false);
- if (_modalStack.isEmpty()) {
- setCurrentAccount(account);
- }
- _modalStack.append(account);
- ownCloudGui::raise();
-}
-
-void SettingsDialog::ceaseModality(Account *account)
-{
- if (account && _modalStack.contains(account)) {
- _modalStack.removeOne(account);
- if (!_modalStack.isEmpty()) {
- setCurrentAccount(_modalStack.first());
- }
- }
- _ui->quickWidget->setEnabled(_modalStack.isEmpty());
-}
-
-AccountView *SettingsDialog::accountView(Account *account) const
-{
- return _viewForAccount.value(account->uuid(), nullptr);
-}
-
-void SettingsDialog::setVisible(bool visible)
-{
- if (!visible) {
- ConfigFile cfg;
- cfg.saveGeometry(this);
- }
-
-#ifdef Q_OS_MAC
- if (visible) {
- setActivationPolicy(ActivationPolicy::Regular);
- } else {
- setActivationPolicy(ActivationPolicy::Accessory);
- }
-#endif
- QMainWindow::setVisible(visible);
-}
-
-void SettingsDialog::setCurrentPage(SettingsPage currentPage)
-{
- _currentPage = currentPage;
- _currentAccount = nullptr;
- switch (_currentPage) {
- case SettingsPage::Activity:
- _ui->stack->setCurrentWidget(_activitySettings);
- break;
- case SettingsPage::Settings:
- _ui->stack->setCurrentWidget(_generalSettings);
- break;
- case SettingsPage::Account:
- // handled by set account
- [[fallthrough]];
- case SettingsPage::None:
- Q_UNREACHABLE();
- }
- Q_EMIT currentAccountChanged();
- Q_EMIT currentPageChanged();
-}
-
-SettingsDialog::SettingsPage SettingsDialog::currentPage() const
-{
- return _currentPage;
-}
-
-
-void SettingsDialog::setCurrentAccount(Account *account)
-{
- if (!account || account == _currentAccount)
- return;
-
- _currentAccount = account;
-
- _ui->stack->setCurrentWidget(accountView(account));
- _currentPage = SettingsPage::Account;
-
- Q_EMIT currentAccountChanged();
- Q_EMIT currentPageChanged();
-}
-
-// this is for qml support
-Account *SettingsDialog::currentAccount() const
-{
- return _currentAccount;
-}
-
-void SettingsDialog::createNewAccount()
-{
- ocApp()->gui()->runAccountWizard();
-}
-
-void SettingsDialog::runFolderWizard(Account *account)
-{
- if (!account)
- return;
- setCurrentAccount(account);
- accountView(_currentAccount)->slotAddFolder();
-}
-
-
-} // namespace OCC
-
-#include "settingsdialog.moc"
diff --git a/src/gui/settingsdialog.h b/src/gui/settingsdialog.h
deleted file mode 100644
index a06651b0945..00000000000
--- a/src/gui/settingsdialog.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) by Daniel Molkentin
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#pragma once
-
-#include "accountstate.h"
-#include "gui/qmlutils.h"
-#include "owncloudgui.h"
-
-#include
-#include
-
-
-namespace OCC {
-
-namespace Ui {
- class SettingsDialog;
-}
-class AccountView;
-class Application;
-class FolderMan;
-class ownCloudGui;
-class ActivitySettings;
-class GeneralSettings;
-
-/**
- * @brief The SettingsDialog class
- * @ingroup gui
- */
-class SettingsDialog : public QMainWindow
-{
- Q_OBJECT
- Q_PROPERTY(SettingsPage currentPage READ currentPage WRITE setCurrentPage NOTIFY currentPageChanged)
- Q_PROPERTY(Account *currentAccount READ currentAccount WRITE setCurrentAccount NOTIFY currentAccountChanged)
- QML_ELEMENT
- QML_UNCREATABLE("C++ only")
- OC_DECLARE_WIDGET_FOCUS
-public:
- enum class SettingsPage { None, Activity, Settings, Account };
- Q_ENUM(SettingsPage)
- explicit SettingsDialog(ownCloudGui *gui, QWidget *parent = nullptr);
- ~SettingsDialog() override;
-
- void addModalWidget(QWidget *w);
-
- void requestModality(Account *account);
- void ceaseModality(Account *account);
-
- AccountView *accountView(Account *account) const;
-
- SettingsPage currentPage() const;
-
- void setCurrentPage(SettingsPage currentPage);
-
- void setCurrentAccount(Account *account);
-
- // todo: #37 - this is stickier to get rid of as it's used in the qml related to the account. That needs to go.
- Account *currentAccount() const;
-
-public Q_SLOTS:
- // this is a direct call from QML
- void createNewAccount();
- void runFolderWizard(Account *account);
-
-
-Q_SIGNALS:
- void currentPageChanged();
- // I think this only goes to qml
- void currentAccountChanged();
-
-protected Q_SLOTS:
- void onAccountAdded(AccountState *state);
- void onAccountRemoved(AccountState *state);
-
-protected:
- void setVisible(bool visible) override;
-
-
-private:
- Ui::SettingsDialog *const _ui;
-
-
- QHash _viewForAccount;
-
- ActivitySettings *_activitySettings;
- ownCloudGui *_gui;
- QList _modalStack;
-
- GeneralSettings *_generalSettings;
- SettingsPage _currentPage = SettingsPage::None;
- // todo: #37
- Account *_currentAccount = nullptr;
-};
-}
diff --git a/src/gui/settingsdialog.ui b/src/gui/settingsdialog.ui
deleted file mode 100644
index c337a27f98f..00000000000
--- a/src/gui/settingsdialog.ui
+++ /dev/null
@@ -1,69 +0,0 @@
-
-
- OCC::SettingsDialog
-
-
-
- 0
- 0
- 800
- 500
-
-
-
- MainWindow
-
-
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
- -
-
-
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
-
-
-
- OCC::QmlUtils::OCQuickWidget
- QWidget
-
- 1
-
-
-
-
-
diff --git a/src/gui/syncerrorwidget.cpp b/src/gui/syncerrorwidget.cpp
index e677c2df87b..5aad4138b09 100644
--- a/src/gui/syncerrorwidget.cpp
+++ b/src/gui/syncerrorwidget.cpp
@@ -28,6 +28,7 @@
#include "theme.h"
#include
+#include
#include
#include "ui_syncerrorwidget.h"
diff --git a/src/gui/traymenucontroller.cpp b/src/gui/traymenucontroller.cpp
new file mode 100644
index 00000000000..a7294655cce
--- /dev/null
+++ b/src/gui/traymenucontroller.cpp
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) by Klaas Freitag
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "traymenucontroller.h"
+
+#include "account.h"
+#include "application.h"
+#include "common/restartmanager.h"
+#include "configfile.h"
+#include "guiutility.h"
+#include "libsync/theme.h"
+
+#include
+#include
+
+#ifdef Q_OS_WIN
+#include
+#endif
+
+using namespace std::chrono_literals;
+
+namespace OCC {
+
+// simple helper to compute the overall status for the tray icon
+SyncResult::Status trayOverallStatus()
+{
+ TrayOverallStatusResult result;
+ for (auto *folder : FolderMan::instance()->folders()) {
+ result.addResult(folder);
+ }
+ if (result.overallStatus().status() == SyncResult::Undefined) {
+ return SyncResult::Offline;
+ }
+ return result.overallStatus().status();
+}
+
+TrayMenuController::TrayMenuController(QObject *parent)
+ : QObject(parent)
+ , _tray(new QSystemTrayIcon(this))
+{
+
+ connect(_tray, &QSystemTrayIcon::activated, this, &TrayMenuController::slotTrayClicked);
+
+ setupTrayContextMenu();
+
+ // init systray
+ slotComputeOverallSyncStatus();
+ _tray->show();
+
+ // Refactoring todo: we have a very nasty habit of connecting to globally available managers, etc inside constructors or similar.
+ // this should only happen when we are dealing with a formal dependency: eg a dep passed by injection and kept as member,
+ // or a dep that is instantiated inside the class (also with a member kept)
+ // in cases like this one, the external deps should be instantiated externally and connected externally. This is normally part
+ // of an app building routine. The global singletons have to go and this is an important step to achieving that.
+ FolderMan *folderMan = FolderMan::instance();
+ connect(folderMan, &FolderMan::folderSyncStateChange, this, &TrayMenuController::slotSyncStateChange);
+}
+
+TrayMenuController::~TrayMenuController()
+{
+}
+
+void TrayMenuController::slotTrayClicked(QSystemTrayIcon::ActivationReason reason)
+{
+ // Left click
+ if (reason == QSystemTrayIcon::Trigger) {
+ // this covers left click - on mac it shows the menu so we don't want to do anything
+ // more. on windows (and linux, presumably, given the original code) we just show the
+ // main window on left click.
+ if (!Utility::isMac())
+ ocApp()->ensureVisible();
+ }
+}
+
+void TrayMenuController::slotSyncStateChange(Folder *folder)
+{
+ slotComputeOverallSyncStatus();
+
+ if (!folder) {
+ return; // Valid, just a general GUI redraw was needed.
+ }
+
+ auto result = folder->syncResult();
+
+ qCInfo(lcApplication) << "Sync state changed for folder " << folder->remoteUrl().toString() << ": " << Utility::enumToDisplayName(result.status());
+}
+
+void TrayMenuController::slotTrayMessageIfServerUnsupported(Account *account)
+{
+ if (account->serverSupportLevel() != Account::ServerSupportLevel::Supported) {
+ slotShowTrayMessage(tr("Unsupported Server Version"),
+ tr("The server on account %1 runs an unsupported version %2. "
+ "Using this client with unsupported server versions is untested and "
+ "potentially dangerous. Proceed at your own risk.")
+ .arg(account->displayNameWithHost(), account->capabilities().status().versionString()));
+ }
+}
+
+QIcon TrayMenuController::getTrayStatusIcon(const SyncResult::Status &status) const
+{
+ auto contextMenuVisible = _tray->contextMenu() && _tray->contextMenu()->isVisible();
+ return Theme::instance()->themeTrayIcon(SyncResult{status}, contextMenuVisible);
+}
+
+void TrayMenuController::slotComputeOverallSyncStatus()
+{
+ auto status = trayOverallStatus();
+ const QIcon statusIcon = getTrayStatusIcon(status);
+ _tray->setIcon(statusIcon);
+}
+
+void TrayMenuController::setupTrayContextMenu()
+{
+ // using the main window as parent for memory management
+ // todo: review this as for some reason I remember there is some other way it's supposed to be done
+ auto menu = new QMenu(ocApp()->mainWindow());
+ menu->setTitle(Theme::instance()->appNameGUI());
+
+ _tray->setContextMenu(menu);
+
+ auto app = ocApp();
+ // Populate the context menu now.
+ menu->addAction(Theme::instance()->applicationIcon(), tr("Show %1").arg(Theme::instance()->appNameGUI()), app, &Application::ensureVisible);
+ menu->addSeparator();
+
+ if (ocApp()->debugMode()) {
+ auto *debugMenu = menu->addMenu(QStringLiteral("Debug actions"));
+ debugMenu->addAction(QStringLiteral("Crash if asserts enabled - OC_ENSURE"), this, [] {
+ if (OC_ENSURE(false)) {
+ Q_UNREACHABLE();
+ }
+ });
+ debugMenu->addAction(QStringLiteral("Crash if asserts enabled - Q_ASSERT"), this, [] { Q_ASSERT(false); });
+ debugMenu->addAction(QStringLiteral("Crash now - Utility::crash()"), this, [] { Utility::crash(); });
+ debugMenu->addAction(QStringLiteral("Crash now - OC_ENFORCE()"), this, [] { OC_ENFORCE(false); });
+ debugMenu->addAction(QStringLiteral("Crash now - qFatal"), this, [] { qFatal("la Qt fatale"); });
+ debugMenu->addAction(QStringLiteral("Restart now"), this, [] { RestartManager::requestRestart(); });
+ debugMenu->addSeparator();
+ auto captivePortalCheckbox = debugMenu->addAction(QStringLiteral("Behind Captive Portal"));
+ captivePortalCheckbox->setCheckable(true);
+ captivePortalCheckbox->setChecked(NetworkInformation::instance()->isForcedCaptivePortal());
+ connect(captivePortalCheckbox, &QAction::triggered, [](bool checked) { NetworkInformation::instance()->setForcedCaptivePortal(checked); });
+
+ menu->addSeparator();
+ }
+
+ if (!Theme::instance()->helpUrl().isEmpty()) {
+ menu->addAction(tr("Help"), this, &TrayMenuController::requestShowHelp);
+ }
+
+ if (! Theme::instance()->about().isEmpty()) {
+ menu->addAction(tr("About %1").arg(Theme::instance()->appNameGUI()), this, &TrayMenuController::requestShowAbout);
+ }
+
+ menu->addAction(tr("Quit %1").arg(Theme::instance()->appNameGUI()), this, &QApplication::quit);
+}
+
+void TrayMenuController::slotShowTrayMessage(const QString &title, const QString &msg, const QIcon &icon)
+{
+ _tray->showMessage(title, msg, icon.isNull() ? Resources::getCoreIcon(QStringLiteral("states/information")) : icon);
+}
+
+void TrayMenuController::slotShowOptionalTrayMessage(const QString &title, const QString &msg, const QIcon &icon)
+{
+ ConfigFile cfg;
+ if (cfg.optionalDesktopNotifications()) {
+ slotShowTrayMessage(title, msg, icon);
+ }
+}
+
+void TrayMenuController::slotShowShareInBrowser(const QString &sharePath, const QString &localPath)
+{
+ QString file;
+ const auto folder = FolderMan::instance()->folderForPath(localPath, &file);
+ if (!folder) {
+ qCWarning(lcApplication) << "Could not open browser share page for" << localPath << "no responsible folder found";
+ return;
+ }
+
+ if (folder->accountState()->account()->capabilities().filesSharing().sharing_roles) {
+ fetchPrivateLinkUrl(folder->accountState()->account(), folder->webDavUrl(), sharePath, this, [](const QUrl &url) {
+ const auto queryUrl = Utility::concatUrlPath(url, QString(), {{QStringLiteral("details"), QStringLiteral("sharing")}});
+ Utility::openBrowser(queryUrl, nullptr);
+ });
+ }
+}
+
+
+} // end namespace
diff --git a/src/gui/owncloudgui.h b/src/gui/traymenucontroller.h
similarity index 57%
rename from src/gui/owncloudgui.h
rename to src/gui/traymenucontroller.h
index 9ab74354138..ae701280728 100644
--- a/src/gui/owncloudgui.h
+++ b/src/gui/traymenucontroller.h
@@ -15,70 +15,41 @@
#pragma once
#include "gui/owncloudguilib.h"
-#include "progressdispatcher.h"
#include "syncresult.h"
-#include
#include
#include
#include
-#define USE_NEW_MAIN_WINDOW
-
namespace OCC {
-namespace Wizard {
- class SetupWizardController;
-}
-class AccountState;
class Account;
class Folder;
-class AboutDialog;
-class SettingsDialog;
class ShareDialog;
-class Application;
-class LogBrowser;
/**
* @brief The ownCloudGui class
* @ingroup gui
*/
-class OWNCLOUDGUI_EXPORT ownCloudGui : public QObject
+class OWNCLOUDGUI_EXPORT TrayMenuController : public QObject
{
Q_OBJECT
public:
- explicit ownCloudGui(Application *parent = nullptr);
- ~ownCloudGui() override;
-
- /**
- * Raises our main Window to the front with the raiseWidget in focus.
- * If raiseWidget is a dialog and not visible yet, ->open will be called.
- * For normal widgets we call showNormal.
- */
- static void raise();
-
- SettingsDialog *settingsDialog() const;
-
- void runAccountWizard();
+ explicit TrayMenuController(QObject *parent);
+ ~TrayMenuController() override;
Q_SIGNALS:
- void requestSetUpSyncFoldersForAccount(AccountState *account, bool useVfs);
- void requestLoadSpacesOnly(AccountState *account);
+ void requestShowAbout();
+ void requestShowHelp();
public Q_SLOTS:
void setupTrayContextMenu();
void slotComputeOverallSyncStatus();
void slotShowTrayMessage(const QString &title, const QString &msg, const QIcon &icon = {});
void slotShowOptionalTrayMessage(const QString &title, const QString &msg, const QIcon &icon = {});
- void slotShowSettings();
- void slotShutdown();
void slotSyncStateChange(Folder *);
void slotTrayClicked(QSystemTrayIcon::ActivationReason reason);
- void slotToggleLogBrowser();
- void slotOpenSettingsDialog();
- void slotHelp();
- void slotAbout();
void slotTrayMessageIfServerUnsupported(Account *account);
/**
@@ -89,20 +60,12 @@ public Q_SLOTS:
* to the folder).
*/
void slotShowShareInBrowser(const QString &sharePath, const QString &localPath);
- void handleAccountSetupError(const QString &error);
private:
QIcon getTrayStatusIcon(const SyncResult::Status &status) const;
QSystemTrayIcon *_tray;
- SettingsDialog *_settingsDialog = nullptr;
QPointer _shareDialog;
-
- Application *_app;
-
- // keeping a pointer on those dialogs allows us to make sure they will be shown only once
- QPointer _wizardController;
- QPointer _aboutDialog;
};
} // namespace OCC
diff --git a/src/gui/updater/appimageupdateavailablewidget.cpp b/src/gui/updater/appimageupdateavailablewidget.cpp
index e71d51a8ed8..2b9457cc57a 100644
--- a/src/gui/updater/appimageupdateavailablewidget.cpp
+++ b/src/gui/updater/appimageupdateavailablewidget.cpp
@@ -24,7 +24,7 @@
namespace OCC {
AppImageUpdateAvailableWidget::AppImageUpdateAvailableWidget(const QVersionNumber ¤tVersion, const QVersionNumber &newVersion, QWidget *parent)
- : QWidget(parent)
+ : QDialog(parent)
, _ui(new Ui::AppImageUpdateAvailableWidgetUi)
{
_ui->setupUi(this);
@@ -47,13 +47,17 @@ AppImageUpdateAvailableWidget::AppImageUpdateAvailableWidget(const QVersionNumbe
// the minimum size of the info label (and a few other labels) depends on their contents
// we can't persuade the dialog to resize automatically to the recommended size in Qt Designer, so we do it manually
- resize(sizeHint());
+ // resize(sizeHint());
// also, we want to prevent users from reducing the widget size too much, i.e., widgets would be hidden partially
- setMinimumSize(sizeHint());
+ // setMinimumSize(sizeHint());
- connect(_ui->buttonBox->button(QDialogButtonBox::Ok), &QPushButton::clicked, this, &AppImageUpdateAvailableWidget::accepted);
- connect(_ui->buttonBox->button(QDialogButtonBox::Cancel), &QPushButton::clicked, this, &AppImageUpdateAvailableWidget::rejected);
- connect(_ui->skipButton, &QPushButton::clicked, this, &AppImageUpdateAvailableWidget::skipUpdateButtonClicked);
+ connect(_ui->skipButton, &QPushButton::clicked, this, &AppImageUpdateAvailableWidget::slotSkipUpdate);
+}
+
+void AppImageUpdateAvailableWidget::slotSkipUpdate()
+{
+ emit skipUpdateButtonClicked();
+ emit finished(QDialog::Rejected);
}
AppImageUpdateAvailableWidget::~AppImageUpdateAvailableWidget()
diff --git a/src/gui/updater/appimageupdateavailablewidget.h b/src/gui/updater/appimageupdateavailablewidget.h
index ead25cfb22d..771daea33b8 100644
--- a/src/gui/updater/appimageupdateavailablewidget.h
+++ b/src/gui/updater/appimageupdateavailablewidget.h
@@ -28,7 +28,7 @@ namespace OCC {
* @brief Dialog shown when updates for the running AppImage are available
* @ingroup gui
*/
-class AppImageUpdateAvailableWidget : public QWidget
+class AppImageUpdateAvailableWidget : public QDialog
{
Q_OBJECT
public:
@@ -42,11 +42,9 @@ class AppImageUpdateAvailableWidget : public QWidget
*/
void skipUpdateButtonClicked();
- /// Emitted when the cancel button is clicked.
- void rejected();
+private slots:
- /// Emitted when the ok button is clicked.
- void accepted();
+ void slotSkipUpdate();
private:
::Ui::AppImageUpdateAvailableWidgetUi *_ui;
diff --git a/src/gui/updater/appimageupdateavailablewidget.ui b/src/gui/updater/appimageupdateavailablewidget.ui
index d03470e8ec9..833f82cd8c3 100644
--- a/src/gui/updater/appimageupdateavailablewidget.ui
+++ b/src/gui/updater/appimageupdateavailablewidget.ui
@@ -1,7 +1,7 @@
AppImageUpdateAvailableWidgetUi
-
+
0
@@ -141,7 +141,40 @@
-
+
+
+ buttonBox
+ rejected()
+ AppImageUpdateAvailableWidgetUi
+ reject()
+
+
+ 367
+ 211
+
+
+ 277
+ 120
+
+
+
+
+ buttonBox
+ accepted()
+ AppImageUpdateAvailableWidgetUi
+ accept()
+
+
+ 367
+ 211
+
+
+ 277
+ 120
+
+
+
+
accept()
reject()
diff --git a/src/gui/updater/appimageupdater.cpp b/src/gui/updater/appimageupdater.cpp
index e95431e8825..6541d614ae7 100644
--- a/src/gui/updater/appimageupdater.cpp
+++ b/src/gui/updater/appimageupdater.cpp
@@ -21,7 +21,7 @@
#include "appimageupdater.h"
#include "common/version.h"
#include "libsync/configfile.h"
-#include "settingsdialog.h"
+#include "mainwindow/modalwrapperwidget.h"
#include "theme.h"
#include "updater_private.h"
@@ -154,16 +154,13 @@ void AppImageUpdater::versionInfoArrived(const UpdateInfo &info)
return;
}
- auto widget = new AppImageUpdateAvailableWidget(currentVersion, newVersion, ocApp()->gui()->settingsDialog());
+ auto widget = new AppImageUpdateAvailableWidget(currentVersion, newVersion, ocApp()->mainWindow());
- connect(widget, &AppImageUpdateAvailableWidget::skipUpdateButtonClicked, this, [newVersion, widget]() {
+ connect(widget, &AppImageUpdateAvailableWidget::skipUpdateButtonClicked, this, [newVersion]() {
qCInfo(lcUpdater) << "Update" << newVersion << "skipped by user";
setPreviouslySkippedVersion(newVersion);
- widget->deleteLater();
});
- connect(widget, &AppImageUpdateAvailableWidget::rejected, this, &QObject::deleteLater);
-
connect(widget, &AppImageUpdateAvailableWidget::accepted, this, [this, widget, appImageUpdaterShim]() {
// binding AppImageUpdaterShim shared pointer to finished callback makes sure the updater is cleaned up when it's done
connect(appImageUpdaterShim, &AppImageUpdaterShim::finished, this, [this](bool succeeded) {
@@ -178,11 +175,10 @@ void AppImageUpdater::versionInfoArrived(const UpdateInfo &info)
setDownloadState(Downloading);
appImageUpdaterShim->startUpdateInBackground();
- widget->deleteLater();
});
- ownCloudGui::raise();
- ocApp()->gui()->settingsDialog()->addModalWidget(widget);
+ ModalWrapperWidget *wrapper = new ModalWrapperWidget(widget, ocApp()->mainWindow());
+ ocApp()->showModalWidget(wrapper);
}
void AppImageUpdater::backgroundCheckForUpdate()
diff --git a/src/gui/updater/newversionavailablewidget.cpp b/src/gui/updater/newversionavailablewidget.cpp
index 042bbc68b9e..4719da97df8 100644
--- a/src/gui/updater/newversionavailablewidget.cpp
+++ b/src/gui/updater/newversionavailablewidget.cpp
@@ -22,7 +22,7 @@
namespace OCC {
NewVersionAvailableWidget::NewVersionAvailableWidget(QWidget *parent, const QString &statusMessage)
- : QWidget(parent)
+ : QDialog(parent)
, _ui(new ::Ui::Ui_NewVersionAvailableWidget)
{
_ui->setupUi(this);
@@ -32,11 +32,11 @@ NewVersionAvailableWidget::NewVersionAvailableWidget(QWidget *parent, const QStr
QPushButton *skipButton = _ui->buttonBox->addButton(tr("Skip this version"), QDialogButtonBox::ResetRole);
QPushButton *getUpdateButton = _ui->buttonBox->addButton(tr("Get update"), QDialogButtonBox::AcceptRole);
- QPushButton *rejectButton = _ui->buttonBox->addButton(tr("Skip this time"), QDialogButtonBox::AcceptRole);
+ QPushButton *rejectButton = _ui->buttonBox->addButton(tr("Skip this time"), QDialogButtonBox::RejectRole);
connect(skipButton, &QAbstractButton::clicked, this, &NewVersionAvailableWidget::skipVersion);
- connect(rejectButton, &QAbstractButton::clicked, this, &NewVersionAvailableWidget::notNow);
- connect(getUpdateButton, &QAbstractButton::clicked, this, &NewVersionAvailableWidget::getUpdate);
+ connect(rejectButton, &QAbstractButton::clicked, this, &QDialog::reject);
+ connect(getUpdateButton, &QAbstractButton::clicked, this, &QDialog::accept);
}
NewVersionAvailableWidget::~NewVersionAvailableWidget()
@@ -47,10 +47,10 @@ NewVersionAvailableWidget::~NewVersionAvailableWidget()
void NewVersionAvailableWidget::skipVersion()
{
Q_EMIT versionSkipped();
- Q_EMIT finished();
+ Q_EMIT finished(QDialog::Rejected);
}
-void NewVersionAvailableWidget::notNow()
+/*void NewVersionAvailableWidget::notNow()
{
Q_EMIT noUpdateNow();
Q_EMIT finished();
@@ -60,6 +60,6 @@ void NewVersionAvailableWidget::getUpdate()
{
Q_EMIT updateNow();
Q_EMIT finished();
-}
+}*/
} // OCC namespace
diff --git a/src/gui/updater/newversionavailablewidget.h b/src/gui/updater/newversionavailablewidget.h
index 81f30ea0026..a5ef3e88048 100644
--- a/src/gui/updater/newversionavailablewidget.h
+++ b/src/gui/updater/newversionavailablewidget.h
@@ -14,8 +14,8 @@
#pragma once
+#include
#include
-#include
namespace Ui {
class Ui_NewVersionAvailableWidget;
@@ -23,7 +23,7 @@ class Ui_NewVersionAvailableWidget;
namespace OCC {
-class NewVersionAvailableWidget : public QWidget
+class NewVersionAvailableWidget : public QDialog
{
Q_OBJECT
@@ -33,14 +33,9 @@ class NewVersionAvailableWidget : public QWidget
private Q_SLOTS:
void skipVersion();
- void notNow();
- void getUpdate();
Q_SIGNALS:
void versionSkipped();
- void noUpdateNow();
- void updateNow();
- void finished();
private:
::Ui::Ui_NewVersionAvailableWidget *_ui;
diff --git a/src/gui/updater/newversionavailablewidget.ui b/src/gui/updater/newversionavailablewidget.ui
index 6825884da11..8599425c36e 100644
--- a/src/gui/updater/newversionavailablewidget.ui
+++ b/src/gui/updater/newversionavailablewidget.ui
@@ -1,7 +1,7 @@
Ui::NewVersionAvailableWidget
-
+
0
@@ -14,7 +14,7 @@
-
- Qt::Vertical
+ Qt::Orientation::Vertical
@@ -53,7 +53,7 @@
true
- Qt::AlignCenter
+ Qt::AlignmentFlag::AlignCenter
@@ -62,14 +62,14 @@
-
- Qt::AlignCenter
+ Qt::AlignmentFlag::AlignCenter
-
- Qt::Vertical
+ Qt::Orientation::Vertical
@@ -82,12 +82,45 @@
-
- QDialogButtonBox::NoButton
+ QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Close|QDialogButtonBox::StandardButton::Ok
-
+
+
+ buttonBox
+ accepted()
+ Ui::NewVersionAvailableWidget
+ accept()
+
+
+ 199
+ 279
+
+
+ 199
+ 149
+
+
+
+
+ buttonBox
+ rejected()
+ Ui::NewVersionAvailableWidget
+ reject()
+
+
+ 199
+ 279
+
+
+ 199
+ 149
+
+
+
+
diff --git a/src/gui/updater/ocupdater.cpp b/src/gui/updater/ocupdater.cpp
index a2979a098a9..fa1c2335f0c 100644
--- a/src/gui/updater/ocupdater.cpp
+++ b/src/gui/updater/ocupdater.cpp
@@ -18,9 +18,10 @@
#include "common/version.h"
#include "config/appconfig.h"
#include "configfile.h"
+#include "mainwindow/modalwrapperwidget.h"
#include "theme.h"
-#include "settingsdialog.h"
+
#include "updatedownloadedwidget.h"
#include "updater/newversionavailablewidget.h"
#include "updater/ocupdater.h"
@@ -48,16 +49,16 @@ UpdaterScheduler::UpdaterScheduler(Application *app, QObject *parent)
// Note: the sparkle-updater is not an OCUpdater
if (auto *updater = qobject_cast(Updater::instance())) {
connect(updater, &OCUpdater::updateAvailableThroughSystem, app,
- [app, updater]() { app->gui()->slotShowTrayMessage(tr("Update available"), updater->statusString()); });
+ [app, updater]() { app->tray()->slotShowTrayMessage(tr("Update available"), updater->statusString()); });
connect(updater, &OCUpdater::updateDownloaded, this, [app, updater, this]() {
// prevent dialog from being displayed twice (rather unlikely, but it won't hurt)
if (_updateDownloadedWidget == nullptr) {
- _updateDownloadedWidget = new UpdateDownloadedWidget(app->gui()->settingsDialog(), updater->statusString());
- ocApp()->gui()->settingsDialog()->addModalWidget(_updateDownloadedWidget);
+ _updateDownloadedWidget = new UpdateDownloadedWidget(app->mainWindow(), updater->statusString());
+ ModalWrapperWidget *wrapper = new ModalWrapperWidget(_updateDownloadedWidget, app->mainWindow());
+ ocApp()->showModalWidget(wrapper);
connect(_updateDownloadedWidget, &UpdateDownloadedWidget::accepted, this, []() { Updater::instance()->applyUpdateAndRestart(); });
- connect(_updateDownloadedWidget, &UpdateDownloadedWidget::finished, this, [this]() { delete _updateDownloadedWidget.data(); });
}
});
@@ -376,13 +377,13 @@ void WindowsUpdater::showNewVersionAvailableWidget(const UpdateInfo &info)
"%2 is available for download. The installed version is %3.
")
.arg(Utility::escape(Theme::instance()->appNameGUI()),
Utility::escape(info.versionString()), Utility::escape(Version::versionWithBuildNumber().toString()));
- auto *widget = new NewVersionAvailableWidget(ocApp()->gui()->settingsDialog(), txt);
+ auto *widget = new NewVersionAvailableWidget(ocApp()->mainWindow(), txt);
connect(widget, &NewVersionAvailableWidget::versionSkipped, this, &WindowsUpdater::slotSetPreviouslySkippedVersion);
- connect(widget, &NewVersionAvailableWidget::updateNow, this, &WindowsUpdater::slotOpenUpdateUrl);
- connect(widget, &NewVersionAvailableWidget::finished, this, [widget]() { delete widget; });
+ connect(widget, &NewVersionAvailableWidget::accepted, this, &WindowsUpdater::slotOpenUpdateUrl);
- ocApp()->gui()->settingsDialog()->addModalWidget(widget);
+ ModalWrapperWidget *wrapper = new ModalWrapperWidget(widget, ocApp()->mainWindow());
+ ocApp()->showModalWidget(wrapper);
}
void WindowsUpdater::showUpdateErrorDialog(const QString &targetVersion)
diff --git a/src/gui/updater/updatedownloadedwidget.cpp b/src/gui/updater/updatedownloadedwidget.cpp
index b69802dd537..b77aa31b774 100644
--- a/src/gui/updater/updatedownloadedwidget.cpp
+++ b/src/gui/updater/updatedownloadedwidget.cpp
@@ -22,7 +22,7 @@
namespace OCC {
UpdateDownloadedWidget::UpdateDownloadedWidget(QWidget *parent, const QString &statusMessage)
- : QWidget(parent)
+ : QDialog(parent)
, _ui(new ::Ui::UpdateDownloadedWidget)
{
_ui->setupUi(this);
@@ -32,9 +32,6 @@ UpdateDownloadedWidget::UpdateDownloadedWidget(QWidget *parent, const QString &s
_ui->descriptionLabel->setText(statusMessage);
- connect(_ui->buttonBox, &QDialogButtonBox::rejected, this, &UpdateDownloadedWidget::reject);
- connect(_ui->buttonBox, &QDialogButtonBox::accepted, this, &UpdateDownloadedWidget::accept);
-
const auto noButton = _ui->buttonBox->button(QDialogButtonBox::No);
const auto yesButton = _ui->buttonBox->button(QDialogButtonBox::Yes);
@@ -49,6 +46,7 @@ UpdateDownloadedWidget::~UpdateDownloadedWidget()
delete _ui;
}
+/*
void UpdateDownloadedWidget::accept()
{
Q_EMIT accepted();
@@ -59,4 +57,5 @@ void UpdateDownloadedWidget::reject()
{
Q_EMIT finished();
}
+*/
} // OCC namespace
diff --git a/src/gui/updater/updatedownloadedwidget.h b/src/gui/updater/updatedownloadedwidget.h
index c45e70d17ab..ccb6773390f 100644
--- a/src/gui/updater/updatedownloadedwidget.h
+++ b/src/gui/updater/updatedownloadedwidget.h
@@ -14,8 +14,7 @@
#pragma once
-#include
-#include
+#include
namespace Ui {
class UpdateDownloadedWidget;
@@ -23,7 +22,7 @@ class UpdateDownloadedWidget;
namespace OCC {
-class UpdateDownloadedWidget : public QWidget
+class UpdateDownloadedWidget : public QDialog
{
Q_OBJECT
@@ -31,14 +30,6 @@ class UpdateDownloadedWidget : public QWidget
explicit UpdateDownloadedWidget(QWidget *parent, const QString &statusMessage);
~UpdateDownloadedWidget();
-public Q_SLOTS:
- void accept();
- void reject();
-
-Q_SIGNALS:
- void accepted();
- void finished();
-
private:
::Ui::UpdateDownloadedWidget *_ui;
};
diff --git a/src/gui/updater/updatedownloadedwidget.ui b/src/gui/updater/updatedownloadedwidget.ui
index cd77a786a76..53392872539 100644
--- a/src/gui/updater/updatedownloadedwidget.ui
+++ b/src/gui/updater/updatedownloadedwidget.ui
@@ -1,7 +1,7 @@
UpdateDownloadedWidget
-
+
0
@@ -20,7 +20,7 @@
-
- Qt::Vertical
+ Qt::Orientation::Vertical
@@ -56,7 +56,7 @@
icon (placeholder)
- Qt::AlignCenter
+ Qt::AlignmentFlag::AlignCenter
@@ -74,7 +74,7 @@
<html><head/><body><p><span style=" font-size:11pt; font-weight:700;">Restart required</span></p></body></html>
- Qt::AlignHCenter|Qt::AlignTop
+ Qt::AlignmentFlag::AlignHCenter|Qt::AlignmentFlag::AlignTop
@@ -96,7 +96,7 @@
Update soandso has been downloaded. Restart now to perform the update?
- Qt::AlignCenter
+ Qt::AlignmentFlag::AlignCenter
true
@@ -106,7 +106,7 @@
-
- Qt::Vertical
+ Qt::Orientation::Vertical
@@ -119,12 +119,45 @@
-
- QDialogButtonBox::No|QDialogButtonBox::Yes
+ QDialogButtonBox::StandardButton::No|QDialogButtonBox::StandardButton::Yes
-
+
+
+ buttonBox
+ accepted()
+ UpdateDownloadedWidget
+ accept()
+
+
+ 206
+ 393
+
+
+ 206
+ 206
+
+
+
+
+ buttonBox
+ rejected()
+ UpdateDownloadedWidget
+ reject()
+
+
+ 206
+ 393
+
+
+ 206
+ 206
+
+
+
+
diff --git a/src/libsync/account.cpp b/src/libsync/account.cpp
index bfd9b5a9bc3..b1653bacefd 100644
--- a/src/libsync/account.cpp
+++ b/src/libsync/account.cpp
@@ -340,7 +340,7 @@ void Account::setCapabilities(const Capabilities &caps)
caps.status().legacyVersion != _capabilities.status().legacyVersion || caps.status().productversion != _capabilities.status().productversion;
_capabilities = caps;
if (versionChanged) {
- Q_EMIT serverVersionChanged();
+ Q_EMIT serverVersionChanged(this);
}
}
diff --git a/src/libsync/account.h b/src/libsync/account.h
index c9aa353a5e6..e7f1bea1ac5 100644
--- a/src/libsync/account.h
+++ b/src/libsync/account.h
@@ -232,7 +232,7 @@ public Q_SLOTS:
// todo: #15
void wantsAccountSaved(Account *acc);
- void serverVersionChanged();
+ void serverVersionChanged(Account *account);
void avatarChanged();
void displayNameChanged();
diff --git a/test/gui/shared/scripts/names.py b/test/gui/shared/scripts/names.py
index 2045c1ddebd..d9aadd691d1 100644
--- a/test/gui/shared/scripts/names.py
+++ b/test/gui/shared/scripts/names.py
@@ -84,3 +84,4 @@
scrollArea_groupBox_QGroupBox = {"container": mainWindow_scrollArea_QScrollArea, "name": "groupBox", "type": "QGroupBox", "visible": 1}
mainWindow_qt_tabwidget_stackedwidget_QStackedWidget = {"name": "qt_tabwidget_stackedwidget", "type": "QStackedWidget", "visible": 1, "window": mainWindow_OCC_MainWindow}
confirmRemoveAccountDialog_QMessageBox = {"name": "confirmRemoveAccountDialog", "type": "QMessageBox", "visible": 1}
+mainWindow_manageAccountMenu_QMenu = {"name": "manageAccountMenu", "type": "QMenu", "visible": 1, "window": mainWindow_OCC_MainWindow}
diff --git a/test/gui/shared/scripts/pageObjects/AccountSetting.py b/test/gui/shared/scripts/pageObjects/AccountSetting.py
index 546e999172d..dbbb759504b 100644
--- a/test/gui/shared/scripts/pageObjects/AccountSetting.py
+++ b/test/gui/shared/scripts/pageObjects/AccountSetting.py
@@ -10,9 +10,8 @@ class AccountSetting:
"visible": 1,
}
ACCOUNT_MENU = {
- "container": names.mainWindow_QMenu,
+ "container": names.mainWindow_manageAccountMenu_QMenu,
"type": "QAction",
- "unnamed": 1,
"visible": True,
}
CONFIRM_REMOVE_CONNECTION_BUTTON = {
@@ -47,26 +46,26 @@ class AccountSetting:
CONFIRMATION_YES_BUTTON = {"type": "QPushButton", "visible": 1}
@staticmethod
- def account_action(action):
+ def account_action(action, name):
squish.clickButton(squish.waitForObject(AccountSetting.MANAGE_ACCOUNT_BUTTON))
action_selector = AccountSetting.ACCOUNT_MENU.copy()
- action_selector.update({"text": action})
+ action_selector.update({"text": action, "name": name})
squish.activateItem(squish.waitForObject(action_selector))
@staticmethod
def remove_account_connection():
- AccountSetting.account_action("Remove")
+ AccountSetting.account_action("Remove", "removeAction")
squish.clickButton(
squish.waitForObject(AccountSetting.CONFIRM_REMOVE_CONNECTION_BUTTON)
)
@staticmethod
def logout():
- AccountSetting.account_action("Log out")
+ AccountSetting.account_action("Log out", "logInOutAction")
@staticmethod
def login():
- AccountSetting.account_action("Log in")
+ AccountSetting.account_action("Log in", "logInOutAction")
@staticmethod
def get_account_connection_label():