diff --git a/YACReaderLibrary/YACReaderLibrary.pro b/YACReaderLibrary/YACReaderLibrary.pro
index f8460faf..b39293fc 100644
--- a/YACReaderLibrary/YACReaderLibrary.pro
+++ b/YACReaderLibrary/YACReaderLibrary.pro
@@ -115,6 +115,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 +185,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 \
@@ -221,6 +223,11 @@ SOURCES += comic_flow.cpp \
SOURCES += ../common/gl/yacreader_flow_gl.cpp
}
+macx {
+ HEADERS += trayhandler.h
+ OBJECTIVE_SOURCES += trayhandler.mm
+}
+
include(./server/server.pri)
include(../custom_widgets/custom_widgets_yacreaderlibrary.pri)
diff --git a/YACReaderLibrary/images_osx.qrc b/YACReaderLibrary/images_osx.qrc
index 14398e66..60489bfb 100644
--- a/YACReaderLibrary/images_osx.qrc
+++ b/YACReaderLibrary/images_osx.qrc
@@ -71,5 +71,6 @@
../images/sidebar/delete_sidebar_osx@2x.png
../images/sidebar/addLabelIcon_osx@2x.png
../images/sidebar/renameListIcon_osx@2x.png
+ macostrayicon.svg
diff --git a/YACReaderLibrary/images_win.qrc b/YACReaderLibrary/images_win.qrc
index fdb1ea0b..cb87e0cf 100644
--- a/YACReaderLibrary/images_win.qrc
+++ b/YACReaderLibrary/images_win.qrc
@@ -41,5 +41,6 @@
../images/lists/label_yellow.png
../images/lists/list.png
../images/empty_reading_list.png
+ icon.ico
diff --git a/YACReaderLibrary/library_window.cpp b/YACReaderLibrary/library_window.cpp
index eae3f19e..7d6c8967 100644
--- a/YACReaderLibrary/library_window.cpp
+++ b/YACReaderLibrary/library_window.cpp
@@ -81,12 +81,16 @@
#include "yacreader_comics_views_manager.h"
+#include "trayicon_controller.h"
+
#include "QsLog.h"
#ifdef Q_OS_WIN
#include
#endif
+using namespace YACReader;
+
LibraryWindow::LibraryWindow()
: QMainWindow(), fullscreen(false), previousFilter(""), fetching(false), status(LibraryWindow::Normal), removeError(false)
{
@@ -136,37 +140,26 @@ void LibraryWindow::setupUI()
else
//if(settings->value(USE_OPEN_GL).toBool() == false)
showMaximized();
-}
-/* //disabled until icons are ready and macos native code is done
- trayIcon.setIcon(QApplication::windowIcon());
- trayIcon.show();
- connect(&trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
- this, SLOT(trayActivation(QSystemTrayIcon::ActivationReason)));
- }
+
+ trayIconController = new TrayIconController(settings, this);
}
-void LibraryWindow::trayActivation(QSystemTrayIcon::ActivationReason reason)
+/*void LibraryWindow::changeEvent(QEvent *event)
{
- if (reason == QSystemTrayIcon::Trigger)
- {
- setWindowState((windowState() & ~Qt::WindowMinimized));
- show();
- activateWindow();
- raise();
- }
-}
-
-
-void LibraryWindow::changeEvent(QEvent *event)
-{
- if (event->type() == QEvent::WindowStateChange && isMinimized())
- {
- hide();
- }
- else
- {
QMainWindow::changeEvent(event);
- }
+
+ if (event->type() == QEvent::WindowStateChange && isMinimized() &&
+ trayIcon.isVisible()) {
+#ifdef Q_OS_MACOS
+ OSXHideDockIcon();
+#endif
+ hide();
+ } else if (event->type() == QEvent::WindowStateChange) {
+#ifdef Q_OS_MACOS
+ OSXShowDockIcon();
+#endif
+ show();
+ }
}*/
void LibraryWindow::doLayout()
@@ -2281,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()
@@ -2318,6 +2312,14 @@ void LibraryWindow::showImportComicsInfo()
#include "startup.h"
extern Startup *s;
void LibraryWindow::closeEvent(QCloseEvent *event)
+{
+ if (!trayIconController->handleCloseToTrayIcon(event)) {
+ event->accept();
+ closeApp();
+ }
+}
+
+void LibraryWindow::prepareToCloseApp()
{
s->stop();
settings->setValue(MAIN_WINDOW_GEOMETRY, saveGeometry());
@@ -2326,8 +2328,13 @@ void LibraryWindow::closeEvent(QCloseEvent *event)
sideBar->close();
QApplication::instance()->processEvents();
- event->accept();
- QMainWindow::closeEvent(event);
+}
+
+void LibraryWindow::closeApp()
+{
+ prepareToCloseApp();
+
+ qApp->exit(0);
}
void LibraryWindow::showNoLibrariesWidget()
@@ -2506,14 +2513,14 @@ void LibraryWindow::showFoldersContextMenu(const QPoint &point)
/*
void LibraryWindow::showSocial()
{
- socialDialog->move(this->mapToGlobal(QPoint(width()-socialDialog->width()-10, centralWidget()->pos().y()+10)));
+ socialDialog->move(this->mapToGlobal(QPoint(width()-socialDialog->width()-10, centralWidget()->pos().y()+10)));
- QModelIndexList indexList = getSelectedComics();
+ QModelIndexList indexList = getSelectedComics();
- ComicDB comic = dmCV->getComic(indexList.at(0));
+ ComicDB comic = dmCV->getComic(indexList.at(0));
- socialDialog->setComic(comic,currentPath());
- socialDialog->setHidden(false);
+ socialDialog->setComic(comic,currentPath());
+ socialDialog->setHidden(false);
}*/
void LibraryWindow::libraryAlreadyExists(const QString &name)
diff --git a/YACReaderLibrary/library_window.h b/YACReaderLibrary/library_window.h
index 1f2bc896..993b58b9 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,8 @@ public slots:
void checkMaxNumLibraries();
void showErrorUpgradingLibrary(const QString &path);
- //void changeEvent(QEvent *event);
+ void prepareToCloseApp();
+ void closeApp();
private:
//fullscreen mode in Windows for preventing this bug: QTBUG-41309 https://bugreports.qt.io/browse/QTBUG-41309
@@ -393,10 +397,8 @@ private:
QPoint previousPos;
QSize previousSize;
std::future upgradeLibraryFuture;
- QSystemTrayIcon trayIcon;
-private slots:
- //void trayActivation(QSystemTrayIcon::ActivationReason reason);
+ TrayIconController *trayIconController;
};
#endif
diff --git a/YACReaderLibrary/macostrayicon.svg b/YACReaderLibrary/macostrayicon.svg
new file mode 100644
index 00000000..03d3446f
--- /dev/null
+++ b/YACReaderLibrary/macostrayicon.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/YACReaderLibrary/main.cpp b/YACReaderLibrary/main.cpp
index 8501179d..62f68584 100644
--- a/YACReaderLibrary/main.cpp
+++ b/YACReaderLibrary/main.cpp
@@ -20,6 +20,9 @@
#include "yacreader_libraries.h"
#include "exit_check.h"
#include "opengl_checker.h"
+#ifdef Q_OS_MACOS
+#include "trayhandler.h"
+#endif
#include "QsLog.h"
#include "QsLogDest.h"
@@ -127,9 +130,12 @@ int main(int argc, char **argv)
app.setApplicationVersion(VERSION);
app.setAttribute(Qt::AA_UseHighDpiPixmaps);
+ // Set window icon according to Freedesktop icon specification
+ // This is mostly relevant for Linux and other Unix systems
if (QIcon::hasThemeIcon("YACReaderLibrary")) {
app.setWindowIcon(QIcon::fromTheme("YACReaderLibrary"));
}
+ // TODO: We might want to add a fallback icon here.
QString destLog = YACReader::getSettingsPath() + "/yacreaderlibrary.log";
QDir().mkpath(YACReader::getSettingsPath());
@@ -239,7 +245,15 @@ int main(int argc, char **argv)
//connections to localServer
- mw->show();
+ // start as tray
+ if (!settings->value(START_TO_TRAY, false).toBool() || !settings->value(CLOSE_TO_TRAY, false).toBool()) {
+ mw->show();
+ }
+#ifdef Q_OS_MACOS
+ else {
+ OSXHideDockIcon();
+ }
+#endif
int ret = app.exec();
diff --git a/YACReaderLibrary/options_dialog.cpp b/YACReaderLibrary/options_dialog.cpp
index 5667ff73..432273a8 100644
--- a/YACReaderLibrary/options_dialog.cpp
+++ b/YACReaderLibrary/options_dialog.cpp
@@ -43,6 +43,27 @@ OptionsDialog::OptionsDialog(QWidget *parent)
#ifndef NO_OPENGL
sw->hide();
#endif
+ // Tray icon settings
+ QGroupBox *trayIconBox = new QGroupBox(tr("Tray icon settings (experimental)"));
+ QVBoxLayout *trayLayout = new QVBoxLayout();
+
+ trayIconCheckbox = new QCheckBox(tr("Close to tray"));
+ startToTrayCheckbox = new QCheckBox(tr("Start into the system tray"));
+
+ connect(trayIconCheckbox, &QCheckBox::clicked,
+ [=](bool checked) {
+ settings->setValue(CLOSE_TO_TRAY, checked);
+ startToTrayCheckbox->setEnabled(checked);
+ emit optionsChanged();
+ });
+ connect(startToTrayCheckbox, &QCheckBox::clicked,
+ [=](bool checked) {
+ settings->setValue(START_TO_TRAY, checked);
+ });
+
+ trayLayout->addWidget(trayIconCheckbox);
+ trayLayout->addWidget(startToTrayCheckbox);
+ trayIconBox->setLayout(trayLayout);
auto apiKeyLayout = new QVBoxLayout();
auto apiKeyButton = new QPushButton(tr("Edit Comic Vine API key"));
@@ -115,6 +136,7 @@ OptionsDialog::OptionsDialog(QWidget *parent)
auto generalW = new QWidget;
generalW->setLayout(generalLayout);
+ generalLayout->addWidget(trayIconBox);
generalLayout->addWidget(shortcutsBox);
generalLayout->addWidget(apiKeyBox);
generalLayout->addStretch();
@@ -146,6 +168,10 @@ void OptionsDialog::restoreOptions(QSettings *settings)
{
YACReaderOptionsDialog::restoreOptions(settings);
+ trayIconCheckbox->setChecked(settings->value(CLOSE_TO_TRAY, false).toBool());
+ startToTrayCheckbox->setChecked(settings->value(START_TO_TRAY, false).toBool());
+ startToTrayCheckbox->setEnabled(trayIconCheckbox->isChecked());
+
bool useBackgroundImage = settings->value(USE_BACKGROUND_IMAGE_IN_GRID_VIEW, true).toBool();
useBackgroundImageCheck->setChecked(useBackgroundImage);
diff --git a/YACReaderLibrary/options_dialog.h b/YACReaderLibrary/options_dialog.h
index 20c542a1..7ecc8511 100644
--- a/YACReaderLibrary/options_dialog.h
+++ b/YACReaderLibrary/options_dialog.h
@@ -34,8 +34,9 @@ private:
QLabel *opacityLabel;
QLabel *blurLabel;
QPushButton *resetButton;
-
QCheckBox *displayContinueReadingBannerCheck;
+ QCheckBox *trayIconCheckbox;
+ QCheckBox *startToTrayCheckbox;
};
#endif
diff --git a/YACReaderLibrary/trayhandler.h b/YACReaderLibrary/trayhandler.h
new file mode 100644
index 00000000..ce898a0e
--- /dev/null
+++ b/YACReaderLibrary/trayhandler.h
@@ -0,0 +1,7 @@
+#ifndef TRAY_HANDLER
+#define TRAY_HANDLER
+
+void OSXShowDockIcon();
+void OSXHideDockIcon();
+
+#endif
\ No newline at end of file
diff --git a/YACReaderLibrary/trayhandler.mm b/YACReaderLibrary/trayhandler.mm
new file mode 100644
index 00000000..9c3cce37
--- /dev/null
+++ b/YACReaderLibrary/trayhandler.mm
@@ -0,0 +1,11 @@
+#import
+#include "trayhandler.h"
+
+void OSXShowDockIcon()
+{
+ [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
+}
+void OSXHideDockIcon()
+{
+ [NSApp setActivationPolicy:NSApplicationActivationPolicyAccessory];
+}
\ No newline at end of file
diff --git a/YACReaderLibrary/trayicon_controller.cpp b/YACReaderLibrary/trayicon_controller.cpp
new file mode 100644
index 00000000..b2098d9c
--- /dev/null
+++ b/YACReaderLibrary/trayicon_controller.cpp
@@ -0,0 +1,102 @@
+#include "trayicon_controller.h"
+
+#include "yacreader_global_gui.h"
+
+#include "library_window.h"
+
+#include
+#include
+
+#ifdef Q_OS_MACOS
+#include "trayhandler.h"
+#endif
+
+using namespace YACReader;
+
+TrayIconController::TrayIconController(QSettings *settings, LibraryWindow *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();
+ }
+ });
+
+ 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, &LibraryWindow::closeApp);
+
+ trayIconMenu = new QMenu(this->window);
+ trayIconMenu->addAction(restoreAction);
+ trayIconMenu->addSeparator();
+ trayIconMenu->addAction(quitAction);
+
+ trayIcon.setContextMenu(trayIconMenu);
+
+ updateIconVisibility();
+}
+
+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..1ff9d407
--- /dev/null
+++ b/YACReaderLibrary/trayicon_controller.h
@@ -0,0 +1,36 @@
+#ifndef TRAYICON_CONTROLLER_H
+#define TRAYICON_CONTROLLER_H
+
+#include
+#include
+
+class LibraryWindow;
+
+namespace YACReader {
+
+class TrayIconController : public QObject
+{
+ Q_OBJECT
+public:
+ TrayIconController(QSettings *settings,
+ LibraryWindow *window);
+
+ void updateIconVisibility();
+
+ bool handleCloseToTrayIcon(QCloseEvent *event);
+
+ QSystemTrayIcon trayIcon;
+
+public slots:
+ void showWindow();
+
+private:
+ QSettings *settings;
+ LibraryWindow *window;
+
+ QMenu *trayIconMenu;
+};
+
+}
+
+#endif // TRAYICON_CONTROLLER_H
diff --git a/common/yacreader_global_gui.h b/common/yacreader_global_gui.h
index 0ec4ab1b..94a876ea 100644
--- a/common/yacreader_global_gui.h
+++ b/common/yacreader_global_gui.h
@@ -17,6 +17,9 @@
#define FULLSCREEN "FULLSCREEN"
#define Y_WINDOW_GEOMETRY "GEOMETRY"
#define MAXIMIZED "MAXIMIZED"
+#define CLOSE_TO_TRAY "CLOSE_TO_TRAY"
+#define CLOSE_TO_TRAY_NOTIFIED "CLOSE_TO_TRAY_NOTIFIED"
+#define START_TO_TRAY "START_TO_TRAY"
#define DOUBLE_PAGE "DOUBLE_PAGE"
#define DOUBLE_MANGA_PAGE "DOUBLE_MANGA_PAGE"
#define BACKGROUND_COLOR "BACKGROUND_COLOR"