First tray attempt, seems to be working

This commit is contained in:
Blue 2022-08-15 19:40:07 +03:00
parent 7192286aeb
commit 7e9eed2075
Signed by untrusted user: blue
GPG Key ID: 9B203B252A63EE38
13 changed files with 201 additions and 7 deletions

View File

@ -8,6 +8,7 @@
- deactivated accounts now don't appear in combobox of "Add contact" and "Join conference" dialogues - deactivated accounts now don't appear in combobox of "Add contact" and "Join conference" dialogues
### New features ### New features
- Now you can enable tray icon from settings!
## Squawk 0.2.2 (May 05, 2022) ## Squawk 0.2.2 (May 05, 2022)
### Bug fixes ### Bug fixes

View File

@ -27,8 +27,14 @@ Application::Application(Core::Squawk* p_core):
dialogueQueue(roster), dialogueQueue(roster),
nowQuitting(false), nowQuitting(false),
destroyingSquawk(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::unnoticedMessage, this, &Application::notify);
connect(&roster, &Models::Roster::unreadMessagesCountChanged, this, &Application::unreadMessagesCountChanged); connect(&roster, &Models::Roster::unreadMessagesCountChanged, this, &Application::unreadMessagesCountChanged);
@ -130,6 +136,12 @@ void Application::quit()
if (squawk != nullptr) { if (squawk != nullptr) {
squawk->close(); squawk->close();
} }
if (trayIcon != nullptr) {
trayIcon->deleteLater();
trayIcon = nullptr;
}
if (!destroyingSquawk) { if (!destroyingSquawk) {
checkForTheLastWindow(); checkForTheLastWindow();
} }
@ -155,6 +167,8 @@ void Application::createMainWindow()
connect(squawk, &Squawk::openedConversation, this, &Application::onSquawkOpenedConversation); connect(squawk, &Squawk::openedConversation, this, &Application::onSquawkOpenedConversation);
connect(squawk, &Squawk::openConversation, this, &Application::openConversation); connect(squawk, &Squawk::openConversation, this, &Application::openConversation);
connect(squawk, &Squawk::changeState, this, &Application::setState); 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::closing, this, &Application::onSquawkClosing);
connect(squawk, &Squawk::modifyAccountRequest, core, &Core::Squawk::modifyAccountRequest); connect(squawk, &Squawk::modifyAccountRequest, core, &Core::Squawk::modifyAccountRequest);
@ -194,8 +208,15 @@ void Application::onSquawkClosing()
squawk->deleteLater(); squawk->deleteLater();
squawk = nullptr; squawk = nullptr;
//for now QSettings settings;
quit(); 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() { 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) void Application::notify(const QString& account, const Shared::Message& msg)
{ {
@ -345,6 +431,10 @@ void Application::readSettings()
setState(Shared::Global::fromInt<Shared::Availability>(avail)); setState(Shared::Global::fromInt<Shared::Availability>(avail));
createMainWindow(); createMainWindow();
if (settings.value("tray", false).toBool() && !settings.value("hideTray", false).toBool()) {
createTrayIcon();
}
} }
void Application::writeSettings() void Application::writeSettings()

View File

@ -21,6 +21,9 @@
#include <QObject> #include <QObject>
#include <QDBusInterface> #include <QDBusInterface>
#include <QSystemTrayIcon>
#include <QMenu>
#include <QAction>
#include "dialogqueue.h" #include "dialogqueue.h"
#include "core/squawk.h" #include "core/squawk.h"
@ -91,13 +94,16 @@ private slots:
void onSquawkDestroyed(); void onSquawkDestroyed();
void onNotificationClosed(quint32 id, quint32 reason); void onNotificationClosed(quint32 id, quint32 reason);
void onNotificationInvoked(quint32 id, const QString& action); void onNotificationInvoked(quint32 id, const QString& action);
void onChangeTray(bool enabled, bool hide);
void trayClicked(QSystemTrayIcon::ActivationReason reason);
void toggleSquawk();
private: private:
void createMainWindow(); void createMainWindow();
void subscribeConversation(Conversation* conv); void subscribeConversation(Conversation* conv);
void checkForTheLastWindow(); void checkForTheLastWindow();
void focusConversation(const Models::Roster::ElId& id, const QString& resource = "", const QString& messageId = ""); void focusConversation(const Models::Roster::ElId& id, const QString& resource = "", const QString& messageId = "");
void createTrayIcon();
private: private:
typedef std::map<Models::Roster::ElId, Conversation*> Conversations; typedef std::map<Models::Roster::ElId, Conversation*> Conversations;
@ -113,6 +119,9 @@ private:
bool nowQuitting; bool nowQuitting;
bool destroyingSquawk; bool destroyingSquawk;
Notifications storage; Notifications storage;
QSystemTrayIcon* trayIcon;
QAction actionQuit;
QAction actionToggle;
}; };
#endif // APPLICATION_H #endif // APPLICATION_H

