From 7e9eed207557188f375d455d442cedacd032ed8e Mon Sep 17 00:00:00 2001 From: blue Date: Mon, 15 Aug 2022 19:40:07 +0300 Subject: [PATCH] First tray attempt, seems to be working --- CHANGELOG.md | 1 + main/application.cpp | 96 ++++++++++++++++++++++++++++- main/application.h | 11 +++- translations/squawk.en.ts | 5 ++ translations/squawk.pt_BR.ts | 5 ++ translations/squawk.ru.ts | 5 ++ ui/squawk.cpp | 3 +- ui/squawk.h | 2 + ui/widgets/settings/pagegeneral.cpp | 33 ++++++++++ ui/widgets/settings/pagegeneral.h | 3 + ui/widgets/settings/pagegeneral.ui | 32 +++++++++- ui/widgets/settings/settings.cpp | 11 ++++ ui/widgets/settings/settings.h | 1 + 13 files changed, 201 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 600c795..40a85c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ - deactivated accounts now don't appear in combobox of "Add contact" and "Join conference" dialogues ### New features +- Now you can enable tray icon from settings! ## Squawk 0.2.2 (May 05, 2022) ### Bug fixes diff --git a/main/application.cpp b/main/application.cpp index 216e322..a319ee5 100644 --- a/main/application.cpp +++ b/main/application.cpp @@ -27,8 +27,14 @@ Application::Application(Core::Squawk* p_core): dialogueQueue(roster), nowQuitting(false), destroyingSquawk(false), - storage() + storage(), + trayIcon(nullptr), + actionQuit(Shared::icon("application-exit"), tr("Quit")), + actionToggle(tr("Minimize to tray")) { + connect(&actionQuit, &QAction::triggered, this, &Application::quit); + connect(&actionToggle, &QAction::triggered, this, &Application::toggleSquawk); + connect(&roster, &Models::Roster::unnoticedMessage, this, &Application::notify); connect(&roster, &Models::Roster::unreadMessagesCountChanged, this, &Application::unreadMessagesCountChanged); @@ -130,6 +136,12 @@ void Application::quit() if (squawk != nullptr) { squawk->close(); } + + if (trayIcon != nullptr) { + trayIcon->deleteLater(); + trayIcon = nullptr; + } + if (!destroyingSquawk) { checkForTheLastWindow(); } @@ -155,6 +167,8 @@ void Application::createMainWindow() connect(squawk, &Squawk::openedConversation, this, &Application::onSquawkOpenedConversation); connect(squawk, &Squawk::openConversation, this, &Application::openConversation); connect(squawk, &Squawk::changeState, this, &Application::setState); + connect(squawk, &Squawk::changeTray, this, &Application::onChangeTray); + connect(squawk, &Squawk::quit, this, &Application::quit); connect(squawk, &Squawk::closing, this, &Application::onSquawkClosing); connect(squawk, &Squawk::modifyAccountRequest, core, &Core::Squawk::modifyAccountRequest); @@ -194,8 +208,15 @@ void Application::onSquawkClosing() squawk->deleteLater(); squawk = nullptr; - //for now - quit(); + QSettings settings; + if (!nowQuitting && QSystemTrayIcon::isSystemTrayAvailable() && settings.value("tray", false).toBool()) { + if (settings.value("hideTray", false).toBool()) { + createTrayIcon(); + } + actionToggle.setText(tr("Show Squawk")); + } else { + quit(); + } } void Application::onSquawkDestroyed() { @@ -205,6 +226,71 @@ void Application::onSquawkDestroyed() { } } +void Application::onChangeTray(bool enabled, bool hide) +{ + if (enabled) { + if (trayIcon == nullptr) { + if (!hide || squawk == nullptr) { + createTrayIcon(); + } + } else { + if (hide && squawk != nullptr) { + trayIcon->deleteLater(); + trayIcon = nullptr; + } + } + } else if (trayIcon == nullptr) { + trayIcon->deleteLater(); + trayIcon = nullptr; + } +} + +void Application::createTrayIcon() +{ + trayIcon = new QSystemTrayIcon(); + + QMenu* trayIconMenu = new QMenu(); + trayIconMenu->addAction(&actionToggle); + trayIconMenu->addAction(&actionQuit); + + trayIcon->setContextMenu(trayIconMenu); + trayIcon->setIcon(QApplication::windowIcon().pixmap(32, 32)); + trayIcon->setToolTip(QApplication::applicationDisplayName()); + + connect(trayIcon, &QSystemTrayIcon::activated, this, &Application::trayClicked); + connect(trayIcon, &QSystemTrayIcon::destroyed, trayIconMenu, &QMenu::deleteLater); + + trayIcon->show(); +} + +void Application::trayClicked(QSystemTrayIcon::ActivationReason reason) +{ + switch (reason) { + case QSystemTrayIcon::Trigger: + case QSystemTrayIcon::DoubleClick: + case QSystemTrayIcon::MiddleClick: + toggleSquawk(); + break; + default: + break; + } +} + +void Application::toggleSquawk() +{ + QSettings settings; + if (squawk == nullptr) { + createMainWindow(); + if (settings.value("hideTray", false).toBool()) { + trayIcon->deleteLater(); + trayIcon = nullptr; + } + + actionToggle.setText(tr("Minimize to tray")); + } else { + squawk->close(); + } +} void Application::notify(const QString& account, const Shared::Message& msg) { @@ -345,6 +431,10 @@ void Application::readSettings() setState(Shared::Global::fromInt(avail)); createMainWindow(); + + if (settings.value("tray", false).toBool() && !settings.value("hideTray", false).toBool()) { + createTrayIcon(); + } } void Application::writeSettings() diff --git a/main/application.h b/main/application.h index 301edc4..db60009 100644 --- a/main/application.h +++ b/main/application.h @@ -21,6 +21,9 @@ #include #include +#include +#include +#include #include "dialogqueue.h" #include "core/squawk.h" @@ -91,13 +94,16 @@ private slots: void onSquawkDestroyed(); void onNotificationClosed(quint32 id, quint32 reason); void onNotificationInvoked(quint32 id, const QString& action); - + void onChangeTray(bool enabled, bool hide); + void trayClicked(QSystemTrayIcon::ActivationReason reason); + void toggleSquawk(); private: void createMainWindow(); void subscribeConversation(Conversation* conv); void checkForTheLastWindow(); void focusConversation(const Models::Roster::ElId& id, const QString& resource = "", const QString& messageId = ""); + void createTrayIcon(); private: typedef std::map Conversations; @@ -113,6 +119,9 @@ private: bool nowQuitting; bool destroyingSquawk; Notifications storage; + QSystemTrayIcon* trayIcon; + QAction actionQuit; + QAction actionToggle; }; #endif // APPLICATION_H diff --git a/translations/squawk.en.ts b/translations/squawk.en.ts index b219af0..0aef979 100644 --- a/translations/squawk.en.ts +++ b/translations/squawk.en.ts @@ -972,6 +972,11 @@ Would you like to check them and try again? Downloads path Downloads path + + + Close to tray icon + Close to tray icon + diff --git a/translations/squawk.pt_BR.ts b/translations/squawk.pt_BR.ts index 6041678..f818e63 100644 --- a/translations/squawk.pt_BR.ts +++ b/translations/squawk.pt_BR.ts @@ -761,6 +761,11 @@ Você pode tentar novamente Downloads path Pasta de downloads + + + Close to tray icon + Fechar ao ícone da bandeja + Browse 6 / 5,000 diff --git a/translations/squawk.ru.ts b/translations/squawk.ru.ts index 39dbfac..1774bb9 100644 --- a/translations/squawk.ru.ts +++ b/translations/squawk.ru.ts @@ -765,6 +765,11 @@ You can try again Downloads path Папка для сохраненных файлов + + + Close to tray icon + Закрывать в трей + Browse Выбрать diff --git a/ui/squawk.cpp b/ui/squawk.cpp index db92e93..39a7202 100644 --- a/ui/squawk.cpp +++ b/ui/squawk.cpp @@ -56,7 +56,7 @@ Squawk::Squawk(Models::Roster& p_rosterModel, QWidget *parent) : connect(m_ui->actionPreferences, &QAction::triggered, this, &Squawk::onPreferences); connect(m_ui->actionAddContact, &QAction::triggered, this, &Squawk::onNewContact); connect(m_ui->actionAddConference, &QAction::triggered, this, &Squawk::onNewConference); - connect(m_ui->actionQuit, &QAction::triggered, this, &Squawk::close); + connect(m_ui->actionQuit, &QAction::triggered, this, &Squawk::quit); connect(m_ui->comboBox, qOverload(&QComboBox::activated), this, &Squawk::onComboboxActivated); //connect(m_ui->roster, &QTreeView::doubleClicked, this, &Squawk::onRosterItemDoubleClicked); connect(m_ui->roster, &QTreeView::customContextMenuRequested, this, &Squawk::onRosterContextMenu); @@ -122,6 +122,7 @@ void Squawk::onPreferences() preferences->setAttribute(Qt::WA_DeleteOnClose); connect(preferences, &Settings::destroyed, this, &Squawk::onPreferencesClosed); connect(preferences, &Settings::changeDownloadsPath, this, &Squawk::changeDownloadsPath); + connect(preferences, &Settings::changeTray, this, &Squawk::changeTray); preferences->show(); } else { diff --git a/ui/squawk.h b/ui/squawk.h index f55a000..19fc058 100644 --- a/ui/squawk.h +++ b/ui/squawk.h @@ -59,6 +59,7 @@ public: signals: void closing(); + void quit(); void newAccountRequest(const QMap&); void removeAccountRequest(const QString&); void connectAccount(const QString&); @@ -74,6 +75,7 @@ signals: void requestVCard(const QString& account, const QString& jid); void uploadVCard(const QString& account, const Shared::VCard& card); void changeDownloadsPath(const QString& path); + void changeTray(bool enabled, bool hide); void notify(const QString& account, const Shared::Message& msg); void changeSubscription(const Models::Roster::ElId& id, bool subscribe); diff --git a/ui/widgets/settings/pagegeneral.cpp b/ui/widgets/settings/pagegeneral.cpp index 9ed46a2..39e155a 100644 --- a/ui/widgets/settings/pagegeneral.cpp +++ b/ui/widgets/settings/pagegeneral.cpp @@ -28,6 +28,23 @@ PageGeneral::PageGeneral(QWidget* parent): QSettings settings; m_ui->downloadsPathInput->setText(settings.value("downloadsPath").toString()); + if (QSystemTrayIcon::isSystemTrayAvailable()) { + bool tray = settings.value("tray", false).toBool(); + m_ui->trayInput->setChecked(tray); + if (tray) { + m_ui->hideTrayInput->setChecked(settings.value("hideTray", false).toBool()); + } else { + m_ui->hideTrayInput->setEnabled(false); + } + + connect(m_ui->trayInput, &QCheckBox::stateChanged, this, &PageGeneral::onTrayChecked); + connect(m_ui->hideTrayInput, &QCheckBox::stateChanged, this, &PageGeneral::onHideTrayChecked); + } else { + m_ui->trayInput->setEnabled(false); + m_ui->hideTrayInput->setEnabled(false); + m_ui->trayInput->setToolTip(tr("Tray is not available for your system")); //TODO translate + } + connect(m_ui->downloadsPathButton, &QPushButton::clicked, this, &PageGeneral::onBrowseButtonClicked); } @@ -76,3 +93,19 @@ void PageGeneral::onDialogDestroyed() { dialog = nullptr; } + +void PageGeneral::onTrayChecked(int state) +{ + bool enabled = state == Qt::Checked; + emit variableModified("tray", enabled); + m_ui->hideTrayInput->setEnabled(enabled); + if (!enabled) { + m_ui->hideTrayInput->setEnabled(false); + } +} + +void PageGeneral::onHideTrayChecked(int state) +{ + bool enabled = state == Qt::Checked; + emit variableModified("hideTray", enabled); +} diff --git a/ui/widgets/settings/pagegeneral.h b/ui/widgets/settings/pagegeneral.h index 7f58d71..15738be 100644 --- a/ui/widgets/settings/pagegeneral.h +++ b/ui/widgets/settings/pagegeneral.h @@ -24,6 +24,7 @@ #include #include #include +#include namespace Ui { @@ -47,6 +48,8 @@ private slots: void onBrowseButtonClicked(); void onDialogAccepted(); void onDialogDestroyed(); + void onTrayChecked(int state); + void onHideTrayChecked(int state); private: QScopedPointer m_ui; diff --git a/ui/widgets/settings/pagegeneral.ui b/ui/widgets/settings/pagegeneral.ui index e412668..e08b606 100644 --- a/ui/widgets/settings/pagegeneral.ui +++ b/ui/widgets/settings/pagegeneral.ui @@ -6,8 +6,8 @@ 0 0 - 400 - 300 + 477 + 310 @@ -39,6 +39,34 @@ + + + + Tray icon + + + + + + + Mimimize Squawk to tray when closing main window + + + + + + + Hide tray icon + + + + + + + Hide tray icon when Squawk main window is visible + + + diff --git a/ui/widgets/settings/settings.cpp b/ui/widgets/settings/settings.cpp index cf5e905..62dd80b 100644 --- a/ui/widgets/settings/settings.cpp +++ b/ui/widgets/settings/settings.cpp @@ -57,6 +57,7 @@ void Settings::onVariableModified(const QString& key, const QVariant& value) void Settings::apply() { QSettings settings; + bool trayChanged = false; for (const std::pair& pair: modifiedSettings) { if (pair.first == "style") { Shared::Global::setStyle(pair.second.toString()); @@ -73,8 +74,18 @@ void Settings::apply() emit changeDownloadsPath(path); } } + } else if (pair.first == "tray" || pair.first == "hideTray") { + bool oldValue = settings.value(pair.first, false).toBool(); + bool newValue = pair.second.toBool(); + if (oldValue != newValue) { + trayChanged = true; + settings.setValue(pair.first, pair.second); + } } + } + if (trayChanged) { + emit changeTray(settings.value("tray", false).toBool(), settings.value("hideTray", false).toBool()); } modifiedSettings.clear(); diff --git a/ui/widgets/settings/settings.h b/ui/widgets/settings/settings.h index 689e0ce..59a65cb 100644 --- a/ui/widgets/settings/settings.h +++ b/ui/widgets/settings/settings.h @@ -45,6 +45,7 @@ public: signals: void changeDownloadsPath(const QString& path); + void changeTray(bool enable, bool hide); public slots: void apply();