refactoring and adding of taskbar overlay icon

This commit is contained in:
Martin Rotter 2022-02-24 11:44:05 +01:00
parent b442d9fb84
commit a52d703e4b
23 changed files with 198 additions and 56 deletions

View file

@ -128,6 +128,10 @@ if(NOT OS2)
list(APPEND QT_COMPONENTS Multimedia) list(APPEND QT_COMPONENTS Multimedia)
endif() endif()
if(WIN32 AND NOT BUILD_WITH_QT6)
list(APPEND QT_COMPONENTS WinExtras)
endif()
if(USE_WEBENGINE) if(USE_WEBENGINE)
list(APPEND QT_COMPONENTS WebEngineWidgets) list(APPEND QT_COMPONENTS WebEngineWidgets)
add_compile_definitions(USE_WEBENGINE) add_compile_definitions(USE_WEBENGINE)

View file

@ -636,6 +636,12 @@ if(USE_WEBENGINE)
) )
endif() endif()
if(WIN32 AND NOT BUILD_WITH_QT6)
target_link_libraries(rssguard PUBLIC
Qt${QT_VERSION_MAJOR}::WinExtras
)
endif()
if(NOT OS2) if(NOT OS2)
target_link_libraries(rssguard PUBLIC target_link_libraries(rssguard PUBLIC
Qt${QT_VERSION_MAJOR}::Multimedia Qt${QT_VERSION_MAJOR}::Multimedia

View file

@ -58,7 +58,7 @@ void DatabaseFactory::determineDriver() {
<< QUOTE_W_SPACE_DOT(ex.message()); << QUOTE_W_SPACE_DOT(ex.message());
if (m_dbDriver->driverType() != DatabaseDriver::DriverType::SQLite) { if (m_dbDriver->driverType() != DatabaseDriver::DriverType::SQLite) {
MessageBox::show(nullptr, MsgBox::show(nullptr,
QMessageBox::Icon::Critical, QMessageBox::Icon::Critical,
tr("Cannot connect to database"), tr("Cannot connect to database"),
tr("Connection to your database was not established with error: '%1'. " tr("Connection to your database was not established with error: '%1'. "

View file

@ -152,7 +152,7 @@ void FormMessageFiltersManager::removeSelectedFilter() {
return; 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?"), tr("Do you really want to remove selected filter?"),
{}, fltr->name(), {}, fltr->name(),
QMessageBox::StandardButton::Yes | QMessageBox::StandardButton::No, 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); m_ui.m_listFilters->setCurrentRow(m_ui.m_listFilters->count() - 1);
} }
catch (const ApplicationException& ex) { 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())); tr("Cannot save new filter, error: '%1'.").arg(ex.message()));
} }
} }
@ -549,7 +549,7 @@ void FormMessageFiltersManager::beautifyScript() {
#endif #endif
if (!proc_clang_format.open() || proc_clang_format.error() == QProcess::ProcessError::FailedToStart) { 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("Cannot find 'clang-format'"),
tr("Script was not beautified, because 'clang-format' tool was not found.")); tr("Script was not beautified, because 'clang-format' tool was not found."));
return; return;
@ -567,7 +567,7 @@ void FormMessageFiltersManager::beautifyScript() {
else { else {
auto err = proc_clang_format.readAllStandardError(); auto err = proc_clang_format.readAllStandardError();
MessageBox::show(this, QMessageBox::Icon::Critical, MsgBox::show(this, QMessageBox::Icon::Critical,
tr("Error"), tr("Error"),
tr("Script was not beautified, because 'clang-format' tool thrown error."), tr("Script was not beautified, because 'clang-format' tool thrown error."),
QString(), QString(),
@ -576,7 +576,7 @@ void FormMessageFiltersManager::beautifyScript() {
} }
else { else {
proc_clang_format.kill(); 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("Beautifier was running for too long time"),
tr("Script was not beautified, is 'clang-format' installed?")); tr("Script was not beautified, is 'clang-format' installed?"));
} }

View file

@ -96,7 +96,7 @@ void FormSettings::applySettings() {
if (!panels_for_restart.isEmpty()) { if (!panels_for_restart.isEmpty()) {
const QStringList changed_settings_description = panels_for_restart.replaceInStrings(QRegularExpression(QSL("^")), const QStringList changed_settings_description = panels_for_restart.replaceInStrings(QRegularExpression(QSL("^")),
QString::fromUtf8(QByteArray(""))); QString::fromUtf8(QByteArray("")));
const QMessageBox::StandardButton clicked_button = MessageBox::show(this, const QMessageBox::StandardButton clicked_button = MsgBox::show(this,
QMessageBox::Icon::Question, QMessageBox::Icon::Question,
tr("Critical settings were changed"), tr("Critical settings were changed"),
tr( tr(
@ -135,7 +135,7 @@ void FormSettings::cancelSettings() {
const QStringList changed_settings_description = changed_panels.replaceInStrings(QRegularExpression(QSL("^")), const QStringList changed_settings_description = changed_panels.replaceInStrings(QRegularExpression(QSL("^")),
QString::fromUtf8(QByteArray(""))); QString::fromUtf8(QByteArray("")));
if (MessageBox::show(this, if (MsgBox::show(this,
QMessageBox::Icon::Critical, QMessageBox::Icon::Critical,
tr("Some settings are changed and will be lost"), tr("Some settings are changed and will be lost"),
tr("Some settings were changed and by cancelling this dialog, you would lose these changes."), tr("Some settings were changed and by cancelling this dialog, you would lose these changes."),

View file

@ -256,7 +256,7 @@ void FeedsView::deleteSelectedItem() {
if (selected_item != nullptr) { if (selected_item != nullptr) {
if (selected_item->canBeDeleted()) { if (selected_item->canBeDeleted()) {
// Ask user first. // Ask user first.
if (MessageBox::show(qApp->mainFormWidget(), if (MsgBox::show(qApp->mainFormWidget(),
QMessageBox::Icon::Question, QMessageBox::Icon::Question,
tr("Deleting \"%1\"").arg(selected_item->title()), tr("Deleting \"%1\"").arg(selected_item->title()),
tr("You are about to completely delete item \"%1\".").arg(selected_item->title()), tr("You are about to completely delete item \"%1\".").arg(selected_item->title()),

View file

@ -12,9 +12,9 @@
#include <QStyle> #include <QStyle>
#include <QtGlobal> #include <QtGlobal>
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. // Determine correct status icon size.
const int icon_size = qApp->style()->pixelMetric(QStyle::PixelMetric::PM_MessageBoxIconSize, nullptr, this); 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)); 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. // Add "don't show this again checkbox.
auto* check_box = new QCheckBox(msg_box); 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); msg_box->setCheckBox(check_box);
} }
QIcon MessageBox::iconForStatus(QMessageBox::Icon status) { QIcon MsgBox::iconForStatus(QMessageBox::Icon status) {
switch (status) { switch (status) {
case QMessageBox::Icon::Information: case QMessageBox::Icon::Information:
return qApp->icons()->fromTheme(QSL("dialog-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, QMessageBox::Icon icon,
const QString& title, const QString& title,
const QString& text, const QString& text,
@ -69,7 +69,7 @@ QMessageBox::StandardButton MessageBox::show(QWidget* parent,
} }
// Create and find needed components. // Create and find needed components.
MessageBox msg_box(parent); MsgBox msg_box(parent);
// Initialize message box properties. // Initialize message box properties.
msg_box.setWindowTitle(title); msg_box.setWindowTitle(title);
@ -81,7 +81,7 @@ QMessageBox::StandardButton MessageBox::show(QWidget* parent,
msg_box.setDefaultButton(default_button); msg_box.setDefaultButton(default_button);
if (dont_show_again != nullptr) { 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) { if (functor) {

View file

@ -8,13 +8,13 @@
#include <functional> #include <functional>
class MessageBox : public QMessageBox { class MsgBox : public QMessageBox {
Q_OBJECT Q_OBJECT
public: public:
// Constructors and destructors. // Constructors and destructors.
explicit MessageBox(QWidget* parent = nullptr); explicit MsgBox(QWidget* parent = nullptr);
// Custom icon setting. // Custom icon setting.
void setIcon(Icon icon); void setIcon(Icon icon);

View file

@ -164,7 +164,7 @@ void MessageBrowser::onAnchorClicked(const QUrl& url) {
} }
else { else {
// User clicked some URL. Open it in external browser or download? // 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.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?")); 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); QAbstractButton* btn_cancel = box.addButton(QMessageBox::StandardButton::Cancel);
bool always; 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.setDefaultButton(QMessageBox::StandardButton::Cancel);
box.exec(); box.exec();
@ -198,7 +198,7 @@ void MessageBrowser::onAnchorClicked(const QUrl& url) {
} }
} }
else { 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."));
} }
} }

View file

@ -561,7 +561,7 @@ void MessagesView::sendSelectedMessageViaEmail() {
const Message message = m_sourceModel->messageAt(m_proxyModel->mapToSource(selectionModel()->selectedRows().at(0)).row()); const Message message = m_sourceModel->messageAt(m_proxyModel->mapToSource(selectionModel()->selectedRows().at(0)).row());
if (!qApp->web()->sendMessageViaEmail(message)) { 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.")); tr("External e-mail client could not be started."));
} }
} }

View file

@ -34,8 +34,11 @@ SettingsGui::SettingsGui(Settings* settings, QWidget* parent) : SettingsPanel(se
<< /*: Version column of skin list. */ tr("Version") << /*: Version column of skin list. */ tr("Version")
<< tr("Author")); << 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),
m_ui->m_tabUi->setTabVisible(m_ui->m_tabUi->indexOf(m_ui->m_tabTaskBar), false); #if (defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)) || defined(Q_OS_WIN)
true);
#else
false);
#endif #endif
m_ui->m_helpCustomSkinColors->setHelpText(tr("You can override some colors defined by your skin here. " 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_checkMonochromeIcons->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::MonochromeTrayIcon)).toBool());
m_ui->m_checkCountUnreadMessages->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::UnreadNumbersInTrayIcon)).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()); m_ui->m_displayUnreadMessageCountOnTaskBar->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::UnreadNumbersOnTaskBar)).toBool());
#endif #endif
@ -336,7 +339,7 @@ void SettingsGui::saveSettings() {
settings()->setValue(GROUP(GUI), GUI::ForceDarkFusion, m_ui->m_checkForceDarkFusion->isChecked()); 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()); settings()->setValue(GROUP(GUI), GUI::UnreadNumbersOnTaskBar, m_ui->m_displayUnreadMessageCountOnTaskBar->isChecked());
#endif #endif

View file

@ -229,7 +229,7 @@ void WebBrowser::setReadabledHtml(const QString& better_html) {
} }
void WebBrowser::readabilityFailed(const QString& error) { void WebBrowser::readabilityFailed(const QString& error) {
MessageBox::show({}, QMessageBox::Icon::Critical, MsgBox::show({}, QMessageBox::Icon::Critical,
tr("Reader mode failed for this website"), tr("Reader mode failed for this website"),
tr("Reader mode cannot be applied to current page."), tr("Reader mode cannot be applied to current page."),
{}, {},

View file

@ -26,6 +26,8 @@
#include <iostream> #include <iostream>
#include <QLoggingCategory> #include <QLoggingCategory>
#include <QPainter>
#include <QPainterPath>
#include <QProcess> #include <QProcess>
#include <QSessionManager> #include <QSessionManager>
#include <QSslSocket> #include <QSslSocket>
@ -50,6 +52,14 @@
#include <QWebEngineProfile> #include <QWebEngineProfile>
#endif #endif
#if defined(Q_OS_WIN)
#include <ShObjIdl.h>
#if QT_VERSION_MAJOR == 5
#include <QtWinExtras/QtWin>
#endif
#endif
Application::Application(const QString& id, int& argc, char** argv) Application::Application(const QString& id, int& argc, char** argv)
: SingleApplication(id, argc, argv), m_updateFeedsLock(new Mutex()) { : SingleApplication(id, argc, argv), m_updateFeedsLock(new Mutex()) {
parseCmdArgumentsFromMyInstance(); parseCmdArgumentsFromMyInstance();
@ -71,6 +81,33 @@ Application::Application(const QString& id, int& argc, char** argv)
m_notifications = new NotificationFactory(this); m_notifications = new NotificationFactory(this);
m_shouldRestart = false; 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<void**>(&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(); determineFirstRuns();
//: Abbreviation of language, e.g. en. //: Abbreviation of language, e.g. en.
@ -156,6 +193,12 @@ Application::Application(const QString& id, int& argc, char** argv)
} }
Application::~Application() { Application::~Application() {
#if defined(Q_OS_WIN)
if (m_windowsTaskBar != nullptr) {
m_windowsTaskBar->Release();
}
#endif
qDebugNN << LOGSEC_CORE << "Destroying Application instance."; qDebugNN << LOGSEC_CORE << "Destroying Application instance.";
} }
@ -551,7 +594,7 @@ void Application::showGuiMessage(Notification::Event event,
if (dest.m_messageBox || msg.m_type == QSystemTrayIcon::MessageIcon::Critical) { if (dest.m_messageBox || msg.m_type == QSystemTrayIcon::MessageIcon::Critical) {
// Tray icon or OSD is not available, display simple text box. // Tray icon or OSD is not available, display simple text box.
MessageBox::show(parent == nullptr ? mainFormWidget() : parent, MsgBox::show(parent == nullptr ? mainFormWidget() : parent,
QMessageBox::Icon(msg.m_type), msg.m_title, msg.m_message, QMessageBox::Icon(msg.m_type), msg.m_title, msg.m_message,
{}, {}, QMessageBox::StandardButton::Ok, QMessageBox::StandardButton::Ok, {}, {}, {}, QMessageBox::StandardButton::Ok, QMessageBox::StandardButton::Ok, {},
action.m_title, action.m_action); action.m_title, action.m_action);
@ -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); 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) #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("/"), QDBusMessage signal = QDBusMessage::createSignal(QSL("/"),
QSL("com.canonical.Unity.LauncherEntry"), QSL("com.canonical.Unity.LauncherEntry"),
QSL("Update")); QSL("Update"));
@ -644,19 +691,89 @@ void Application::showMessagesNumber(int unread_messages, bool any_feed_has_new_
QVariantMap setProperty; QVariantMap setProperty;
setProperty.insert("count", qint64(unread_messages)); 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); setProperty.insert("count-visible", task_bar_count_enabled && unread_messages > 0);
signal << setProperty; signal << setProperty;
QDBusConnection::sessionBus().send(signal); 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 #endif
mainForm()->setWindowTitle(unread_messages > 0 HRESULT overlay_result = m_windowsTaskBar->SetOverlayIcon(reinterpret_cast<HWND>(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<HWND>(m_mainForm->winId()), 50, 100);
//m_taskbar->SetProgressState(reinterpret_cast<HWND>(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("%1 (%2)").arg(QSL(APP_NAME), QString::number(unread_messages))
: QSL(APP_NAME)); : 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() { void Application::restart() {
m_shouldRestart = true; m_shouldRestart = true;

View file

@ -44,6 +44,10 @@ class QWebEngineDownloadItem;
class WebFactory; class WebFactory;
class NotificationFactory; class NotificationFactory;
#if defined(Q_OS_WIN)
struct ITaskbarList4;
#endif
struct GuiMessage { struct GuiMessage {
public: public:
GuiMessage(QString title, QString message, QSystemTrayIcon::MessageIcon type) GuiMessage(QString title, QString message, QSystemTrayIcon::MessageIcon type)
@ -189,6 +193,10 @@ class RSSGUARD_DLLSPEC Application : public SingleApplication {
void onAdBlockFailure(); void onAdBlockFailure();
#endif #endif
#if defined(Q_OS_WIN)
QImage generateOverlayIcon(int number) const;
#endif
void onFeedUpdatesFinished(const FeedDownloadResults& results); void onFeedUpdatesFinished(const FeedDownloadResults& results);
private: private:
@ -234,6 +242,10 @@ class RSSGUARD_DLLSPEC Application : public SingleApplication {
bool m_firstRunCurrentVersion; bool m_firstRunCurrentVersion;
QString m_customDataFolder; QString m_customDataFolder;
bool m_allowMultipleInstances; bool m_allowMultipleInstances;
#if defined(Q_OS_WIN)
ITaskbarList4* m_windowsTaskBar;
#endif
}; };
inline Application* Application::instance() { inline Application* Application::instance() {

View file

@ -260,7 +260,7 @@ DVALUE(bool) GUI::ForceDarkFusionDef = false;
DKEY GUI::UnreadNumbersInTrayIcon = "show_unread_numbers_in_tray_icon"; DKEY GUI::UnreadNumbersInTrayIcon = "show_unread_numbers_in_tray_icon";
DVALUE(bool) GUI::UnreadNumbersInTrayIconDef = true; 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"; DKEY GUI::UnreadNumbersOnTaskBar = "show_unread_numbers_on_task_bar";
DVALUE(bool) GUI::UnreadNumbersOnTaskBarDef = true; DVALUE(bool) GUI::UnreadNumbersOnTaskBarDef = true;
#endif #endif

View file

@ -267,7 +267,7 @@ namespace GUI {
KEY UnreadNumbersInTrayIcon; KEY UnreadNumbersInTrayIcon;
VALUE(bool) UnreadNumbersInTrayIconDef; 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; KEY UnreadNumbersOnTaskBar;
VALUE(bool) UnreadNumbersOnTaskBarDef; VALUE(bool) UnreadNumbersOnTaskBarDef;
#endif #endif

View file

@ -61,7 +61,7 @@ void AdBlockDialog::saveOnClose() {
<< "Failed to enable AdBlock, error:" << "Failed to enable AdBlock, error:"
<< QUOTE_W_SPACE_DOT(ex.message()); << QUOTE_W_SPACE_DOT(ex.message());
MessageBox::show(this, MsgBox::show(this,
QMessageBox::Icon::Critical, QMessageBox::Icon::Critical,
tr("Cannot enable AdBlock"), tr("Cannot enable AdBlock"),
tr("There is some error in AdBlock component and it cannot be enabled. " tr("There is some error in AdBlock component and it cannot be enabled. "

View file

@ -204,7 +204,7 @@ void DownloadItem::openFile() {
void DownloadItem::openFolder() { void DownloadItem::openFolder() {
if (m_output.exists()) { if (m_output.exists()) {
if (!SystemFactory::openFolderFile(m_output.fileName())) { if (!SystemFactory::openFolderFile(m_output.fileName())) {
MessageBox::show(this, MsgBox::show(this,
QMessageBox::Icon::Warning, QMessageBox::Icon::Warning,
tr("Cannot open directory"), tr("Cannot open directory"),
tr("Cannot open output directory. Open it manually."), tr("Cannot open output directory. Open it manually."),

View file

@ -101,7 +101,7 @@ bool WebFactory::openUrlInExternalBrowser(const QString& url) const {
if (!result) { if (!result) {
// We display GUI information that browser was not probably opened. // We display GUI information that browser was not probably opened.
MessageBox::show(qApp->mainFormWidget(), MsgBox::show(qApp->mainFormWidget(),
QMessageBox::Icon::Critical, QMessageBox::Icon::Critical,
tr("Navigate to website manually"), tr("Navigate to website manually"),
tr("%1 was unable to launch your web browser with the given URL, you need to open the " tr("%1 was unable to launch your web browser with the given URL, you need to open the "

View file

@ -129,7 +129,7 @@ void FormAddEditEmail::onOkClicked() {
accept(); accept();
} }
catch (const ApplicationException& ex) { 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."), tr("E-mail NOT sent"), tr("Your e-mail message wasn't sent."),
QString(), QString(),
ex.message()); ex.message());

View file

@ -204,7 +204,7 @@ void FormStandardImportExport::selectImportFile() {
} }
m_ui->m_lblSelectFile->setStatus(WidgetWithStatus::StatusType::Ok, QDir::toNativeSeparators(selected_file), tr("File is selected.")); 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, QMessageBox::Icon::Warning,
tr("Get online metadata"), tr("Get online metadata"),
tr("Metadata for your feeds can be fetched online. Note that the action " tr("Metadata for your feeds can be fetched online. Note that the action "

View file

@ -54,7 +54,7 @@ void StandardServiceRoot::start(bool freshly_activated) {
if (freshly_activated && getSubTreeFeeds().isEmpty()) { if (freshly_activated && getSubTreeFeeds().isEmpty()) {
// In other words, if there are no feeds or categories added. // 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("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?"), tr("Do you want to load initial set of feeds?"),
QString(), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { QString(), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
@ -81,7 +81,7 @@ void StandardServiceRoot::start(bool freshly_activated) {
} }
} }
catch (ApplicationException& ex) { 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 { else {

View file

@ -44,7 +44,7 @@ void FormTtRssNote::sendNote() {
accept(); accept();
} }
else { else {
MessageBox::show({}, QMessageBox::Icon::Critical, MsgBox::show({}, QMessageBox::Icon::Critical,
tr("Cannot share note"), tr("Cannot share note"),
tr("There was an error, when trying to send your custom note."), tr("There was an error, when trying to send your custom note."),
{}, {},