From 4f240ddb7f8fa2cb2211105756202daca010b008 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Sun, 9 Jun 2019 09:14:35 -0400 Subject: fixes toolbar and menu icons not respecting the stylesheet --- src/mainwindow.cpp | 79 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 66 insertions(+), 13 deletions(-) (limited to 'src/mainwindow.cpp') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index b19e7573..62846da8 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -401,8 +401,6 @@ MainWindow::MainWindow(QSettings &initSettings connect(&m_IntegratedBrowser, SIGNAL(requestDownload(QUrl,QNetworkReply*)), &m_OrganizerCore, SLOT(requestDownload(QUrl,QNetworkReply*))); - connect(this, SIGNAL(styleChanged(QString)), this, SLOT(updateStyle(QString))); - m_CheckBSATimer.setSingleShot(true); connect(&m_CheckBSATimer, SIGNAL(timeout()), this, SLOT(checkBSAList())); @@ -465,19 +463,65 @@ MainWindow::MainWindow(QSettings &initSettings refreshExecutablesList(); updatePinnedExecutables(); - - for (QAction *action : ui->toolBar->actions()) { - // set the name of the widget to the name of the action to allow styling - QWidget *actionWidget = ui->toolBar->widgetForAction(action); - actionWidget->setObjectName(action->objectName()); - actionWidget->style()->unpolish(actionWidget); - actionWidget->style()->polish(actionWidget); - } - + resetActionIcons(); updatePluginCount(); updateModCount(); } +void MainWindow::resetActionIcons() +{ + // this is a bit of a hack + // + // the .qss files have historically set qproperty-icon by id and these ids + // correspond to the QActions created in the .ui file + // + // the problem is that QActions do not support having their icon property + // set from a .qss because they're not widgets (they don't inherit from + // QWidget), and styling only works on widget + // + // a QAction _does_ have an associated icon, it just can't be set from a .qss + // file + // + // so here, a dummy QToolButton widget is created for each QAction and is + // given the same name as the action, which makes it pick up the icon + // specified in the .qss file + // + // that icon is then given to the widget used by the QAction (if it's some + // sort of button, which typically happens on the toolbar) _and_ to the + // QAction itself, which is used in the menu bar + + // QActions created from the .ui file are children of the main window + for (QAction* action : findChildren()) { + // creating a dummy button + auto dummy = std::make_unique(); + + // reusing the action name + dummy->setObjectName(action->objectName()); + + // styling the button, this has to be done manually because the button is + // never added anywhere + style()->polish(dummy.get()); + + // the button's icon may be null if it wasn't specified in the .qss file, + // which can happen if the stylesheet just doesn't override icons, or for + // other actions like the pinned custom executables + const auto icon = dummy->icon(); + if (icon.isNull()) { + continue; + } + + // button associated with the action on the toolbar + QWidget* actionWidget = ui->toolBar->widgetForAction(action); + + if (auto* actionButton=dynamic_cast(actionWidget)) { + actionButton->setIcon(icon); + } + + // the action's icon is used by the menu bar + action->setIcon(icon); + } +} + MainWindow::~MainWindow() { @@ -565,8 +609,7 @@ void MainWindow::allowListResize() void MainWindow::updateStyle(const QString&) { - // no effect? - ensurePolished(); + resetActionIcons(); } void MainWindow::resizeEvent(QResizeEvent *event) @@ -1049,6 +1092,16 @@ void MainWindow::showEvent(QShowEvent *event) QMainWindow::showEvent(event); if (!m_WasVisible) { + // this needs to be connected here instead of in the constructor because the + // actual changing of the stylesheet is done by MOApplication, which + // connects its signal in runApplication() (in main.cpp), and that happens + // _after_ the MainWindow is constructed, but _before_ it is shown + // + // by connecting the event here, changing the style setting will first be + // handled by MOApplication, and then in updateStyle(), at which point the + // stylesheet has already been set correctly + connect(this, SIGNAL(styleChanged(QString)), this, SLOT(updateStyle(QString))); + // only the first time the window becomes visible m_Tutorial.registerControl(); -- cgit v1.3.1 From c31f8b7e314d08022d1d8e50cc77e727eb4bcb5c Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Sun, 9 Jun 2019 09:42:22 -0400 Subject: fixed notification icon not respecting the stylesheet on startup --- src/mainwindow.cpp | 57 ++++++++++++++++++++++++++++++++++++++++++++++++------ src/mainwindow.h | 4 ++++ 2 files changed, 55 insertions(+), 6 deletions(-) (limited to 'src/mainwindow.cpp') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 62846da8..a20f49f8 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -490,6 +490,10 @@ void MainWindow::resetActionIcons() // sort of button, which typically happens on the toolbar) _and_ to the // QAction itself, which is used in the menu bar + // clearing the notification, will be set below if the stylesheet has set + // anything for it + m_originalNotificationIcon = {}; + // QActions created from the .ui file are children of the main window for (QAction* action : findChildren()) { // creating a dummy button @@ -519,7 +523,16 @@ void MainWindow::resetActionIcons() // the action's icon is used by the menu bar action->setIcon(icon); + + if (action == ui->actionNotifications) { + // if the stylesheet has set a notification icon, remember it here so it + // can be used in updateProblemsButton() + m_originalNotificationIcon = icon; + } } + + // update the button for the potentially new icon + updateProblemsButton(); } @@ -831,20 +844,52 @@ void MainWindow::scheduleUpdateButton() void MainWindow::updateProblemsButton() { - size_t numProblems = checkForProblems(); + // if the current stylesheet doesn't provide an icon, this is used instead + const char* DefaultIconName = ":/MO/gui/warning"; + + const std::size_t numProblems = checkForProblems(); + + // starting icon + const QIcon original = m_originalNotificationIcon.isNull() ? + QIcon(DefaultIconName) : m_originalNotificationIcon; + + // final icon + QIcon final; + if (numProblems > 0) { ui->actionNotifications->setToolTip(tr("There are notifications to read")); - QPixmap mergedIcon = QPixmap(":/MO/gui/warning").scaled(64, 64); + // will contain the original icon, plus a notification count; this also + // makes sure the pixmap is exactly 64x64 by 1) requesting the icon that's + // as close to 64x64 as possible, then scaling it up if it's too small + QPixmap merged = original.pixmap(64, 64).scaled(64, 64); + { - QPainter painter(&mergedIcon); - std::string badgeName = std::string(":/MO/gui/badge_") + (numProblems < 10 ? std::to_string(static_cast(numProblems)) : "more"); + QPainter painter(&merged); + + const std::string badgeName = + std::string(":/MO/gui/badge_") + + (numProblems < 10 ? std::to_string(static_cast(numProblems)) : "more"); + painter.drawPixmap(32, 32, 32, 32, QPixmap(badgeName.c_str())); } - ui->actionNotifications->setIcon(QIcon(mergedIcon)); + + final = QIcon(merged); } else { ui->actionNotifications->setToolTip(tr("There are no notifications")); - ui->actionNotifications->setIcon(QIcon(":/MO/gui/warning")); + + // no change + final = original; + } + + // setting the icon on the action (shown on the menu) + ui->actionNotifications->setIcon(final); + + // setting the icon on the toolbar button + if (auto* actionWidget=ui->toolBar->widgetForAction(ui->actionNotifications)) { + if (auto* button=dynamic_cast(actionWidget)) { + button->setIcon(final); + } } } diff --git a/src/mainwindow.h b/src/mainwindow.h index 07a580c3..b8d9f49f 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -398,6 +398,10 @@ private: MOBase::DelayedFileWriter m_ArchiveListWriter; + // icon set by the stylesheet, used to remember its original appearance + // when painting the count + QIcon m_originalNotificationIcon; + enum class ShortcutType { Toolbar, Desktop, -- cgit v1.3.1 From 89aa616a61d41d65698d9abcd914e5e9acfc3131 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Sun, 9 Jun 2019 09:59:16 -0400 Subject: clarified some comments --- src/mainwindow.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/mainwindow.cpp') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index a20f49f8..911d0ff1 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -849,7 +849,7 @@ void MainWindow::updateProblemsButton() const std::size_t numProblems = checkForProblems(); - // starting icon + // original icon without a count painted on it const QIcon original = m_originalNotificationIcon.isNull() ? QIcon(DefaultIconName) : m_originalNotificationIcon; @@ -860,8 +860,8 @@ void MainWindow::updateProblemsButton() ui->actionNotifications->setToolTip(tr("There are notifications to read")); // will contain the original icon, plus a notification count; this also - // makes sure the pixmap is exactly 64x64 by 1) requesting the icon that's - // as close to 64x64 as possible, then scaling it up if it's too small + // makes sure the pixmap is exactly 64x64 by requesting the icon that's + // as close to 64x64 as possible, and then scaling it up if it's too small QPixmap merged = original.pixmap(64, 64).scaled(64, 64); { -- cgit v1.3.1