View File

@ -972,6 +972,11 @@ Would you like to check them and try again?</translation>
<source>Downloads path</source> <source>Downloads path</source>
<translation>Downloads path</translation> <translation>Downloads path</translation>
</message> </message>
<message>
<location filename="../ui/widgets/settings/pagegeneral.ui" line="45"/>
<source>Close to tray icon</source>
<translation>Close to tray icon</translation>
</message>
<message> <message>
<location filename="../ui/widgets/settings/pagegeneral.ui" line="36"/> <location filename="../ui/widgets/settings/pagegeneral.ui" line="36"/>
<location filename="../build/squawk_autogen/include/ui_pagegeneral.h" line="70"/> <location filename="../build/squawk_autogen/include/ui_pagegeneral.h" line="70"/>

View File

@ -761,6 +761,11 @@ Você pode tentar novamente</translation>
<source>Downloads path</source> <source>Downloads path</source>
<translation>Pasta de downloads</translation> <translation>Pasta de downloads</translation>
</message> </message>
<message>
<location filename="../ui/widgets/settings/pagegeneral.ui" line="45"/>
<source>Close to tray icon</source>
<translation>Fechar ao ícone da bandeja</translation>
</message>
<message> <message>
<source>Browse</source> <source>Browse</source>
<translation>6 / 5,000 <translation>6 / 5,000

View File

@ -765,6 +765,11 @@ You can try again</source>
<source>Downloads path</source> <source>Downloads path</source>
<translation>Папка для сохраненных файлов</translation> <translation>Папка для сохраненных файлов</translation>
</message> </message>
<message>
<location filename="../ui/widgets/settings/pagegeneral.ui" line="45"/>
<source>Close to tray icon</source>
<translation>Закрывать в трей</translation>
</message>
<message> <message>
<source>Browse</source> <source>Browse</source>
<translation>Выбрать</translation> <translation>Выбрать</translation>

View File

