From 312f7b52d442e548b55a58a57960295e13a011ef Mon Sep 17 00:00:00 2001 From: Alexey Rochev Date: Tue, 26 Dec 2023 00:55:48 +0300 Subject: [PATCH 1/8] Fix crash --- src/ui/screens/mainwindow/mainwindow.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/ui/screens/mainwindow/mainwindow.cpp b/src/ui/screens/mainwindow/mainwindow.cpp index 4717002d..b2eb926a 100644 --- a/src/ui/screens/mainwindow/mainwindow.cpp +++ b/src/ui/screens/mainwindow/mainwindow.cpp @@ -259,7 +259,6 @@ namespace tremotesf { mWindow->restoreState(Settings::instance()->mainWindowState()); mToolBarAction->setChecked(!mToolBar.isHidden()); - mWindow->restoreGeometry(Settings::instance()->mainWindowGeometry()); QObject::connect( &mViewModel, @@ -319,6 +318,14 @@ namespace tremotesf { } ); } + + // restoreGeometry() may call MainWindow::event() but we are still in MainWindow constructor + // Call it on the next event loop iteration + QMetaObject::invokeMethod( + this, + [this] { mWindow->restoreGeometry(Settings::instance()->mainWindowGeometry()); }, + Qt::QueuedConnection + ); } Q_DISABLE_COPY_MOVE(Impl) From 7d7cfe0be34a53f739952d05227461b284d81047 Mon Sep 17 00:00:00 2001 From: Alexey Rochev Date: Tue, 26 Dec 2023 00:34:25 +0300 Subject: [PATCH 2/8] Explicitly activate window on startup only for Wayland --- src/startup/main.cpp | 2 +- src/ui/screens/mainwindow/mainwindow.cpp | 16 +++++++++++++--- src/ui/screens/mainwindow/mainwindow.h | 2 +- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/startup/main.cpp b/src/startup/main.cpp index b1c90a2c..92fdc46a 100644 --- a/src/startup/main.cpp +++ b/src/startup/main.cpp @@ -188,7 +188,7 @@ int main(int argc, char** argv) { const SaveWindowStateDispatcher saveStateDispatcher{}; MainWindow window(std::move(args.files), std::move(args.urls)); - window.showMinimized(args.minimized); + window.initialShow(args.minimized); if (signalHandler.isExitRequested()) { return EXIT_SUCCESS; diff --git a/src/ui/screens/mainwindow/mainwindow.cpp b/src/ui/screens/mainwindow/mainwindow.cpp index b2eb926a..053c4735 100644 --- a/src/ui/screens/mainwindow/mainwindow.cpp +++ b/src/ui/screens/mainwindow/mainwindow.cpp @@ -376,7 +376,13 @@ namespace tremotesf { mTorrentsView.saveState(); } - void activateMainWindow() { activateWindow(mWindow, {}, {}); } +#if defined(TREMOTESF_UNIX_FREEDESKTOP) + void activateMainWindowOnWayland() { + if (KWindowSystem::isPlatformWayland()) { + activeWindowOnWayland(mWindow, {}); + } + } +#endif private: MainWindow* mWindow; @@ -1623,10 +1629,14 @@ namespace tremotesf { QSize MainWindow::sizeHint() const { return minimumSizeHint().expandedTo(QSize(896, 640)); } - void MainWindow::showMinimized(bool minimized) { + void MainWindow::initialShow(bool minimized) { if (!(minimized && Settings::instance()->showTrayIcon() && QSystemTrayIcon::isSystemTrayAvailable())) { show(); - mImpl->activateMainWindow(); +#if defined(TREMOTESF_UNIX_FREEDESKTOP) + // On Wayland we need to explicitly activate our window to consume XDG_ACTIVATION_TOKEN environment variable + // possible set by whoever launched us, both in Qt 6 and Qt 5 (KWindowSystem) paths + mImpl->activateMainWindowOnWayland(); +#endif } } diff --git a/src/ui/screens/mainwindow/mainwindow.h b/src/ui/screens/mainwindow/mainwindow.h index 14557559..72135601 100644 --- a/src/ui/screens/mainwindow/mainwindow.h +++ b/src/ui/screens/mainwindow/mainwindow.h @@ -20,7 +20,7 @@ namespace tremotesf { Q_DISABLE_COPY_MOVE(MainWindow) QSize sizeHint() const override; - void showMinimized(bool minimized); + void initialShow(bool minimized); protected: bool event(QEvent* event) override; From 94d57b985f3f650bb994c21d480c1c38fa32d40e Mon Sep 17 00:00:00 2001 From: Alexey Rochev Date: Tue, 26 Dec 2023 00:52:19 +0300 Subject: [PATCH 3/8] Don't activate dialogs that we've just created --- src/ui/screens/mainwindow/mainwindow.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/ui/screens/mainwindow/mainwindow.cpp b/src/ui/screens/mainwindow/mainwindow.cpp index 053c4735..3a9f8d69 100644 --- a/src/ui/screens/mainwindow/mainwindow.cpp +++ b/src/ui/screens/mainwindow/mainwindow.cpp @@ -833,7 +833,6 @@ namespace tremotesf { auto dialog = new AddTorrentDialog(mViewModel.rpc(), filePath, AddTorrentDialog::Mode::File, mWindow); dialog->setAttribute(Qt::WA_DeleteOnClose); dialog->show(); - activateWindow(dialog); } } @@ -842,7 +841,6 @@ namespace tremotesf { auto dialog = new AddTorrentDialog(mViewModel.rpc(), url, AddTorrentDialog::Mode::Url, mWindow); dialog->setAttribute(Qt::WA_DeleteOnClose); dialog->show(); - activateWindow(dialog); } } From 215b0c461a19a2c0585baa05e1d8d2f7bd6e5250 Mon Sep 17 00:00:00 2001 From: Alexey Rochev Date: Tue, 26 Dec 2023 00:59:29 +0300 Subject: [PATCH 4/8] Combine xdg activation token and startup activation id into a struct --- src/ipc/ipcserver.h | 17 ++++-- src/ipc/ipcserver_dbus_service.cpp | 20 ++++++- src/ipc/ipcserver_socket.cpp | 2 +- src/ui/screens/mainwindow/mainwindow.cpp | 57 +++++++++---------- .../mainwindow/mainwindowviewmodel.cpp | 21 ++++--- .../screens/mainwindow/mainwindowviewmodel.h | 14 ++++- 6 files changed, 78 insertions(+), 53 deletions(-) diff --git a/src/ipc/ipcserver.h b/src/ipc/ipcserver.h index cca88683..d57a9484 100644 --- a/src/ipc/ipcserver.h +++ b/src/ipc/ipcserver.h @@ -5,9 +5,17 @@ #ifndef TREMOTESF_IPCSERVER_H #define TREMOTESF_IPCSERVER_H +#include #include namespace tremotesf { + struct WindowActivationToken { +#ifdef TREMOTESF_UNIX_FREEDESKTOP + std::optional x11StartupNotificationId{}; + std::optional waylandXdfActivationToken{}; +#endif + }; + class IpcServer : public QObject { Q_OBJECT @@ -18,12 +26,9 @@ namespace tremotesf { inline explicit IpcServer(QObject* parent = nullptr) : QObject(parent){}; signals: - void windowActivationRequested( - const QString& torrentHash, const QByteArray& startupNotificationId, const QByteArray& xdgActivationToken - ); - void torrentsAddingRequested( - const QStringList& files, const QStringList& urls, const QByteArray& startupNoficationId - ); + void windowActivationRequested(const QString& torrentHash, const WindowActivationToken& token); + void + torrentsAddingRequested(const QStringList& files, const QStringList& urls, const WindowActivationToken& token); }; } diff --git a/src/ipc/ipcserver_dbus_service.cpp b/src/ipc/ipcserver_dbus_service.cpp index c77bcce7..baf3301c 100644 --- a/src/ipc/ipcserver_dbus_service.cpp +++ b/src/ipc/ipcserver_dbus_service.cpp @@ -16,6 +16,21 @@ SPECIALIZE_FORMATTER_FOR_QDEBUG(QVariantMap) SPECIALIZE_FORMATTER_FOR_QDEBUG(QVariantList) namespace tremotesf { + namespace { + WindowActivationToken platformDataToWindowActivationToken(const QVariantMap& platformData) { + WindowActivationToken token{}; + if (const auto startupId = platformData.value(IpcDbusService::desktopStartupIdField).toByteArray(); + !startupId.isEmpty()) { + token.x11StartupNotificationId = startupId; + } + if (const auto activationToken = platformData.value(IpcDbusService::xdgActivationTokenField).toByteArray(); + !activationToken.isEmpty()) { + token.waylandXdfActivationToken = activationToken; + } + return token; + } + } + IpcDbusService::IpcDbusService(IpcServerDbus* ipcServer, QObject* parent) : QObject(parent), mIpcServer(ipcServer) { new OrgFreedesktopApplicationAdaptor(this); @@ -39,8 +54,7 @@ namespace tremotesf { logInfo("Window activation requested, platform_data = {}", platform_data); emit mIpcServer->windowActivationRequested( platform_data.value(torrentHashField).toString(), - platform_data.value(desktopStartupIdField).toByteArray(), - platform_data.value(xdgActivationTokenField).toByteArray() + platformDataToWindowActivationToken(platform_data) ); } @@ -57,7 +71,7 @@ namespace tremotesf { } } } - emit mIpcServer->torrentsAddingRequested(files, urls, platform_data.value(desktopStartupIdField).toByteArray()); + emit mIpcServer->torrentsAddingRequested(files, urls, platformDataToWindowActivationToken(platform_data)); } void IpcDbusService::ActivateAction( diff --git a/src/ipc/ipcserver_socket.cpp b/src/ipc/ipcserver_socket.cpp index 6f83898b..6e68bbfd 100644 --- a/src/ipc/ipcserver_socket.cpp +++ b/src/ipc/ipcserver_socket.cpp @@ -88,7 +88,7 @@ namespace tremotesf { const QByteArray message(socket->readAll()); if (message.size() == 1 && message.front() == activateWindowMessage) { logInfo("IpcServerSocket: window activation requested"); - emit windowActivationRequested({}, {}, {}); + emit windowActivationRequested({}, {}); } else { QCborParserError error{}; const auto cbor = QCborValue::fromCbor(message, &error); diff --git a/src/ui/screens/mainwindow/mainwindow.cpp b/src/ui/screens/mainwindow/mainwindow.cpp index 3a9f8d69..ec30ffe2 100644 --- a/src/ui/screens/mainwindow/mainwindow.cpp +++ b/src/ui/screens/mainwindow/mainwindow.cpp @@ -1389,10 +1389,7 @@ namespace tremotesf { bool shouldShowWindows() const { return mWindow->isHidden() || mWindow->isMinimized(); } - void showWindowsAndActivateMainOrDialog( - [[maybe_unused]] const QByteArray& newStartupNotificationId = {}, - [[maybe_unused]] const QByteArray& newXdgActivationToken = {} - ) { + void showWindowsAndActivateMainOrDialog([[maybe_unused]] const WindowActivationToken& activationToken = {}) { logInfo("Showing windows"); if constexpr (targetOs == TargetOs::UnixMacOS) { if (isNSAppHidden()) { @@ -1412,31 +1409,28 @@ namespace tremotesf { lastDialog = widget; } } - QWidget* widgetToActivate = qApp->activeModalWidget(); - if (!widgetToActivate) { - widgetToActivate = lastDialog; + QWidget* dialogToActivate = qApp->activeModalWidget(); + if (!dialogToActivate) { + dialogToActivate = lastDialog; } - if (!widgetToActivate) { - widgetToActivate = mWindow; + activateWindow(mWindow, activationToken); + if (dialogToActivate) { + activateWindow(dialogToActivate); } - activateWindow(widgetToActivate, newStartupNotificationId, newXdgActivationToken); } - void activateWindow( - QWidget* widgetToActivate, - [[maybe_unused]] const QByteArray& newStartupNotificationId = {}, - [[maybe_unused]] const QByteArray& newXdgActivationToken = {} - ) { + void + activateWindow(QWidget* widgetToActivate, [[maybe_unused]] const WindowActivationToken& activationToken = {}) { logInfo("Activating window {}", *widgetToActivate); #ifdef TREMOTESF_UNIX_FREEDESKTOP switch (KWindowSystem::platform()) { case KWindowSystem::Platform::X11: logDebug("Windowing system is X11"); - activeWindowOnX11(widgetToActivate, newStartupNotificationId); + activeWindowOnX11(widgetToActivate, activationToken.x11StartupNotificationId); break; case KWindowSystem::Platform::Wayland: logDebug("Windowing system is Wayland"); - activeWindowOnWayland(widgetToActivate, newXdgActivationToken); + activeWindowOnWayland(widgetToActivate, activationToken.waylandXdfActivationToken); break; default: logWarning("Unknown windowing system"); @@ -1449,30 +1443,31 @@ namespace tremotesf { } #ifdef TREMOTESF_UNIX_FREEDESKTOP - void activeWindowOnX11(QWidget* widgetToActivate, const QByteArray& newStartupNotificationId) { - if (!newStartupNotificationId.isEmpty()) { - logInfo("Removing startup notification with id '{}'", newStartupNotificationId); - KStartupInfo::setNewStartupId(widgetToActivate->windowHandle(), newStartupNotificationId); - KStartupInfo::appStarted(newStartupNotificationId); + void activeWindowOnX11(QWidget* widgetToActivate, const std::optional& newStartupNotificationId) { + if (newStartupNotificationId.has_value()) { + logInfo("Removing startup notification with id '{}'", *newStartupNotificationId); + KStartupInfo::setNewStartupId(widgetToActivate->windowHandle(), *newStartupNotificationId); + KStartupInfo::appStarted(*newStartupNotificationId); } widgetToActivate->activateWindow(); } void activeWindowOnWayland( - [[maybe_unused]] QWidget* widgetToActivate, [[maybe_unused]] const QByteArray& newXdgActivationToken + [[maybe_unused]] QWidget* widgetToActivate, + [[maybe_unused]] const std::optional& newXdgActivationToken ) { # if QT_VERSION_MAJOR >= 6 - if (!newXdgActivationToken.isEmpty()) { - logInfo("Updating xdg-activation token with new value '{}'", newXdgActivationToken); + if (newXdgActivationToken.has_value()) { + logInfo("Updating xdg-activation token with new value '{}'", *newXdgActivationToken); // Qt gets new token from XDG_ACTIVATION_TOKEN environment variable // It we be read and unset in QWidget::activateWindow() call below - qputenv(xdgActivationTokenEnvVariable, newXdgActivationToken); + qputenv(xdgActivationTokenEnvVariable, *newXdgActivationToken); } widgetToActivate->activateWindow(); # elif KWINDOWSYSTEM_VERSION >= QT_VERSION_CHECK(5, 89, 0) - if (!newXdgActivationToken.isEmpty()) { - logInfo("Updating xdg-activation token with new value '{}'", newXdgActivationToken); - KWindowSystem::setCurrentXdgActivationToken(newXdgActivationToken); + if (newXdgActivationToken.has_value()) { + logInfo("Updating xdg-activation token with new value '{}'", *newXdgActivationToken); + KWindowSystem::setCurrentXdgActivationToken(*newXdgActivationToken); } if (const auto handle = widgetToActivate->windowHandle(); handle) { KWindowSystem::activateWindow(handle); @@ -1543,12 +1538,12 @@ namespace tremotesf { &mViewModel, &MainWindowViewModel::showAddTorrentDialogs, this, - [messageWidget, this](const auto& files, const auto& urls) { + [messageWidget, this](const auto& files, const auto& urls, const auto& activationToken) { if (messageWidget->isVisible()) { messageWidget->animatedHide(); } const bool wasHidden = mWindow->isHidden(); - showWindowsAndActivateMainOrDialog(); + showWindowsAndActivateMainOrDialog(activationToken); if (wasHidden) { runAfterDelay([files, urls, this] { showAddTorrentFileDialogs(files); diff --git a/src/ui/screens/mainwindow/mainwindowviewmodel.cpp b/src/ui/screens/mainwindow/mainwindowviewmodel.cpp index aa7ee3bc..24bd30f7 100644 --- a/src/ui/screens/mainwindow/mainwindowviewmodel.cpp +++ b/src/ui/screens/mainwindow/mainwindowviewmodel.cpp @@ -63,7 +63,7 @@ namespace tremotesf { QMetaObject::invokeMethod( this, [commandLineFiles = std::move(commandLineFiles), commandLineUrls = std::move(commandLineUrls), this] { - addTorrents(commandLineFiles, commandLineUrls, true); + addTorrents(commandLineFiles, commandLineUrls, {}, true); }, Qt::QueuedConnection ); @@ -74,16 +74,16 @@ namespace tremotesf { ipcServer, &IpcServer::windowActivationRequested, this, - [=, this](const auto&, const auto& startupNoficationId, const auto& xdgActivationToken) { - emit showWindow(startupNoficationId, xdgActivationToken); - } + [=, this](const auto&, const auto& activationToken) { emit showWindow(activationToken); } ); QObject::connect( ipcServer, &IpcServer::torrentsAddingRequested, this, - [=, this](const auto& files, const auto& urls) { addTorrents(files, urls); } + [=, this](const auto& files, const auto& urls, const auto& activationToken) { + addTorrents(files, urls, activationToken); + } ); #ifdef Q_OS_MACOS @@ -106,7 +106,7 @@ namespace tremotesf { if ((!mPendingFilesToOpen.empty() || !mPendingUrlsToOpen.empty())) { const QStringList files = std::move(mPendingFilesToOpen); const QStringList urls = std::move(mPendingUrlsToOpen); - emit showAddTorrentDialogs(files, urls); + emit showAddTorrentDialogs(files, urls, {}); } } }); @@ -169,7 +169,7 @@ namespace tremotesf { void MainWindowViewModel::setupNotificationsController(QSystemTrayIcon* trayIcon) { const auto controller = NotificationsController::createInstance(trayIcon, &mRpc, this); QObject::connect(controller, &NotificationsController::notificationClicked, this, [this] { - emit showWindow({}, {}); + emit showWindow({}); }); } @@ -185,13 +185,16 @@ namespace tremotesf { } void MainWindowViewModel::addTorrents( - const QStringList& files, const QStringList& urls, bool showDelayedMessageWithDelay + const QStringList& files, + const QStringList& urls, + const WindowActivationToken& activationToken, + bool showDelayedMessageWithDelay ) { logInfo("MainWindowViewModel: addTorrents() called"); logInfo("MainWindowViewModel: files = {}", files); logInfo("MainWindowViewModel: urls = {}", urls); if (mRpc.isConnected()) { - emit showAddTorrentDialogs(files, urls); + emit showAddTorrentDialogs(files, urls, activationToken); } else { mPendingFilesToOpen.append(files); mPendingUrlsToOpen.append(urls); diff --git a/src/ui/screens/mainwindow/mainwindowviewmodel.h b/src/ui/screens/mainwindow/mainwindowviewmodel.h index 85623ab6..8247b504 100644 --- a/src/ui/screens/mainwindow/mainwindowviewmodel.h +++ b/src/ui/screens/mainwindow/mainwindowviewmodel.h @@ -8,6 +8,7 @@ #include #include +#include "ipc/ipcserver.h" #include "rpc/rpc.h" class QByteArray; @@ -42,11 +43,18 @@ namespace tremotesf { QStringList mPendingUrlsToOpen{}; QTimer* delayedTorrentAddMessageTimer{}; - void addTorrents(const QStringList& files, const QStringList& urls, bool showDelayedMessageWithDelay = false); + void addTorrents( + const QStringList& files, + const QStringList& urls, + const WindowActivationToken& activationToken = {}, + bool showDelayedMessageWithDelay = false + ); signals: - void showWindow(const QByteArray& newStartupNotificationId, const QByteArray& newXdgActivationToken); - void showAddTorrentDialogs(const QStringList& files, const QStringList& urls); + void showWindow(const WindowActivationToken& activationToken); + void showAddTorrentDialogs( + const QStringList& files, const QStringList& urls, const WindowActivationToken& activationToken + ); void showDelayedTorrentAddMessage(const QStringList& torrents); }; } From e341eaba382055b048500f5cf4279ea13fce3ba8 Mon Sep 17 00:00:00 2001 From: Alexey Rochev Date: Tue, 26 Dec 2023 01:11:35 +0300 Subject: [PATCH 5/8] Remove artificial delays after showing window --- src/ui/screens/mainwindow/mainwindow.cpp | 108 +++++++++-------------- 1 file changed, 43 insertions(+), 65 deletions(-) diff --git a/src/ui/screens/mainwindow/mainwindow.cpp b/src/ui/screens/mainwindow/mainwindow.cpp index ec30ffe2..b254e809 100644 --- a/src/ui/screens/mainwindow/mainwindow.cpp +++ b/src/ui/screens/mainwindow/mainwindow.cpp @@ -278,11 +278,15 @@ namespace tremotesf { ); if (mViewModel.performStartupAction() == MainWindowViewModel::StartupActionResult::ShowAddServerDialog) { - runAfterDelay([this] { - auto dialog = new ServerEditDialog(nullptr, -1, mWindow); - dialog->setAttribute(Qt::WA_DeleteOnClose); - dialog->open(); - }); + QMetaObject::invokeMethod( + this, + [this] { + auto* const dialog = new ServerEditDialog(nullptr, -1, mWindow); + dialog->setAttribute(Qt::WA_DeleteOnClose); + dialog->open(); + }, + Qt::QueuedConnection + ); } QObject::connect(qApp, &QCoreApplication::aboutToQuit, this, [this] { @@ -460,17 +464,10 @@ namespace tremotesf { mConnectionDependentActions.push_back(&mAddTorrentFileAction); QObject::connect(&mAddTorrentLinkAction, &QAction::triggered, this, [this] { - auto showDialog = [this] { - auto dialog = new AddTorrentDialog(mViewModel.rpc(), QString(), AddTorrentDialog::Mode::Url); - dialog->setAttribute(Qt::WA_DeleteOnClose); - dialog->show(); - }; if (mWindow->isHidden()) { showWindowsAndActivateMainOrDialog(); - runAfterDelay(showDialog); - } else { - showDialog(); } + showAddTorrentLinkDialog(); }); mConnectionDependentActions.push_back(&mAddTorrentLinkAction); @@ -792,39 +789,33 @@ namespace tremotesf { } void addTorrentsFiles() { - auto showDialog = [this] { - auto settings = Settings::instance(); - auto directory = settings->rememberOpenTorrentDir() ? settings->lastOpenTorrentDirectory() : QString{}; - if (directory.isEmpty()) { - directory = QDir::homePath(); - } - auto fileDialog = new QFileDialog( - mWindow, - //: File chooser dialog title - qApp->translate("tremotesf", "Select Files"), - directory, - //: Torrent file type. Parentheses and text within them must remain unchanged - qApp->translate("tremotesf", "Torrent Files (*.torrent)") - ); - fileDialog->setAttribute(Qt::WA_DeleteOnClose); - fileDialog->setFileMode(QFileDialog::ExistingFiles); - - QObject::connect(fileDialog, &QFileDialog::accepted, this, [fileDialog, this] { - showAddTorrentFileDialogs(fileDialog->selectedFiles()); - }); - - if constexpr (targetOs == TargetOs::Windows) { - fileDialog->open(); - } else { - fileDialog->show(); - } - }; - if (mWindow->isHidden()) { showWindowsAndActivateMainOrDialog(); - runAfterDelay(showDialog); + } + auto* const settings = Settings::instance(); + auto directory = settings->rememberOpenTorrentDir() ? settings->lastOpenTorrentDirectory() : QString{}; + if (directory.isEmpty()) { + directory = QDir::homePath(); + } + auto* const fileDialog = new QFileDialog( + mWindow, + //: File chooser dialog title + qApp->translate("tremotesf", "Select Files"), + directory, + //: Torrent file type. Parentheses and text within them must remain unchanged + qApp->translate("tremotesf", "Torrent Files (*.torrent)") + ); + fileDialog->setAttribute(Qt::WA_DeleteOnClose); + fileDialog->setFileMode(QFileDialog::ExistingFiles); + + QObject::connect(fileDialog, &QFileDialog::accepted, this, [fileDialog, this] { + showAddTorrentFileDialogs(fileDialog->selectedFiles()); + }); + + if constexpr (targetOs == TargetOs::Windows) { + fileDialog->open(); } else { - showDialog(); + fileDialog->show(); } } @@ -838,12 +829,16 @@ namespace tremotesf { void showAddTorrentLinkDialogs(const QStringList& urls) { for (const QString& url : urls) { - auto dialog = new AddTorrentDialog(mViewModel.rpc(), url, AddTorrentDialog::Mode::Url, mWindow); - dialog->setAttribute(Qt::WA_DeleteOnClose); - dialog->show(); + showAddTorrentLinkDialog(url); } } + void showAddTorrentLinkDialog(const QString& url = {}) { + auto dialog = new AddTorrentDialog(mViewModel.rpc(), url, AddTorrentDialog::Mode::Url, mWindow); + dialog->setAttribute(Qt::WA_DeleteOnClose); + dialog->show(); + } + void updateTorrentActions() { const auto actions = mTorrentMenu->actions(); @@ -1500,15 +1495,6 @@ namespace tremotesf { } } - void runAfterDelay(const std::function& function) { - auto timer = new QTimer(this); - timer->setInterval(100); - timer->setSingleShot(true); - QObject::connect(timer, &QTimer::timeout, this, function); - QObject::connect(timer, &QTimer::timeout, timer, &QTimer::deleteLater); - timer->start(); - } - void openTorrentsFiles() { const QModelIndexList selectedRows(mTorrentsView.selectionModel()->selectedRows()); for (const QModelIndex& index : selectedRows) { @@ -1542,17 +1528,9 @@ namespace tremotesf { if (messageWidget->isVisible()) { messageWidget->animatedHide(); } - const bool wasHidden = mWindow->isHidden(); showWindowsAndActivateMainOrDialog(activationToken); - if (wasHidden) { - runAfterDelay([files, urls, this] { - showAddTorrentFileDialogs(files); - showAddTorrentLinkDialogs(urls); - }); - } else { - showAddTorrentFileDialogs(files); - showAddTorrentLinkDialogs(urls); - } + showAddTorrentFileDialogs(files); + showAddTorrentLinkDialogs(urls); } ); From ce4073e5759fb190405e9660e8f49f90ad786a2b Mon Sep 17 00:00:00 2001 From: Alexey Rochev Date: Wed, 27 Dec 2023 22:47:47 +0300 Subject: [PATCH 6/8] Activate main window when we are adding torrents when disconnected --- src/ui/screens/mainwindow/mainwindow.cpp | 2 +- src/ui/screens/mainwindow/mainwindowviewmodel.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ui/screens/mainwindow/mainwindow.cpp b/src/ui/screens/mainwindow/mainwindow.cpp index b254e809..3fbf191c 100644 --- a/src/ui/screens/mainwindow/mainwindow.cpp +++ b/src/ui/screens/mainwindow/mainwindow.cpp @@ -1538,7 +1538,7 @@ namespace tremotesf { &mViewModel, &MainWindowViewModel::showDelayedTorrentAddMessage, this, - [messageWidget](const QStringList& torrents) { + [this, messageWidget](const QStringList& torrents) { logDebug("MainWindow: showing delayed torrent add message"); messageWidget->setMessageType(KMessageWidget::Information); //: Message shown when user attempts to add torrent while disconnect from server. After that will be list of added torrents diff --git a/src/ui/screens/mainwindow/mainwindowviewmodel.cpp b/src/ui/screens/mainwindow/mainwindowviewmodel.cpp index 24bd30f7..62a7bbb6 100644 --- a/src/ui/screens/mainwindow/mainwindowviewmodel.cpp +++ b/src/ui/screens/mainwindow/mainwindowviewmodel.cpp @@ -199,6 +199,7 @@ namespace tremotesf { mPendingFilesToOpen.append(files); mPendingUrlsToOpen.append(urls); logInfo("Delaying opening torrents until connected to server"); + emit showWindow(activationToken); if (showDelayedMessageWithDelay) { if (delayedTorrentAddMessageTimer) { delayedTorrentAddMessageTimer->stop(); From 329873d628d433fb94134763135fe0ed1b0c61a0 Mon Sep 17 00:00:00 2001 From: Alexey Rochev Date: Wed, 27 Dec 2023 22:55:53 +0300 Subject: [PATCH 7/8] Simplify logic for showing delayed torrent adding message when connecting --- .../mainwindow/mainwindowviewmodel.cpp | 19 +++++++++++-------- .../screens/mainwindow/mainwindowviewmodel.h | 5 +---- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/ui/screens/mainwindow/mainwindowviewmodel.cpp b/src/ui/screens/mainwindow/mainwindowviewmodel.cpp index 62a7bbb6..3c982198 100644 --- a/src/ui/screens/mainwindow/mainwindowviewmodel.cpp +++ b/src/ui/screens/mainwindow/mainwindowviewmodel.cpp @@ -63,7 +63,7 @@ namespace tremotesf { QMetaObject::invokeMethod( this, [commandLineFiles = std::move(commandLineFiles), commandLineUrls = std::move(commandLineUrls), this] { - addTorrents(commandLineFiles, commandLineUrls, {}, true); + addTorrents(commandLineFiles, commandLineUrls, {}); }, Qt::QueuedConnection ); @@ -99,6 +99,7 @@ namespace tremotesf { QObject::connect(&mRpc, &Rpc::connectedChanged, this, [this] { if (mRpc.isConnected()) { if (delayedTorrentAddMessageTimer) { + logInfo("Cancelling showing delayed torrent adding message"); delayedTorrentAddMessageTimer->stop(); delayedTorrentAddMessageTimer->deleteLater(); delayedTorrentAddMessageTimer = nullptr; @@ -185,22 +186,22 @@ namespace tremotesf { } void MainWindowViewModel::addTorrents( - const QStringList& files, - const QStringList& urls, - const WindowActivationToken& activationToken, - bool showDelayedMessageWithDelay + const QStringList& files, const QStringList& urls, const WindowActivationToken& activationToken ) { logInfo("MainWindowViewModel: addTorrents() called"); logInfo("MainWindowViewModel: files = {}", files); logInfo("MainWindowViewModel: urls = {}", urls); - if (mRpc.isConnected()) { + const auto connectionState = mRpc.connectionState(); + if (connectionState == RpcConnectionState::Connected) { emit showAddTorrentDialogs(files, urls, activationToken); } else { mPendingFilesToOpen.append(files); mPendingUrlsToOpen.append(urls); - logInfo("Delaying opening torrents until connected to server"); + logInfo("Postponing opening torrents until connected to server"); emit showWindow(activationToken); - if (showDelayedMessageWithDelay) { + // If we are connecting then wait a bit before showing message + if (connectionState == RpcConnectionState::Connecting) { + logInfo("We are already connecting, wait a bit before showing message"); if (delayedTorrentAddMessageTimer) { delayedTorrentAddMessageTimer->stop(); delayedTorrentAddMessageTimer->deleteLater(); @@ -209,6 +210,7 @@ namespace tremotesf { delayedTorrentAddMessageTimer->setInterval(initialDelayedTorrentAddMessageDelay); delayedTorrentAddMessageTimer->setSingleShot(true); QObject::connect(delayedTorrentAddMessageTimer, &QTimer::timeout, this, [=, this] { + logInfo("Showing delayed torrent adding message"); delayedTorrentAddMessageTimer = nullptr; emit showDelayedTorrentAddMessage(files + urls); }); @@ -220,6 +222,7 @@ namespace tremotesf { ); delayedTorrentAddMessageTimer->start(); } else { + logInfo("Showing delayed torrent adding message"); emit showDelayedTorrentAddMessage(files + urls); } } diff --git a/src/ui/screens/mainwindow/mainwindowviewmodel.h b/src/ui/screens/mainwindow/mainwindowviewmodel.h index 8247b504..00169224 100644 --- a/src/ui/screens/mainwindow/mainwindowviewmodel.h +++ b/src/ui/screens/mainwindow/mainwindowviewmodel.h @@ -44,10 +44,7 @@ namespace tremotesf { QTimer* delayedTorrentAddMessageTimer{}; void addTorrents( - const QStringList& files, - const QStringList& urls, - const WindowActivationToken& activationToken = {}, - bool showDelayedMessageWithDelay = false + const QStringList& files, const QStringList& urls, const WindowActivationToken& activationToken = {} ); signals: From 40c39af378e1a4d88191c0f97b5a9adbe5c59bae Mon Sep 17 00:00:00 2001 From: Alexey Rochev Date: Thu, 28 Dec 2023 01:10:10 +0300 Subject: [PATCH 8/8] Adjust logging levels --- src/ui/screens/mainwindow/mainwindow.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ui/screens/mainwindow/mainwindow.cpp b/src/ui/screens/mainwindow/mainwindow.cpp index 3fbf191c..c2447eac 100644 --- a/src/ui/screens/mainwindow/mainwindow.cpp +++ b/src/ui/screens/mainwindow/mainwindow.cpp @@ -158,7 +158,7 @@ namespace tremotesf { } void showAndRaiseWindow(QWidget* window) { - logDebug( + logInfo( "Showing {}, it is hidden = {}, minimized = {}", *window, window->isHidden(), @@ -1388,7 +1388,7 @@ namespace tremotesf { logInfo("Showing windows"); if constexpr (targetOs == TargetOs::UnixMacOS) { if (isNSAppHidden()) { - logDebug("NSApp is hidden, unhiding it"); + logInfo("NSApp is hidden, unhiding it"); unhideNSApp(); } else { logDebug("NSApp is not hidden");