From f8945e1da02621acfb957de37723515a668ae688 Mon Sep 17 00:00:00 2001 From: Martin Rotter Date: Mon, 6 Oct 2014 18:35:34 +0200 Subject: [PATCH] Fixed #79. --- resources/text/CHANGELOG | 2 +- src/gui/formsettings.cpp | 6 +++-- src/gui/formsettings.ui | 7 ++++++ src/gui/systemtrayicon.cpp | 31 ++++++++++++++++++----- src/gui/systemtrayicon.h | 16 +++++++++--- src/main.cpp | 8 ++++-- src/miscellaneous/systemfactory.cpp | 39 ++++++++++++++++++++++++++--- src/miscellaneous/systemfactory.h | 9 +++++++ 8 files changed, 100 insertions(+), 18 deletions(-) diff --git a/resources/text/CHANGELOG b/resources/text/CHANGELOG index 272d3279a..2aaa4b53d 100644 --- a/resources/text/CHANGELOG +++ b/resources/text/CHANGELOG @@ -3,7 +3,7 @@ Fixed: Added: diff --git a/src/gui/formsettings.cpp b/src/gui/formsettings.cpp index 2d81a4fc1..40ca73a6b 100755 --- a/src/gui/formsettings.cpp +++ b/src/gui/formsettings.cpp @@ -590,6 +590,7 @@ void FormSettings::selectSqlBackend(int index) { void FormSettings::loadGeneral() { m_ui->m_checkAutostart->setText(m_ui->m_checkAutostart->text().arg(APP_NAME)); + m_ui->m_checkForUpdatesOnStart->setChecked(qApp->settings()->value(APP_CFG_GEN, "update_on_start", true).toBool()); // Load auto-start status. SystemFactory::AutoStartStatus autostart_status = qApp->system()->getAutoStartStatus(); @@ -609,14 +610,15 @@ void FormSettings::loadGeneral() { } void FormSettings::saveGeneral() { - // If auto-start feature is available and user wants - // to turn it on, then turn it on. + // If auto-start feature is available and user wants to turn it on, then turn it on. if (m_ui->m_checkAutostart->isChecked()) { qApp->system()->setAutoStartStatus(SystemFactory::Enabled); } else { qApp->system()->setAutoStartStatus(SystemFactory::Disabled); } + + qApp->settings()->setValue(APP_CFG_GEN, "update_on_start", m_ui->m_checkForUpdatesOnStart->isChecked()); } void FormSettings::loadInterface() { diff --git a/src/gui/formsettings.ui b/src/gui/formsettings.ui index 924a4ef08..71a4fc800 100644 --- a/src/gui/formsettings.ui +++ b/src/gui/formsettings.ui @@ -116,6 +116,13 @@ + + + + Check for updates on application startup + + + diff --git a/src/gui/systemtrayicon.cpp b/src/gui/systemtrayicon.cpp index 4049e5113..a6e1cfd19 100755 --- a/src/gui/systemtrayicon.cpp +++ b/src/gui/systemtrayicon.cpp @@ -52,7 +52,9 @@ SystemTrayIcon::SystemTrayIcon(const QString &normal_icon, : QSystemTrayIcon(parent), m_normalIcon(normal_icon), m_plainPixmap(plain_icon), - m_font(QFont()) { + m_font(QFont()), + m_bubbleClickTarget(NULL), + m_bubbleClickSlot(NULL) { qDebug("Creating SystemTrayIcon instance."); m_font.setBold(true); @@ -62,8 +64,7 @@ SystemTrayIcon::SystemTrayIcon(const QString &normal_icon, setContextMenu(parent->trayMenu()); // Create necessary connections. - connect(this, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), - this, SLOT(onActivated(QSystemTrayIcon::ActivationReason))); + connect(this, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(onActivated(QSystemTrayIcon::ActivationReason))); } SystemTrayIcon::~SystemTrayIcon() { @@ -88,9 +89,7 @@ bool SystemTrayIcon::isSystemTrayAvailable() { } bool SystemTrayIcon::isSystemTrayActivated() { - return SystemTrayIcon::isSystemTrayAvailable() && qApp->settings()->value(APP_CFG_GUI, - "use_tray_icon", - true).toBool(); + return SystemTrayIcon::isSystemTrayAvailable() && qApp->settings()->value(APP_CFG_GUI, "use_tray_icon", true).toBool(); } void SystemTrayIcon::showPrivate() { @@ -166,3 +165,23 @@ void SystemTrayIcon::setNumber(int number) { QSystemTrayIcon::setIcon(QIcon(background)); } } + +void SystemTrayIcon::showMessage(const QString &title, const QString &message, QSystemTrayIcon::MessageIcon icon, + int milliseconds_timeout_hint, QObject *click_target, const char *click_slot) { + if (m_bubbleClickTarget != NULL && m_bubbleClickSlot != NULL) { + // Disconnect previous bubble click signalling. + disconnect(this, SIGNAL(messageClicked()), m_bubbleClickTarget, m_bubbleClickSlot); + } + + m_bubbleClickSlot = (char*) click_slot; + m_bubbleClickTarget = click_target; + + if (click_target != NULL && click_slot != NULL) { + // Establish new connection for bubble click. + connect(this, SIGNAL(messageClicked()), click_target, click_slot); + } + + // NOTE: If connections do not work, then use QMetaObject::invokeMethod(...). + + QSystemTrayIcon::showMessage(title, message, icon, milliseconds_timeout_hint); +} diff --git a/src/gui/systemtrayicon.h b/src/gui/systemtrayicon.h index ec56ee070..1d6a97723 100644 --- a/src/gui/systemtrayicon.h +++ b/src/gui/systemtrayicon.h @@ -19,6 +19,9 @@ #define SYSTEMTRAYICON_H #include + +#include "definitions/definitions.h" + #include #include #include @@ -51,6 +54,13 @@ class SystemTrayIcon : public QSystemTrayIcon { FormMain *parent = 0); virtual ~SystemTrayIcon(); + // Sets the number to be visible in the tray icon, number <= 0 removes it. + void setNumber(int number = -1); + + void showMessage(const QString &title, const QString &message, MessageIcon icon = Information, + int milliseconds_timeout_hint = TRAY_ICON_BUBBLE_TIMEOUT, QObject *click_target = NULL, + const char *click_slot = NULL); + // Returns true if tray icon CAN be constructed on this machine. static bool isSystemTrayAvailable(); @@ -58,9 +68,6 @@ class SystemTrayIcon : public QSystemTrayIcon { // application settings. static bool isSystemTrayActivated(); - // Sets the number to be visible in the tray icon, number <= 0 removes it. - void setNumber(int number = -1); - public slots: void show(); @@ -72,6 +79,9 @@ class SystemTrayIcon : public QSystemTrayIcon { QIcon m_normalIcon; QPixmap m_plainPixmap; QFont m_font; + + QObject *m_bubbleClickTarget; + char *m_bubbleClickSlot; }; #endif // SYSTEMTRAYICON_H diff --git a/src/main.cpp b/src/main.cpp index 7bdd6d062..5ea671299 100755 --- a/src/main.cpp +++ b/src/main.cpp @@ -33,6 +33,7 @@ #include #include #include +#include int main(int argc, char *argv[]) { @@ -111,11 +112,14 @@ int main(int argc, char *argv[]) { // Display tray icon if it is enabled and available. if (SystemTrayIcon::isSystemTrayActivated()) { qApp->showTrayIcon(); + + if (qApp->settings()->value(APP_CFG_GEN, "update_on_start", true).toBool()) { + QTimer::singleShot(STARTUP_UPDATE_DELAY, application.system(), SLOT(checkForUpdatesAsynchronously())); + } } // Setup single-instance behavior. - QObject::connect(&application, SIGNAL(messageReceived(QString)), - &application, SLOT(processExecutionMessage(QString))); + QObject::connect(&application, SIGNAL(messageReceived(QString)), &application, SLOT(processExecutionMessage(QString))); // Enter global event loop. return Application::exec(); diff --git a/src/miscellaneous/systemfactory.cpp b/src/miscellaneous/systemfactory.cpp index 821716239..908984273 100755 --- a/src/miscellaneous/systemfactory.cpp +++ b/src/miscellaneous/systemfactory.cpp @@ -18,7 +18,9 @@ #include "miscellaneous/systemfactory.h" #include "network-web/networkfactory.h" +#include "gui/formmain.h" #include "miscellaneous/application.h" +#include "miscellaneous/systemfactory.h" #if defined(Q_OS_WIN) #include @@ -29,7 +31,17 @@ #include #include #include +#include +#include +#if QT_VERSION >= 0x050000 +#include +#else +#include +#endif + + +typedef QPair UpdateCheck; SystemFactory::SystemFactory(QObject *parent) : QObject(parent) { } @@ -43,10 +55,7 @@ SystemFactory::AutoStartStatus SystemFactory::getAutoStartStatus() { #if defined(Q_OS_WIN) QSettings registry_key("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Run", QSettings::NativeFormat); - bool autostart_enabled = registry_key.value(APP_LOW_NAME, - "").toString().replace('\\', - '/') == - Application::applicationFilePath(); + bool autostart_enabled = registry_key.value(APP_LOW_NAME, "").toString().replace('\\', '/') == Application::applicationFilePath(); if (autostart_enabled) { return SystemFactory::Enabled; @@ -200,3 +209,25 @@ UpdateInfo SystemFactory::parseUpdatesFile(const QByteArray &updates_file) { return update; } + +void SystemFactory::checkForUpdatesAsynchronously() { + QFutureWatcher *watcher_for_future = new QFutureWatcher(this); + + connect(watcher_for_future, SIGNAL(finished()), this, SLOT(handleBackgroundUpdatesCheck())); + watcher_for_future->setFuture(QtConcurrent::run(this, &SystemFactory::checkForUpdates)); +} + +void SystemFactory::handleBackgroundUpdatesCheck() { + QFutureWatcher *future_watcher = static_cast*>(sender()); + UpdateCheck updates = future_watcher->result(); + + if (updates.second == QNetworkReply::NoError && updates.first.m_availableVersion != APP_VERSION) { + if (SystemTrayIcon::isSystemTrayActivated()) { + qApp->trayIcon()->showMessage(tr("New version available"), + tr("Click the bubble for more information."), + QSystemTrayIcon::Information, + TRAY_ICON_BUBBLE_TIMEOUT, + qApp->mainForm(), SLOT(showUpdates())); + } + } +} diff --git a/src/miscellaneous/systemfactory.h b/src/miscellaneous/systemfactory.h index 9a76efffa..e9cbad968 100644 --- a/src/miscellaneous/systemfactory.h +++ b/src/miscellaneous/systemfactory.h @@ -88,6 +88,15 @@ class SystemFactory : public QObject { // Tries to download list with new updates. QPair checkForUpdates(); + public slots: + void checkForUpdatesAsynchronously(); + + private slots: + void handleBackgroundUpdatesCheck(); + + signals: + void updateCheckedAsynchronously(QPair update_info); + private: // Performs parsing of downloaded file with list of updates. UpdateInfo parseUpdatesFile(const QByteArray &updates_file);