From 8e99d9e59fa634a8743b731bb2b73b1a25695e3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20=C3=81ngel=20San=20Mart=C3=ADn?= Date: Sat, 21 Sep 2019 10:47:01 +0200 Subject: [PATCH] Extract the system tray functionality to its own class LibraryWindow is already a monster, so we'll try to not make it bigger. --- YACReaderLibrary/YACReaderLibrary.pro | 3 + YACReaderLibrary/library_window.cpp | 61 ++++++-------- YACReaderLibrary/library_window.h | 10 ++- YACReaderLibrary/trayicon_controller.cpp | 100 +++++++++++++++++++++++ YACReaderLibrary/trayicon_controller.h | 34 ++++++++ 5 files changed, 167 insertions(+), 41 deletions(-) create mode 100644 YACReaderLibrary/trayicon_controller.cpp create mode 100644 YACReaderLibrary/trayicon_controller.h diff --git a/YACReaderLibrary/YACReaderLibrary.pro b/YACReaderLibrary/YACReaderLibrary.pro index c1365c47..cf53e885 100644 --- a/YACReaderLibrary/YACReaderLibrary.pro +++ b/YACReaderLibrary/YACReaderLibrary.pro @@ -13,6 +13,7 @@ INCLUDEPATH += . \ ./comic_vine/model DEFINES += SERVER_RELEASE NOMINMAX YACREADER_LIBRARY +QMAKE_MAC_SDK = macosx10.15 # load default build flags include (../config.pri) @@ -115,6 +116,7 @@ HEADERS += comic_flow.h \ ../common/pdf_comic.h \ no_libraries_widget.h \ import_widget.h \ + trayicon_controller.h \ yacreader_local_server.h \ yacreader_main_toolbar.h \ comics_remover.h \ @@ -184,6 +186,7 @@ SOURCES += comic_flow.cpp \ ../common/onstart_flow_selection_dialog.cpp \ no_libraries_widget.cpp \ import_widget.cpp \ + trayicon_controller.cpp \ yacreader_local_server.cpp \ yacreader_main_toolbar.cpp \ comics_remover.cpp \ diff --git a/YACReaderLibrary/library_window.cpp b/YACReaderLibrary/library_window.cpp index 1a1d51f7..21b2e81a 100644 --- a/YACReaderLibrary/library_window.cpp +++ b/YACReaderLibrary/library_window.cpp @@ -81,14 +81,15 @@ #include "yacreader_comics_views_manager.h" +#include "trayicon_controller.h" + #include "QsLog.h" #ifdef Q_OS_WIN #include #endif -#ifdef Q_OS_MACOS -#include "trayhandler.h" -#endif + +using namespace YACReader; LibraryWindow::LibraryWindow() : QMainWindow(), fullscreen(false), previousFilter(""), fetching(false), status(LibraryWindow::Normal), removeError(false) @@ -140,50 +141,26 @@ void LibraryWindow::setupUI() //if(settings->value(USE_OPEN_GL).toBool() == false) showMaximized(); - // If a window icon was set in main() we reuse it for the tray too. - // This allows support for third party icon themes on Freedesktop(Linux/Unix) - // systems. - if (!QApplication::windowIcon().isNull()) { - trayIcon.setIcon(QApplication::windowIcon()); - } else { -#ifdef Q_OS_WIN - trayIcon.setIcon(QIcon(":/icon.ico")); -#else -#ifdef Q_OS_MACOS - auto icon = QIcon(":/macostrayicon.svg"); - icon.setIsMask(true); - trayIcon.setIcon(icon); -#else - trayIcon.setIcon(QIcon(":/images/iconLibrary.png")); -#endif -#endif - } - - connect(&trayIcon, &QSystemTrayIcon::activated, - [=](QSystemTrayIcon::ActivationReason reason) { - if (reason == QSystemTrayIcon::Trigger) { -#ifdef Q_OS_MACOS - OSXShowDockIcon(); -#endif - setWindowState((windowState() & ~Qt::WindowMinimized) | Qt::WindowActive); - show(); - } - }); - trayIcon.setVisible(settings->value(MINIMIZE_TO_TRAY, true).toBool()); + trayIconController = new TrayIconController(settings, this); } -void LibraryWindow::changeEvent(QEvent *event) +/*void LibraryWindow::changeEvent(QEvent *event) { + QMainWindow::changeEvent(event); + if (event->type() == QEvent::WindowStateChange && isMinimized() && trayIcon.isVisible()) { #ifdef Q_OS_MACOS OSXHideDockIcon(); #endif hide(); - return; + } else if (event->type() == QEvent::WindowStateChange) { +#ifdef Q_OS_MACOS + OSXShowDockIcon(); +#endif + show(); } - QMainWindow::changeEvent(event); -} +}*/ void LibraryWindow::doLayout() { @@ -2297,8 +2274,9 @@ void LibraryWindow::importLibrary(QString clc, QString destPath, QString name) void LibraryWindow::reloadOptions() { - //comicFlow->setFlowType(flowType); comicsViewsManager->comicsView->updateConfig(settings); + + trayIconController->updateIconVisibility(); } QString LibraryWindow::currentPath() @@ -2334,6 +2312,13 @@ void LibraryWindow::showImportComicsInfo() #include "startup.h" extern Startup *s; void LibraryWindow::closeEvent(QCloseEvent *event) +{ + if (!trayIconController->handleCloseToTrayIcon(event)) { + closeApp(event); + } +} + +void LibraryWindow::closeApp(QCloseEvent *event) { s->stop(); settings->setValue(MAIN_WINDOW_GEOMETRY, saveGeometry()); diff --git a/YACReaderLibrary/library_window.h b/YACReaderLibrary/library_window.h index c934946e..3d557fc3 100644 --- a/YACReaderLibrary/library_window.h +++ b/YACReaderLibrary/library_window.h @@ -5,7 +5,6 @@ #include #include #include -#include #include "yacreader_global_gui.h" #include "yacreader_libraries.h" @@ -77,6 +76,10 @@ class EmptySpecialListWidget; class EmptyReadingListWidget; class YACReaderComicsViewsManager; +namespace YACReader { +class TrayIconController; +} + #include "comic_db.h" using namespace YACReader; @@ -385,7 +388,7 @@ public slots: void checkMaxNumLibraries(); void showErrorUpgradingLibrary(const QString &path); - void changeEvent(QEvent *event); + void closeApp(QCloseEvent *event); private: //fullscreen mode in Windows for preventing this bug: QTBUG-41309 https://bugreports.qt.io/browse/QTBUG-41309 @@ -393,7 +396,8 @@ private: QPoint previousPos; QSize previousSize; std::future upgradeLibraryFuture; - QSystemTrayIcon trayIcon; + + TrayIconController *trayIconController; }; #endif diff --git a/YACReaderLibrary/trayicon_controller.cpp b/YACReaderLibrary/trayicon_controller.cpp new file mode 100644 index 00000000..208d6b1c --- /dev/null +++ b/YACReaderLibrary/trayicon_controller.cpp @@ -0,0 +1,100 @@ +#include "trayicon_controller.h" + +#include "yacreader_global_gui.h" + +#include +#include + +#ifdef Q_OS_MACOS +#include "trayhandler.h" +#endif + +using namespace YACReader; + +TrayIconController::TrayIconController(QSettings *settings, QMainWindow *window) + : QObject(nullptr), settings(settings), window(window) +{ + + // If a window icon was set in main() we reuse it for the tray too. + // This allows support for third party icon themes on Freedesktop(Linux/Unix) + // systems. + if (!QApplication::windowIcon().isNull()) { + trayIcon.setIcon(QApplication::windowIcon()); + } else { +#ifdef Q_OS_WIN + trayIcon.setIcon(QIcon(":/icon.ico")); +#else +#ifdef Q_OS_MACOS + auto icon = QIcon(":/macostrayicon.svg"); + icon.setIsMask(true); + trayIcon.setIcon(icon); +#else + trayIcon.setIcon(QIcon(":/images/iconLibrary.png")); +#endif +#endif + } + + connect(&trayIcon, &QSystemTrayIcon::activated, + [=](QSystemTrayIcon::ActivationReason reason) { + if (reason == QSystemTrayIcon::DoubleClick) { + showWindow(); + } + }); + + updateIconVisibility(); + + auto restoreAction = new QAction(tr("&Restore"), this); + connect(restoreAction, &QAction::triggered, this, &TrayIconController::showWindow); + + auto quitAction = new QAction(tr("&Quit"), this); + connect(quitAction, &QAction::triggered, window, &QMainWindow::close); + + trayIconMenu = new QMenu(this->window); + trayIconMenu->addAction(restoreAction); + trayIconMenu->addSeparator(); + trayIconMenu->addAction(quitAction); + + trayIcon.setContextMenu(trayIconMenu); +} + +void TrayIconController::updateIconVisibility() +{ + trayIcon.setVisible(settings->value(CLOSE_TO_TRAY, false).toBool()); +} + +bool TrayIconController::handleCloseToTrayIcon(QCloseEvent *event) +{ +#ifdef Q_OS_OSX + if (!event->spontaneous() || !window->isVisible()) { + return false; + } +#endif + if (trayIcon.isVisible()) { + if (!settings->value(CLOSE_TO_TRAY_NOTIFIED, false).toBool()) { + QMessageBox::information(window, tr("Systray"), + tr("YACReaderLibrary will keep running in the " + "system tray. To terminate the program, " + "choose Quit in the context menu " + "of the system tray icon.")); + settings->setValue(CLOSE_TO_TRAY_NOTIFIED, true); + } +#ifdef Q_OS_OSX + OSXHideDockIcon(); +#endif + window->hide(); + event->ignore(); + return true; + } else { + return false; + } +} + +void TrayIconController::showWindow() +{ +#ifdef Q_OS_MACOS + OSXShowDockIcon(); +#endif + window->showNormal(); + window->raise(); // for MacOS + window->activateWindow(); // for Windows +} diff --git a/YACReaderLibrary/trayicon_controller.h b/YACReaderLibrary/trayicon_controller.h new file mode 100644 index 00000000..649121ba --- /dev/null +++ b/YACReaderLibrary/trayicon_controller.h @@ -0,0 +1,34 @@ +#ifndef TRAYICON_CONTROLLER_H +#define TRAYICON_CONTROLLER_H + +#include +#include + +namespace YACReader { + +class TrayIconController : public QObject +{ + Q_OBJECT +public: + TrayIconController(QSettings *settings, + QMainWindow *window); + + void updateIconVisibility(); + + bool handleCloseToTrayIcon(QCloseEvent *event); + + QSystemTrayIcon trayIcon; + +public slots: + void showWindow(); + +private: + QSettings *settings; + QMainWindow *window; + + QMenu *trayIconMenu; +}; + +} + +#endif // TRAYICON_CONTROLLER_H