From c1e9a0714f5f54ab3d4c8eab2f56fb348fac1ea5 Mon Sep 17 00:00:00 2001 From: Modspike Date: Wed, 17 Jun 2026 18:20:29 +0200 Subject: [PATCH 01/24] first pass splitting accountView logic to controller the basics are done here, and the account view still works in the new gui after the changes. --- src/gui/accountsgui/accountsguicontroller.cpp | 14 +- src/gui/accountsgui/accountview.cpp | 356 +++--------------- src/gui/accountsgui/accountview.h | 59 +-- src/gui/accountsgui/accountviewcontroller.cpp | 266 ++++++++++++- src/gui/accountsgui/accountviewcontroller.h | 32 +- src/gui/settingsdialog.cpp | 4 +- 6 files changed, 371 insertions(+), 360 deletions(-) diff --git a/src/gui/accountsgui/accountsguicontroller.cpp b/src/gui/accountsgui/accountsguicontroller.cpp index fb1bc93ef81..61715229e99 100644 --- a/src/gui/accountsgui/accountsguicontroller.cpp +++ b/src/gui/accountsgui/accountsguicontroller.cpp @@ -21,6 +21,7 @@ #include "accountmanager.h" #include "accountplaceholderwidget.h" +#include "accountsgui/accountviewcontroller.h" #include "accountstate.h" #include "accountview.h" #include "creds/abstractcredentials.h" @@ -63,22 +64,21 @@ 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); + 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())); diff --git a/src/gui/accountsgui/accountview.cpp b/src/gui/accountsgui/accountview.cpp index 867cb9fe411..a6699443956 100644 --- a/src/gui/accountsgui/accountview.cpp +++ b/src/gui/accountsgui/accountview.cpp @@ -14,359 +14,99 @@ #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; -} - 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()); + _ui->setupUi(this); + _ui->connectionStatusLabel->clear(); - buildManageAccountMenu(); - - 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; -} - -void AccountView::accountSettingUpChanged(bool settingUp) -{ - if (settingUp) { - ui->spinner->startAnimation(); - ui->stackedWidget->setCurrentWidget(ui->loadingPage); - } else { - ui->spinner->stopAnimation(); - ui->stackedWidget->setCurrentWidget(ui->accountFoldersView); - } + delete _ui; } -void AccountView::slotAddFolder() +void AccountView::setAccountMenu(QMenu *menu) { - if (!_accountState || !_accountState->account()) { - return; + if (QMenu *oldMenu = _ui->manageAccountButton->menu()) { + _ui->manageAccountButton->setMenu(nullptr); + delete oldMenu; } - - 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); + _ui->manageAccountButton->setMenu(menu); } -void AccountView::slotFolderWizardAccepted() +void AccountView::setTopStackWidget(QWidget *widget) { - if (!_accountState) { - return; - } - - FolderWizard *folderWizard = qobject_cast(sender()); - if (!folderWizard) - return; + // should not contain this widget already + Q_ASSERT(_ui->stackedWidget->indexOf(widget) < 0); - 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->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; + _ui->spinner->stopAnimation(); + _ui->stackedWidget->setCurrentWidget(_ui->accountFoldersView); } - - if (!icon.isNull()) { - ui->warningLabel->setPixmap(icon.pixmap(ui->warningLabel->size())); - } - ui->warningLabel->setVisible(statusIcon != StatusIcon::None); } - -void AccountView::buildManageAccountMenu() +void AccountView::slotAddFolder() { - 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); + // temp until we get rid of the SettingsDialog + emit addFolderClicked(); } -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(); + _ui->accountStatus->setVisible(!message.isEmpty()); - Q_ASSERT(_accountState && _accountState->account()); - -#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..2a3042e1011 100644 --- a/src/gui/accountsgui/accountview.h +++ b/src/gui/accountsgui/accountview.h @@ -40,8 +40,7 @@ class FolderMan; class Account; class AccountState; -// class FolderStatusModel; -class FolderStatusDelegate; +class AccountFoldersView; /** * @brief The AccountView class @@ -52,57 +51,35 @@ 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; + void setAccountMenu(QMenu *menu); + 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); + // 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 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 addFolderClicked(); 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..837c5477541 100644 --- a/src/gui/accountsgui/accountviewcontroller.cpp +++ b/src/gui/accountsgui/accountviewcontroller.cpp @@ -14,14 +14,278 @@ #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; + + AccountFoldersController *foldersController = new AccountFoldersController(_accountState, _view->foldersView(), this); + connect(foldersController, &AccountFoldersController::requestAddFolder, this, &AccountViewController::onAddFolder); + 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; + + QMenu *menu = new QMenu(_view); + menu->setAccessibleName(tr("Account options menu")); + + auto *logInOutAction = menu->addAction(tr("Log in"), this, &AccountViewController::onToggleSignInState); + + 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, &AccountViewController::onOpenAccountInBrowser); + menu->addAction(tr("Remove"), this, &AccountViewController::onDeleteAccount); + + _view->setAccountMenu(menu); +} + +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::lookupIcon(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; + } + + _view->setConnectionLabel(text, lookupIcon(icon), errors); +} + +void AccountViewController::onAddFolder() +{ + 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(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, _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..ba6f5cf1f56 100644 --- a/src/gui/accountsgui/accountviewcontroller.h +++ b/src/gui/accountsgui/accountviewcontroller.h @@ -14,22 +14,50 @@ #pragma once +#include "accountstate.h" #include +#include 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); 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 onAddFolder(); + void onFolderWizardAccepted(); + + void finishAccountModalWidget(AccountModalWidget *widget); private: - AccountView *_view = nullptr; + QPointer _view = nullptr; + QPointer _accountState; + + void buildManageAccountMenu(); + QIcon lookupIcon(StatusIcon status); }; } diff --git a/src/gui/settingsdialog.cpp b/src/gui/settingsdialog.cpp index 448b2045e34..a6d17057906 100644 --- a/src/gui/settingsdialog.cpp +++ b/src/gui/settingsdialog.cpp @@ -13,6 +13,7 @@ */ #include "settingsdialog.h" +#include "accountsgui/accountviewcontroller.h" #include "ui_settingsdialog.h" #include "accountmanager.h" @@ -167,7 +168,8 @@ void SettingsDialog::onAccountAdded(AccountState *state) // 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); + auto accountView = new AccountView(this); + auto accountViewController = new AccountViewController(accountView, state, this); _ui->stack->addWidget(accountView); _viewForAccount.insert(state->account()->uuid(), accountView); From 3822d59e747556752566f6a227012493152cb9dd Mon Sep 17 00:00:00 2001 From: Modspike Date: Thu, 18 Jun 2026 11:13:23 +0200 Subject: [PATCH 02/24] remove uses of SettingsDialog deleting the class to come --- .../FoldersGui/accountfolderscontroller.cpp | 11 +-- src/gui/accountstate.cpp | 6 +- src/gui/application.cpp | 55 ++++------- src/gui/application.h | 7 +- src/gui/folder.cpp | 6 +- src/gui/folderwizard/folderwizard.cpp | 4 +- src/gui/generalsettings.cpp | 6 +- src/gui/guiutility.cpp | 1 - src/gui/main.cpp | 8 +- src/gui/mainwindow/mainwindowcontroller.h | 3 +- src/gui/mainwindow/settingsview.cpp | 6 +- src/gui/networkadapters/resolveurladapter.cpp | 1 - .../newaccountwizard/oauthpagecontroller.cpp | 8 +- src/gui/owncloudgui.cpp | 92 ++----------------- src/gui/owncloudgui.h | 10 +- src/gui/settingsdialog.cpp | 7 +- src/gui/settingsdialog.h | 2 +- 17 files changed, 61 insertions(+), 172 deletions(-) diff --git a/src/gui/FoldersGui/accountfolderscontroller.cpp b/src/gui/FoldersGui/accountfolderscontroller.cpp index 893ba230caf..d7e934d2c87 100644 --- a/src/gui/FoldersGui/accountfolderscontroller.cpp +++ b/src/gui/FoldersGui/accountfolderscontroller.cpp @@ -20,9 +20,8 @@ #include "commonstrings.h" #include "configfile.h" #include "foldermodelcontroller.h" -#include "folderwizard.h" +#include "mainwindow/mainwindow.h" #include "selectivesyncwidget.h" -#include "settingsdialog.h" #include "guiutility.h" #include "networkjobs.h" @@ -196,7 +195,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 +277,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 +299,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 +329,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/accountstate.cpp b/src/gui/accountstate.cpp index a865caf8830..6ee99ac894c 100644 --- a/src/gui/accountstate.cpp +++ b/src/gui/accountstate.cpp @@ -20,7 +20,7 @@ #include "libsync/creds/abstractcredentials.h" -#include "gui/settingsdialog.h" +#include "gui/mainwindow/mainwindow.h" #include "gui/tlserrordialog.h" #include "socketapi/socketapi.h" @@ -101,7 +101,7 @@ 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(); msgBox->open(); @@ -353,7 +353,7 @@ 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()); + TlsErrorDialog tlsDlg(filteredErrors, _account->url().host(), ocApp()->mainWindow()); ownCloudGui::raise(); int res = tlsDlg.exec(); if (res == TlsErrorDialog::Accepted) { diff --git a/src/gui/application.cpp b/src/gui/application.cpp index 5681408d9c2..01a2f4fe377 100644 --- a/src/gui/application.cpp +++ b/src/gui/application.cpp @@ -26,7 +26,6 @@ #include "folderman.h" #include "mainwindow/mainwindow.h" #include "mainwindow/mainwindowcontroller.h" -#include "settingsdialog.h" #include "socketapi/socketapi.h" #include "theme.h" @@ -85,32 +84,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); @@ -135,16 +112,7 @@ Application::~Application() } } -void Application::lastAccountStateRemoved() 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 -} - +// move to owncloudgui or wherever we end up consolidating the tray meny/socketApi management void Application::slotAccountStateAdded(AccountState *accountState) const { if (!accountState || !accountState->account()) @@ -155,6 +123,8 @@ void Application::slotAccountStateAdded(AccountState *accountState) const connect(accountState, &AccountState::stateChanged, _gui.data(), &ownCloudGui::slotComputeOverallSyncStatus); connect(account, &Account::serverVersionChanged, _gui.data(), [account, this] { _gui->slotTrayMessageIfServerUnsupported(account); }); + // todo dc-310 - 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) // 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 +132,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(); @@ -203,6 +169,19 @@ bool Application::debugMode() return _debugMode; } +void Application::buildAppGuis() +{ + Q_ASSERT(!_mainWin && !_gui); + _mainWin = new MainWindow(); + _mainController = new MainWindowController(_mainWin, this); + + // Setting up the gui class will allow tray notifications for the + // setup that follows, like folder setup + _gui = new ownCloudGui(this); + connect(_gui, &ownCloudGui::requestAboutDialog, _mainController, &MainWindowController::onAbout); + connect(FolderMan::instance()->socketApi(), &SocketApi::shareCommandReceived, _gui.data(), &ownCloudGui::slotShowShareInBrowser); +} + std::unique_ptr Application::createInstance(Platform *platform, const QString &displayLanguage, bool debugMode) { Q_ASSERT(!_instance); diff --git a/src/gui/application.h b/src/gui/application.h index 29772b6668d..8a4fba0cccb 100644 --- a/src/gui/application.h +++ b/src/gui/application.h @@ -52,9 +52,13 @@ class OWNCLOUDGUI_EXPORT Application : public QObject 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 actios + void buildAppGuis(); + ownCloudGui *gui() const; - // try to get rid of this before the end. currently needed to raise the main window via owncloudgui + // this is needed primarily to parent message boxes MainWindow *mainWindow() { return _mainWin; } QString displayLanguage() const; @@ -75,7 +79,6 @@ 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); diff --git a/src/gui/folder.cpp b/src/gui/folder.cpp index 269659bd33d..4c19f954976 100644 --- a/src/gui/folder.cpp +++ b/src/gui/folder.cpp @@ -28,12 +28,12 @@ #include "configfile.h" #include "filesystem.h" #include "folderman.h" -#include "foldermanagement/foldermanagementutils.h" #include "folderwatcher.h" #include "libsync/graphapi/spacesmanager.h" #include "localdiscoverytracker.h" +// it is used directly as parent for message box. ignore clangd here +#include "mainwindow/mainwindow.h" #include "scheduling/syncscheduler.h" -#include "settingsdialog.h" #include "socketapi/socketapi.h" #include "syncengine.h" #include "syncresult.h" @@ -1044,7 +1044,7 @@ void Folder::slotWatcherUnreliable(const QString &message) "\n" "%1") .arg(message), - {}, ocApp()->gui()->settingsDialog()); + {}, ocApp()->mainWindow()); msgBox->setAttribute(Qt::WA_DeleteOnClose); ownCloudGui::raise(); diff --git a/src/gui/folderwizard/folderwizard.cpp b/src/gui/folderwizard/folderwizard.cpp index 2dce6412dd5..cb8d905f641 100644 --- a/src/gui/folderwizard/folderwizard.cpp +++ b/src/gui/folderwizard/folderwizard.cpp @@ -24,7 +24,7 @@ #include "common/asserts.h" #include "common/vfs.h" #include "gui/application.h" -#include "gui/settingsdialog.h" +#include "gui/mainwindow/mainwindow.h" #include "theme.h" #include "gui/folderman.h" @@ -137,7 +137,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 index dbee5941949..b7c975b3092 100644 --- a/src/gui/generalsettings.cpp +++ b/src/gui/generalsettings.cpp @@ -15,11 +15,9 @@ #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/mainwindow/mainwindow.h" #include "gui/translations.h" #include "libsync/configfile.h" #include "libsync/theme.h" @@ -143,7 +141,7 @@ void GeneralSettings::slotToggleOptionalDesktopNotifications(bool enable) void GeneralSettings::slotIgnoreFilesEditor() { if (_ignoreEditor.isNull()) { - _ignoreEditor = new IgnoreListEditor(ocApp()->gui()->settingsDialog()); + _ignoreEditor = new IgnoreListEditor(ocApp()->mainWindow()); _ignoreEditor->setAttribute(Qt::WA_DeleteOnClose, true); ownCloudGui::raise(); _ignoreEditor->open(); 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/main.cpp b/src/gui/main.cpp index f82a7e91fc7..dfd9863f41a 100644 --- a/src/gui/main.cpp +++ b/src/gui/main.cpp @@ -441,6 +441,7 @@ int main(int argc, char **argv) // 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); + ocApp->buildAppGuis(); ocApp->updateAutoRun(firstRun); QObject::connect(platform.get(), &Platform::requestAttention, ocApp->gui(), &ownCloudGui::slotShowSettings); @@ -488,13 +489,6 @@ int main(int argc, char **argv) // 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); - } -#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/mainwindowcontroller.h b/src/gui/mainwindow/mainwindowcontroller.h index 7dc20c0a67d..4ac63f78ef0 100644 --- a/src/gui/mainwindow/mainwindowcontroller.h +++ b/src/gui/mainwindow/mainwindowcontroller.h @@ -29,6 +29,7 @@ class MainWindowController : public QObject // public for now void setup(); + void onAbout(); private: void buildMenuActions(); @@ -37,7 +38,7 @@ class MainWindowController : public QObject void onAddAccount(); void onSettings(); - void onAbout(); + void onQuit(); MainWindow *_window = nullptr; diff --git a/src/gui/mainwindow/settingsview.cpp b/src/gui/mainwindow/settingsview.cpp index ec2569bf264..fc32d4d7d5c 100644 --- a/src/gui/mainwindow/settingsview.cpp +++ b/src/gui/mainwindow/settingsview.cpp @@ -15,11 +15,9 @@ #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/mainwindow/mainwindow.h" #include "gui/translations.h" #include "libsync/configfile.h" #include "libsync/theme.h" @@ -141,7 +139,7 @@ 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(); _ignoreEditor->open(); diff --git a/src/gui/networkadapters/resolveurladapter.cpp b/src/gui/networkadapters/resolveurladapter.cpp index 49b1fe18d45..fb56523392c 100644 --- a/src/gui/networkadapters/resolveurladapter.cpp +++ b/src/gui/networkadapters/resolveurladapter.cpp @@ -18,7 +18,6 @@ #include "common/utility.h" #include "gui/application.h" #include "gui/owncloudgui.h" -#include "gui/settingsdialog.h" #include "gui/tlserrordialog.h" #include diff --git a/src/gui/newaccountwizard/oauthpagecontroller.cpp b/src/gui/newaccountwizard/oauthpagecontroller.cpp index 317092fb4a0..a3a5a573b1e 100644 --- a/src/gui/newaccountwizard/oauthpagecontroller.cpp +++ b/src/gui/newaccountwizard/oauthpagecontroller.cpp @@ -221,7 +221,13 @@ bool OAuthPageController::validate() void OAuthPageController::authUrlReady() { _authEndpoint = _oauth->authorisationLink().toString(QUrl::FullyEncoded); - Q_ASSERT(!_authEndpoint.isEmpty()); + + // I hit this when demo was down - browser showed "We're having trouble connecting to the login service. If the problem continues, please contact support." + // Q_ASSERT(!_authEndpoint.isEmpty()); + if (_authEndpoint.isEmpty()) { + handleError(tr("Unable to connect to the login service. If the problem continues, please contact support.")); + return; + } QFontMetrics metrics(_urlField->font()); QString elidedText = metrics.elidedText(_authEndpoint, Qt::ElideRight, _urlField->width()); diff --git a/src/gui/owncloudgui.cpp b/src/gui/owncloudgui.cpp index ecebf2f27cd..8e591c61edc 100644 --- a/src/gui/owncloudgui.cpp +++ b/src/gui/owncloudgui.cpp @@ -28,7 +28,6 @@ #include "logbrowser.h" #include "mainwindow/mainwindow.h" #include "progressdispatcher.h" -#include "settingsdialog.h" #include "newaccountwizard/newaccountbuilder.h" #include "newaccountwizard/newaccountmodel.h" @@ -66,12 +65,8 @@ SyncResult::Status trayOverallStatus() 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); @@ -92,25 +87,19 @@ ownCloudGui::ownCloudGui(Application *parent) ownCloudGui::~ownCloudGui() { - delete _settingsDialog; } -// This should rather be in application.... or rather in ConfigFile? +// todo dc-310 - finally figure out what this is trying to accomplish void ownCloudGui::slotOpenSettingsDialog() { // if account is set up, start the configuration wizard. if (!AccountManager::instance()->accounts().isEmpty()) { - if (QApplication::activeWindow() != _settingsDialog) { + if (QApplication::activeWindow() != ocApp()->mainWindow()) { slotShowSettings(); } else { // ????!!!!????????? - _settingsDialog->close(); + ocApp()->mainWindow()->close(); } - } else { -#ifndef USE_NEW_MAIN_WINDOW - qCInfo(lcApplication) << "No configured folders yet, starting setup wizard"; - runAccountWizard(); -#endif } } @@ -122,7 +111,7 @@ void ownCloudGui::slotTrayClicked(QSystemTrayIcon::ActivationReason reason) // 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()) { + if (ocApp()->mainWindow()->isVisible()) { raise(); } #else @@ -168,15 +157,10 @@ void ownCloudGui::slotComputeOverallSyncStatus() _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); + auto menu = new QMenu(ocApp()->mainWindow()); menu->setTitle(Theme::instance()->appNameGUI()); _tray->setContextMenu(menu); @@ -211,7 +195,7 @@ void ownCloudGui::setupTrayContextMenu() } if (! Theme::instance()->about().isEmpty()) { - menu->addAction(tr("About %1").arg(Theme::instance()->appNameGUI()), this, &ownCloudGui::slotAbout); + menu->addAction(tr("About %1").arg(Theme::instance()->appNameGUI()), this, &ownCloudGui::requestAboutDialog); } menu->addAction(tr("Quit %1").arg(Theme::instance()->appNameGUI()), _app, &QApplication::quit); @@ -230,59 +214,14 @@ void ownCloudGui::slotShowOptionalTrayMessage(const QString &title, const QStrin } } -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()); + auto logBrowser = new LogBrowser(ocApp()->mainWindow()); logBrowser->setAttribute(Qt::WA_DeleteOnClose); ownCloudGui::raise(); logBrowser->open(); @@ -293,17 +232,11 @@ void ownCloudGui::slotHelp() QDesktopServices::openUrl(QUrl(Theme::instance()->helpUrl())); } +// todo: dc-310 move this to main window 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(); @@ -344,14 +277,5 @@ void ownCloudGui::slotShowShareInBrowser(const QString &sharePath, const QString } } -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/owncloudgui.h b/src/gui/owncloudgui.h index 9ab74354138..6badf0c985b 100644 --- a/src/gui/owncloudgui.h +++ b/src/gui/owncloudgui.h @@ -58,13 +58,10 @@ class OWNCLOUDGUI_EXPORT ownCloudGui : public QObject */ static void raise(); - SettingsDialog *settingsDialog() const; - - void runAccountWizard(); - Q_SIGNALS: void requestSetUpSyncFoldersForAccount(AccountState *account, bool useVfs); void requestLoadSpacesOnly(AccountState *account); + void requestAboutDialog(); public Q_SLOTS: void setupTrayContextMenu(); @@ -72,13 +69,11 @@ public Q_SLOTS: 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,15 +84,14 @@ 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; + // dc-310 get rid of this member and just use ocApp() Application *_app; // keeping a pointer on those dialogs allows us to make sure they will be shown only once diff --git a/src/gui/settingsdialog.cpp b/src/gui/settingsdialog.cpp index a6d17057906..b00c68a6d86 100644 --- a/src/gui/settingsdialog.cpp +++ b/src/gui/settingsdialog.cpp @@ -121,7 +121,7 @@ SettingsDialog::SettingsDialog(ownCloudGui *gui, QWidget *parent) _generalSettings = new GeneralSettings; _ui->stack->addWidget(_generalSettings); - connect(_generalSettings, &GeneralSettings::showAbout, gui, &ownCloudGui::slotAbout); + // connect(_generalSettings, &GeneralSettings::showAbout, gui, &ownCloudGui::slotAbout); connect(_generalSettings, &GeneralSettings::moveToTrashChanged, FolderMan::instance(), &FolderMan::updateMoveToTrash); ConfigFile().restoreGeometry(this); @@ -296,11 +296,6 @@ Account *SettingsDialog::currentAccount() const return _currentAccount; } -void SettingsDialog::createNewAccount() -{ - ocApp()->gui()->runAccountWizard(); -} - void SettingsDialog::runFolderWizard(Account *account) { if (!account) diff --git a/src/gui/settingsdialog.h b/src/gui/settingsdialog.h index a06651b0945..7888c9f74e8 100644 --- a/src/gui/settingsdialog.h +++ b/src/gui/settingsdialog.h @@ -70,7 +70,7 @@ class SettingsDialog : public QMainWindow public Q_SLOTS: // this is a direct call from QML - void createNewAccount(); + // void createNewAccount(); void runFolderWizard(Account *account); From 185e75ea16376a313d703505bb39c2f8de68d391 Mon Sep 17 00:00:00 2001 From: Modspike Date: Thu, 18 Jun 2026 11:25:55 +0200 Subject: [PATCH 03/24] missed one update --- src/gui/creds/requestauthenticationcontroller.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/gui/creds/requestauthenticationcontroller.cpp b/src/gui/creds/requestauthenticationcontroller.cpp index 4d83c3f72f0..2c00d306940 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(); From b790bfb4db196c7084e720c8f8dcceb8ede33d6a Mon Sep 17 00:00:00 2001 From: Modspike Date: Thu, 18 Jun 2026 11:45:34 +0200 Subject: [PATCH 04/24] revert fix for dc-312 get it from master once merged. --- src/gui/newaccountwizard/oauthpagecontroller.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/gui/newaccountwizard/oauthpagecontroller.cpp b/src/gui/newaccountwizard/oauthpagecontroller.cpp index a3a5a573b1e..317092fb4a0 100644 --- a/src/gui/newaccountwizard/oauthpagecontroller.cpp +++ b/src/gui/newaccountwizard/oauthpagecontroller.cpp @@ -221,13 +221,7 @@ bool OAuthPageController::validate() void OAuthPageController::authUrlReady() { _authEndpoint = _oauth->authorisationLink().toString(QUrl::FullyEncoded); - - // I hit this when demo was down - browser showed "We're having trouble connecting to the login service. If the problem continues, please contact support." - // Q_ASSERT(!_authEndpoint.isEmpty()); - if (_authEndpoint.isEmpty()) { - handleError(tr("Unable to connect to the login service. If the problem continues, please contact support.")); - return; - } + Q_ASSERT(!_authEndpoint.isEmpty()); QFontMetrics metrics(_urlField->font()); QString elidedText = metrics.elidedText(_authEndpoint, Qt::ElideRight, _urlField->width()); From 242a3486e13c84c4aee1a727b7ad710a6c14ce70 Mon Sep 17 00:00:00 2001 From: Modspike Date: Thu, 18 Jun 2026 13:22:16 +0200 Subject: [PATCH 05/24] moving raise behavior to main window --- src/gui/accountsgui/accountsguicontroller.cpp | 5 +-- src/gui/accountstate.cpp | 4 +-- src/gui/application.cpp | 1 - src/gui/application.h | 1 + .../creds/requestauthenticationcontroller.cpp | 2 +- src/gui/folder.cpp | 2 +- src/gui/generalsettings.cpp | 2 +- src/gui/main.cpp | 8 ++--- src/gui/mainwindow/mainwindow.cpp | 24 +++++++++++++ src/gui/mainwindow/mainwindow.h | 5 ++- src/gui/mainwindow/mainwindowcontroller.cpp | 4 +++ src/gui/mainwindow/settingsview.cpp | 2 +- src/gui/networkadapters/resolveurladapter.cpp | 4 +-- .../newaccountwizardcontroller.cpp | 7 ++-- src/gui/owncloudgui.cpp | 34 ++----------------- src/gui/owncloudgui.h | 7 ---- src/gui/settingsdialog.cpp | 4 +-- 17 files changed, 57 insertions(+), 59 deletions(-) diff --git a/src/gui/accountsgui/accountsguicontroller.cpp b/src/gui/accountsgui/accountsguicontroller.cpp index 61715229e99..8f2cb1328a8 100644 --- a/src/gui/accountsgui/accountsguicontroller.cpp +++ b/src/gui/accountsgui/accountsguicontroller.cpp @@ -24,6 +24,7 @@ #include "accountsgui/accountviewcontroller.h" #include "accountstate.h" #include "accountview.h" +#include "application.h" #include "creds/abstractcredentials.h" #include "folderman.h" #include "mainwindow/mainwindow.h" @@ -153,7 +154,7 @@ void AccountsGuiController::runAccountWizard() NewAccountWizard wizard(_window); NewAccountModel model(nullptr); NewAccountWizardController wizardController(&model, &wizard, nullptr); - ownCloudGui::raise(); + ocApp()->mainWindow()->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 @@ -251,7 +252,7 @@ void AccountsGuiController::startModal(QUuid accountId) action->setIcon(Resources::getCoreIcon("states/warning")); action->setChecked(true); - ownCloudGui::raise(); + ocApp()->mainWindow()->ensureVisible(); } void AccountsGuiController::endModal(QUuid accountId) diff --git a/src/gui/accountstate.cpp b/src/gui/accountstate.cpp index 6ee99ac894c..2c0252722b4 100644 --- a/src/gui/accountstate.cpp +++ b/src/gui/accountstate.cpp @@ -103,7 +103,7 @@ void AccountState::connectAccount() connect(_account.data(), &Account::appProviderErrorOccured, this, [](const QString &error) { QMessageBox *msgBox = new QMessageBox(QMessageBox::Information, Theme::instance()->appNameGUI(), error, {}, ocApp()->mainWindow()); msgBox->setAttribute(Qt::WA_DeleteOnClose); - ownCloudGui::raise(); + ocApp()->mainWindow()->ensureVisible(); msgBox->open(); }); } @@ -354,7 +354,7 @@ void AccountState::handleSslConnectionErrors(const QList &errors, boo certs << error.certificate(); } TlsErrorDialog tlsDlg(filteredErrors, _account->url().host(), ocApp()->mainWindow()); - ownCloudGui::raise(); + ocApp()->mainWindow()->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 01a2f4fe377..3db12301ebb 100644 --- a/src/gui/application.cpp +++ b/src/gui/application.cpp @@ -24,7 +24,6 @@ #include "configfile.h" #include "folder.h" #include "folderman.h" -#include "mainwindow/mainwindow.h" #include "mainwindow/mainwindowcontroller.h" #include "socketapi/socketapi.h" #include "theme.h" diff --git a/src/gui/application.h b/src/gui/application.h index 8a4fba0cccb..0dbaa422b3c 100644 --- a/src/gui/application.h +++ b/src/gui/application.h @@ -17,6 +17,7 @@ #include "gui/owncloudguilib.h" #include "folderman.h" +#include "mainwindow/mainwindow.h" #include "owncloudgui.h" #include "platform.h" diff --git a/src/gui/creds/requestauthenticationcontroller.cpp b/src/gui/creds/requestauthenticationcontroller.cpp index 2c00d306940..26eded62484 100644 --- a/src/gui/creds/requestauthenticationcontroller.cpp +++ b/src/gui/creds/requestauthenticationcontroller.cpp @@ -130,6 +130,6 @@ void RequestAuthenticationController::handleOAuthResult(OAuth::Result result, co Q_EMIT authenticationSucceeded(accessToken, refreshToken); } - ownCloudGui::raise(); + ocApp()->mainWindow()->ensureVisible(); } } diff --git a/src/gui/folder.cpp b/src/gui/folder.cpp index 4c19f954976..6bde825b785 100644 --- a/src/gui/folder.cpp +++ b/src/gui/folder.cpp @@ -1047,7 +1047,7 @@ void Folder::slotWatcherUnreliable(const QString &message) {}, ocApp()->mainWindow()); msgBox->setAttribute(Qt::WA_DeleteOnClose); - ownCloudGui::raise(); + ocApp()->mainWindow()->ensureVisible(); msgBox->open(); } diff --git a/src/gui/generalsettings.cpp b/src/gui/generalsettings.cpp index b7c975b3092..d5f8d4786de 100644 --- a/src/gui/generalsettings.cpp +++ b/src/gui/generalsettings.cpp @@ -143,7 +143,7 @@ void GeneralSettings::slotIgnoreFilesEditor() if (_ignoreEditor.isNull()) { _ignoreEditor = new IgnoreListEditor(ocApp()->mainWindow()); _ignoreEditor->setAttribute(Qt::WA_DeleteOnClose, true); - ownCloudGui::raise(); + ocApp()->mainWindow()->ensureVisible(); _ignoreEditor->open(); } } diff --git a/src/gui/main.cpp b/src/gui/main.cpp index dfd9863f41a..5ac676632f3 100644 --- a/src/gui/main.cpp +++ b/src/gui/main.cpp @@ -444,7 +444,7 @@ int main(int argc, char **argv) ocApp->buildAppGuis(); ocApp->updateAutoRun(firstRun); - QObject::connect(platform.get(), &Platform::requestAttention, ocApp->gui(), &ownCloudGui::slotShowSettings); + QObject::connect(platform.get(), &Platform::requestAttention, ocApp->mainWindow(), &MainWindow::ensureVisible); // Refactoring todo: convert lambda to function QObject::connect(&singleApplication, &KDSingleApplication::messageReceived, ocApp.get(), [&](const QByteArray &message) { @@ -454,7 +454,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->mainWindow()->ensureVisible(); } if (options.quitInstance) { qApp->quit(); @@ -485,8 +485,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. + ocApp->mainWindow()->ensureVisible(); + // ocApp->gui()->slotShowSettings(); } // Now that everything is up and running, start accepting connections/requests from the shell integration. diff --git a/src/gui/mainwindow/mainwindow.cpp b/src/gui/mainwindow/mainwindow.cpp index 183fd122e6b..235b128fa52 100644 --- a/src/gui/mainwindow/mainwindow.cpp +++ b/src/gui/mainwindow/mainwindow.cpp @@ -273,6 +273,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..c6337036385 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); diff --git a/src/gui/mainwindow/mainwindowcontroller.cpp b/src/gui/mainwindow/mainwindowcontroller.cpp index 6badfad36db..dc5455cf2e4 100644 --- a/src/gui/mainwindow/mainwindowcontroller.cpp +++ b/src/gui/mainwindow/mainwindowcontroller.cpp @@ -17,6 +17,7 @@ #include "aboutview.h" #include "accountmanager.h" #include "accountsgui/accountsguicontroller.h" +#include "application.h" #include "localactivitywidget.h" #include "mainwindow.h" #include "modalwrapperwidget.h" @@ -104,6 +105,8 @@ void MainWindowController::createActivityAction() void MainWindowController::onAddAccount() { + // it's not always the case that the window is visible on start so be sure to raise + _window->ensureVisible(); _accountsController->runAccountWizard(); } @@ -116,6 +119,7 @@ void MainWindowController::onSettings() void MainWindowController::onAbout() { + _window->ensureVisible(); AboutView *aboutPanel = new AboutView(_window); ModalWrapperWidget *wrapper = new ModalWrapperWidget(aboutPanel, _window); _window->showModalWidget(wrapper); diff --git a/src/gui/mainwindow/settingsview.cpp b/src/gui/mainwindow/settingsview.cpp index fc32d4d7d5c..5c9f7643f39 100644 --- a/src/gui/mainwindow/settingsview.cpp +++ b/src/gui/mainwindow/settingsview.cpp @@ -141,7 +141,7 @@ void SettingsView::slotIgnoreFilesEditor() if (_ignoreEditor.isNull()) { _ignoreEditor = new IgnoreListEditor(ocApp()->mainWindow()); _ignoreEditor->setAttribute(Qt::WA_DeleteOnClose, true); - ownCloudGui::raise(); + ocApp()->mainWindow()->ensureVisible(); _ignoreEditor->open(); } } diff --git a/src/gui/networkadapters/resolveurladapter.cpp b/src/gui/networkadapters/resolveurladapter.cpp index fb56523392c..7afe6dd408a 100644 --- a/src/gui/networkadapters/resolveurladapter.cpp +++ b/src/gui/networkadapters/resolveurladapter.cpp @@ -17,7 +17,7 @@ #include "abstractcorejob.h" #include "common/utility.h" #include "gui/application.h" -#include "gui/owncloudgui.h" +#include "gui/mainwindow/mainwindow.h" #include "gui/tlserrordialog.h" #include @@ -94,7 +94,7 @@ void ResolveUrlAdapter::handleSslErrors(const QList &errors) } else { auto *tlsErrorDialog = new TlsErrorDialog(filtered, reply->url().host(), _tlsDialogParent); - ownCloudGui::raise(); + ocApp()->mainWindow()->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/newaccountwizardcontroller.cpp b/src/gui/newaccountwizard/newaccountwizardcontroller.cpp index ec8a486fe1f..80f407982ae 100644 --- a/src/gui/newaccountwizard/newaccountwizardcontroller.cpp +++ b/src/gui/newaccountwizard/newaccountwizardcontroller.cpp @@ -16,13 +16,14 @@ #include "accessmanager.h" #include "advancedsettingspagecontroller.h" +#include "application.h" #include "authsuccesspagecontroller.h" #include "common/utility.h" +#include "mainwindow/mainwindow.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 +178,7 @@ void NewAccountWizardController::onOAuthValidationCompleted(const OCC::OAuthPage _model->setWebfingerUserInfoUrl(results.webfingerUserUrl); _wizard->setCurrentId(_authSuccessPageIndex); - ownCloudGui::raise(); + ocApp()->mainWindow()->ensureVisible(); // on mac, for unknown reasons, the main window is active after raise _wizard->activateWindow(); } @@ -187,7 +188,7 @@ void NewAccountWizardController::onOauthValidationFailed(const OCC::OAuthPageRes if (!_wizard) return; Q_UNUSED(results); - ownCloudGui::raise(); + ocApp()->mainWindow()->ensureVisible(); _wizard->activateWindow(); } diff --git a/src/gui/owncloudgui.cpp b/src/gui/owncloudgui.cpp index 8e591c61edc..40154ace5dc 100644 --- a/src/gui/owncloudgui.cpp +++ b/src/gui/owncloudgui.cpp @@ -112,7 +112,7 @@ void ownCloudGui::slotTrayClicked(QSystemTrayIcon::ActivationReason reason) // However if the settings dialog is already visible but hidden // by other applications, this will bring it to the front. if (ocApp()->mainWindow()->isVisible()) { - raise(); + ocApp()->mainWindow()->ensureVisible(); } #else slotOpenSettingsDialog(); @@ -216,14 +216,14 @@ void ownCloudGui::slotShowOptionalTrayMessage(const QString &title, const QStrin void ownCloudGui::slotShowSettings() { - raise(); + ocApp()->mainWindow()->ensureVisible(); } void ownCloudGui::slotToggleLogBrowser() { auto logBrowser = new LogBrowser(ocApp()->mainWindow()); logBrowser->setAttribute(Qt::WA_DeleteOnClose); - ownCloudGui::raise(); + ocApp()->mainWindow()->ensureVisible(); logBrowser->open(); } @@ -232,34 +232,6 @@ void ownCloudGui::slotHelp() QDesktopServices::openUrl(QUrl(Theme::instance()->helpUrl())); } -// todo: dc-310 move this to main window -void ownCloudGui::raise() -{ - QMainWindow *window; - window = ocApp()->mainWindow(); - 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; diff --git a/src/gui/owncloudgui.h b/src/gui/owncloudgui.h index 6badf0c985b..bfe1797bd28 100644 --- a/src/gui/owncloudgui.h +++ b/src/gui/owncloudgui.h @@ -51,13 +51,6 @@ class OWNCLOUDGUI_EXPORT ownCloudGui : public QObject 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(); - Q_SIGNALS: void requestSetUpSyncFoldersForAccount(AccountState *account, bool useVfs); void requestLoadSpacesOnly(AccountState *account); diff --git a/src/gui/settingsdialog.cpp b/src/gui/settingsdialog.cpp index b00c68a6d86..1d54b78f18c 100644 --- a/src/gui/settingsdialog.cpp +++ b/src/gui/settingsdialog.cpp @@ -196,7 +196,7 @@ void SettingsDialog::onAccountRemoved(AccountState *state) void SettingsDialog::addModalWidget(QWidget *w) { - ownCloudGui::raise(); + // ownCloudGui::raise(); if (_ui->dialogStack->indexOf(w) == -1) { _ui->dialogStack->addWidget(w); _ui->dialogStack->setCurrentWidget(w); @@ -213,7 +213,7 @@ void SettingsDialog::requestModality(Account *account) setCurrentAccount(account); } _modalStack.append(account); - ownCloudGui::raise(); + // ownCloudGui::raise(); } void SettingsDialog::ceaseModality(Account *account) From dd3951e766712af9567121466842ae6925de7a57 Mon Sep 17 00:00:00 2001 From: Modspike Date: Thu, 18 Jun 2026 16:37:37 +0200 Subject: [PATCH 06/24] eliminate some obsolete classes these have been replaced with MainWindow, SettngsView and AboutView (all in subfolder mainwindow) --- src/gui/CMakeLists.txt | 6 - src/gui/aboutdialog.cpp | 133 ---------------- src/gui/aboutdialog.h | 42 ----- src/gui/aboutdialog.ui | 191 ---------------------- src/gui/generalsettings.cpp | 198 ----------------------- src/gui/generalsettings.h | 67 -------- src/gui/generalsettings.ui | 282 -------------------------------- src/gui/owncloudgui.cpp | 6 - src/gui/settingsdialog.cpp | 310 ------------------------------------ src/gui/settingsdialog.h | 105 ------------ src/gui/settingsdialog.ui | 69 -------- 11 files changed, 1409 deletions(-) delete mode 100644 src/gui/aboutdialog.cpp delete mode 100644 src/gui/aboutdialog.h delete mode 100644 src/gui/aboutdialog.ui delete mode 100644 src/gui/generalsettings.cpp delete mode 100644 src/gui/generalsettings.h delete mode 100644 src/gui/generalsettings.ui delete mode 100644 src/gui/settingsdialog.cpp delete mode 100644 src/gui/settingsdialog.h delete mode 100644 src/gui/settingsdialog.ui diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index ae91f802dc5..0c375d1b9eb 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -3,20 +3,16 @@ 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 @@ -30,7 +26,6 @@ set(client_SRCS folder.cpp folderman.cpp folderwatcher.cpp - generalsettings.cpp ignorelisteditor.cpp lockwatcher.cpp logbrowser.cpp @@ -43,7 +38,6 @@ set(client_SRCS syncerrorwidget.cpp activitysettings.cpp selectivesyncwidget.cpp - settingsdialog.cpp tlserrordialog.cpp syncrunfilelog.cpp accountstate.cpp 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/generalsettings.cpp b/src/gui/generalsettings.cpp deleted file mode 100644 index d5f8d4786de..00000000000 --- a/src/gui/generalsettings.cpp +++ /dev/null @@ -1,198 +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 "gui/application.h" -#include "gui/ignorelisteditor.h" -#include "gui/mainwindow/mainwindow.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()->mainWindow()); - _ignoreEditor->setAttribute(Qt::WA_DeleteOnClose, true); - ocApp()->mainWindow()->ensureVisible(); - _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 -
networksettings.h
- 1 -
-
- - autostartCheckBox - desktopNotificationsCheckBox - monoIconsCheckBox - languageDropdown - syncHiddenFilesCheckBox - crashreporterCheckBox - moveToTrashCheckBox - ignoredFilesButton - logSettingsButton - widget - scrollArea - about_pushButton - - - -
diff --git a/src/gui/owncloudgui.cpp b/src/gui/owncloudgui.cpp index 40154ace5dc..21210856ad3 100644 --- a/src/gui/owncloudgui.cpp +++ b/src/gui/owncloudgui.cpp @@ -13,7 +13,6 @@ */ #include "owncloudgui.h" -#include "aboutdialog.h" #include "account.h" #include "accountmanager.h" #include "accountstate.h" @@ -29,11 +28,6 @@ #include "mainwindow/mainwindow.h" #include "progressdispatcher.h" -#include "newaccountwizard/newaccountbuilder.h" -#include "newaccountwizard/newaccountmodel.h" -#include "newaccountwizard/newaccountwizard.h" -#include "newaccountwizard/newaccountwizardcontroller.h" - #include "resources/resources.h" #include diff --git a/src/gui/settingsdialog.cpp b/src/gui/settingsdialog.cpp deleted file mode 100644 index 1d54b78f18c..00000000000 --- a/src/gui/settingsdialog.cpp +++ /dev/null @@ -1,310 +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 "accountsgui/accountviewcontroller.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(this); - auto accountViewController = new AccountViewController(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::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 7888c9f74e8..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 -
gui/qmlutils.h
- 1 -
-
- - -
From a58b18596b5da2cc25a1727e68cacfb768a780e2 Mon Sep 17 00:00:00 2001 From: Modspike Date: Fri, 19 Jun 2026 14:47:26 +0200 Subject: [PATCH 07/24] various improvements fixed missing folder wizard after create account with selective sync refactored the manage account menu actions renamed a few things --- .../FoldersGui/accountfolderscontroller.cpp | 22 +------ src/gui/FoldersGui/accountfolderscontroller.h | 5 +- src/gui/accountsgui/accountsguicontroller.cpp | 16 ++--- src/gui/accountsgui/accountsguicontroller.h | 4 +- src/gui/accountsgui/accountview.cpp | 23 +++---- src/gui/accountsgui/accountview.h | 7 +-- src/gui/accountsgui/accountviewcontroller.cpp | 60 +++++++++++++------ src/gui/accountsgui/accountviewcontroller.h | 12 +++- .../newaccountwizard/newaccountbuilder.cpp | 2 +- src/gui/newaccountwizard/newaccountbuilder.h | 2 +- 10 files changed, 83 insertions(+), 70 deletions(-) diff --git a/src/gui/FoldersGui/accountfolderscontroller.cpp b/src/gui/FoldersGui/accountfolderscontroller.cpp index d7e934d2c87..aef84830a9b 100644 --- a/src/gui/FoldersGui/accountfolderscontroller.cpp +++ b/src/gui/FoldersGui/accountfolderscontroller.cpp @@ -84,27 +84,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() 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/accountsgui/accountsguicontroller.cpp b/src/gui/accountsgui/accountsguicontroller.cpp index 8f2cb1328a8..c1914ce7a82 100644 --- a/src/gui/accountsgui/accountsguicontroller.cpp +++ b/src/gui/accountsgui/accountsguicontroller.cpp @@ -76,6 +76,8 @@ void AccountsGuiController::onAccountAdded(AccountState *state) accountView->setObjectName(QString("accountView_%1").arg(accountId.toString())); 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); @@ -229,19 +231,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) 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 a6699443956..b3cd3da89d0 100644 --- a/src/gui/accountsgui/accountview.cpp +++ b/src/gui/accountsgui/accountview.cpp @@ -35,13 +35,20 @@ AccountView::~AccountView() delete _ui; } -void AccountView::setAccountMenu(QMenu *menu) +void AccountView::setAccountMenuActions(QList actions) { - if (QMenu *oldMenu = _ui->manageAccountButton->menu()) { - _ui->manageAccountButton->setMenu(nullptr); - delete oldMenu; + QMenu *menu = _ui->manageAccountButton->menu(); + if (!menu) { + menu = new QMenu(this); + menu->setAccessibleName(tr("Account options menu")); + connect(menu, &QMenu::aboutToShow, this, &AccountView::requestMenuActionUpdate); + } else { + menu->clear(); } - _ui->manageAccountButton->setMenu(menu); + + menu->addActions(actions); + if (_ui->manageAccountButton->menu() == nullptr) + _ui->manageAccountButton->setMenu(menu); } void AccountView::setTopStackWidget(QWidget *widget) @@ -74,12 +81,6 @@ void AccountView::accountSettingUpChanged(bool settingUp) } } -void AccountView::slotAddFolder() -{ - // temp until we get rid of the SettingsDialog - emit addFolderClicked(); -} - void AccountView::showEvent(QShowEvent *ev) { Q_UNUSED(ev); diff --git a/src/gui/accountsgui/accountview.h b/src/gui/accountsgui/accountview.h index 2a3042e1011..b0c53f5cd0e 100644 --- a/src/gui/accountsgui/accountview.h +++ b/src/gui/accountsgui/accountview.h @@ -54,7 +54,7 @@ class OWNCLOUDGUI_EXPORT AccountView : public QWidget explicit AccountView(QWidget *parent); ~AccountView() override; - void setAccountMenu(QMenu *menu); + 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 @@ -68,12 +68,9 @@ class OWNCLOUDGUI_EXPORT AccountView : public QWidget AccountFoldersView *foldersView(); void accountSettingUpChanged(bool settingUp); - // this is called by SettingsDialog directly but should be corrected to either respond to signal, or just make - // it a normal function - void slotAddFolder(); signals: - void addFolderClicked(); + void requestMenuActionUpdate(); protected: void showEvent(QShowEvent *ev) override; diff --git a/src/gui/accountsgui/accountviewcontroller.cpp b/src/gui/accountsgui/accountviewcontroller.cpp index 837c5477541..d6d1761bba2 100644 --- a/src/gui/accountsgui/accountviewcontroller.cpp +++ b/src/gui/accountsgui/accountviewcontroller.cpp @@ -41,8 +41,10 @@ AccountViewController::AccountViewController(AccountView *view, AccountState *st 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::onAddFolder); + connect(foldersController, &AccountFoldersController::requestAddFolder, this, &AccountViewController::runFolderWizard); connect(foldersController, &AccountFoldersController::requestAccountModalWidget, this, &AccountViewController::addAccountModalWidget); connect(_accountState, &AccountState::stateChanged, this, &AccountViewController::onAccountStateChanged); @@ -85,22 +87,46 @@ void AccountViewController::buildManageAccountMenu() if (!_view || !_accountState) return; - QMenu *menu = new QMenu(_view); - menu->setAccessibleName(tr("Account options menu")); + QList actions; - auto *logInOutAction = menu->addAction(tr("Log in"), this, &AccountViewController::onToggleSignInState); + _logInOut = new QAction(tr("Log in"), this); + _logInOut->setObjectName("logInOutAction"); + connect(_logInOut, &QAction::triggered, this, &AccountViewController::onToggleSignInState); + actions.push_back(_logInOut); - 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()); - }); + _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); +} - menu->addAction(CommonStrings::showInWebBrowser(), this, &AccountViewController::onOpenAccountInBrowser); - menu->addAction(tr("Remove"), this, &AccountViewController::onDeleteAccount); +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; + } - _view->setAccountMenu(menu); + _logInOut->setText(_accountState->isSignedOut() ? tr("Log in") : tr("Log out")); + _reconnect->setEnabled(!_accountState->isConnected() && !_accountState->isSignedOut()); } void AccountViewController::addAccountModalWidget(AccountModalWidget *widget) @@ -160,7 +186,7 @@ void AccountViewController::onDeleteAccount() messageBox->open(); } -QIcon AccountViewController::lookupIcon(StatusIcon status) +QIcon AccountViewController::lookupStatusIcon(StatusIcon status) { QIcon icon; switch (status) { @@ -246,10 +272,10 @@ void AccountViewController::onAccountStateChanged(AccountState::State state) break; } - _view->setConnectionLabel(text, lookupIcon(icon), errors); + _view->setConnectionLabel(text, lookupStatusIcon(icon), errors); } -void AccountViewController::onAddFolder() +void AccountViewController::runFolderWizard() { if (!_accountState || !_accountState->account() || !_view) return; @@ -258,7 +284,7 @@ void AccountViewController::onAddFolder() FolderWizard *folderWizard = new FolderWizard(_accountState->account(), _view); connect(folderWizard, &QDialog::accepted, this, &AccountViewController::onFolderWizardAccepted); - // connect(folderWizard, &QDialog::rejected, this, [] { qCInfo(lcAccountView) << "Folder wizard cancelled"; }); + 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 diff --git a/src/gui/accountsgui/accountviewcontroller.h b/src/gui/accountsgui/accountviewcontroller.h index ba6f5cf1f56..4f00f507347 100644 --- a/src/gui/accountsgui/accountviewcontroller.h +++ b/src/gui/accountsgui/accountviewcontroller.h @@ -18,6 +18,8 @@ #include #include +class QAction; + namespace OCC { class AccountView; @@ -32,6 +34,7 @@ class AccountViewController : public QObject 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 @@ -47,7 +50,6 @@ class AccountViewController : public QObject void onOpenAccountInBrowser(); void onToggleSignInState(); - void onAddFolder(); void onFolderWizardAccepted(); void finishAccountModalWidget(AccountModalWidget *widget); @@ -56,8 +58,14 @@ class AccountViewController : public QObject QPointer _view = nullptr; QPointer _accountState; + QAction *_logInOut = nullptr; + QAction *_reconnect = nullptr; + QAction *_showInBrowser = nullptr; + QAction *_remove = nullptr; + void buildManageAccountMenu(); - QIcon lookupIcon(StatusIcon status); + void refreshAccountActions(); + QIcon lookupStatusIcon(StatusIcon status); }; } 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: From 6ad4e7577fe2627e489d252b2d6b453bd7ab40e3 Mon Sep 17 00:00:00 2001 From: Modspike Date: Fri, 19 Jun 2026 14:55:57 +0200 Subject: [PATCH 08/24] moved accountmodalwidget to accountsgui --- src/gui/CMakeLists.txt | 4 -- src/gui/accountsgui/CMakeLists.txt | 4 ++ src/gui/accountsgui/accountmodalwidget.cpp | 83 ++++++++++++++++++++++ src/gui/accountsgui/accountmodalwidget.h | 60 ++++++++++++++++ src/gui/accountsgui/accountmodalwidget.ui | 42 +++++++++++ 5 files changed, 189 insertions(+), 4 deletions(-) create mode 100644 src/gui/accountsgui/accountmodalwidget.cpp create mode 100644 src/gui/accountsgui/accountmodalwidget.h create mode 100644 src/gui/accountsgui/accountmodalwidget.ui diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 0c375d1b9eb..2f507783d60 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -9,15 +9,11 @@ set(client_UI_SRCS syncerrorwidget.ui tlserrordialog.ui logbrowser.ui - accountsgui/accountview.ui ) set(client_SRCS accountmanager.cpp - accountmodalwidget.cpp - accountmodalwidget.ui - application.cpp fetchserversettings.cpp clientproxy.cpp 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..1cbd622c4ff --- /dev/null +++ b/src/gui/accountsgui/accountmodalwidget.cpp @@ -0,0 +1,83 @@ +/* + * 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 "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..c30131ec9cb --- /dev/null +++ b/src/gui/accountsgui/accountmodalwidget.h @@ -0,0 +1,60 @@ +/* + * 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 "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 + + + + + + + + From f5dc998ca52d9c252770df0a09cc7453d3b24893 Mon Sep 17 00:00:00 2001 From: Modspike Date: Mon, 22 Jun 2026 12:07:56 +0200 Subject: [PATCH 09/24] blind refactor of the updater with most changes in the updatedownloadedwidget which has been converted to QDialog it basically was a QDialog but with the button signals/slots hand coded instead of just using the base dialog impl. needs testing on platform that actually supports the updater impl --- src/gui/accountsgui/accountviewcontroller.cpp | 3 ++ src/gui/main.cpp | 2 +- src/gui/mainwindow/modalwrapperwidget.cpp | 23 +++++---- src/gui/mainwindow/modalwrapperwidget.h | 14 ++++++ src/gui/updater/ocupdater.cpp | 11 +++-- src/gui/updater/updatedownloadedwidget.cpp | 7 ++- src/gui/updater/updatedownloadedwidget.h | 13 +---- src/gui/updater/updatedownloadedwidget.ui | 49 ++++++++++++++++--- 8 files changed, 85 insertions(+), 37 deletions(-) diff --git a/src/gui/accountsgui/accountviewcontroller.cpp b/src/gui/accountsgui/accountviewcontroller.cpp index d6d1761bba2..864ac9b778a 100644 --- a/src/gui/accountsgui/accountviewcontroller.cpp +++ b/src/gui/accountsgui/accountviewcontroller.cpp @@ -270,6 +270,9 @@ void AccountViewController::onAccountStateChanged(AccountState::State state) text = tr("Disconnected"); icon = StatusIcon::Disconnected; break; + default: + text = tr("Invalid connection status"); + icon = StatusIcon::None; } _view->setConnectionLabel(text, lookupStatusIcon(icon), errors); diff --git a/src/gui/main.cpp b/src/gui/main.cpp index 5ac676632f3..c0e4be1d50d 100644 --- a/src/gui/main.cpp +++ b/src/gui/main.cpp @@ -440,7 +440,7 @@ int main(int argc, char **argv) // 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->buildAppGuis(); ocApp->updateAutoRun(firstRun); 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/updater/ocupdater.cpp b/src/gui/updater/ocupdater.cpp index a2979a098a9..713e4b12837 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" @@ -53,11 +54,13 @@ UpdaterScheduler::UpdaterScheduler(Application *app, QObject *parent) 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()->mainWindow()->showModalWidget(wrapper); connect(_updateDownloadedWidget, &UpdateDownloadedWidget::accepted, this, []() { Updater::instance()->applyUpdateAndRestart(); }); - connect(_updateDownloadedWidget, &UpdateDownloadedWidget::finished, this, [this]() { delete _updateDownloadedWidget.data(); }); + // the wrapper is deleted by the main window on finished - this is unnecessary + // connect(_updateDownloadedWidget, &UpdateDownloadedWidget::finished, this, [this]() { delete _updateDownloadedWidget.data(); }); } }); 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 + + + + From f0fe71041e57e78dfe2590bdf5e354e159d8f8ba Mon Sep 17 00:00:00 2001 From: Modspike Date: Mon, 22 Jun 2026 14:07:34 +0200 Subject: [PATCH 10/24] possibly fixed windows updater --- src/gui/updater/newversionavailablewidget.cpp | 14 +++--- src/gui/updater/newversionavailablewidget.h | 11 ++--- src/gui/updater/newversionavailablewidget.ui | 47 ++++++++++++++++--- src/gui/updater/ocupdater.cpp | 9 ++-- 4 files changed, 56 insertions(+), 25 deletions(-) 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..cca54b2bec4 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,11 @@ class NewVersionAvailableWidget : public QWidget private Q_SLOTS: void skipVersion(); - void notNow(); - void getUpdate(); + // 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 713e4b12837..74867bd3860 100644 --- a/src/gui/updater/ocupdater.cpp +++ b/src/gui/updater/ocupdater.cpp @@ -379,13 +379,14 @@ 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); + // connect(widget, &NewVersionAvailableWidget::finished, this, [widget]() { delete widget; }); - ocApp()->gui()->settingsDialog()->addModalWidget(widget); + ModalWrapperWidget *wrapper = new ModalWrapperWidget(widget, ocApp()->mainWindow()); + ocApp()->mainWindow()->showModalWidget(wrapper); } void WindowsUpdater::showUpdateErrorDialog(const QString &targetVersion) From ee86d38cb60b21c6d0357ced8c085c9407855411 Mon Sep 17 00:00:00 2001 From: Modspike Date: Mon, 22 Jun 2026 14:29:19 +0200 Subject: [PATCH 11/24] maybe fixed linux updater --- .../updater/appimageupdateavailablewidget.cpp | 16 +++++--- .../updater/appimageupdateavailablewidget.h | 8 ++-- .../updater/appimageupdateavailablewidget.ui | 37 ++++++++++++++++++- src/gui/updater/appimageupdater.cpp | 14 +++---- src/gui/updater/newversionavailablewidget.h | 2 - 5 files changed, 53 insertions(+), 24 deletions(-) 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..9c14784a31e 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()->mainWindow()->showModalWidget(wrapper); } void AppImageUpdater::backgroundCheckForUpdate() diff --git a/src/gui/updater/newversionavailablewidget.h b/src/gui/updater/newversionavailablewidget.h index cca54b2bec4..a5ef3e88048 100644 --- a/src/gui/updater/newversionavailablewidget.h +++ b/src/gui/updater/newversionavailablewidget.h @@ -33,8 +33,6 @@ class NewVersionAvailableWidget : public QDialog private Q_SLOTS: void skipVersion(); - // void notNow(); - // void getUpdate(); Q_SIGNALS: void versionSkipped(); From 2beaed880b053ffeeac5c0dc82cc12612582c0e8 Mon Sep 17 00:00:00 2001 From: Modspike Date: Mon, 22 Jun 2026 14:58:02 +0200 Subject: [PATCH 12/24] fix windows? --- src/gui/mainwindow/mainwindow.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gui/mainwindow/mainwindow.cpp b/src/gui/mainwindow/mainwindow.cpp index 235b128fa52..de147ab4aa9 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); From 9ef21129d56ca66f880337c97736b1a6b6e57a4c Mon Sep 17 00:00:00 2001 From: Modspike Date: Thu, 25 Jun 2026 17:46:42 +0200 Subject: [PATCH 13/24] moving things around also removed the very strange impls related to clicking the tray menu icon --- src/gui/accountsgui/accountsguicontroller.cpp | 2 +- src/gui/application.cpp | 5 +++ src/gui/application.h | 11 ++++-- src/gui/main.cpp | 5 +-- src/gui/mainwindow/mainwindow.cpp | 2 +- src/gui/mainwindow/mainwindow.h | 2 +- src/gui/mainwindow/mainwindowcontroller.cpp | 15 ++------ src/gui/mainwindow/mainwindowcontroller.h | 6 ++- src/gui/owncloudgui.cpp | 38 ++++--------------- src/gui/owncloudgui.h | 6 --- 10 files changed, 31 insertions(+), 61 deletions(-) diff --git a/src/gui/accountsgui/accountsguicontroller.cpp b/src/gui/accountsgui/accountsguicontroller.cpp index c1914ce7a82..e4a47cda98b 100644 --- a/src/gui/accountsgui/accountsguicontroller.cpp +++ b/src/gui/accountsgui/accountsguicontroller.cpp @@ -156,7 +156,7 @@ void AccountsGuiController::runAccountWizard() NewAccountWizard wizard(_window); NewAccountModel model(nullptr); NewAccountWizardController wizardController(&model, &wizard, nullptr); - ocApp()->mainWindow()->ensureVisible(); + _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 diff --git a/src/gui/application.cpp b/src/gui/application.cpp index 3db12301ebb..6ae7243d90c 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" @@ -174,6 +175,9 @@ void Application::buildAppGuis() _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 _gui = new ownCloudGui(this); @@ -185,6 +189,7 @@ std::unique_ptr Application::createInstance(Platform *platform, con { Q_ASSERT(!_instance); _instance = new Application(platform, displayLanguage, debugMode); + _instance->buildAppGuis(); return std::unique_ptr(_instance); } diff --git a/src/gui/application.h b/src/gui/application.h index 0dbaa422b3c..b1a90472e72 100644 --- a/src/gui/application.h +++ b/src/gui/application.h @@ -39,6 +39,7 @@ class Theme; class Folder; class MainWindow; class MainWindowController; +class AccountsGuiController; /** * @brief The Application class @@ -53,10 +54,6 @@ class OWNCLOUDGUI_EXPORT Application : public QObject 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 actios - void buildAppGuis(); - ownCloudGui *gui() const; // this is needed primarily to parent message boxes @@ -81,6 +78,11 @@ protected Q_SLOTS: void slotCleanup(); void slotAccountStateAdded(AccountState *accountState) const; +private: + // 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(); + private: explicit Application(Platform *platform, const QString &displayLanguage, bool debugMode); @@ -88,6 +90,7 @@ protected Q_SLOTS: MainWindow *_mainWin = nullptr; MainWindowController *_mainController = nullptr; + AccountsGuiController *_accountsGuiController = nullptr; const bool _debugMode = false; QString _displayLanguage; diff --git a/src/gui/main.cpp b/src/gui/main.cpp index c0e4be1d50d..9bdbeb504f2 100644 --- a/src/gui/main.cpp +++ b/src/gui/main.cpp @@ -437,11 +437,8 @@ 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 std::unique_ptr ocApp = Application::createInstance(platform.get(), displayLanguage, options.debugMode); - ocApp->buildAppGuis(); + ocApp->updateAutoRun(firstRun); QObject::connect(platform.get(), &Platform::requestAttention, ocApp->mainWindow(), &MainWindow::ensureVisible); diff --git a/src/gui/mainwindow/mainwindow.cpp b/src/gui/mainwindow/mainwindow.cpp index de147ab4aa9..6fa8e9f7965 100644 --- a/src/gui/mainwindow/mainwindow.cpp +++ b/src/gui/mainwindow/mainwindow.cpp @@ -178,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); diff --git a/src/gui/mainwindow/mainwindow.h b/src/gui/mainwindow/mainwindow.h index c6337036385..153a59bf7ee 100644 --- a/src/gui/mainwindow/mainwindow.h +++ b/src/gui/mainwindow/mainwindow.h @@ -46,7 +46,7 @@ class OWNCLOUDGUI_EXPORT 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 dc5455cf2e4..f6bf16b0664 100644 --- a/src/gui/mainwindow/mainwindowcontroller.cpp +++ b/src/gui/mainwindow/mainwindowcontroller.cpp @@ -43,8 +43,6 @@ void MainWindowController::setup() createSyncErrorsAction(); createActivityAction(); buildMenuActions(); - - _accountsController = new AccountsGuiController(AccountManager::instance(), _window, this); } void MainWindowController::buildMenuActions() @@ -53,7 +51,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); @@ -89,7 +87,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() @@ -100,14 +98,7 @@ void MainWindowController::createActivityAction() activityAction->setCheckable(true); auto localActivityWidget = new LocalActivityWidget(_window); activityAction->setData(QVariant::fromValue(localActivityWidget)); - _window->addGeneralAction(activityAction); -} - -void MainWindowController::onAddAccount() -{ - // it's not always the case that the window is visible on start so be sure to raise - _window->ensureVisible(); - _accountsController->runAccountWizard(); + _window->addViewAction(activityAction); } void MainWindowController::onSettings() diff --git a/src/gui/mainwindow/mainwindowcontroller.h b/src/gui/mainwindow/mainwindowcontroller.h index 4ac63f78ef0..b074bcf5ed5 100644 --- a/src/gui/mainwindow/mainwindowcontroller.h +++ b/src/gui/mainwindow/mainwindowcontroller.h @@ -29,19 +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(); +signals: + void requestAccountWizard(); + private: void buildMenuActions(); void createSyncErrorsAction(); void createActivityAction(); - void onAddAccount(); void onSettings(); void onQuit(); MainWindow *_window = nullptr; - AccountsGuiController *_accountsController = nullptr; }; } diff --git a/src/gui/owncloudgui.cpp b/src/gui/owncloudgui.cpp index 21210856ad3..407a9cd705c 100644 --- a/src/gui/owncloudgui.cpp +++ b/src/gui/owncloudgui.cpp @@ -83,34 +83,15 @@ ownCloudGui::~ownCloudGui() { } -// todo dc-310 - finally figure out what this is trying to accomplish -void ownCloudGui::slotOpenSettingsDialog() -{ - // if account is set up, start the configuration wizard. - if (!AccountManager::instance()->accounts().isEmpty()) { - if (QApplication::activeWindow() != ocApp()->mainWindow()) { - slotShowSettings(); - } else { - // ????!!!!????????? - ocApp()->mainWindow()->close(); - } - } -} - 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 (ocApp()->mainWindow()->isVisible()) { + // 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()->mainWindow()->ensureVisible(); - } -#else - slotOpenSettingsDialog(); -#endif } } @@ -153,14 +134,16 @@ void ownCloudGui::slotComputeOverallSyncStatus() void ownCloudGui::setupTrayContextMenu() { - // using the main windows (_settingsDialog) as parent for memory management + // 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); // Populate the context menu now. - menu->addAction(Theme::instance()->applicationIcon(), tr("Show %1").arg(Theme::instance()->appNameGUI()), this, &ownCloudGui::slotShowSettings); + menu->addAction( + Theme::instance()->applicationIcon(), tr("Show %1").arg(Theme::instance()->appNameGUI()), ocApp()->mainWindow(), &MainWindow::ensureVisible); menu->addSeparator(); if (_app->debugMode()) { @@ -208,11 +191,6 @@ void ownCloudGui::slotShowOptionalTrayMessage(const QString &title, const QStrin } } -void ownCloudGui::slotShowSettings() -{ - ocApp()->mainWindow()->ensureVisible(); -} - void ownCloudGui::slotToggleLogBrowser() { auto logBrowser = new LogBrowser(ocApp()->mainWindow()); diff --git a/src/gui/owncloudgui.h b/src/gui/owncloudgui.h index bfe1797bd28..0f5815da5d6 100644 --- a/src/gui/owncloudgui.h +++ b/src/gui/owncloudgui.h @@ -23,8 +23,6 @@ #include #include -#define USE_NEW_MAIN_WINDOW - namespace OCC { namespace Wizard { @@ -52,8 +50,6 @@ class OWNCLOUDGUI_EXPORT ownCloudGui : public QObject ~ownCloudGui() override; Q_SIGNALS: - void requestSetUpSyncFoldersForAccount(AccountState *account, bool useVfs); - void requestLoadSpacesOnly(AccountState *account); void requestAboutDialog(); public Q_SLOTS: @@ -61,11 +57,9 @@ public Q_SLOTS: 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 slotSyncStateChange(Folder *); void slotTrayClicked(QSystemTrayIcon::ActivationReason reason); void slotToggleLogBrowser(); - void slotOpenSettingsDialog(); void slotHelp(); void slotTrayMessageIfServerUnsupported(Account *account); From 793f7711ca8dd676bcbd12dabb7b5e4076c9f7f3 Mon Sep 17 00:00:00 2001 From: Modspike Date: Fri, 26 Jun 2026 08:53:59 +0200 Subject: [PATCH 14/24] moving more things around mostly to get non-tray related stuff out of owncloudgui, but also to "request" functionality that lives primarily in main window controller --- src/gui/application.cpp | 4 +++- src/gui/mainwindow/mainwindowcontroller.cpp | 9 ++++++--- src/gui/mainwindow/mainwindowcontroller.h | 2 +- src/gui/mainwindow/settingsview.cpp | 21 +++++++++++++-------- src/gui/mainwindow/settingsview.h | 3 ++- src/gui/owncloudgui.cpp | 17 ++--------------- src/gui/owncloudgui.h | 5 ++--- 7 files changed, 29 insertions(+), 32 deletions(-) diff --git a/src/gui/application.cpp b/src/gui/application.cpp index 6ae7243d90c..920af0d5fdb 100644 --- a/src/gui/application.cpp +++ b/src/gui/application.cpp @@ -181,7 +181,9 @@ void Application::buildAppGuis() // Setting up the gui class will allow tray notifications for the // setup that follows, like folder setup _gui = new ownCloudGui(this); - connect(_gui, &ownCloudGui::requestAboutDialog, _mainController, &MainWindowController::onAbout); + connect(_gui, &ownCloudGui::requestShowAbout, _mainController, &MainWindowController::onAbout); + connect(_gui, &ownCloudGui::requestShowHelp, _mainController, &MainWindowController::onHelp); + connect(FolderMan::instance()->socketApi(), &SocketApi::shareCommandReceived, _gui.data(), &ownCloudGui::slotShowShareInBrowser); } diff --git a/src/gui/mainwindow/mainwindowcontroller.cpp b/src/gui/mainwindow/mainwindowcontroller.cpp index f6bf16b0664..c66103177b1 100644 --- a/src/gui/mainwindow/mainwindowcontroller.cpp +++ b/src/gui/mainwindow/mainwindowcontroller.cpp @@ -15,8 +15,6 @@ #include "mainwindowcontroller.h" #include "aboutview.h" -#include "accountmanager.h" -#include "accountsgui/accountsguicontroller.h" #include "application.h" #include "localactivitywidget.h" #include "mainwindow.h" @@ -26,8 +24,8 @@ #include "theme.h" #include +#include #include -#include namespace OCC { @@ -116,6 +114,11 @@ void MainWindowController::onAbout() _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 b074bcf5ed5..e34a0806323 100644 --- a/src/gui/mainwindow/mainwindowcontroller.h +++ b/src/gui/mainwindow/mainwindowcontroller.h @@ -31,6 +31,7 @@ class MainWindowController : public QObject 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(); @@ -41,7 +42,6 @@ class MainWindowController : public QObject void createActivityAction(); void onSettings(); - void onQuit(); MainWindow *_window = nullptr; diff --git a/src/gui/mainwindow/settingsview.cpp b/src/gui/mainwindow/settingsview.cpp index 5c9f7643f39..e6ef866e5a1 100644 --- a/src/gui/mainwindow/settingsview.cpp +++ b/src/gui/mainwindow/settingsview.cpp @@ -15,12 +15,12 @@ #include "settingsview.h" #include "ui_settingsview.h" -#include "gui/application.h" -#include "gui/ignorelisteditor.h" -#include "gui/mainwindow/mainwindow.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 @@ -72,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(); @@ -193,4 +190,12 @@ void SettingsView::loadLanguageNamesIntoDropdown() } } +void SettingsView::slotShowLogSettings() +{ + auto logBrowser = new LogBrowser(ocApp()->mainWindow()); + logBrowser->setAttribute(Qt::WA_DeleteOnClose); + ocApp()->mainWindow()->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/owncloudgui.cpp b/src/gui/owncloudgui.cpp index 407a9cd705c..d2d0a4b3198 100644 --- a/src/gui/owncloudgui.cpp +++ b/src/gui/owncloudgui.cpp @@ -168,11 +168,11 @@ void ownCloudGui::setupTrayContextMenu() } if (!Theme::instance()->helpUrl().isEmpty()) { - menu->addAction(tr("Help"), this, &ownCloudGui::slotHelp); + menu->addAction(tr("Help"), this, &ownCloudGui::requestShowHelp); } if (! Theme::instance()->about().isEmpty()) { - menu->addAction(tr("About %1").arg(Theme::instance()->appNameGUI()), this, &ownCloudGui::requestAboutDialog); + menu->addAction(tr("About %1").arg(Theme::instance()->appNameGUI()), this, &ownCloudGui::requestShowAbout); } menu->addAction(tr("Quit %1").arg(Theme::instance()->appNameGUI()), _app, &QApplication::quit); @@ -191,19 +191,6 @@ void ownCloudGui::slotShowOptionalTrayMessage(const QString &title, const QStrin } } -void ownCloudGui::slotToggleLogBrowser() -{ - auto logBrowser = new LogBrowser(ocApp()->mainWindow()); - logBrowser->setAttribute(Qt::WA_DeleteOnClose); - ocApp()->mainWindow()->ensureVisible(); - logBrowser->open(); -} - -void ownCloudGui::slotHelp() -{ - QDesktopServices::openUrl(QUrl(Theme::instance()->helpUrl())); -} - void ownCloudGui::slotShowShareInBrowser(const QString &sharePath, const QString &localPath) { QString file; diff --git a/src/gui/owncloudgui.h b/src/gui/owncloudgui.h index 0f5815da5d6..5104b0c7970 100644 --- a/src/gui/owncloudgui.h +++ b/src/gui/owncloudgui.h @@ -50,7 +50,8 @@ class OWNCLOUDGUI_EXPORT ownCloudGui : public QObject ~ownCloudGui() override; Q_SIGNALS: - void requestAboutDialog(); + void requestShowAbout(); + void requestShowHelp(); public Q_SLOTS: void setupTrayContextMenu(); @@ -59,8 +60,6 @@ public Q_SLOTS: void slotShowOptionalTrayMessage(const QString &title, const QString &msg, const QIcon &icon = {}); void slotSyncStateChange(Folder *); void slotTrayClicked(QSystemTrayIcon::ActivationReason reason); - void slotToggleLogBrowser(); - void slotHelp(); void slotTrayMessageIfServerUnsupported(Account *account); /** From 2b2df6c5d324019e1cb23d61f902db63df8a5640 Mon Sep 17 00:00:00 2001 From: Modspike Date: Fri, 26 Jun 2026 09:51:56 +0200 Subject: [PATCH 15/24] hide access to MainWindow from Application the point is: if you can get MainWindow you can call all the public interfaces of MainWindow, which would include things like addViewAction and other stuff that should not be called "by just anyone". Replace the truly necessary public interface with wrappers in Application and only return QMainWindow * from Application::mainWindow() --- src/gui/accountsgui/accountsguicontroller.cpp | 2 +- src/gui/accountstate.cpp | 4 ++-- src/gui/application.cpp | 19 +++++++++++++++++++ src/gui/application.h | 16 +++++++++++++--- .../creds/requestauthenticationcontroller.cpp | 2 +- src/gui/folder.cpp | 2 +- src/gui/main.cpp | 7 +++---- src/gui/mainwindow/settingsview.cpp | 4 ++-- src/gui/networkadapters/resolveurladapter.cpp | 2 +- .../newaccountwizardcontroller.cpp | 4 ++-- src/gui/owncloudgui.cpp | 5 ++--- src/gui/updater/ocupdater.cpp | 7 ++----- 12 files changed, 49 insertions(+), 25 deletions(-) diff --git a/src/gui/accountsgui/accountsguicontroller.cpp b/src/gui/accountsgui/accountsguicontroller.cpp index e4a47cda98b..b6b3ef9e538 100644 --- a/src/gui/accountsgui/accountsguicontroller.cpp +++ b/src/gui/accountsgui/accountsguicontroller.cpp @@ -252,7 +252,7 @@ void AccountsGuiController::startModal(QUuid accountId) action->setIcon(Resources::getCoreIcon("states/warning")); action->setChecked(true); - ocApp()->mainWindow()->ensureVisible(); + ocApp()->ensureVisible(); } void AccountsGuiController::endModal(QUuid accountId) diff --git a/src/gui/accountstate.cpp b/src/gui/accountstate.cpp index 2c0252722b4..a9201bb4565 100644 --- a/src/gui/accountstate.cpp +++ b/src/gui/accountstate.cpp @@ -103,7 +103,7 @@ void AccountState::connectAccount() connect(_account.data(), &Account::appProviderErrorOccured, this, [](const QString &error) { QMessageBox *msgBox = new QMessageBox(QMessageBox::Information, Theme::instance()->appNameGUI(), error, {}, ocApp()->mainWindow()); msgBox->setAttribute(Qt::WA_DeleteOnClose); - ocApp()->mainWindow()->ensureVisible(); + ocApp()->ensureVisible(); msgBox->open(); }); } @@ -354,7 +354,7 @@ void AccountState::handleSslConnectionErrors(const QList &errors, boo certs << error.certificate(); } TlsErrorDialog tlsDlg(filteredErrors, _account->url().host(), ocApp()->mainWindow()); - ocApp()->mainWindow()->ensureVisible(); + 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 920af0d5fdb..03f00af6d30 100644 --- a/src/gui/application.cpp +++ b/src/gui/application.cpp @@ -25,6 +25,7 @@ #include "configfile.h" #include "folder.h" #include "folderman.h" +#include "mainwindow/mainwindow.h" #include "mainwindow/mainwindowcontroller.h" #include "socketapi/socketapi.h" #include "theme.h" @@ -112,6 +113,24 @@ Application::~Application() } } +QMainWindow *Application::mainWindow() +{ + return _mainWin; +} + +void Application::ensureVisible() +{ + if (_mainWin) + _mainWin->ensureVisible(); +} + +void Application::showModalWidget(ModalWrapperWidget *wrapper) +{ + 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 { diff --git a/src/gui/application.h b/src/gui/application.h index b1a90472e72..7f92b815e80 100644 --- a/src/gui/application.h +++ b/src/gui/application.h @@ -17,10 +17,10 @@ #include "gui/owncloudguilib.h" #include "folderman.h" -#include "mainwindow/mainwindow.h" #include "owncloudgui.h" #include "platform.h" +#include #include class QMessageBox; @@ -40,6 +40,7 @@ class Folder; class MainWindow; class MainWindowController; class AccountsGuiController; +class ModalWrapperWidget; /** * @brief The Application class @@ -56,8 +57,17 @@ class OWNCLOUDGUI_EXPORT Application : public QObject ownCloudGui *gui() const; - // this is needed primarily to parent message boxes - MainWindow *mainWindow() { return _mainWin; } + // 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(); + + // redirect to MainWindow::ensureVisible -> protect access to main window interface + void ensureVisible(); + + // 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); QString displayLanguage() const; diff --git a/src/gui/creds/requestauthenticationcontroller.cpp b/src/gui/creds/requestauthenticationcontroller.cpp index 26eded62484..fcdd25b5c92 100644 --- a/src/gui/creds/requestauthenticationcontroller.cpp +++ b/src/gui/creds/requestauthenticationcontroller.cpp @@ -130,6 +130,6 @@ void RequestAuthenticationController::handleOAuthResult(OAuth::Result result, co Q_EMIT authenticationSucceeded(accessToken, refreshToken); } - ocApp()->mainWindow()->ensureVisible(); + ocApp()->ensureVisible(); } } diff --git a/src/gui/folder.cpp b/src/gui/folder.cpp index 6bde825b785..07ee1100b2c 100644 --- a/src/gui/folder.cpp +++ b/src/gui/folder.cpp @@ -1047,7 +1047,7 @@ void Folder::slotWatcherUnreliable(const QString &message) {}, ocApp()->mainWindow()); msgBox->setAttribute(Qt::WA_DeleteOnClose); - ocApp()->mainWindow()->ensureVisible(); + ocApp()->ensureVisible(); msgBox->open(); } diff --git a/src/gui/main.cpp b/src/gui/main.cpp index 9bdbeb504f2..25a4bcd7c12 100644 --- a/src/gui/main.cpp +++ b/src/gui/main.cpp @@ -441,7 +441,7 @@ int main(int argc, char **argv) ocApp->updateAutoRun(firstRun); - QObject::connect(platform.get(), &Platform::requestAttention, ocApp->mainWindow(), &MainWindow::ensureVisible); + QObject::connect(platform.get(), &Platform::requestAttention, ocApp.get(), &Application::ensureVisible); // Refactoring todo: convert lambda to function QObject::connect(&singleApplication, &KDSingleApplication::messageReceived, ocApp.get(), [&](const QByteArray &message) { @@ -451,7 +451,7 @@ int main(int argc, char **argv) const QStringList optionsStrings = msg.mid(msgParseOptionsC().size()).split(QLatin1Char('|')); CommandLineOptions options = parseOptions(optionsStrings); if (options.show) { - ocApp->mainWindow()->ensureVisible(); + ocApp->ensureVisible(); } if (options.quitInstance) { qApp->quit(); @@ -482,8 +482,7 @@ int main(int argc, char **argv) } if (options.show) { - ocApp->mainWindow()->ensureVisible(); - // ocApp->gui()->slotShowSettings(); + ocApp->ensureVisible(); } // Now that everything is up and running, start accepting connections/requests from the shell integration. diff --git a/src/gui/mainwindow/settingsview.cpp b/src/gui/mainwindow/settingsview.cpp index e6ef866e5a1..b9fb3ae8119 100644 --- a/src/gui/mainwindow/settingsview.cpp +++ b/src/gui/mainwindow/settingsview.cpp @@ -138,7 +138,7 @@ void SettingsView::slotIgnoreFilesEditor() if (_ignoreEditor.isNull()) { _ignoreEditor = new IgnoreListEditor(ocApp()->mainWindow()); _ignoreEditor->setAttribute(Qt::WA_DeleteOnClose, true); - ocApp()->mainWindow()->ensureVisible(); + ocApp()->ensureVisible(); _ignoreEditor->open(); } } @@ -194,7 +194,7 @@ void SettingsView::slotShowLogSettings() { auto logBrowser = new LogBrowser(ocApp()->mainWindow()); logBrowser->setAttribute(Qt::WA_DeleteOnClose); - ocApp()->mainWindow()->ensureVisible(); + ocApp()->ensureVisible(); logBrowser->open(); } diff --git a/src/gui/networkadapters/resolveurladapter.cpp b/src/gui/networkadapters/resolveurladapter.cpp index 7afe6dd408a..e36a1fa1398 100644 --- a/src/gui/networkadapters/resolveurladapter.cpp +++ b/src/gui/networkadapters/resolveurladapter.cpp @@ -94,7 +94,7 @@ void ResolveUrlAdapter::handleSslErrors(const QList &errors) } else { auto *tlsErrorDialog = new TlsErrorDialog(filtered, reply->url().host(), _tlsDialogParent); - ocApp()->mainWindow()->ensureVisible(); + 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/newaccountwizardcontroller.cpp b/src/gui/newaccountwizard/newaccountwizardcontroller.cpp index 80f407982ae..4e1e250c828 100644 --- a/src/gui/newaccountwizard/newaccountwizardcontroller.cpp +++ b/src/gui/newaccountwizard/newaccountwizardcontroller.cpp @@ -178,7 +178,7 @@ void NewAccountWizardController::onOAuthValidationCompleted(const OCC::OAuthPage _model->setWebfingerUserInfoUrl(results.webfingerUserUrl); _wizard->setCurrentId(_authSuccessPageIndex); - ocApp()->mainWindow()->ensureVisible(); + ocApp()->ensureVisible(); // on mac, for unknown reasons, the main window is active after raise _wizard->activateWindow(); } @@ -188,7 +188,7 @@ void NewAccountWizardController::onOauthValidationFailed(const OCC::OAuthPageRes if (!_wizard) return; Q_UNUSED(results); - ocApp()->mainWindow()->ensureVisible(); + ocApp()->ensureVisible(); _wizard->activateWindow(); } diff --git a/src/gui/owncloudgui.cpp b/src/gui/owncloudgui.cpp index d2d0a4b3198..dbc703cbb21 100644 --- a/src/gui/owncloudgui.cpp +++ b/src/gui/owncloudgui.cpp @@ -91,7 +91,7 @@ void ownCloudGui::slotTrayClicked(QSystemTrayIcon::ActivationReason reason) // more. on windows (and linux, presumably, given the original code) we just show the // main window on left click. if (!Utility::isMac()) - ocApp()->mainWindow()->ensureVisible(); + ocApp()->ensureVisible(); } } @@ -142,8 +142,7 @@ void ownCloudGui::setupTrayContextMenu() _tray->setContextMenu(menu); // Populate the context menu now. - menu->addAction( - Theme::instance()->applicationIcon(), tr("Show %1").arg(Theme::instance()->appNameGUI()), ocApp()->mainWindow(), &MainWindow::ensureVisible); + menu->addAction(Theme::instance()->applicationIcon(), tr("Show %1").arg(Theme::instance()->appNameGUI()), ocApp(), &Application::ensureVisible); menu->addSeparator(); if (_app->debugMode()) { diff --git a/src/gui/updater/ocupdater.cpp b/src/gui/updater/ocupdater.cpp index 74867bd3860..ecfe561ba58 100644 --- a/src/gui/updater/ocupdater.cpp +++ b/src/gui/updater/ocupdater.cpp @@ -56,11 +56,9 @@ UpdaterScheduler::UpdaterScheduler(Application *app, QObject *parent) if (_updateDownloadedWidget == nullptr) { _updateDownloadedWidget = new UpdateDownloadedWidget(app->mainWindow(), updater->statusString()); ModalWrapperWidget *wrapper = new ModalWrapperWidget(_updateDownloadedWidget, app->mainWindow()); - ocApp()->mainWindow()->showModalWidget(wrapper); + ocApp()->showModalWidget(wrapper); connect(_updateDownloadedWidget, &UpdateDownloadedWidget::accepted, this, []() { Updater::instance()->applyUpdateAndRestart(); }); - // the wrapper is deleted by the main window on finished - this is unnecessary - // connect(_updateDownloadedWidget, &UpdateDownloadedWidget::finished, this, [this]() { delete _updateDownloadedWidget.data(); }); } }); @@ -383,10 +381,9 @@ void WindowsUpdater::showNewVersionAvailableWidget(const UpdateInfo &info) connect(widget, &NewVersionAvailableWidget::versionSkipped, this, &WindowsUpdater::slotSetPreviouslySkippedVersion); connect(widget, &NewVersionAvailableWidget::accepted, this, &WindowsUpdater::slotOpenUpdateUrl); - // connect(widget, &NewVersionAvailableWidget::finished, this, [widget]() { delete widget; }); ModalWrapperWidget *wrapper = new ModalWrapperWidget(widget, ocApp()->mainWindow()); - ocApp()->mainWindow()->showModalWidget(wrapper); + ocApp()->showModalWidget(wrapper); } void WindowsUpdater::showUpdateErrorDialog(const QString &targetVersion) From 48941b283d73ebf402bf62e6897b1a46cd1c6ae6 Mon Sep 17 00:00:00 2001 From: Modspike Date: Fri, 26 Jun 2026 10:12:12 +0200 Subject: [PATCH 16/24] rename ownCloudGui to TrayMenuController it does what it says on the tin! --- src/gui/CMakeLists.txt | 2 +- src/gui/accountsgui/accountview.cpp | 2 ++ src/gui/accountsgui/accountview.h | 14 +++----- src/gui/application.cpp | 12 +++---- src/gui/application.h | 6 ++-- src/gui/localactivitywidget.cpp | 1 + src/gui/localactivitywidget.h | 2 +- src/gui/main.cpp | 1 - .../newaccountwizardcontroller.cpp | 2 -- src/gui/syncerrorwidget.cpp | 1 + ...owncloudgui.cpp => traymenucontroller.cpp} | 32 +++++++++---------- .../{owncloudgui.h => traymenucontroller.h} | 6 ++-- 12 files changed, 38 insertions(+), 43 deletions(-) rename src/gui/{owncloudgui.cpp => traymenucontroller.cpp} (86%) rename src/gui/{owncloudgui.h => traymenucontroller.h} (93%) diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 2f507783d60..705c677319e 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -28,7 +28,7 @@ set(client_SRCS networkinformation.cpp networksettings.cpp openfilemanager.cpp - owncloudgui.cpp + traymenucontroller.cpp localactivitywidget.cpp protocolitem.cpp syncerrorwidget.cpp diff --git a/src/gui/accountsgui/accountview.cpp b/src/gui/accountsgui/accountview.cpp index b3cd3da89d0..ce1cbdfccd3 100644 --- a/src/gui/accountsgui/accountview.cpp +++ b/src/gui/accountsgui/accountview.cpp @@ -16,6 +16,8 @@ #include "accountview.h" #include "ui_accountview.h" +#include + namespace OCC { AccountView::AccountView(QWidget *parent) diff --git a/src/gui/accountsgui/accountview.h b/src/gui/accountsgui/accountview.h index b0c53f5cd0e..bbd257b3909 100644 --- a/src/gui/accountsgui/accountview.h +++ b/src/gui/accountsgui/accountview.h @@ -16,18 +16,12 @@ #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; +// class QModelIndex; +// class QNetworkReply; +// class QLabel; +// class QStandardItemModel; namespace OCC { class AccountModalWidget; diff --git a/src/gui/application.cpp b/src/gui/application.cpp index 03f00af6d30..cdd95d08e66 100644 --- a/src/gui/application.cpp +++ b/src/gui/application.cpp @@ -51,7 +51,7 @@ QString Application::displayLanguage() const return _displayLanguage; } -ownCloudGui *Application::gui() const +TrayMenuController *Application::gui() const { return _gui; } @@ -139,7 +139,7 @@ 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(accountState, &AccountState::stateChanged, _gui.data(), &TrayMenuController::slotComputeOverallSyncStatus); connect(account, &Account::serverVersionChanged, _gui.data(), [account, this] { _gui->slotTrayMessageIfServerUnsupported(account); }); // todo dc-310 - this does not belong here! This can be done in the folder man when it's given a "new" account @@ -199,11 +199,11 @@ void Application::buildAppGuis() // Setting up the gui class will allow tray notifications for the // setup that follows, like folder setup - _gui = new ownCloudGui(this); - connect(_gui, &ownCloudGui::requestShowAbout, _mainController, &MainWindowController::onAbout); - connect(_gui, &ownCloudGui::requestShowHelp, _mainController, &MainWindowController::onHelp); + _gui = new TrayMenuController(this); + connect(_gui, &TrayMenuController::requestShowAbout, _mainController, &MainWindowController::onAbout); + connect(_gui, &TrayMenuController::requestShowHelp, _mainController, &MainWindowController::onHelp); - connect(FolderMan::instance()->socketApi(), &SocketApi::shareCommandReceived, _gui.data(), &ownCloudGui::slotShowShareInBrowser); + connect(FolderMan::instance()->socketApi(), &SocketApi::shareCommandReceived, _gui.data(), &TrayMenuController::slotShowShareInBrowser); } std::unique_ptr Application::createInstance(Platform *platform, const QString &displayLanguage, bool debugMode) diff --git a/src/gui/application.h b/src/gui/application.h index 7f92b815e80..f149c17d78d 100644 --- a/src/gui/application.h +++ b/src/gui/application.h @@ -17,8 +17,8 @@ #include "gui/owncloudguilib.h" #include "folderman.h" -#include "owncloudgui.h" #include "platform.h" +#include "traymenucontroller.h" #include #include @@ -55,7 +55,7 @@ class OWNCLOUDGUI_EXPORT Application : public QObject bool debugMode(); - ownCloudGui *gui() const; + TrayMenuController *gui() 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! @@ -96,7 +96,7 @@ protected Q_SLOTS: private: explicit Application(Platform *platform, const QString &displayLanguage, bool debugMode); - QPointer _gui = {}; + QPointer _gui = {}; MainWindow *_mainWin = nullptr; MainWindowController *_mainController = nullptr; 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 25a4bcd7c12..5af6c5bd057 100644 --- a/src/gui/main.cpp +++ b/src/gui/main.cpp @@ -443,7 +443,6 @@ int main(int argc, char **argv) QObject::connect(platform.get(), &Platform::requestAttention, ocApp.get(), &Application::ensureVisible); - // 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; diff --git a/src/gui/newaccountwizard/newaccountwizardcontroller.cpp b/src/gui/newaccountwizard/newaccountwizardcontroller.cpp index 4e1e250c828..0cc4acdeabc 100644 --- a/src/gui/newaccountwizard/newaccountwizardcontroller.cpp +++ b/src/gui/newaccountwizard/newaccountwizardcontroller.cpp @@ -19,11 +19,9 @@ #include "application.h" #include "authsuccesspagecontroller.h" #include "common/utility.h" -#include "mainwindow/mainwindow.h" #include "newaccountmodel.h" #include "newaccountwizard.h" #include "oauthpagecontroller.h" -#include "owncloudgui.h" #include "theme.h" #include "urlpagecontroller.h" 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/owncloudgui.cpp b/src/gui/traymenucontroller.cpp similarity index 86% rename from src/gui/owncloudgui.cpp rename to src/gui/traymenucontroller.cpp index dbc703cbb21..df5a6169cb7 100644 --- a/src/gui/owncloudgui.cpp +++ b/src/gui/traymenucontroller.cpp @@ -12,7 +12,7 @@ * for more details. */ -#include "owncloudgui.h" +#include "traymenucontroller.h" #include "account.h" #include "accountmanager.h" #include "accountstate.h" @@ -56,13 +56,13 @@ SyncResult::Status trayOverallStatus() return result.overallStatus().status(); } -ownCloudGui::ownCloudGui(Application *parent) +TrayMenuController::TrayMenuController(Application *parent) : QObject(parent) , _tray(new QSystemTrayIcon(this)) , _app(parent) { - connect(_tray, &QSystemTrayIcon::activated, this, &ownCloudGui::slotTrayClicked); + connect(_tray, &QSystemTrayIcon::activated, this, &TrayMenuController::slotTrayClicked); setupTrayContextMenu(); @@ -76,14 +76,14 @@ ownCloudGui::ownCloudGui(Application *parent) // 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); + connect(folderMan, &FolderMan::folderSyncStateChange, this, &TrayMenuController::slotSyncStateChange); } -ownCloudGui::~ownCloudGui() +TrayMenuController::~TrayMenuController() { } -void ownCloudGui::slotTrayClicked(QSystemTrayIcon::ActivationReason reason) +void TrayMenuController::slotTrayClicked(QSystemTrayIcon::ActivationReason reason) { // Left click if (reason == QSystemTrayIcon::Trigger) { @@ -95,7 +95,7 @@ void ownCloudGui::slotTrayClicked(QSystemTrayIcon::ActivationReason reason) } } -void ownCloudGui::slotSyncStateChange(Folder *folder) +void TrayMenuController::slotSyncStateChange(Folder *folder) { slotComputeOverallSyncStatus(); @@ -108,7 +108,7 @@ void ownCloudGui::slotSyncStateChange(Folder *folder) qCInfo(lcApplication) << "Sync state changed for folder " << folder->remoteUrl().toString() << ": " << Utility::enumToDisplayName(result.status()); } -void ownCloudGui::slotTrayMessageIfServerUnsupported(Account *account) +void TrayMenuController::slotTrayMessageIfServerUnsupported(Account *account) { if (account->serverSupportLevel() != Account::ServerSupportLevel::Supported) { slotShowTrayMessage(tr("Unsupported Server Version"), @@ -119,20 +119,20 @@ void ownCloudGui::slotTrayMessageIfServerUnsupported(Account *account) } } -QIcon ownCloudGui::getTrayStatusIcon(const SyncResult::Status &status) const +QIcon TrayMenuController::getTrayStatusIcon(const SyncResult::Status &status) const { auto contextMenuVisible = _tray->contextMenu() && _tray->contextMenu()->isVisible(); return Theme::instance()->themeTrayIcon(SyncResult{status}, contextMenuVisible); } -void ownCloudGui::slotComputeOverallSyncStatus() +void TrayMenuController::slotComputeOverallSyncStatus() { auto status = trayOverallStatus(); const QIcon statusIcon = getTrayStatusIcon(status); _tray->setIcon(statusIcon); } -void ownCloudGui::setupTrayContextMenu() +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 @@ -167,22 +167,22 @@ void ownCloudGui::setupTrayContextMenu() } if (!Theme::instance()->helpUrl().isEmpty()) { - menu->addAction(tr("Help"), this, &ownCloudGui::requestShowHelp); + menu->addAction(tr("Help"), this, &TrayMenuController::requestShowHelp); } if (! Theme::instance()->about().isEmpty()) { - menu->addAction(tr("About %1").arg(Theme::instance()->appNameGUI()), this, &ownCloudGui::requestShowAbout); + menu->addAction(tr("About %1").arg(Theme::instance()->appNameGUI()), this, &TrayMenuController::requestShowAbout); } menu->addAction(tr("Quit %1").arg(Theme::instance()->appNameGUI()), _app, &QApplication::quit); } -void ownCloudGui::slotShowTrayMessage(const QString &title, const QString &msg, const QIcon &icon) +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 ownCloudGui::slotShowOptionalTrayMessage(const QString &title, const QString &msg, const QIcon &icon) +void TrayMenuController::slotShowOptionalTrayMessage(const QString &title, const QString &msg, const QIcon &icon) { ConfigFile cfg; if (cfg.optionalDesktopNotifications()) { @@ -190,7 +190,7 @@ void ownCloudGui::slotShowOptionalTrayMessage(const QString &title, const QStrin } } -void ownCloudGui::slotShowShareInBrowser(const QString &sharePath, const QString &localPath) +void TrayMenuController::slotShowShareInBrowser(const QString &sharePath, const QString &localPath) { QString file; const auto folder = FolderMan::instance()->folderForPath(localPath, &file); diff --git a/src/gui/owncloudgui.h b/src/gui/traymenucontroller.h similarity index 93% rename from src/gui/owncloudgui.h rename to src/gui/traymenucontroller.h index 5104b0c7970..7a30cdf00d2 100644 --- a/src/gui/owncloudgui.h +++ b/src/gui/traymenucontroller.h @@ -42,12 +42,12 @@ 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; + explicit TrayMenuController(Application *parent = nullptr); + ~TrayMenuController() override; Q_SIGNALS: void requestShowAbout(); From 04517e37ccadaab0b636cf75dcf5b3944ab16fc1 Mon Sep 17 00:00:00 2001 From: Modspike Date: Fri, 26 Jun 2026 11:12:51 +0200 Subject: [PATCH 17/24] cleanup related to tray menu controller also removed a bunch of dead includes here and ther --- src/gui/accountsgui/accountview.h | 5 ----- src/gui/application.cpp | 35 ++++++++++++----------------- src/gui/application.h | 15 ++++++------- src/gui/folder.cpp | 4 ++-- src/gui/traymenucontroller.cpp | 37 +++++++++++-------------------- src/gui/traymenucontroller.h | 19 +--------------- src/gui/updater/ocupdater.cpp | 2 +- src/libsync/account.cpp | 2 +- src/libsync/account.h | 2 +- 9 files changed, 40 insertions(+), 81 deletions(-) diff --git a/src/gui/accountsgui/accountview.h b/src/gui/accountsgui/accountview.h index bbd257b3909..ad2903d5e50 100644 --- a/src/gui/accountsgui/accountview.h +++ b/src/gui/accountsgui/accountview.h @@ -18,11 +18,6 @@ #include -// class QModelIndex; -// class QNetworkReply; -// class QLabel; -// class QStandardItemModel; - namespace OCC { class AccountModalWidget; diff --git a/src/gui/application.cpp b/src/gui/application.cpp index cdd95d08e66..04cf7367dc9 100644 --- a/src/gui/application.cpp +++ b/src/gui/application.cpp @@ -29,6 +29,7 @@ #include "mainwindow/mainwindowcontroller.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; } -TrayMenuController *Application::gui() const +TrayMenuController *Application::tray() const { - return _gui; + return _trayController; } Application *Application::_instance = nullptr; @@ -103,28 +104,20 @@ 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() +QMainWindow *Application::mainWindow() const { return _mainWin; } -void Application::ensureVisible() +void Application::ensureVisible() const { if (_mainWin) _mainWin->ensureVisible(); } -void Application::showModalWidget(ModalWrapperWidget *wrapper) +void Application::showModalWidget(ModalWrapperWidget *wrapper) const { if (_mainWin) _mainWin->showModalWidget(wrapper); @@ -139,8 +132,8 @@ 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(), &TrayMenuController::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 dc-310 - 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) @@ -180,7 +173,7 @@ void Application::updateAutoRun(bool firstRun) void Application::slotUseMonoIconsChanged(bool) { - _gui->slotComputeOverallSyncStatus(); + _trayController->slotComputeOverallSyncStatus(); } bool Application::debugMode() @@ -190,7 +183,7 @@ bool Application::debugMode() void Application::buildAppGuis() { - Q_ASSERT(!_mainWin && !_gui); + Q_ASSERT(!_mainWin && !_trayController); _mainWin = new MainWindow(); _mainController = new MainWindowController(_mainWin, this); @@ -199,11 +192,11 @@ void Application::buildAppGuis() // Setting up the gui class will allow tray notifications for the // setup that follows, like folder setup - _gui = new TrayMenuController(this); - connect(_gui, &TrayMenuController::requestShowAbout, _mainController, &MainWindowController::onAbout); - connect(_gui, &TrayMenuController::requestShowHelp, _mainController, &MainWindowController::onHelp); + _trayController = new TrayMenuController(this); + connect(_trayController, &TrayMenuController::requestShowAbout, _mainController, &MainWindowController::onAbout); + connect(_trayController, &TrayMenuController::requestShowHelp, _mainController, &MainWindowController::onHelp); - connect(FolderMan::instance()->socketApi(), &SocketApi::shareCommandReceived, _gui.data(), &TrayMenuController::slotShowShareInBrowser); + connect(FolderMan::instance()->socketApi(), &SocketApi::shareCommandReceived, _trayController, &TrayMenuController::slotShowShareInBrowser); } std::unique_ptr Application::createInstance(Platform *platform, const QString &displayLanguage, bool debugMode) diff --git a/src/gui/application.h b/src/gui/application.h index f149c17d78d..0973020916a 100644 --- a/src/gui/application.h +++ b/src/gui/application.h @@ -14,9 +14,8 @@ #pragma once -#include "gui/owncloudguilib.h" - #include "folderman.h" +#include "gui/owncloudguilib.h" #include "platform.h" #include "traymenucontroller.h" @@ -42,6 +41,7 @@ class MainWindowController; class AccountsGuiController; class ModalWrapperWidget; + /** * @brief The Application class * @ingroup gui @@ -55,19 +55,19 @@ class OWNCLOUDGUI_EXPORT Application : public QObject bool debugMode(); - TrayMenuController *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(); + QMainWindow *mainWindow() const; // redirect to MainWindow::ensureVisible -> protect access to main window interface - void ensureVisible(); + 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); + void showModalWidget(ModalWrapperWidget *wrapper) const; QString displayLanguage() const; @@ -96,11 +96,10 @@ protected Q_SLOTS: private: explicit Application(Platform *platform, const QString &displayLanguage, bool debugMode); - QPointer _gui = {}; - MainWindow *_mainWin = nullptr; MainWindowController *_mainController = nullptr; AccountsGuiController *_accountsGuiController = nullptr; + TrayMenuController *_trayController = nullptr; const bool _debugMode = false; QString _displayLanguage; diff --git a/src/gui/folder.cpp b/src/gui/folder.cpp index 07ee1100b2c..c843d980eea 100644 --- a/src/gui/folder.cpp +++ b/src/gui/folder.cpp @@ -422,7 +422,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 +1028,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) diff --git a/src/gui/traymenucontroller.cpp b/src/gui/traymenucontroller.cpp index df5a6169cb7..a7294655cce 100644 --- a/src/gui/traymenucontroller.cpp +++ b/src/gui/traymenucontroller.cpp @@ -13,27 +13,16 @@ */ #include "traymenucontroller.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 "resources/resources.h" #include -#include -#include -#include +#include #ifdef Q_OS_WIN #include @@ -56,10 +45,9 @@ SyncResult::Status trayOverallStatus() return result.overallStatus().status(); } -TrayMenuController::TrayMenuController(Application *parent) +TrayMenuController::TrayMenuController(QObject *parent) : QObject(parent) , _tray(new QSystemTrayIcon(this)) - , _app(parent) { connect(_tray, &QSystemTrayIcon::activated, this, &TrayMenuController::slotTrayClicked); @@ -141,22 +129,23 @@ void TrayMenuController::setupTrayContextMenu() _tray->setContextMenu(menu); + auto app = ocApp(); // Populate the context menu now. - menu->addAction(Theme::instance()->applicationIcon(), tr("Show %1").arg(Theme::instance()->appNameGUI()), ocApp(), &Application::ensureVisible); + menu->addAction(Theme::instance()->applicationIcon(), tr("Show %1").arg(Theme::instance()->appNameGUI()), app, &Application::ensureVisible); menu->addSeparator(); - if (_app->debugMode()) { + if (ocApp()->debugMode()) { auto *debugMenu = menu->addMenu(QStringLiteral("Debug actions")); - debugMenu->addAction(QStringLiteral("Crash if asserts enabled - OC_ENSURE"), _app, [] { + 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"), _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->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); @@ -174,7 +163,7 @@ void TrayMenuController::setupTrayContextMenu() menu->addAction(tr("About %1").arg(Theme::instance()->appNameGUI()), this, &TrayMenuController::requestShowAbout); } - menu->addAction(tr("Quit %1").arg(Theme::instance()->appNameGUI()), _app, &QApplication::quit); + menu->addAction(tr("Quit %1").arg(Theme::instance()->appNameGUI()), this, &QApplication::quit); } void TrayMenuController::slotShowTrayMessage(const QString &title, const QString &msg, const QIcon &icon) diff --git a/src/gui/traymenucontroller.h b/src/gui/traymenucontroller.h index 7a30cdf00d2..ae701280728 100644 --- a/src/gui/traymenucontroller.h +++ b/src/gui/traymenucontroller.h @@ -15,28 +15,18 @@ #pragma once #include "gui/owncloudguilib.h" -#include "progressdispatcher.h" #include "syncresult.h" -#include #include #include #include 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 @@ -46,7 +36,7 @@ class OWNCLOUDGUI_EXPORT TrayMenuController : public QObject { Q_OBJECT public: - explicit TrayMenuController(Application *parent = nullptr); + explicit TrayMenuController(QObject *parent); ~TrayMenuController() override; Q_SIGNALS: @@ -76,13 +66,6 @@ public Q_SLOTS: QSystemTrayIcon *_tray; QPointer _shareDialog; - - // dc-310 get rid of this member and just use ocApp() - 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/ocupdater.cpp b/src/gui/updater/ocupdater.cpp index ecfe561ba58..fa1c2335f0c 100644 --- a/src/gui/updater/ocupdater.cpp +++ b/src/gui/updater/ocupdater.cpp @@ -49,7 +49,7 @@ 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) 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(); From c4adacf6e37943fdf1b6ebb2228153a33f3cae83 Mon Sep 17 00:00:00 2001 From: Modspike Date: Fri, 26 Jun 2026 11:55:05 +0200 Subject: [PATCH 18/24] nothing interesting here just amended a comment and removed some whitespace --- src/gui/application.cpp | 4 ++-- src/gui/main.cpp | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/gui/application.cpp b/src/gui/application.cpp index 04cf7367dc9..21eadb8fc73 100644 --- a/src/gui/application.cpp +++ b/src/gui/application.cpp @@ -135,8 +135,8 @@ void Application::slotAccountStateAdded(AccountState *accountState) const connect(accountState, &AccountState::stateChanged, _trayController, &TrayMenuController::slotComputeOverallSyncStatus); connect(account, &Account::serverVersionChanged, _trayController, &TrayMenuController::slotTrayMessageIfServerUnsupported); - // todo dc-310 - 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) + // 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); }); diff --git a/src/gui/main.cpp b/src/gui/main.cpp index 5af6c5bd057..63ecf028865 100644 --- a/src/gui/main.cpp +++ b/src/gui/main.cpp @@ -438,9 +438,7 @@ int main(int argc, char **argv) } 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(&singleApplication, &KDSingleApplication::messageReceived, ocApp.get(), [&](const QByteArray &message) { From 14d44716add07d4238da0df25b7b07c70d6956d8 Mon Sep 17 00:00:00 2001 From: Modspike Date: Fri, 26 Jun 2026 14:48:52 +0200 Subject: [PATCH 19/24] fixing broken sync on load from config overzealous cleanup of application removed key connection that queued folders loaded from config squis tests should now pass --- src/gui/application.cpp | 9 +++++++++ src/gui/application.h | 3 +++ 2 files changed, 12 insertions(+) diff --git a/src/gui/application.cpp b/src/gui/application.cpp index 21eadb8fc73..ed9a1ae2329 100644 --- a/src/gui/application.cpp +++ b/src/gui/application.cpp @@ -199,11 +199,20 @@ void Application::buildAppGuis() 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 0973020916a..918c6e3238d 100644 --- a/src/gui/application.h +++ b/src/gui/application.h @@ -93,6 +93,9 @@ protected Q_SLOTS: // it's actions void buildAppGuis(); + // this is currently fairly empty, but will be moving other manager init stuff in here. + void setupManagers(); + private: explicit Application(Platform *platform, const QString &displayLanguage, bool debugMode); From 3e6ad18f495fd322577706d94e13064c07cd6b8d Mon Sep 17 00:00:00 2001 From: Modspike Date: Fri, 26 Jun 2026 15:02:02 +0200 Subject: [PATCH 20/24] fixing linux. again. --- src/gui/updater/appimageupdater.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/updater/appimageupdater.cpp b/src/gui/updater/appimageupdater.cpp index 9c14784a31e..6541d614ae7 100644 --- a/src/gui/updater/appimageupdater.cpp +++ b/src/gui/updater/appimageupdater.cpp @@ -178,7 +178,7 @@ void AppImageUpdater::versionInfoArrived(const UpdateInfo &info) }); ModalWrapperWidget *wrapper = new ModalWrapperWidget(widget, ocApp()->mainWindow()); - ocApp()->mainWindow()->showModalWidget(wrapper); + ocApp()->showModalWidget(wrapper); } void AppImageUpdater::backgroundCheckForUpdate() From 35d15b6a6d4121eabfeea9068e72188ffb3bd0ac Mon Sep 17 00:00:00 2001 From: Modspike Date: Fri, 26 Jun 2026 15:32:18 +0200 Subject: [PATCH 21/24] removed dead mainwindow.h includes also added object name to manage account menu --- src/gui/FoldersGui/accountfolderscontroller.cpp | 1 - src/gui/accountsgui/accountview.cpp | 1 + src/gui/accountstate.cpp | 1 - src/gui/folder.cpp | 2 -- src/gui/folderwizard/folderwizard.cpp | 1 - src/gui/networkadapters/resolveurladapter.cpp | 1 - 6 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/gui/FoldersGui/accountfolderscontroller.cpp b/src/gui/FoldersGui/accountfolderscontroller.cpp index aef84830a9b..2803481f4e8 100644 --- a/src/gui/FoldersGui/accountfolderscontroller.cpp +++ b/src/gui/FoldersGui/accountfolderscontroller.cpp @@ -20,7 +20,6 @@ #include "commonstrings.h" #include "configfile.h" #include "foldermodelcontroller.h" -#include "mainwindow/mainwindow.h" #include "selectivesyncwidget.h" #include "guiutility.h" diff --git a/src/gui/accountsgui/accountview.cpp b/src/gui/accountsgui/accountview.cpp index ce1cbdfccd3..3d92335e58b 100644 --- a/src/gui/accountsgui/accountview.cpp +++ b/src/gui/accountsgui/accountview.cpp @@ -42,6 +42,7 @@ void AccountView::setAccountMenuActions(QList actions) 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 { diff --git a/src/gui/accountstate.cpp b/src/gui/accountstate.cpp index a9201bb4565..096410bf33d 100644 --- a/src/gui/accountstate.cpp +++ b/src/gui/accountstate.cpp @@ -20,7 +20,6 @@ #include "libsync/creds/abstractcredentials.h" -#include "gui/mainwindow/mainwindow.h" #include "gui/tlserrordialog.h" #include "socketapi/socketapi.h" diff --git a/src/gui/folder.cpp b/src/gui/folder.cpp index c843d980eea..d14c0e3cb3f 100644 --- a/src/gui/folder.cpp +++ b/src/gui/folder.cpp @@ -31,8 +31,6 @@ #include "folderwatcher.h" #include "libsync/graphapi/spacesmanager.h" #include "localdiscoverytracker.h" -// it is used directly as parent for message box. ignore clangd here -#include "mainwindow/mainwindow.h" #include "scheduling/syncscheduler.h" #include "socketapi/socketapi.h" #include "syncengine.h" diff --git a/src/gui/folderwizard/folderwizard.cpp b/src/gui/folderwizard/folderwizard.cpp index cb8d905f641..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/mainwindow/mainwindow.h" #include "theme.h" #include "gui/folderman.h" diff --git a/src/gui/networkadapters/resolveurladapter.cpp b/src/gui/networkadapters/resolveurladapter.cpp index e36a1fa1398..07dffd43733 100644 --- a/src/gui/networkadapters/resolveurladapter.cpp +++ b/src/gui/networkadapters/resolveurladapter.cpp @@ -17,7 +17,6 @@ #include "abstractcorejob.h" #include "common/utility.h" #include "gui/application.h" -#include "gui/mainwindow/mainwindow.h" #include "gui/tlserrordialog.h" #include From b957f1c42e53f51fcaa52eabaeb75747490b87c9 Mon Sep 17 00:00:00 2001 From: Prajwol Amatya Date: Mon, 29 Jun 2026 10:30:28 +0545 Subject: [PATCH 22/24] test: update account menu selector Signed-off-by: Prajwol Amatya --- test/gui/shared/scripts/names.py | 1 + .../shared/scripts/pageObjects/AccountSetting.py | 13 ++++++------- 2 files changed, 7 insertions(+), 7 deletions(-) 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(): From aab2ea7b6b37a1ea55a9156a065233acd7f0b68e Mon Sep 17 00:00:00 2001 From: Modspike Date: Wed, 1 Jul 2026 11:22:36 +0200 Subject: [PATCH 23/24] added whitespace try to force the never finished license bot to finish! --- src/gui/accountsgui/accountsguicontroller.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gui/accountsgui/accountsguicontroller.cpp b/src/gui/accountsgui/accountsguicontroller.cpp index b6b3ef9e538..ece1debbc5d 100644 --- a/src/gui/accountsgui/accountsguicontroller.cpp +++ b/src/gui/accountsgui/accountsguicontroller.cpp @@ -68,6 +68,7 @@ void AccountsGuiController::onAccountAdded(AccountState *state) Account *account = state->account(); QUuid accountId = account->uuid(); + connect(account, &Account::avatarChanged, this, &AccountsGuiController::onAccountAvatarChanged); auto accountView = new AccountView(nullptr); From 89d18b533cb04bcba6ac63a7e9dd0d4e09862703 Mon Sep 17 00:00:00 2001 From: Modspike Date: Wed, 1 Jul 2026 14:34:13 +0200 Subject: [PATCH 24/24] fixing copyright --- src/gui/accountsgui/accountmodalwidget.cpp | 2 +- src/gui/accountsgui/accountmodalwidget.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/accountsgui/accountmodalwidget.cpp b/src/gui/accountsgui/accountmodalwidget.cpp index 1cbd622c4ff..c4b922d0160 100644 --- a/src/gui/accountsgui/accountmodalwidget.cpp +++ b/src/gui/accountsgui/accountmodalwidget.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) by Hannah von Reth + * 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 diff --git a/src/gui/accountsgui/accountmodalwidget.h b/src/gui/accountsgui/accountmodalwidget.h index c30131ec9cb..aedbabc7f02 100644 --- a/src/gui/accountsgui/accountmodalwidget.h +++ b/src/gui/accountsgui/accountmodalwidget.h @@ -1,5 +1,5 @@ /* - * Copyright (C) by Hannah von Reth + * 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