Ubuntu Tray Icon at Start Up (#6889)

* refactored and setup retries

* undoing suggested change, due to older qt on CI

* ensuring a fresh connection for checking tray icon

* cleaning debug messages

* Update ChangeLog

* removed <iostream> unneeded include

* incorporating suggestions

* incorporated SonarCloud suggestions, changed timer

* additional suggestion -applied on legacy base

* added a const version of appConfig
This commit is contained in:
Ignacio Rodríguez 2021-01-10 20:31:56 +07:00 committed by GitHub
parent 30b2fdc4e3
commit c06cdda15f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 97 additions and 45 deletions

View file

@ -1,5 +1,6 @@
v1.13.1-snapshot
===========
- #6889 Systray Icon on Ubuntu Auto Start (take 2)
===========
v1.13.0-stable

View file

@ -19,7 +19,7 @@
#define DOWNLOAD_URL "http://symless.com/?source=gui"
#define HELP_URL "http://symless.com/help?source=gui"
#include <iostream>
#include <array>
#include "MainWindow.h"
@ -112,8 +112,6 @@ MainWindow::MainWindow (AppConfig& appConfig,
m_pSynergy(NULL),
m_SynergyState(synergyDisconnected),
m_ServerConfig(5, 3, m_AppConfig->screenName(), this),
m_pTrayIcon(NULL),
m_pTrayIconMenu(NULL),
m_AlreadyHidden(false),
m_pMenuBar(NULL),
m_pMenuFile(NULL),
@ -228,7 +226,20 @@ MainWindow::~MainWindow()
void MainWindow::open()
{
createTrayIcon();
std::array<QAction *, 7> trayMenu = {
m_pActionStartSynergy,
m_pActionStopSynergy,
nullptr,
m_pActionMinimize,
m_pActionRestore,
nullptr,
m_pActionQuit
};
m_trayIcon.create(trayMenu, [this](QObject const *o, const char *s) {
connect(o, s, this, SLOT(trayActivated(QSystemTrayIcon::ActivationReason)));
setIcon(synergyDisconnected);
});
if (appConfig().getAutoHide()) {
hide();
@ -251,31 +262,6 @@ void MainWindow::setStatus(const QString &status)
m_pStatusLabel->setText(status);
}
void MainWindow::createTrayIcon()
{
m_pTrayIconMenu = new QMenu(this);
m_pTrayIconMenu->addAction(m_pActionStartSynergy);
m_pTrayIconMenu->addAction(m_pActionStopSynergy);
m_pTrayIconMenu->addSeparator();
m_pTrayIconMenu->addAction(m_pActionMinimize);
m_pTrayIconMenu->addAction(m_pActionRestore);
m_pTrayIconMenu->addSeparator();
m_pTrayIconMenu->addAction(m_pActionQuit);
m_pTrayIcon = new QSystemTrayIcon(this);
m_pTrayIcon->setContextMenu(m_pTrayIconMenu);
m_pTrayIcon->setToolTip("Synergy");
connect(m_pTrayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
this, SLOT(trayActivated(QSystemTrayIcon::ActivationReason)));
setIcon(synergyDisconnected);
m_pTrayIcon->show();
}
void MainWindow::retranslateMenuBar()
{
m_pMenuFile->setTitle(tr("&File"));
@ -366,7 +352,8 @@ void MainWindow::zeroConfToggled() {
updateAutoConfigWidgets();
#endif
}
void MainWindow::setIcon(qSynergyState state)
void MainWindow::setIcon(qSynergyState state) const
{
QIcon icon;
@ -379,8 +366,7 @@ void MainWindow::setIcon(qSynergyState state)
icon.addFile(synergyDefaultIconFiles[state]);
#endif
if (m_pTrayIcon)
m_pTrayIcon->setIcon(icon);
m_trayIcon.set(icon);
}
void MainWindow::trayActivated(QSystemTrayIcon::ActivationReason reason)
@ -847,7 +833,7 @@ QString MainWindow::configFilename()
return filename;
}
QString MainWindow::address()
QString MainWindow::address() const
{
QString i = appConfig().networkInterface();
return (!i.isEmpty() ? i : "") + ":" + QString::number(appConfig().port());

View file

@ -23,6 +23,7 @@
#include <QSettings>
#include <QProcess>
#include <QThread>
#include <QMutex>
#include "ui_MainWindowBase.h"
@ -34,7 +35,7 @@
#include "ActivationDialog.h"
#include "ConfigWriter.h"
#include <QMutex>
#include "TrayIcon.h"
class QAction;
class QMenu;
@ -108,7 +109,7 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase
int synergyState() const { return m_SynergyState; }
QString hostname() const { return m_pLineEditHostname->text(); }
QString configFilename();
QString address();
QString address() const;
QString appPath(const QString& name);
void open();
void clearLog();
@ -166,6 +167,7 @@ public slots:
// TODO This should be properly using the ConfigWriter system.
QSettings& settings() { return GUI::Config::ConfigWriter::make()->settings(); }
AppConfig& appConfig() { return *m_AppConfig; }
AppConfig const& appConfig() const { return *m_AppConfig; }
QProcess* synergyProcess() { return m_pSynergy; }
void setSynergyProcess(QProcess* p) { m_pSynergy = p; }
void initConnections();
@ -173,7 +175,7 @@ public slots:
void createStatusBar();
void createTrayIcon();
void loadSettings();
void setIcon(qSynergyState state);
void setIcon(qSynergyState state) const;
void setSynergyState(qSynergyState state);
bool checkForApp(int which, QString& app);
bool clientArgs(QStringList& args, QString& app);
@ -221,8 +223,6 @@ public slots:
QProcess* m_pSynergy;
int m_SynergyState;
ServerConfig m_ServerConfig;
QSystemTrayIcon* m_pTrayIcon;
QMenu* m_pTrayIconMenu;
bool m_AlreadyHidden;
VersionChecker m_VersionChecker;
IpcClient m_IpcClient;
@ -232,6 +232,7 @@ public slots:
QMenu* m_pMenuWindow;
QMenu* m_pMenuHelp;
QAbstractButton* m_pCancelButton;
TrayIcon m_trayIcon;
qRuningState m_ExpectedRunningState;
QMutex m_StopDesktopMutex;
SslCertificate* m_pSslCertificate;

View file

@ -43,14 +43,14 @@ class ScreenSetupView : public QTableView
ScreenSetupModel* model() const;
protected:
void mouseDoubleClickEvent(QMouseEvent*);
void mouseDoubleClickEvent(QMouseEvent*) override;
void setTableSize();
void resizeEvent(QResizeEvent*);
void dragEnterEvent(QDragEnterEvent* event);
void dragMoveEvent(QDragMoveEvent* event);
void startDrag(Qt::DropActions supportedActions);
QStyleOptionViewItem viewOptions() const;
void scrollTo(const QModelIndex&, ScrollHint) {}
void resizeEvent(QResizeEvent*) override;
void dragEnterEvent(QDragEnterEvent* event) override;
void dragMoveEvent(QDragMoveEvent* event) override;
void startDrag(Qt::DropActions supportedActions) override;
QStyleOptionViewItem viewOptions() const override;
void scrollTo(const QModelIndex&, ScrollHint) override {}
};
#endif

19
src/gui/src/TrayIcon.cpp Normal file
View file

@ -0,0 +1,19 @@
#include "TrayIcon.h"
void TrayIcon::tryCreate() const
{
QSystemTrayIcon trayIcon; // by creating a new tray icon, we actually make the DBus implementation refresh the connection (DBus)
trayIcon.hide(); // we ony hide it in order for the compiler to not optimise-out the object (make some use of it)
if (QSystemTrayIcon::isSystemTrayAvailable()) { // this ends up calling the underlying DBus connection (on DBus)
m_pTrayIcon->show();
m_connector(m_pTrayIcon.get(), SIGNAL(activated(QSystemTrayIcon::ActivationReason)));
}
else {
QTimer::singleShot(2500, this, &TrayIcon::tryCreate);
}
}
void TrayIcon::set(const QIcon& icon) const
{
m_pTrayIcon->setIcon(icon);
}

45
src/gui/src/TrayIcon.h Normal file
View file

@ -0,0 +1,45 @@
#pragma once
#include <QObject>
#include <QTimer>
#include <QSystemTrayIcon>
#include <QMenu>
#include <functional>
#include <memory>
class TrayIcon : public QObject
{
Q_OBJECT
public:
using TConnector = std::function<void(QObject const *, const char *)>;
template<typename TActionContainer>
void create(TActionContainer const &actionContainer, TConnector const &connector)
{
m_connector = connector;
m_pTrayIconMenu = std::make_unique<QMenu>();
for (auto action: actionContainer) {
if (action) {
m_pTrayIconMenu->addAction(action);
}
else {
m_pTrayIconMenu->addSeparator();
}
}
m_pTrayIcon = std::make_unique<QSystemTrayIcon>();
m_pTrayIcon->setContextMenu(m_pTrayIconMenu.get());
m_pTrayIcon->setToolTip("Synergy");
tryCreate();
}
void tryCreate() const;
void set(const QIcon& icon) const;
private:
std::unique_ptr<QSystemTrayIcon> m_pTrayIcon {};
std::unique_ptr<QMenu> m_pTrayIconMenu {};
TConnector m_connector;
};