From a52d703e4b312dd8de471992f76fa3bdd1350de4 Mon Sep 17 00:00:00 2001 From: Martin Rotter Date: Thu, 24 Feb 2022 11:44:05 +0100 Subject: [PATCH] refactoring and adding of taskbar overlay icon --- CMakeLists.txt | 4 + src/librssguard/CMakeLists.txt | 6 + src/librssguard/database/databasefactory.cpp | 2 +- .../gui/dialogs/formmessagefiltersmanager.cpp | 10 +- src/librssguard/gui/dialogs/formsettings.cpp | 4 +- src/librssguard/gui/feedsview.cpp | 2 +- src/librssguard/gui/messagebox.cpp | 14 +- src/librssguard/gui/messagebox.h | 4 +- src/librssguard/gui/messagebrowser.cpp | 6 +- src/librssguard/gui/messagesview.cpp | 2 +- src/librssguard/gui/settings/settingsgui.cpp | 11 +- src/librssguard/gui/webbrowser.cpp | 10 +- src/librssguard/miscellaneous/application.cpp | 135 ++++++++++++++++-- src/librssguard/miscellaneous/application.h | 12 ++ src/librssguard/miscellaneous/settings.cpp | 2 +- src/librssguard/miscellaneous/settings.h | 2 +- .../network-web/adblock/adblockdialog.cpp | 14 +- .../network-web/downloadmanager.cpp | 2 +- src/librssguard/network-web/webfactory.cpp | 2 +- .../services/gmail/gui/formaddeditemail.cpp | 2 +- .../standard/gui/formstandardimportexport.cpp | 2 +- .../services/standard/standardserviceroot.cpp | 4 +- .../services/tt-rss/gui/formttrssnote.cpp | 2 +- 23 files changed, 198 insertions(+), 56 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9f73fb998..c4cf12c25 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -128,6 +128,10 @@ if(NOT OS2) list(APPEND QT_COMPONENTS Multimedia) endif() +if(WIN32 AND NOT BUILD_WITH_QT6) + list(APPEND QT_COMPONENTS WinExtras) +endif() + if(USE_WEBENGINE) list(APPEND QT_COMPONENTS WebEngineWidgets) add_compile_definitions(USE_WEBENGINE) diff --git a/src/librssguard/CMakeLists.txt b/src/librssguard/CMakeLists.txt index 1be67a101..33858fd7b 100644 --- a/src/librssguard/CMakeLists.txt +++ b/src/librssguard/CMakeLists.txt @@ -636,6 +636,12 @@ if(USE_WEBENGINE) ) endif() +if(WIN32 AND NOT BUILD_WITH_QT6) + target_link_libraries(rssguard PUBLIC + Qt${QT_VERSION_MAJOR}::WinExtras + ) +endif() + if(NOT OS2) target_link_libraries(rssguard PUBLIC Qt${QT_VERSION_MAJOR}::Multimedia diff --git a/src/librssguard/database/databasefactory.cpp b/src/librssguard/database/databasefactory.cpp index 3f80a405c..cf2aa7c3b 100644 --- a/src/librssguard/database/databasefactory.cpp +++ b/src/librssguard/database/databasefactory.cpp @@ -58,7 +58,7 @@ void DatabaseFactory::determineDriver() { << QUOTE_W_SPACE_DOT(ex.message()); if (m_dbDriver->driverType() != DatabaseDriver::DriverType::SQLite) { - MessageBox::show(nullptr, + MsgBox::show(nullptr, QMessageBox::Icon::Critical, tr("Cannot connect to database"), tr("Connection to your database was not established with error: '%1'. " diff --git a/src/librssguard/gui/dialogs/formmessagefiltersmanager.cpp b/src/librssguard/gui/dialogs/formmessagefiltersmanager.cpp index 37faa4c83..86902a15c 100644 --- a/src/librssguard/gui/dialogs/formmessagefiltersmanager.cpp +++ b/src/librssguard/gui/dialogs/formmessagefiltersmanager.cpp @@ -152,7 +152,7 @@ void FormMessageFiltersManager::removeSelectedFilter() { return; } - if (MessageBox::show(this, QMessageBox::Icon::Question, tr("Are you sure?"), + if (MsgBox::show(this, QMessageBox::Icon::Question, tr("Are you sure?"), tr("Do you really want to remove selected filter?"), {}, fltr->name(), QMessageBox::StandardButton::Yes | QMessageBox::StandardButton::No, @@ -186,7 +186,7 @@ void FormMessageFiltersManager::addNewFilter(const QString& filter_script) { m_ui.m_listFilters->setCurrentRow(m_ui.m_listFilters->count() - 1); } catch (const ApplicationException& ex) { - MessageBox::show(this, QMessageBox::Icon::Critical, tr("Error"), + MsgBox::show(this, QMessageBox::Icon::Critical, tr("Error"), tr("Cannot save new filter, error: '%1'.").arg(ex.message())); } } @@ -549,7 +549,7 @@ void FormMessageFiltersManager::beautifyScript() { #endif if (!proc_clang_format.open() || proc_clang_format.error() == QProcess::ProcessError::FailedToStart) { - MessageBox::show(this, QMessageBox::Icon::Critical, + MsgBox::show(this, QMessageBox::Icon::Critical, tr("Cannot find 'clang-format'"), tr("Script was not beautified, because 'clang-format' tool was not found.")); return; @@ -567,7 +567,7 @@ void FormMessageFiltersManager::beautifyScript() { else { auto err = proc_clang_format.readAllStandardError(); - MessageBox::show(this, QMessageBox::Icon::Critical, + MsgBox::show(this, QMessageBox::Icon::Critical, tr("Error"), tr("Script was not beautified, because 'clang-format' tool thrown error."), QString(), @@ -576,7 +576,7 @@ void FormMessageFiltersManager::beautifyScript() { } else { proc_clang_format.kill(); - MessageBox::show(this, QMessageBox::Icon::Critical, + MsgBox::show(this, QMessageBox::Icon::Critical, tr("Beautifier was running for too long time"), tr("Script was not beautified, is 'clang-format' installed?")); } diff --git a/src/librssguard/gui/dialogs/formsettings.cpp b/src/librssguard/gui/dialogs/formsettings.cpp index 28cd7a103..502b55c6f 100644 --- a/src/librssguard/gui/dialogs/formsettings.cpp +++ b/src/librssguard/gui/dialogs/formsettings.cpp @@ -96,7 +96,7 @@ void FormSettings::applySettings() { if (!panels_for_restart.isEmpty()) { const QStringList changed_settings_description = panels_for_restart.replaceInStrings(QRegularExpression(QSL("^")), QString::fromUtf8(QByteArray(" • "))); - const QMessageBox::StandardButton clicked_button = MessageBox::show(this, + const QMessageBox::StandardButton clicked_button = MsgBox::show(this, QMessageBox::Icon::Question, tr("Critical settings were changed"), tr( @@ -135,7 +135,7 @@ void FormSettings::cancelSettings() { const QStringList changed_settings_description = changed_panels.replaceInStrings(QRegularExpression(QSL("^")), QString::fromUtf8(QByteArray(" • "))); - if (MessageBox::show(this, + if (MsgBox::show(this, QMessageBox::Icon::Critical, tr("Some settings are changed and will be lost"), tr("Some settings were changed and by cancelling this dialog, you would lose these changes."), diff --git a/src/librssguard/gui/feedsview.cpp b/src/librssguard/gui/feedsview.cpp index 8d9f0a059..f9dbdf52a 100644 --- a/src/librssguard/gui/feedsview.cpp +++ b/src/librssguard/gui/feedsview.cpp @@ -256,7 +256,7 @@ void FeedsView::deleteSelectedItem() { if (selected_item != nullptr) { if (selected_item->canBeDeleted()) { // Ask user first. - if (MessageBox::show(qApp->mainFormWidget(), + if (MsgBox::show(qApp->mainFormWidget(), QMessageBox::Icon::Question, tr("Deleting \"%1\"").arg(selected_item->title()), tr("You are about to completely delete item \"%1\".").arg(selected_item->title()), diff --git a/src/librssguard/gui/messagebox.cpp b/src/librssguard/gui/messagebox.cpp index b546c1dd0..fdc4eea32 100644 --- a/src/librssguard/gui/messagebox.cpp +++ b/src/librssguard/gui/messagebox.cpp @@ -12,9 +12,9 @@ #include #include -MessageBox::MessageBox(QWidget* parent) : QMessageBox(parent) {} +MsgBox::MsgBox(QWidget* parent) : QMessageBox(parent) {} -void MessageBox::setIcon(QMessageBox::Icon icon) { +void MsgBox::setIcon(QMessageBox::Icon icon) { // Determine correct status icon size. const int icon_size = qApp->style()->pixelMetric(QStyle::PixelMetric::PM_MessageBoxIconSize, nullptr, this); @@ -22,7 +22,7 @@ void MessageBox::setIcon(QMessageBox::Icon icon) { setIconPixmap(iconForStatus(icon).pixmap(icon_size, icon_size)); } -void MessageBox::setCheckBox(QMessageBox* msg_box, const QString& text, bool* data) { +void MsgBox::setCheckBox(QMessageBox* msg_box, const QString& text, bool* data) { // Add "don't show this again checkbox. auto* check_box = new QCheckBox(msg_box); @@ -34,7 +34,7 @@ void MessageBox::setCheckBox(QMessageBox* msg_box, const QString& text, bool* da msg_box->setCheckBox(check_box); } -QIcon MessageBox::iconForStatus(QMessageBox::Icon status) { +QIcon MsgBox::iconForStatus(QMessageBox::Icon status) { switch (status) { case QMessageBox::Icon::Information: return qApp->icons()->fromTheme(QSL("dialog-information")); @@ -53,7 +53,7 @@ QIcon MessageBox::iconForStatus(QMessageBox::Icon status) { } } -QMessageBox::StandardButton MessageBox::show(QWidget* parent, +QMessageBox::StandardButton MsgBox::show(QWidget* parent, QMessageBox::Icon icon, const QString& title, const QString& text, @@ -69,7 +69,7 @@ QMessageBox::StandardButton MessageBox::show(QWidget* parent, } // Create and find needed components. - MessageBox msg_box(parent); + MsgBox msg_box(parent); // Initialize message box properties. msg_box.setWindowTitle(title); @@ -81,7 +81,7 @@ QMessageBox::StandardButton MessageBox::show(QWidget* parent, msg_box.setDefaultButton(default_button); if (dont_show_again != nullptr) { - MessageBox::setCheckBox(&msg_box, tr("Do not show this dialog again."), dont_show_again); + MsgBox::setCheckBox(&msg_box, tr("Do not show this dialog again."), dont_show_again); } if (functor) { diff --git a/src/librssguard/gui/messagebox.h b/src/librssguard/gui/messagebox.h index d2b6f1408..85ee5a9e7 100644 --- a/src/librssguard/gui/messagebox.h +++ b/src/librssguard/gui/messagebox.h @@ -8,13 +8,13 @@ #include -class MessageBox : public QMessageBox { +class MsgBox : public QMessageBox { Q_OBJECT public: // Constructors and destructors. - explicit MessageBox(QWidget* parent = nullptr); + explicit MsgBox(QWidget* parent = nullptr); // Custom icon setting. void setIcon(Icon icon); diff --git a/src/librssguard/gui/messagebrowser.cpp b/src/librssguard/gui/messagebrowser.cpp index f82125827..3cc89303e 100644 --- a/src/librssguard/gui/messagebrowser.cpp +++ b/src/librssguard/gui/messagebrowser.cpp @@ -164,7 +164,7 @@ void MessageBrowser::onAnchorClicked(const QUrl& url) { } else { // User clicked some URL. Open it in external browser or download? - MessageBox box(qApp->mainFormWidget()); + MsgBox box(qApp->mainFormWidget()); box.setText(tr("You clicked some link. You can download the link contents or open it in external web browser.")); box.setInformativeText(tr("What action do you want to take?")); @@ -175,7 +175,7 @@ void MessageBrowser::onAnchorClicked(const QUrl& url) { QAbstractButton* btn_cancel = box.addButton(QMessageBox::StandardButton::Cancel); bool always; - MessageBox::setCheckBox(&box, tr("Always open links in external browser."), &always); + MsgBox::setCheckBox(&box, tr("Always open links in external browser."), &always); box.setDefaultButton(QMessageBox::StandardButton::Cancel); box.exec(); @@ -198,7 +198,7 @@ void MessageBrowser::onAnchorClicked(const QUrl& url) { } } else { - MessageBox::show(qApp->mainFormWidget(), QMessageBox::Warning, tr("Incorrect link"), tr("Selected hyperlink is invalid.")); + MsgBox::show(qApp->mainFormWidget(), QMessageBox::Warning, tr("Incorrect link"), tr("Selected hyperlink is invalid.")); } } diff --git a/src/librssguard/gui/messagesview.cpp b/src/librssguard/gui/messagesview.cpp index bcb09e9ed..610617c3b 100644 --- a/src/librssguard/gui/messagesview.cpp +++ b/src/librssguard/gui/messagesview.cpp @@ -561,7 +561,7 @@ void MessagesView::sendSelectedMessageViaEmail() { const Message message = m_sourceModel->messageAt(m_proxyModel->mapToSource(selectionModel()->selectedRows().at(0)).row()); if (!qApp->web()->sendMessageViaEmail(message)) { - MessageBox::show(this, QMessageBox::Critical, tr("Problem with starting external e-mail client"), + MsgBox::show(this, QMessageBox::Critical, tr("Problem with starting external e-mail client"), tr("External e-mail client could not be started.")); } } diff --git a/src/librssguard/gui/settings/settingsgui.cpp b/src/librssguard/gui/settings/settingsgui.cpp index 4d9494593..2a5b5a01a 100644 --- a/src/librssguard/gui/settings/settingsgui.cpp +++ b/src/librssguard/gui/settings/settingsgui.cpp @@ -34,8 +34,11 @@ SettingsGui::SettingsGui(Settings* settings, QWidget* parent) : SettingsPanel(se << /*: Version column of skin list. */ tr("Version") << tr("Author")); -#if !defined(Q_OS_UNIX) || defined(Q_OS_MACOS) - m_ui->m_tabUi->setTabVisible(m_ui->m_tabUi->indexOf(m_ui->m_tabTaskBar), false); + m_ui->m_tabUi->setTabVisible(m_ui->m_tabUi->indexOf(m_ui->m_tabTaskBar), +#if (defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)) || defined(Q_OS_WIN) + true); +#else + false); #endif m_ui->m_helpCustomSkinColors->setHelpText(tr("You can override some colors defined by your skin here. " @@ -152,7 +155,7 @@ void SettingsGui::loadSettings() { m_ui->m_checkMonochromeIcons->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::MonochromeTrayIcon)).toBool()); m_ui->m_checkCountUnreadMessages->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::UnreadNumbersInTrayIcon)).toBool()); -#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS) +#if (defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)) || defined(Q_OS_WIN) m_ui->m_displayUnreadMessageCountOnTaskBar->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::UnreadNumbersOnTaskBar)).toBool()); #endif @@ -336,7 +339,7 @@ void SettingsGui::saveSettings() { settings()->setValue(GROUP(GUI), GUI::ForceDarkFusion, m_ui->m_checkForceDarkFusion->isChecked()); -#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS) +#if (defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)) || defined(Q_OS_WIN) settings()->setValue(GROUP(GUI), GUI::UnreadNumbersOnTaskBar, m_ui->m_displayUnreadMessageCountOnTaskBar->isChecked()); #endif diff --git a/src/librssguard/gui/webbrowser.cpp b/src/librssguard/gui/webbrowser.cpp index bfbfd9ce5..4f8b95c7b 100644 --- a/src/librssguard/gui/webbrowser.cpp +++ b/src/librssguard/gui/webbrowser.cpp @@ -229,11 +229,11 @@ void WebBrowser::setReadabledHtml(const QString& better_html) { } void WebBrowser::readabilityFailed(const QString& error) { - MessageBox::show({}, QMessageBox::Icon::Critical, - tr("Reader mode failed for this website"), - tr("Reader mode cannot be applied to current page."), - {}, - error); + MsgBox::show({}, QMessageBox::Icon::Critical, + tr("Reader mode failed for this website"), + tr("Reader mode cannot be applied to current page."), + {}, + error); } void WebBrowser::initializeLayout() { diff --git a/src/librssguard/miscellaneous/application.cpp b/src/librssguard/miscellaneous/application.cpp index ef66a45a9..d4867f8ac 100644 --- a/src/librssguard/miscellaneous/application.cpp +++ b/src/librssguard/miscellaneous/application.cpp @@ -26,6 +26,8 @@ #include #include +#include +#include #include #include #include @@ -50,6 +52,14 @@ #include #endif +#if defined(Q_OS_WIN) +#include + +#if QT_VERSION_MAJOR == 5 +#include +#endif +#endif + Application::Application(const QString& id, int& argc, char** argv) : SingleApplication(id, argc, argv), m_updateFeedsLock(new Mutex()) { parseCmdArgumentsFromMyInstance(); @@ -71,6 +81,33 @@ Application::Application(const QString& id, int& argc, char** argv) m_notifications = new NotificationFactory(this); m_shouldRestart = false; +#if defined(Q_OS_WIN) + m_windowsTaskBar = nullptr; + + const GUID qIID_ITaskbarList4 = { 0xc43dc798, 0x95d1, 0x4bea, { 0x90, 0x30, 0xbb, 0x99, 0xe2, 0x98, 0x3a, 0x1a } }; + HRESULT task_result = CoCreateInstance(CLSID_TaskbarList, + nullptr, + CLSCTX_INPROC_SERVER, + qIID_ITaskbarList4, + reinterpret_cast(&m_windowsTaskBar)); + + if (FAILED(task_result)) { + qCriticalNN << LOGSEC_CORE + << "Taskbar integration for Windows failed to initialize with HRESULT:" + << QUOTE_W_SPACE_DOT(task_result); + + m_windowsTaskBar = nullptr; + } + else if (FAILED(m_windowsTaskBar->HrInit())) { + qCriticalNN << LOGSEC_CORE + << "Taskbar integration for Windows failed to initialize with inner HRESULT:" + << QUOTE_W_SPACE_DOT(m_windowsTaskBar->HrInit()); + + m_windowsTaskBar->Release(); + m_windowsTaskBar = nullptr; + } +#endif + determineFirstRuns(); //: Abbreviation of language, e.g. en. @@ -156,6 +193,12 @@ Application::Application(const QString& id, int& argc, char** argv) } Application::~Application() { +#if defined(Q_OS_WIN) + if (m_windowsTaskBar != nullptr) { + m_windowsTaskBar->Release(); + } +#endif + qDebugNN << LOGSEC_CORE << "Destroying Application instance."; } @@ -551,10 +594,10 @@ void Application::showGuiMessage(Notification::Event event, if (dest.m_messageBox || msg.m_type == QSystemTrayIcon::MessageIcon::Critical) { // Tray icon or OSD is not available, display simple text box. - MessageBox::show(parent == nullptr ? mainFormWidget() : parent, - QMessageBox::Icon(msg.m_type), msg.m_title, msg.m_message, - {}, {}, QMessageBox::StandardButton::Ok, QMessageBox::StandardButton::Ok, {}, - action.m_title, action.m_action); + MsgBox::show(parent == nullptr ? mainFormWidget() : parent, + QMessageBox::Icon(msg.m_type), msg.m_title, msg.m_message, + {}, {}, QMessageBox::StandardButton::Ok, QMessageBox::StandardButton::Ok, {}, + action.m_title, action.m_action); } else if (dest.m_statusBar && mainForm()->statusBar() != nullptr && mainForm()->statusBar()->isVisible()) { mainForm()->statusBar()->showMessage(msg.m_message); @@ -634,7 +677,11 @@ void Application::showMessagesNumber(int unread_messages, bool any_feed_has_new_ m_trayIcon->setNumber(unread_messages, any_feed_has_new_unread_messages); } + // Set task bar overlay with number of unread articles. #if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS) + // Use D-Bus "LauncherEntry" service on Linux. + bool task_bar_count_enabled = settings()->value(GROUP(GUI), + SETTING(GUI::UnreadNumbersOnTaskBar)).toBool(); QDBusMessage signal = QDBusMessage::createSignal(QSL("/"), QSL("com.canonical.Unity.LauncherEntry"), QSL("Update")); @@ -644,20 +691,90 @@ void Application::showMessagesNumber(int unread_messages, bool any_feed_has_new_ QVariantMap setProperty; setProperty.insert("count", qint64(unread_messages)); - bool task_bar_count_enabled = settings()->value(GROUP(GUI), - SETTING(GUI::UnreadNumbersOnTaskBar)).toBool(); setProperty.insert("count-visible", task_bar_count_enabled && unread_messages > 0); signal << setProperty; QDBusConnection::sessionBus().send(signal); +#elif defined(Q_OS_WIN) + // Use SetOverlayIcon Windows API method on Windows. + bool task_bar_count_enabled = settings()->value(GROUP(GUI), + SETTING(GUI::UnreadNumbersOnTaskBar)).toBool(); + + if (m_mainForm != nullptr) { + QImage overlay_icon = generateOverlayIcon(unread_messages); + +#if QT_VERSION_MAJOR == 5 + HICON overlay_hicon = QtWin::toHICON(QPixmap::fromImage(overlay_icon)); +#else + HICON overlay_hicon = overlay_icon.toHICON(); #endif - mainForm()->setWindowTitle(unread_messages > 0 - ? QSL("%1 (%2)").arg(QSL(APP_NAME), QString::number(unread_messages)) - : QSL(APP_NAME)); + HRESULT overlay_result = m_windowsTaskBar->SetOverlayIcon(reinterpret_cast(m_mainForm->winId()), + (task_bar_count_enabled && unread_messages > 0) + ? overlay_hicon + : nullptr, + nullptr); + + DestroyIcon(overlay_hicon); + + if (FAILED(overlay_result)) { + qCriticalNN << LOGSEC_CORE << "Failed to set overlay icon with HRESULT:" << QUOTE_W_SPACE_DOT(overlay_result); + } + + //m_taskbar->SetProgressValue(reinterpret_cast(m_mainForm->winId()), 50, 100); + //m_taskbar->SetProgressState(reinterpret_cast(m_mainForm->winId()), TBPFLAG::TBPF_ERROR); + } +#endif + + if (m_mainForm != nullptr) { + m_mainForm->setWindowTitle(unread_messages > 0 + ? QSL("%1 (%2)").arg(QSL(APP_NAME), QString::number(unread_messages)) + : QSL(APP_NAME)); + } } +#if defined(Q_OS_WIN) +QImage Application::generateOverlayIcon(int number) const { + QImage img(64, 64, QImage::Format::Format_ARGB32); + QPainter p; + QString num_txt = number > 999 ? QChar(8734) : QString::number(number); + QPainterPath rounded_rectangle; rounded_rectangle.addRoundedRect(QRectF(img.rect()), 15, 15); + QFont fon = font(); + + if (num_txt.size() == 3) { + fon.setPixelSize(img.width() * 0.52); + } + else if (num_txt.size() == 2) { + fon.setPixelSize(img.width() * 0.65); + } + else { + fon.setPixelSize(img.width() * 0.85); + } + + p.begin(&img); + p.setFont(fon); + + p.setRenderHint(QPainter::RenderHint::SmoothPixmapTransform, true); + p.setRenderHint(QPainter::RenderHint::TextAntialiasing, true); + + img.fill(Qt::GlobalColor::transparent); + + p.fillPath(rounded_rectangle, Qt::GlobalColor::white); + + p.setPen(Qt::GlobalColor::black); + p.drawPath(rounded_rectangle); + + p.drawText(img.rect(), + num_txt, + QTextOption(Qt::AlignmentFlag::AlignCenter)); + p.end(); + + return img; +} + +#endif + void Application::restart() { m_shouldRestart = true; quit(); diff --git a/src/librssguard/miscellaneous/application.h b/src/librssguard/miscellaneous/application.h index 9c23c13b2..78b6baca4 100644 --- a/src/librssguard/miscellaneous/application.h +++ b/src/librssguard/miscellaneous/application.h @@ -44,6 +44,10 @@ class QWebEngineDownloadItem; class WebFactory; class NotificationFactory; +#if defined(Q_OS_WIN) +struct ITaskbarList4; +#endif + struct GuiMessage { public: GuiMessage(QString title, QString message, QSystemTrayIcon::MessageIcon type) @@ -189,6 +193,10 @@ class RSSGUARD_DLLSPEC Application : public SingleApplication { void onAdBlockFailure(); #endif +#if defined(Q_OS_WIN) + QImage generateOverlayIcon(int number) const; +#endif + void onFeedUpdatesFinished(const FeedDownloadResults& results); private: @@ -234,6 +242,10 @@ class RSSGUARD_DLLSPEC Application : public SingleApplication { bool m_firstRunCurrentVersion; QString m_customDataFolder; bool m_allowMultipleInstances; + +#if defined(Q_OS_WIN) + ITaskbarList4* m_windowsTaskBar; +#endif }; inline Application* Application::instance() { diff --git a/src/librssguard/miscellaneous/settings.cpp b/src/librssguard/miscellaneous/settings.cpp index eafa4f06f..6fd7df468 100644 --- a/src/librssguard/miscellaneous/settings.cpp +++ b/src/librssguard/miscellaneous/settings.cpp @@ -260,7 +260,7 @@ DVALUE(bool) GUI::ForceDarkFusionDef = false; DKEY GUI::UnreadNumbersInTrayIcon = "show_unread_numbers_in_tray_icon"; DVALUE(bool) GUI::UnreadNumbersInTrayIconDef = true; -#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS) +#if (defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)) || defined(Q_OS_WIN) DKEY GUI::UnreadNumbersOnTaskBar = "show_unread_numbers_on_task_bar"; DVALUE(bool) GUI::UnreadNumbersOnTaskBarDef = true; #endif diff --git a/src/librssguard/miscellaneous/settings.h b/src/librssguard/miscellaneous/settings.h index abdfca435..bae444e93 100644 --- a/src/librssguard/miscellaneous/settings.h +++ b/src/librssguard/miscellaneous/settings.h @@ -267,7 +267,7 @@ namespace GUI { KEY UnreadNumbersInTrayIcon; VALUE(bool) UnreadNumbersInTrayIconDef; -#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS) +#if (defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)) || defined(Q_OS_WIN) KEY UnreadNumbersOnTaskBar; VALUE(bool) UnreadNumbersOnTaskBarDef; #endif diff --git a/src/librssguard/network-web/adblock/adblockdialog.cpp b/src/librssguard/network-web/adblock/adblockdialog.cpp index 6d6e0acbe..88b3cdeab 100644 --- a/src/librssguard/network-web/adblock/adblockdialog.cpp +++ b/src/librssguard/network-web/adblock/adblockdialog.cpp @@ -61,13 +61,13 @@ void AdBlockDialog::saveOnClose() { << "Failed to enable AdBlock, error:" << QUOTE_W_SPACE_DOT(ex.message()); - MessageBox::show(this, - QMessageBox::Icon::Critical, - tr("Cannot enable AdBlock"), - tr("There is some error in AdBlock component and it cannot be enabled. " - "Check error message below (or application debug log) for more information."), - {}, - ex.message()); + MsgBox::show(this, + QMessageBox::Icon::Critical, + tr("Cannot enable AdBlock"), + tr("There is some error in AdBlock component and it cannot be enabled. " + "Check error message below (or application debug log) for more information."), + {}, + ex.message()); } } diff --git a/src/librssguard/network-web/downloadmanager.cpp b/src/librssguard/network-web/downloadmanager.cpp index 04b74e931..c627fbdae 100644 --- a/src/librssguard/network-web/downloadmanager.cpp +++ b/src/librssguard/network-web/downloadmanager.cpp @@ -204,7 +204,7 @@ void DownloadItem::openFile() { void DownloadItem::openFolder() { if (m_output.exists()) { if (!SystemFactory::openFolderFile(m_output.fileName())) { - MessageBox::show(this, + MsgBox::show(this, QMessageBox::Icon::Warning, tr("Cannot open directory"), tr("Cannot open output directory. Open it manually."), diff --git a/src/librssguard/network-web/webfactory.cpp b/src/librssguard/network-web/webfactory.cpp index 48357ab73..e1fc9676a 100644 --- a/src/librssguard/network-web/webfactory.cpp +++ b/src/librssguard/network-web/webfactory.cpp @@ -101,7 +101,7 @@ bool WebFactory::openUrlInExternalBrowser(const QString& url) const { if (!result) { // We display GUI information that browser was not probably opened. - MessageBox::show(qApp->mainFormWidget(), + MsgBox::show(qApp->mainFormWidget(), QMessageBox::Icon::Critical, tr("Navigate to website manually"), tr("%1 was unable to launch your web browser with the given URL, you need to open the " diff --git a/src/librssguard/services/gmail/gui/formaddeditemail.cpp b/src/librssguard/services/gmail/gui/formaddeditemail.cpp index 74dd8faa3..944673d16 100644 --- a/src/librssguard/services/gmail/gui/formaddeditemail.cpp +++ b/src/librssguard/services/gmail/gui/formaddeditemail.cpp @@ -129,7 +129,7 @@ void FormAddEditEmail::onOkClicked() { accept(); } catch (const ApplicationException& ex) { - MessageBox::show(this, QMessageBox::Icon::Critical, + MsgBox::show(this, QMessageBox::Icon::Critical, tr("E-mail NOT sent"), tr("Your e-mail message wasn't sent."), QString(), ex.message()); diff --git a/src/librssguard/services/standard/gui/formstandardimportexport.cpp b/src/librssguard/services/standard/gui/formstandardimportexport.cpp index 0a21e778b..665e90210 100644 --- a/src/librssguard/services/standard/gui/formstandardimportexport.cpp +++ b/src/librssguard/services/standard/gui/formstandardimportexport.cpp @@ -204,7 +204,7 @@ void FormStandardImportExport::selectImportFile() { } m_ui->m_lblSelectFile->setStatus(WidgetWithStatus::StatusType::Ok, QDir::toNativeSeparators(selected_file), tr("File is selected.")); - QMessageBox::StandardButton answer = MessageBox::show(this, + QMessageBox::StandardButton answer = MsgBox::show(this, QMessageBox::Icon::Warning, tr("Get online metadata"), tr("Metadata for your feeds can be fetched online. Note that the action " diff --git a/src/librssguard/services/standard/standardserviceroot.cpp b/src/librssguard/services/standard/standardserviceroot.cpp index 91ae9125d..37bf2956f 100644 --- a/src/librssguard/services/standard/standardserviceroot.cpp +++ b/src/librssguard/services/standard/standardserviceroot.cpp @@ -54,7 +54,7 @@ void StandardServiceRoot::start(bool freshly_activated) { if (freshly_activated && getSubTreeFeeds().isEmpty()) { // In other words, if there are no feeds or categories added. - if (MessageBox::show(qApp->mainFormWidget(), QMessageBox::Question, QObject::tr("Load initial set of feeds"), + if (MsgBox::show(qApp->mainFormWidget(), QMessageBox::Question, QObject::tr("Load initial set of feeds"), tr("This new account does not include any feeds. You can now add default set of feeds."), tr("Do you want to load initial set of feeds?"), QString(), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { @@ -81,7 +81,7 @@ void StandardServiceRoot::start(bool freshly_activated) { } } catch (ApplicationException& ex) { - MessageBox::show(qApp->mainFormWidget(), QMessageBox::Critical, tr("Error when loading initial feeds"), ex.message()); + MsgBox::show(qApp->mainFormWidget(), QMessageBox::Critical, tr("Error when loading initial feeds"), ex.message()); } } else { diff --git a/src/librssguard/services/tt-rss/gui/formttrssnote.cpp b/src/librssguard/services/tt-rss/gui/formttrssnote.cpp index 8a66eb81b..065d52985 100644 --- a/src/librssguard/services/tt-rss/gui/formttrssnote.cpp +++ b/src/librssguard/services/tt-rss/gui/formttrssnote.cpp @@ -44,7 +44,7 @@ void FormTtRssNote::sendNote() { accept(); } else { - MessageBox::show({}, QMessageBox::Icon::Critical, + MsgBox::show({}, QMessageBox::Icon::Critical, tr("Cannot share note"), tr("There was an error, when trying to send your custom note."), {},