From f9e6d36b5a064e02c8bcdf319f62ffcaa4e70e37 Mon Sep 17 00:00:00 2001
From: Lukas Holecek <hluk@email.cz>
Date: Sat, 27 Mar 2021 14:50:28 +0100
Subject: [PATCH] Allow setting and updating theme manually

Adds "style" option and styles() function.

This allows updating application style/theme in case system theme
changes without notifying the application.
---
 docs/scripting-api.rst                  | 10 ++++++++++
 src/app/clipboardserver.cpp             | 18 +++++++++++++++++-
 src/common/appconfig.h                  |  4 ++++
 src/gui/commandcompleterdocumentation.h |  1 +
 src/gui/configurationmanager.cpp        |  2 ++
 src/scriptable/scriptable.cpp           |  5 +++++
 src/scriptable/scriptable.h             |  2 ++
 src/scriptable/scriptableproxy.cpp      |  7 +++++++
 src/scriptable/scriptableproxy.h        |  2 ++
 9 files changed, 50 insertions(+), 1 deletion(-)

diff --git a/docs/scripting-api.rst b/docs/scripting-api.rst
index 3657c3369..07185a425 100644
--- a/docs/scripting-api.rst
+++ b/docs/scripting-api.rst
@@ -1198,6 +1198,16 @@ omitted.
 
    Sets clipboard data for menu commands.
 
+.. js:function:: styles()
+
+   List available styles for ``style`` option.
+
+   To change or update style use::
+
+   .. code-block:: js
+
+       config("style", styleName)
+
 Types
 -----
 
diff --git a/src/app/clipboardserver.cpp b/src/app/clipboardserver.cpp
index 6c0820f86..e6fde8891 100644
--- a/src/app/clipboardserver.cpp
+++ b/src/app/clipboardserver.cpp
@@ -50,6 +50,7 @@
 #include <QMessageBox>
 #include <QMimeData>
 #include <QSessionManager>
+#include <QStyleFactory>
 #include <QTextEdit>
 
 #ifdef NO_GLOBAL_SHORTCUTS
@@ -655,11 +656,24 @@ void ClipboardServer::loadSettings()
 
     m_sharedData->itemFactory->loadItemFactorySettings(&settings);
 
+    AppConfig appConfig;
+
+    const QString styleName = appConfig.option<Config::style>();
+    if ( !styleName.isEmpty() ) {
+        log( QString("Style: %1").arg(styleName) );
+        QStyle *style = QStyleFactory::create(styleName);
+        if (style) {
+            QApplication::setStyle(style);
+        } else {
+            const QString styles = QStyleFactory::keys().join(", ");
+            log( QString("Failed to set style, valid are: %1").arg(styles), LogWarning );
+        }
+    }
+
     settings.beginGroup("Theme");
     m_sharedData->theme.loadTheme(settings);
     settings.endGroup();
 
-    AppConfig appConfig;
     m_sharedData->editor = appConfig.option<Config::editor>();
     m_sharedData->maxItems = appConfig.option<Config::maxitems>();
     m_sharedData->textWrap = appConfig.option<Config::text_wrap>();
@@ -685,6 +699,8 @@ void ClipboardServer::loadSettings()
         startMonitoring();
     }
 
+    m_updateThemeTimer.stop();
+
     COPYQ_LOG("Configuration loaded");
 }
 
diff --git a/src/common/appconfig.h b/src/common/appconfig.h
index 17e99b737..94c0ec4b0 100644
--- a/src/common/appconfig.h
+++ b/src/common/appconfig.h
@@ -403,6 +403,10 @@ struct window_wait_for_modifiers_released_ms : Config<int> {
     static Value defaultValue() { return 50; }
 };
 
+struct style : Config<QString> {
+    static QString name() { return "style"; }
+};
+
 } // namespace Config
 
 class AppConfig final
