From 85fa86625b6164e4f887887520c383ab9fc7726d Mon Sep 17 00:00:00 2001 From: Jonas Kvinge Date: Wed, 6 May 2020 21:43:44 +0200 Subject: [PATCH] Fix infinite loop in stylesheetloader Fixes #361 --- src/CMakeLists.txt | 1 + src/core/mainwindow.cpp | 4 -- src/core/stylesheetloader.cpp | 110 +++++++++++++++++++++------------- src/core/stylesheetloader.h | 23 +++++-- 4 files changed, 87 insertions(+), 51 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8d46a70ef..1d42f0c9a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -294,6 +294,7 @@ set(HEADERS core/standarditemiconloader.h core/systemtrayicon.h core/mimedata.h + core/stylesheetloader.h engine/enginebase.h engine/devicefinders.h diff --git a/src/core/mainwindow.cpp b/src/core/mainwindow.cpp index 92a86a8fe..e1eab4628 100644 --- a/src/core/mainwindow.cpp +++ b/src/core/mainwindow.cpp @@ -758,7 +758,6 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co app_->appearance()->LoadUserTheme(); StyleSheetLoader *css_loader = new StyleSheetLoader(this); css_loader->SetStyleSheet(this, ":/style/strawberry.css"); - RefreshStyleSheet(); // Load playlists app_->playlist_manager()->Init(app_->collection_backend(), app_->playlist_backend(), ui_->playlist_sequence, ui_->playlist); @@ -859,8 +858,6 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co } if (app_->scrobbler()->IsEnabled() && !app_->scrobbler()->IsOffline()) app_->scrobbler()->Submit(); - RefreshStyleSheet(); - qLog(Debug) << "Started" << QThread::currentThread(); initialised_ = true; @@ -964,7 +961,6 @@ void MainWindow::ReloadAllSettings() { void MainWindow::RefreshStyleSheet() { QString contents(styleSheet()); - setStyleSheet(""); setStyleSheet(contents); } diff --git a/src/core/stylesheetloader.cpp b/src/core/stylesheetloader.cpp index 41a5de181..7d08d3d1b 100644 --- a/src/core/stylesheetloader.cpp +++ b/src/core/stylesheetloader.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -36,22 +37,16 @@ #include "core/logging.h" #include "stylesheetloader.h" -StyleSheetLoader::StyleSheetLoader(QObject *parent) : QObject(parent) {} +StyleSheetLoader::StyleSheetLoader(QObject *parent) : QObject(parent), timer_reset_counter_(new QTimer(this)) { -void StyleSheetLoader::SetStyleSheet(QWidget *widget, const QString &filename) { + timer_reset_counter_->setSingleShot(true); + timer_reset_counter_->setInterval(1000); - widgets_[widget] = qMakePair(filename, QString()); - widget->installEventFilter(this); - UpdateStyleSheet(widget); + connect(timer_reset_counter_, SIGNAL(timeout()), this, SLOT(ResetCounters())); } -void StyleSheetLoader::UpdateStyleSheet(QWidget *widget) { - - if (!widget || !widgets_.contains(widget)) return; - - QString filename(widgets_[widget].first); - QString stylesheet(widgets_[widget].second); +void StyleSheetLoader::SetStyleSheet(QWidget *widget, const QString &filename) { // Load the file QFile file(filename); @@ -60,56 +55,71 @@ void StyleSheetLoader::UpdateStyleSheet(QWidget *widget) { return; } QTextStream stream(&file); - QString contents; + QString stylesheet; forever { QString line = stream.readLine(); - contents.append(line); + stylesheet.append(line); if (stream.atEnd()) break; } file.close(); + StyleSheetData styledata; + styledata.filename_ = filename; + styledata.stylesheet_template_ = stylesheet; + styledata.stylesheet_current_ = widget->styleSheet(); + styledata_[widget] = styledata; + + widget->installEventFilter(this); + UpdateStyleSheet(widget, styledata); + +} + +void StyleSheetLoader::UpdateStyleSheet(QWidget *widget, StyleSheetData styledata) { + + QString stylesheet = styledata.stylesheet_template_; + // Replace %palette-role with actual colours QPalette p(widget->palette()); QColor alt = p.color(QPalette::AlternateBase); alt.setAlpha(50); - contents.replace("%palette-alternate-base", QString("rgba(%1,%2,%3,%4%)") + stylesheet.replace("%palette-alternate-base", QString("rgba(%1,%2,%3,%4%)") .arg(alt.red()) .arg(alt.green()) .arg(alt.blue()) .arg(alt.alpha())); - ReplaceColor(&contents, "Window", p, QPalette::Window); - ReplaceColor(&contents, "Background", p, QPalette::Background); - ReplaceColor(&contents, "WindowText", p, QPalette::WindowText); - ReplaceColor(&contents, "Foreground", p, QPalette::Foreground); - ReplaceColor(&contents, "Base", p, QPalette::Base); - ReplaceColor(&contents, "AlternateBase", p, QPalette::AlternateBase); - ReplaceColor(&contents, "ToolTipBase", p, QPalette::ToolTipBase); - ReplaceColor(&contents, "ToolTipText", p, QPalette::ToolTipText); - ReplaceColor(&contents, "Text", p, QPalette::Text); - ReplaceColor(&contents, "Button", p, QPalette::Button); - ReplaceColor(&contents, "ButtonText", p, QPalette::ButtonText); - ReplaceColor(&contents, "BrightText", p, QPalette::BrightText); - ReplaceColor(&contents, "Light", p, QPalette::Light); - ReplaceColor(&contents, "Midlight", p, QPalette::Midlight); - ReplaceColor(&contents, "Dark", p, QPalette::Dark); - ReplaceColor(&contents, "Mid", p, QPalette::Mid); - ReplaceColor(&contents, "Shadow", p, QPalette::Shadow); - ReplaceColor(&contents, "Highlight", p, QPalette::Highlight); - ReplaceColor(&contents, "HighlightedText", p, QPalette::HighlightedText); - ReplaceColor(&contents, "Link", p, QPalette::Link); - ReplaceColor(&contents, "LinkVisited", p, QPalette::LinkVisited); + ReplaceColor(&stylesheet, "Window", p, QPalette::Window); + ReplaceColor(&stylesheet, "Background", p, QPalette::Background); + ReplaceColor(&stylesheet, "WindowText", p, QPalette::WindowText); + ReplaceColor(&stylesheet, "Foreground", p, QPalette::Foreground); + ReplaceColor(&stylesheet, "Base", p, QPalette::Base); + ReplaceColor(&stylesheet, "AlternateBase", p, QPalette::AlternateBase); + ReplaceColor(&stylesheet, "ToolTipBase", p, QPalette::ToolTipBase); + ReplaceColor(&stylesheet, "ToolTipText", p, QPalette::ToolTipText); + ReplaceColor(&stylesheet, "Text", p, QPalette::Text); + ReplaceColor(&stylesheet, "Button", p, QPalette::Button); + ReplaceColor(&stylesheet, "ButtonText", p, QPalette::ButtonText); + ReplaceColor(&stylesheet, "BrightText", p, QPalette::BrightText); + ReplaceColor(&stylesheet, "Light", p, QPalette::Light); + ReplaceColor(&stylesheet, "Midlight", p, QPalette::Midlight); + ReplaceColor(&stylesheet, "Dark", p, QPalette::Dark); + ReplaceColor(&stylesheet, "Mid", p, QPalette::Mid); + ReplaceColor(&stylesheet, "Shadow", p, QPalette::Shadow); + ReplaceColor(&stylesheet, "Highlight", p, QPalette::Highlight); + ReplaceColor(&stylesheet, "HighlightedText", p, QPalette::HighlightedText); + ReplaceColor(&stylesheet, "Link", p, QPalette::Link); + ReplaceColor(&stylesheet, "LinkVisited", p, QPalette::LinkVisited); #ifdef Q_OS_MACOS - contents.replace("macos", "*"); + stylesheet.replace("macos", "*"); #endif - if (contents == stylesheet) return; - - widget->setStyleSheet(""); - widget->setStyleSheet(contents); - widgets_[widget] = qMakePair(filename, contents); + if (stylesheet != styledata.stylesheet_current_) { + widget->setStyleSheet(stylesheet); + styledata.stylesheet_current_ = widget->styleSheet(); + styledata_[widget] = styledata; + } } @@ -126,9 +136,23 @@ bool StyleSheetLoader::eventFilter(QObject *obj, QEvent *event) { if (event->type() != QEvent::PaletteChange) return false; QWidget *widget = qobject_cast(obj); - if (!widget || !widgets_.contains(widget)) return false; + if (!widget || !styledata_.contains(widget)) return false; - UpdateStyleSheet(widget); + StyleSheetData styledata = styledata_[widget]; + ++styledata.count_; + styledata_[widget] = styledata; + timer_reset_counter_->start(); + if (styledata.count_ < 5) { + UpdateStyleSheet(widget, styledata); + } return false; } + +void StyleSheetLoader::ResetCounters() { + + for (QMap::iterator i = styledata_.begin() ; i != styledata_.end() ; ++i) { + i.value().count_ = 0; + } + +} diff --git a/src/core/stylesheetloader.h b/src/core/stylesheetloader.h index 8e677dcb5..cf1eee413 100644 --- a/src/core/stylesheetloader.h +++ b/src/core/stylesheetloader.h @@ -31,9 +31,12 @@ #include class QWidget; +class QTimer; class QEvent; class StyleSheetLoader : public QObject { + Q_OBJECT + public: explicit StyleSheetLoader(QObject *parent = nullptr); @@ -46,12 +49,24 @@ class StyleSheetLoader : public QObject { bool eventFilter(QObject *obj, QEvent *event); private: - void UpdateStyleSheet(QWidget *widget); - void ReplaceColor(QString *css, const QString name, const QPalette &palette, QPalette::ColorRole role) const; + struct StyleSheetData { + StyleSheetData() : count_(0) {} + QString filename_; + QString stylesheet_template_; + QString stylesheet_current_; + int count_; + }; private: - QMap> widgets_; + void UpdateStyleSheet(QWidget *widget, StyleSheetData styledata); + void ReplaceColor(QString *css, const QString name, const QPalette &palette, QPalette::ColorRole role) const; + + private slots: + void ResetCounters(); + + private: + QMap styledata_; + QTimer *timer_reset_counter_; }; #endif // STYLESHEETLOADER_H -