@ -56,7 +56,7 @@ Squawk::Squawk(Models::Roster& p_rosterModel, QWidget *parent) :
connect(m_ui->actionPreferences, &QAction::triggered, this, &Squawk::onPreferences); connect(m_ui->actionPreferences, &QAction::triggered, this, &Squawk::onPreferences);
connect(m_ui->actionAddContact, &QAction::triggered, this, &Squawk::onNewContact); connect(m_ui->actionAddContact, &QAction::triggered, this, &Squawk::onNewContact);
connect(m_ui->actionAddConference, &QAction::triggered, this, &Squawk::onNewConference); 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<int>(&QComboBox::activated), this, &Squawk::onComboboxActivated); connect(m_ui->comboBox, qOverload<int>(&QComboBox::activated), this, &Squawk::onComboboxActivated);
//connect(m_ui->roster, &QTreeView::doubleClicked, this, &Squawk::onRosterItemDoubleClicked); //connect(m_ui->roster, &QTreeView::doubleClicked, this, &Squawk::onRosterItemDoubleClicked);
connect(m_ui->roster, &QTreeView::customContextMenuRequested, this, &Squawk::onRosterContextMenu); connect(m_ui->roster, &QTreeView::customContextMenuRequested, this, &Squawk::onRosterContextMenu);
@ -122,6 +122,7 @@ void Squawk::onPreferences()
preferences->setAttribute(Qt::WA_DeleteOnClose); preferences->setAttribute(Qt::WA_DeleteOnClose);
connect(preferences, &Settings::destroyed, this, &Squawk::onPreferencesClosed); connect(preferences, &Settings::destroyed, this, &Squawk::onPreferencesClosed);
connect(preferences, &Settings::changeDownloadsPath, this, &Squawk::changeDownloadsPath); connect(preferences, &Settings::changeDownloadsPath, this, &Squawk::changeDownloadsPath);
connect(preferences, &Settings::changeTray, this, &Squawk::changeTray);
preferences->show(); preferences->show();
} else { } else {

View File

@ -59,6 +59,7 @@ public:
signals: signals:
void closing(); void closing();
void quit();
void newAccountRequest(const QMap<QString, QVariant>&); void newAccountRequest(const QMap<QString, QVariant>&);
void removeAccountRequest(const QString&); void removeAccountRequest(const QString&);
void connectAccount(const QString&); void connectAccount(const QString&);
@ -74,6 +75,7 @@ signals:
void requestVCard(const QString& account, const QString& jid); void requestVCard(const QString& account, const QString& jid);
void uploadVCard(const QString& account, const Shared::VCard& card); void uploadVCard(const QString& account, const Shared::VCard& card);
void changeDownloadsPath(const QString& path); void changeDownloadsPath(const QString& path);
void changeTray(bool enabled, bool hide);
void notify(const QString& account, const Shared::Message& msg); void notify(const QString& account, const Shared::Message& msg);
void changeSubscription(const Models::Roster::ElId& id, bool subscribe); void changeSubscription(const Models::Roster::ElId& id, bool subscribe);

View File

@ -28,6 +28,23 @@ PageGeneral::PageGeneral(QWidget* parent):
QSettings settings; QSettings settings;
m_ui->downloadsPathInput->setText(settings.value("downloadsPath").toString()); 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); connect(m_ui->downloadsPathButton, &QPushButton::clicked, this, &PageGeneral::onBrowseButtonClicked);
} }
@ -76,3 +93,19 @@ void PageGeneral::onDialogDestroyed()
{ {
dialog = nullptr; 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);
}

View File

@ -24,6 +24,7 @@
#include <QVariant> #include <QVariant>
#include <QSettings> #include <QSettings>
#include <QFileDialog> #include <QFileDialog>
#include <QSystemTrayIcon>
namespace Ui namespace Ui
{ {
@ -47,6 +48,8 @@ private slots:
void onBrowseButtonClicked(); void onBrowseButtonClicked();
void onDialogAccepted(); void onDialogAccepted();
void onDialogDestroyed(); void onDialogDestroyed();
void onTrayChecked(int state);
void onHideTrayChecked(int state);
private: private:
QScopedPointer<Ui::PageGeneral> m_ui; QScopedPointer<Ui::PageGeneral> m_ui;

View File

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>400</width> <width>477</width>
<height>300</height> <height>310</height>
</rect> </rect>
</property> </property>
<layout class="QFormLayout" name="formLayout"> <layout class="QFormLayout" name="formLayout">
@ -39,6 +39,34 @@
</item> </item>
</layout> </layout>
</item> </item>
<item row="2" column="0">
<widget class="QLabel" name="trayLabel">
<property name="text">
<string>Tray icon</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="trayInput">
<property name="text">
<string>Mimimize Squawk to tray when closing main window</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="hideTrayLabel">
<property name="text">
<string>Hide tray icon</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QCheckBox" name="hideTrayInput">
<property name="text">
<string>Hide tray icon when Squawk main window is visible</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
<resources/> <resources/>

View File

@ -57,6 +57,7 @@ void Settings::onVariableModified(const QString& key, const QVariant& value)
void Settings::apply() void Settings::apply()
{ {
QSettings settings; QSettings settings;
bool trayChanged = false;
for (const std::pair<const QString, QVariant>& pair: modifiedSettings) { for (const std::pair<const QString, QVariant>& pair: modifiedSettings) {
if (pair.first == "style") { if (pair.first == "style") {
Shared::Global::setStyle(pair.second.toString()); Shared::Global::setStyle(pair.second.toString());
@ -73,8 +74,18 @@ void Settings::apply()
emit changeDownloadsPath(path); 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(); modifiedSettings.clear();

View File

@ -45,6 +45,7 @@ public:
signals: signals:
void changeDownloadsPath(const QString& path); void changeDownloadsPath(const QString& path);
void changeTray(bool enable, bool hide);
public slots: public slots:
void apply(); void apply();