diff --git a/src/gui/commandcompleterdocumentation.h b/src/gui/commandcompleterdocumentation.h
index 54b6572d7..2e2934fcf 100644
--- a/src/gui/commandcompleterdocumentation.h
+++ b/src/gui/commandcompleterdocumentation.h
@@ -169,6 +169,7 @@ void addDocumentation(AddDocumentationCallback addDocumentation)
     addDocumentation("showDataNotification", "showDataNotification()", "Show notification for current data.");
     addDocumentation("hideDataNotification", "hideDataNotification()", "Hide notification for current data.");
     addDocumentation("setClipboardData", "setClipboardData()", "Sets clipboard data for menu commands.");
+    addDocumentation("styles", "styles()", "List available styles for `style` option.");
     addDocumentation("ByteArray", "ByteArray", "Wrapper for QByteArray Qt class.");
     addDocumentation("File", "File", "Wrapper for QFile Qt class.");
     addDocumentation("Dir", "Dir", "Wrapper for QDir Qt class.");
diff --git a/src/gui/configurationmanager.cpp b/src/gui/configurationmanager.cpp
index 32e3907c4..ca9a90244 100644
--- a/src/gui/configurationmanager.cpp
+++ b/src/gui/configurationmanager.cpp
@@ -344,6 +344,8 @@ void ConfigurationManager::initOptions()
     bind<Config::window_wait_after_raised_ms>();
     bind<Config::window_key_press_time_ms>();
     bind<Config::window_wait_for_modifiers_released_ms>();
+
+    bind<Config::style>();
 }
 
 template <typename Config, typename Widget>
diff --git a/src/scriptable/scriptable.cpp b/src/scriptable/scriptable.cpp
index 85cf18be5..97d0385da 100644
--- a/src/scriptable/scriptable.cpp
+++ b/src/scriptable/scriptable.cpp
@@ -2704,6 +2704,11 @@ QJSValue Scriptable::clipboardFormatsToSave()
     return toScriptValue(formats, this);
 }
 
+QJSValue Scriptable::styles()
+{
+    return toScriptValue( m_proxy->styles(), this );
+}
+
 void Scriptable::onExecuteOutput(const QByteArray &output)
 {
     m_executeStdoutData.append(output);
diff --git a/src/scriptable/scriptable.h b/src/scriptable/scriptable.h
index 7516aa7c6..f4afe8482 100644
--- a/src/scriptable/scriptable.h
+++ b/src/scriptable/scriptable.h
@@ -388,6 +388,8 @@ public slots:
 
     QJSValue clipboardFormatsToSave();
 
+    QJSValue styles();
+
 signals:
     void finished();
     void dataReceived(const QByteArray &data);
diff --git a/src/scriptable/scriptableproxy.cpp b/src/scriptable/scriptableproxy.cpp
index d51284160..c80632734 100644
--- a/src/scriptable/scriptableproxy.cpp
+++ b/src/scriptable/scriptableproxy.cpp
@@ -79,6 +79,7 @@
 #include <QScreen>
 #include <QShortcut>
 #include <QSpinBox>
+#include <QStyleFactory>
 #include <QTextEdit>
 #include <QUrl>
 
@@ -2250,6 +2251,12 @@ bool ScriptableProxy::hasClipboardFormat(const QString &mime, ClipboardMode mode
     return data && data->hasFormat(mime);
 }
 
+QStringList ScriptableProxy::styles()
+{
+    INVOKE(styles, ());
+    return QStyleFactory::keys();
+}
+
 ClipboardBrowser *ScriptableProxy::fetchBrowser(const QString &tabName)
 {
     if (tabName.isEmpty()) {
diff --git a/src/scriptable/scriptableproxy.h b/src/scriptable/scriptableproxy.h
index 305ec800d..c400f9d08 100644
--- a/src/scriptable/scriptableproxy.h
+++ b/src/scriptable/scriptableproxy.h
@@ -253,6 +253,8 @@ public slots:
     QByteArray getClipboardData(const QString &mime, ClipboardMode mode);
     bool hasClipboardFormat(const QString &mime, ClipboardMode mode);
 
+    QStringList styles();
+
 signals:
     void functionCallFinished(int functionCallId, const QVariant &returnValue);
     void inputDialogFinished(int dialogId, const NamedValueList &result);
-- 
GitLab