diff --git a/src/app/application.cpp b/src/app/application.cpp index 5b3124a45..ab595cdfb 100644 --- a/src/app/application.cpp +++ b/src/app/application.cpp @@ -96,6 +96,7 @@ #include "gui/shutdownconfirmdialog.h" #include "gui/uithememanager.h" #include "gui/utils.h" +#include "gui/windowstate.h" #endif // DISABLE_GUI #ifndef DISABLE_WEBUI @@ -138,6 +139,7 @@ Application::Application(int &argc, char **argv) , m_processMemoryPriority(SETTINGS_KEY(u"ProcessMemoryPriority"_qs)) #endif #ifndef DISABLE_GUI + , m_startUpWindowState(u"GUI/StartUpWindowState"_qs) , m_storeNotificationTorrentAdded(NOTIFICATIONS_SETTINGS_KEY(u"TorrentAdded"_qs)) #endif { @@ -222,6 +224,16 @@ MainWindow *Application::mainWindow() return m_window; } +WindowState Application::startUpWindowState() const +{ + return m_startUpWindowState; +} + +void Application::setStartUpWindowState(const WindowState windowState) +{ + m_startUpWindowState = windowState; +} + bool Application::isTorrentAddedNotificationsEnabled() const { return m_storeNotificationTorrentAdded; @@ -726,11 +738,8 @@ try desktopIntegrationMenu->addAction(actionExit); m_desktopIntegration->setMenu(desktopIntegrationMenu); -#endif - const auto *pref = Preferences::instance(); -#ifndef Q_OS_MACOS - const bool isHidden = m_desktopIntegration->isActive() && pref->startMinimized() && pref->minimizeToTray(); + const bool isHidden = m_desktopIntegration->isActive() && (startUpWindowState() == WindowState::Hidden); #else const bool isHidden = false; #endif @@ -740,7 +749,7 @@ try createStartupProgressDialog(); // Add a small delay to avoid "flashing" the progress dialog in case there are not many torrents to restore. m_startupProgressDialog->setMinimumDuration(1000); - if (pref->startMinimized()) + if (startUpWindowState() != WindowState::Normal) m_startupProgressDialog->setWindowState(Qt::WindowMinimized); } else @@ -795,8 +804,14 @@ try disconnect(m_desktopIntegration, &DesktopIntegration::activationRequested, this, &Application::createStartupProgressDialog); // we must not delete menu while it is used by DesktopIntegration auto *oldMenu = m_desktopIntegration->menu(); - const MainWindow::State windowState = (!m_startupProgressDialog || (m_startupProgressDialog->windowState() & Qt::WindowMinimized)) - ? MainWindow::Minimized : MainWindow::Normal; +#ifndef Q_OS_MACOS + const WindowState windowState = !m_startupProgressDialog ? WindowState::Hidden + : (m_startupProgressDialog->windowState() & Qt::WindowMinimized) ? WindowState::Minimized + : WindowState::Normal; +#else + const WindowState windowState = (m_startupProgressDialog->windowState() & Qt::WindowMinimized) + ? WindowState::Minimized : WindowState::Normal; +#endif m_window = new MainWindow(this, windowState); delete oldMenu; delete m_startupProgressDialog; diff --git a/src/app/application.h b/src/app/application.h index 21f1dc132..5ae5f281f 100644 --- a/src/app/application.h +++ b/src/app/application.h @@ -130,6 +130,9 @@ public: DesktopIntegration *desktopIntegration() override; MainWindow *mainWindow() override; + WindowState startUpWindowState() const override; + void setStartUpWindowState(WindowState windowState) override; + bool isTorrentAddedNotificationsEnabled() const override; void setTorrentAddedNotificationsEnabled(bool value) override; #endif @@ -203,6 +206,7 @@ private: #endif #ifndef DISABLE_GUI + SettingValue m_startUpWindowState; SettingValue m_storeNotificationTorrentAdded; DesktopIntegration *m_desktopIntegration = nullptr; diff --git a/src/app/upgrade.cpp b/src/app/upgrade.cpp index 9a22515c5..5882b0b95 100644 --- a/src/app/upgrade.cpp +++ b/src/app/upgrade.cpp @@ -39,13 +39,12 @@ #include "base/profile.h" #include "base/settingsstorage.h" #include "base/settingvalue.h" -#include "base/utils/fs.h" #include "base/utils/io.h" #include "base/utils/string.h" namespace { - const int MIGRATION_VERSION = 4; + const int MIGRATION_VERSION = 5; const QString MIGRATION_VERSION_KEY = u"Meta/MigrationVersion"_qs; void exportWebUIHttpsFiles() @@ -384,6 +383,18 @@ namespace } } #endif + + void migrateStartupWindowState() + { + auto *settingsStorage = SettingsStorage::instance(); + if (settingsStorage->hasKey(u"Preferences/General/StartMinimized"_qs)) + { + const auto startMinimized = settingsStorage->loadValue(u"Preferences/General/StartMinimized"_qs); + const auto minimizeToTray = settingsStorage->loadValue(u"Preferences/General/MinimizeToTray"_qs); + const QString windowState = startMinimized ? (minimizeToTray ? u"Hidden"_qs : u"Minimized"_qs) : u"Normal"_qs; + settingsStorage->storeValue(u"GUI/StartUpWindowState"_qs, windowState); + } + } } bool upgrade(const bool /*ask*/) @@ -413,6 +424,9 @@ bool upgrade(const bool /*ask*/) migrateMemoryPrioritySettings(); #endif + if (version < 5) + migrateStartupWindowState(); + version = MIGRATION_VERSION; } diff --git a/src/base/preferences.cpp b/src/base/preferences.cpp index 101eefd77..1623e7f3d 100644 --- a/src/base/preferences.cpp +++ b/src/base/preferences.cpp @@ -279,16 +279,6 @@ void Preferences::setStatusbarDisplayed(const bool displayed) setValue(u"Preferences/General/StatusbarDisplayed"_qs, displayed); } -bool Preferences::startMinimized() const -{ - return value(u"Preferences/General/StartMinimized"_qs, false); -} - -void Preferences::setStartMinimized(const bool b) -{ - setValue(u"Preferences/General/StartMinimized"_qs, b); -} - bool Preferences::isSplashScreenDisabled() const { return value(u"Preferences/General/NoSplashScreen"_qs, true); diff --git a/src/base/preferences.h b/src/base/preferences.h index 0dde9afef..fa10fca50 100644 --- a/src/base/preferences.h +++ b/src/base/preferences.h @@ -121,8 +121,6 @@ public: void setStatusbarDisplayed(bool displayed); bool isToolbarDisplayed() const; void setToolbarDisplayed(bool displayed); - bool startMinimized() const; - void setStartMinimized(bool b); bool isSplashScreenDisabled() const; void setSplashScreenDisabled(bool b); bool preventFromSuspendWhenDownloading() const; diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index eae9acf98..40c5ed7a8 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -125,6 +125,7 @@ add_library(qbt_gui STATIC utils.h watchedfolderoptionsdialog.h watchedfoldersmodel.h + windowstate.h # sources aboutdialog.cpp diff --git a/src/gui/desktopintegration.cpp b/src/gui/desktopintegration.cpp index c24c807ca..ee0950924 100644 --- a/src/gui/desktopintegration.cpp +++ b/src/gui/desktopintegration.cpp @@ -104,7 +104,7 @@ bool DesktopIntegration::isActive() const #ifdef Q_OS_MACOS return true; #else - return QSystemTrayIcon::isSystemTrayAvailable(); + return m_systrayIcon && QSystemTrayIcon::isSystemTrayAvailable(); #endif } diff --git a/src/gui/gui.pri b/src/gui/gui.pri index 85bde0b9e..15e5fdfd4 100644 --- a/src/gui/gui.pri +++ b/src/gui/gui.pri @@ -83,7 +83,8 @@ HEADERS += \ $$PWD/uithememanager.h \ $$PWD/utils.h \ $$PWD/watchedfolderoptionsdialog.h \ - $$PWD/watchedfoldersmodel.h + $$PWD/watchedfoldersmodel.h \ + $$PWD/windowstate.h SOURCES += \ $$PWD/aboutdialog.cpp \ diff --git a/src/gui/interfaces/iguiapplication.h b/src/gui/interfaces/iguiapplication.h index 96daea2df..941a8bd18 100644 --- a/src/gui/interfaces/iguiapplication.h +++ b/src/gui/interfaces/iguiapplication.h @@ -1,7 +1,7 @@ /* * Bittorrent Client using Qt and libtorrent. * Copyright (C) 2022 Mike Tzou (Chocobo1) - * Copyright (C) 2015, 2019 Vladimir Golovnev + * Copyright (C) 2015-2022 Vladimir Golovnev * Copyright (C) 2006 Christophe Dumez * * This program is free software; you can redistribute it and/or @@ -31,6 +31,7 @@ #pragma once #include "base/interfaces/iapplication.h" +#include "gui/windowstate.h" class DesktopIntegration; class MainWindow; @@ -43,6 +44,9 @@ public: virtual DesktopIntegration *desktopIntegration() = 0; virtual MainWindow *mainWindow() = 0; + virtual WindowState startUpWindowState() const = 0; + virtual void setStartUpWindowState(WindowState windowState) = 0; + virtual bool isTorrentAddedNotificationsEnabled() const = 0; virtual void setTorrentAddedNotificationsEnabled(bool value) = 0; }; diff --git a/src/gui/mainwindow.cpp b/src/gui/mainwindow.cpp index 448a0ab41..3054d2180 100644 --- a/src/gui/mainwindow.cpp +++ b/src/gui/mainwindow.cpp @@ -1,5 +1,6 @@ /* * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2022 Vladimir Golovnev * Copyright (C) 2006 Christophe Dumez * * This program is free software; you can redistribute it and/or @@ -115,7 +116,7 @@ namespace } } -MainWindow::MainWindow(IGUIApplication *app, const State initialState) +MainWindow::MainWindow(IGUIApplication *app, WindowState initialState) : GUIApplicationComponent(app) , m_ui(new Ui::MainWindow) , m_storeExecutionLogEnabled(EXECUTIONLOG_SETTINGS_KEY(u"Enabled"_qs)) @@ -374,27 +375,27 @@ MainWindow::MainWindow(IGUIApplication *app, const State initialState) }); #ifdef Q_OS_MACOS - // Make sure the Window is visible if we don't have a tray icon - if (initialState == Minimized) - { - showMinimized(); - } - else + if (initialState == WindowState::Normal) { show(); activateWindow(); raise(); } + else + { + // Make sure the Window is visible if we don't have a tray icon + showMinimized(); + } #else if (app->desktopIntegration()->isActive()) { - if ((initialState != Minimized) && !m_uiLocked) + if ((initialState == WindowState::Normal) && !m_uiLocked) { show(); activateWindow(); raise(); } - else if (initialState == Minimized) + else if (initialState == WindowState::Minimized) { showMinimized(); if (pref->minimizeToTray()) @@ -411,7 +412,7 @@ MainWindow::MainWindow(IGUIApplication *app, const State initialState) else { // Make sure the Window is visible if we don't have a tray icon - if (initialState == Minimized) + if (initialState != WindowState::Normal) { showMinimized(); } diff --git a/src/gui/mainwindow.h b/src/gui/mainwindow.h index e7af3d2e0..4c2b876ed 100644 --- a/src/gui/mainwindow.h +++ b/src/gui/mainwindow.h @@ -1,5 +1,6 @@ /* * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2022 Vladimir Golovnev * Copyright (C) 2006 Christophe Dumez * * This program is free software; you can redistribute it and/or @@ -35,6 +36,7 @@ #include "base/logger.h" #include "base/settingvalue.h" #include "guiapplicationcomponent.h" +#include "windowstate.h" class QCloseEvent; class QFileSystemWatcher; @@ -74,13 +76,7 @@ class MainWindow final : public QMainWindow, public GUIApplicationComponent Q_DISABLE_COPY_MOVE(MainWindow) public: - enum State - { - Normal, - Minimized - }; - - explicit MainWindow(IGUIApplication *app, State initialState = Normal); + explicit MainWindow(IGUIApplication *app, WindowState initialState = WindowState::Normal); ~MainWindow() override; QWidget *currentTabWidget() const; diff --git a/src/gui/optionsdialog.cpp b/src/gui/optionsdialog.cpp index 2ae1359e1..7535805eb 100644 --- a/src/gui/optionsdialog.cpp +++ b/src/gui/optionsdialog.cpp @@ -249,10 +249,16 @@ void OptionsDialog::loadBehaviorTabOptions() m_ui->checkStartup->setVisible(false); #endif m_ui->checkShowSplash->setChecked(!pref->isSplashScreenDisabled()); - m_ui->checkStartMinimized->setChecked(pref->startMinimized()); m_ui->checkProgramExitConfirm->setChecked(pref->confirmOnExit()); m_ui->checkProgramAutoExitConfirm->setChecked(!pref->dontConfirmAutoExit()); + m_ui->windowStateComboBox->addItem(tr("Normal"), QVariant::fromValue(WindowState::Normal)); + m_ui->windowStateComboBox->addItem(tr("Minimized"), QVariant::fromValue(WindowState::Minimized)); +#ifndef Q_OS_MACOS + m_ui->windowStateComboBox->addItem(tr("Hidden"), QVariant::fromValue(WindowState::Hidden)); +#endif + m_ui->windowStateComboBox->setCurrentIndex(m_ui->windowStateComboBox->findData(QVariant::fromValue(app()->startUpWindowState()))); + #if !(defined(Q_OS_WIN) || defined(Q_OS_MACOS)) m_ui->groupFileAssociation->setVisible(false); m_ui->checkProgramUpdates->setVisible(false); @@ -330,13 +336,13 @@ void OptionsDialog::loadBehaviorTabOptions() connect(m_ui->checkStartup, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); #endif connect(m_ui->checkShowSplash, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->checkStartMinimized, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); connect(m_ui->checkProgramExitConfirm, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); connect(m_ui->checkProgramAutoExitConfirm, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); connect(m_ui->checkShowSystray, &QGroupBox::toggled, this, &ThisType::enableApplyButton); connect(m_ui->checkMinimizeToSysTray, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); connect(m_ui->checkCloseToSystray, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); connect(m_ui->comboTrayIcon, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton); + connect(m_ui->windowStateComboBox, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton); connect(m_ui->checkPreventFromSuspendWhenDownloading, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); connect(m_ui->checkPreventFromSuspendWhenSeeding, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); @@ -399,7 +405,6 @@ void OptionsDialog::saveBehaviorTabOptions() const pref->setActionOnDblClOnTorrentFn(m_ui->actionTorrentFnOnDblClBox->currentData().toInt()); pref->setSplashScreenDisabled(isSplashScreenDisabled()); - pref->setStartMinimized(startMinimized()); pref->setConfirmOnExit(m_ui->checkProgramExitConfirm->isChecked()); pref->setDontConfirmAutoExit(!m_ui->checkProgramAutoExitConfirm->isChecked()); @@ -447,6 +452,8 @@ void OptionsDialog::saveBehaviorTabOptions() const app()->setFileLoggerDeleteOld(m_ui->checkFileLogDelete->isChecked()); app()->setFileLoggerEnabled(m_ui->checkFileLog->isChecked()); + app()->setStartUpWindowState(m_ui->windowStateComboBox->currentData().value()); + session->setPerformanceWarningEnabled(m_ui->checkBoxPerformanceWarning->isChecked()); } @@ -1379,11 +1386,6 @@ bool OptionsDialog::isUPnPEnabled() const return m_ui->checkUPnP->isChecked(); } -bool OptionsDialog::startMinimized() const -{ - return m_ui->checkStartMinimized->isChecked(); -} - // Return Share ratio qreal OptionsDialog::getMaxRatio() const { diff --git a/src/gui/optionsdialog.h b/src/gui/optionsdialog.h index b3d9788b4..819f0a694 100644 --- a/src/gui/optionsdialog.h +++ b/src/gui/optionsdialog.h @@ -143,7 +143,6 @@ private: // General options void initializeLanguageCombo(); QString getLocale() const; - bool startMinimized() const; bool isSplashScreenDisabled() const; #ifdef Q_OS_WIN bool WinStartup() const; diff --git a/src/gui/optionsdialog.ui b/src/gui/optionsdialog.ui index e407d79e9..029ef056e 100644 --- a/src/gui/optionsdialog.ui +++ b/src/gui/optionsdialog.ui @@ -404,14 +404,35 @@ - - - When qBittorrent is started, the main window will be minimized - - - Start qBittorrent minimized - - + + + + + Window state on start up: + + + + + + + qBittorrent window state on start up + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + @@ -3640,7 +3661,7 @@ Use ';' to split multiple entries. Can use wildcard '*'. actionTorrentFnOnDblClBox checkStartup checkShowSplash - checkStartMinimized + windowStateComboBox checkProgramExitConfirm checkShowSystray checkMinimizeToSysTray diff --git a/src/gui/windowstate.h b/src/gui/windowstate.h new file mode 100644 index 000000000..a1d4a8f32 --- /dev/null +++ b/src/gui/windowstate.h @@ -0,0 +1,46 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2022 Vladimir Golovnev + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +#pragma once + +#include + +inline namespace WindowStateNS +{ + Q_NAMESPACE + + enum class WindowState + { + Normal, + Minimized, +#ifndef Q_OS_MACOS + Hidden +#endif + }; + Q_ENUM_NS(WindowState); +}