diff --git a/syncthingwidgets/webview/webpage.cpp b/syncthingwidgets/webview/webpage.cpp index 7e9e137..1bab395 100644 --- a/syncthingwidgets/webview/webpage.cpp +++ b/syncthingwidgets/webview/webpage.cpp @@ -15,7 +15,10 @@ #include #include #if defined(SYNCTHINGWIDGETS_USE_WEBENGINE) +#include #include +#include +#include #include #include #elif defined(SYNCTHINGWIDGETS_USE_WEBKIT) @@ -26,13 +29,6 @@ #include #endif -#ifdef SYNCTHINGWIDGETS_STYLE_SCROLL_BARS -#include -#include -#include -#include -#endif - #include using namespace Data; @@ -79,7 +75,7 @@ WebPage::WebPage(WebViewDialog *dlg, SYNCTHINGWIDGETS_WEB_VIEW *view) setParent(m_view); } -#ifdef SYNCTHINGWIDGETS_STYLE_SCROLL_BARS +#ifdef SYNCTHINGWIDGETS_USE_WEBENGINE styleScrollBars(); #endif } @@ -165,28 +161,46 @@ bool WebPage::canIgnoreCertificateError(const QWebEngineCertificateError &certif return true; } -#ifdef SYNCTHINGWIDGETS_STYLE_SCROLL_BARS /*! * \brief Inserts the specified \a cssCode which must *not* contain single quotes. * \remarks This is done as demonstrated in Qt's "WebEngine StyleSheet Browser Example". */ -void WebPage::insertStyleSheet(const QString &name, const QString &cssCode) +void WebPage::insertStyleSheet(const QString &name, const QString &cssCode, bool immediate) { auto script = QWebEngineScript(); auto s = QString::fromLatin1("(function() {" - " css = document.createElement('style');" + " existing = document.getElementById('%1');" + " css = existing || document.createElement('style');" " css.type = 'text/css';" - " css.id = '%1';" - " css.innerText = '%2';" - " document.head.appendChild(css);" + " css.id = '%2';" + " css.innerText = '%3';" + " existing ? null : document.head.appendChild(css);" "})()") - .arg(name, cssCode.simplified()); + .arg(name, name, cssCode.simplified()); + if (immediate) { + runJavaScript(s, QWebEngineScript::ApplicationWorld); + } script.setName(name); script.setSourceCode(s); script.setInjectionPoint(QWebEngineScript::DocumentReady); script.setRunsOnSubFrames(true); script.setWorldId(QWebEngineScript::ApplicationWorld); - scripts().insert(script); + auto &sc = scripts(); + auto existingScripts = sc.find(name); + for (const auto &existingScript : existingScripts) { + sc.remove(existingScript); + sc.remove(existingScript); + } + sc.insert(script); +} + +/*! + * \brief Returns a CSS "rgba(…)"-specification for the specified \a color. + */ +static QString rgba(const QColor &color) +{ + return QStringLiteral("rgba(%1, %2, %3, %4)") + .arg(QString::number(color.red()), QString::number(color.green()), QString::number(color.blue()), QString::number(color.alphaF())); } /*! @@ -194,20 +208,36 @@ void WebPage::insertStyleSheet(const QString &name, const QString &cssCode) * \remarks The CSS code is taken from KDE's PIM Messagelib: * https://invent.kde.org/pim/messagelib/-/blob/74192072a305cceccdeea2dd0bc10c98e36445ac/messageviewer/src/viewer/csshelperbase.cpp#L512 */ -void WebPage::styleScrollBars() +void WebPage::styleScrollBars(bool immediate) { - const auto *const currentStyle = QApplication::style(); - if (!currentStyle->name().contains(QStringLiteral("breeze"), Qt::CaseInsensitive)) { + if (!m_view) { return; } + + // determine colors from palette + const auto palette = m_view->palette(); + const auto alphaF = 0.75f; + auto highlightColor = palette.color(QPalette::Active, QPalette::Highlight); + auto highlightColorInactive = QColor::fromHsv(highlightColor.hue(), 0, highlightColor.value()); + highlightColor.setAlphaF(alphaF); + highlightColorInactive.setAlphaF(alphaF); + const auto frameColorN = QStringLiteral("#e5e5e5"); + const auto backgroundColor = palette.color(QPalette::Active, QPalette::Base); + const auto backgroundColorN = backgroundColor.name(); + if (backgroundColor.value() > 200 && highlightColorInactive.value() > 200) { + highlightColorInactive = highlightColorInactive.darker(125); + } + const auto highlightColorN = rgba(highlightColor); + const auto highlightColorInactiveN = rgba(highlightColorInactive); + // clang-format off insertStyleSheet(QStringLiteral("breeze-scroll-bars"), QStringLiteral( "html::-webkit-scrollbar {\n" " /* we will add padding as \"border\" in the thumb*/\n" " height: 20px;\n" " width: 20px;\n" - " background: white;\n" - " border-left: 1px solid #e5e5e5;\n" + " background: %1;\n" + " border-left: 1px solid %2;\n" " padding-left: 1px;\n" "}\n\n" @@ -218,7 +248,7 @@ void WebPage::styleScrollBars() "}\n\n" "html::-webkit-scrollbar-thumb {\n" - " background-color: #CBCDCD;\n" + " background-color: %3;\n" " border: 6px solid transparent;\n" " border-radius: 20px;\n" " background-clip: content-box;\n" @@ -228,19 +258,18 @@ void WebPage::styleScrollBars() "}\n\n" "html::-webkit-scrollbar-thumb:window-inactive {\n" - " background-color: #949699; /* when window is inactive it is gray */\n" + " background-color: %4; /* when window is inactive it is gray */\n" "}\n\n" "html::-webkit-scrollbar-thumb:hover {\n" - " background-color: #93CEE9; /* hovered is a lighter blue */\n" + " background-color: %5; /* hovered is a lighter blue */\n" "}\n\n" "html::-webkit-scrollbar-corner {\n" - " background-color: white;\n" - "}\n\n")); + " background-color: %6;\n" + "}\n\n").arg(backgroundColorN, frameColorN, highlightColorInactiveN, highlightColorInactiveN, highlightColorN, backgroundColorN), immediate); // clang-format on } -#endif /*! * \brief Accepts self-signed certificates used by the Syncthing GUI as configured. diff --git a/syncthingwidgets/webview/webpage.h b/syncthingwidgets/webview/webpage.h index 9ae0442..b9babf2 100644 --- a/syncthingwidgets/webview/webpage.h +++ b/syncthingwidgets/webview/webpage.h @@ -16,11 +16,6 @@ QT_FORWARD_DECLARE_CLASS(QNetworkReply) QT_FORWARD_DECLARE_CLASS(QNetworkRequest) QT_FORWARD_DECLARE_CLASS(QSslError) -#if defined(SYNCTHINGWIDGETS_USE_WEBENGINE) && QT_VERSION >= QT_VERSION_CHECK(6, 1, 0) \ - && (defined(Q_OS_UNIX) && !defined(Q_OS_ANDROID) && !defined(Q_OS_DARWIN)) -#define SYNCTHINGWIDGETS_STYLE_SCROLL_BARS -#endif - namespace QtGui { class WebViewDialog; @@ -35,6 +30,9 @@ public: #endif static bool isSamePage(const QUrl &url1, const QUrl &url2); +#ifdef SYNCTHINGWIDGETS_USE_WEBENGINE + void styleScrollBars(bool immediate = false); +#endif protected: SYNCTHINGWIDGETS_WEB_PAGE *createWindow(WebWindowType type) override; @@ -70,10 +68,7 @@ private Q_SLOTS: private: #ifdef SYNCTHINGWIDGETS_USE_WEBENGINE bool canIgnoreCertificateError(const QWebEngineCertificateError &certificateError) const; -#endif -#ifdef SYNCTHINGWIDGETS_STYLE_SCROLL_BARS - void insertStyleSheet(const QString &name, const QString &source); - void styleScrollBars(); + void insertStyleSheet(const QString &name, const QString &cssCode, bool immediate); #endif static bool handleNavigationRequest(const QUrl ¤tUrl, const QUrl &url); diff --git a/syncthingwidgets/webview/webviewdialog.cpp b/syncthingwidgets/webview/webviewdialog.cpp index 4aa0d52..39f98b4 100644 --- a/syncthingwidgets/webview/webviewdialog.cpp +++ b/syncthingwidgets/webview/webviewdialog.cpp @@ -157,6 +157,11 @@ bool WebViewDialog::eventFilter(QObject *watched, QEvent *event) case QEvent::KeyPress: keyPressEvent(static_cast(event)); break; + case QEvent::PaletteChange: + if (auto *const page = qobject_cast(m_view->page())) { + page->styleScrollBars(true); + } + break; default:; } return QMainWindow::eventFilter(watched, event);