From 7adbdc017982aec8645e152c7891ea51f84ff8ee Mon Sep 17 00:00:00 2001
From: J-P Nurmi <jpnurmi@digia.com>
Date: Fri, 24 May 2013 09:31:37 +0200
Subject: [PATCH] Make QQuickSettings::style a property with a notifier signal

Change-Id: I9f1690524e29cd7fe0ab35be216aca9a6edd35ca
Reviewed-by: Jens Bache-Wiig <jens.bache-wiig@digia.com>
---
 src/controls/Button.qml               |  2 +-
 src/controls/CheckBox.qml             |  2 +-
 src/controls/ComboBox.qml             |  2 +-
 src/controls/GroupBox.qml             |  2 +-
 src/controls/Menu.qml                 |  2 +-
 src/controls/MenuBar.qml              |  2 +-
 src/controls/ProgressBar.qml          |  2 +-
 src/controls/RadioButton.qml          |  2 +-
 src/controls/ScrollView.qml           |  2 +-
 src/controls/Slider.qml               |  2 +-
 src/controls/SpinBox.qml              |  2 +-
 src/controls/StatusBar.qml            |  2 +-
 src/controls/TabView.qml              |  2 +-
 src/controls/TableView.qml            |  2 +-
 src/controls/TextField.qml            |  2 +-
 src/controls/ToolBar.qml              |  2 +-
 src/controls/ToolButton.qml           |  2 +-
 src/private/FocusFrame.qml            |  2 +-
 src/private/plugin.cpp                |  2 +-
 src/private/qquickcontrolsettings.cpp | 95 ++++++++++++++++++++++-----
 src/private/qquickcontrolsettings_p.h | 27 +++++++-
 21 files changed, 122 insertions(+), 38 deletions(-)

diff --git a/src/controls/Button.qml b/src/controls/Button.qml
index cf725085c..2418bfa2d 100644
--- a/src/controls/Button.qml
+++ b/src/controls/Button.qml
@@ -102,7 +102,7 @@ BasicButton {
 
     Accessible.name: text
 
-    style: Qt.createComponent(Settings.theme() + "/ButtonStyle.qml", button)
+    style: Qt.createComponent(Settings.style + "/ButtonStyle.qml", button)
 
     Binding {
         target: menu
diff --git a/src/controls/CheckBox.qml b/src/controls/CheckBox.qml
index 46f9068d2..ad82a9487 100644
--- a/src/controls/CheckBox.qml
+++ b/src/controls/CheckBox.qml
@@ -129,7 +129,7 @@ AbstractCheckable {
     */
     property bool __ignoreChecked: false
 
-    style: Qt.createComponent(Settings.theme() + "/CheckBoxStyle.qml", checkBox)
+    style: Qt.createComponent(Settings.style + "/CheckBoxStyle.qml", checkBox)
 
     activeFocusOnTab: true
 
diff --git a/src/controls/ComboBox.qml b/src/controls/ComboBox.qml
index 219dc3b36..4d2073604 100644
--- a/src/controls/ComboBox.qml
+++ b/src/controls/ComboBox.qml
@@ -97,7 +97,7 @@ Control {
     /*! \internal */
     property var __popup: popup
 
-    style: Qt.createComponent(Settings.theme() + "/ComboBoxStyle.qml", comboBox)
+    style: Qt.createComponent(Settings.style + "/ComboBoxStyle.qml", comboBox)
 
     activeFocusOnTab: true
 
diff --git a/src/controls/GroupBox.qml b/src/controls/GroupBox.qml
index 6342d2789..e358dd9d0 100644
--- a/src/controls/GroupBox.qml
+++ b/src/controls/GroupBox.qml
@@ -151,7 +151,7 @@ Item {
     readonly property alias contentItem: container
 
     /*! \internal */
-    property Component style: Qt.createComponent(Settings.theme() + "/GroupBoxStyle.qml", groupbox)
+    property Component style: Qt.createComponent(Settings.style + "/GroupBoxStyle.qml", groupbox)
 
     /*! \internal */
     property alias __checkbox: check
diff --git a/src/controls/Menu.qml b/src/controls/Menu.qml
index 8b6a35b99..e89099db4 100644
--- a/src/controls/Menu.qml
+++ b/src/controls/Menu.qml
@@ -130,7 +130,7 @@ MenuPrivate {
     property Component __selfComponent: null
 
     /*! \internal */
-    property Component style: Qt.createComponent(Settings.theme() + "/MenuStyle.qml", root)
+    property Component style: Qt.createComponent(Settings.style + "/MenuStyle.qml", root)
 
     /*! \internal */
     property var __menuBar: null
diff --git a/src/controls/MenuBar.qml b/src/controls/MenuBar.qml
index cee213963..65af1c124 100644
--- a/src/controls/MenuBar.qml
+++ b/src/controls/MenuBar.qml
@@ -74,7 +74,7 @@ MenuBarPrivate {
     id: root
 
     /*! \internal */
-    property Component style: Qt.createComponent(Settings.theme() + "/MenuBarStyle.qml", root)
+    property Component style: Qt.createComponent(Settings.style + "/MenuBarStyle.qml", root)
 
     /*! \internal */
     __contentItem: Loader {
diff --git a/src/controls/ProgressBar.qml b/src/controls/ProgressBar.qml
index 92181df17..1e78ed92a 100644
--- a/src/controls/ProgressBar.qml
+++ b/src/controls/ProgressBar.qml
@@ -97,7 +97,7 @@ Control {
     property int orientation: Qt.Horizontal
 
     /*! \internal */
-    style: Qt.createComponent(Settings.theme() + "/ProgressBarStyle.qml", progressbar)
+    style: Qt.createComponent(Settings.style + "/ProgressBarStyle.qml", progressbar)
 
     /*! \internal */
     property bool __initialized: false
diff --git a/src/controls/RadioButton.qml b/src/controls/RadioButton.qml
index 7fb4decda..963d085cb 100644
--- a/src/controls/RadioButton.qml
+++ b/src/controls/RadioButton.qml
@@ -87,7 +87,7 @@ AbstractCheckable {
 
         \codeline Qt.createComponent("path/to/style.qml", radioButtonId);
     */
-    style: Qt.createComponent(Settings.theme() + "/RadioButtonStyle.qml", radioButton)
+    style: Qt.createComponent(Settings.style + "/RadioButtonStyle.qml", radioButton)
 
     __cycleStatesHandler: function() { checked = !checked; }
 }
diff --git a/src/controls/ScrollView.qml b/src/controls/ScrollView.qml
index 4d06c3f3f..bbd21b24d 100644
--- a/src/controls/ScrollView.qml
+++ b/src/controls/ScrollView.qml
@@ -144,7 +144,7 @@ FocusScope {
     /*! \internal */
     property alias __verticalScrollBar: scroller.verticalScrollBar
     /*! \internal */
-    property Component style: Qt.createComponent(Settings.theme() + "/ScrollViewStyle.qml", root)
+    property Component style: Qt.createComponent(Settings.style + "/ScrollViewStyle.qml", root)
 
     /* \internal */
     property Style __style: styleLoader.item
diff --git a/src/controls/Slider.qml b/src/controls/Slider.qml
index d53255a3c..469843c6e 100644
--- a/src/controls/Slider.qml
+++ b/src/controls/Slider.qml
@@ -187,7 +187,7 @@ Control {
         return Math.round(v);
     }
 
-    style: Qt.createComponent(Settings.theme() + "/SliderStyle.qml", slider)
+    style: Qt.createComponent(Settings.style + "/SliderStyle.qml", slider)
 
     Keys.onRightPressed: value += (maximumValue - minimumValue)/10.0
     Keys.onLeftPressed: value -= (maximumValue - minimumValue)/10.0
diff --git a/src/controls/SpinBox.qml b/src/controls/SpinBox.qml
index ab0eeb0b2..bf8e66473 100644
--- a/src/controls/SpinBox.qml
+++ b/src/controls/SpinBox.qml
@@ -131,7 +131,7 @@ Control {
     */
     property bool activeFocusOnPress: true
 
-    style: Qt.createComponent(Settings.theme() + "/SpinBoxStyle.qml", spinbox)
+    style: Qt.createComponent(Settings.style + "/SpinBoxStyle.qml", spinbox)
 
     /*! \internal */
     function __increment() {
diff --git a/src/controls/StatusBar.qml b/src/controls/StatusBar.qml
index 248c16eeb..13edc5eff 100644
--- a/src/controls/StatusBar.qml
+++ b/src/controls/StatusBar.qml
@@ -73,7 +73,7 @@ Item {
     width: parent ? parent.width : implicitWidth
     implicitWidth: loader.item.implicitHeight
     implicitHeight: loader.item ? loader.item.implicitHeight : 0
-    property Component style: Qt.createComponent(Settings.theme() + "/StatusBarStyle.qml", statusbar)
+    property Component style: Qt.createComponent(Settings.style + "/StatusBarStyle.qml", statusbar)
     Loader {
         id: loader
         anchors.fill: parent
diff --git a/src/controls/TabView.qml b/src/controls/TabView.qml
index 7871cdd68..98c2466b8 100644
--- a/src/controls/TabView.qml
+++ b/src/controls/TabView.qml
@@ -141,7 +141,7 @@ FocusScope {
     property ListModel __tabs: ListModel { }
 
     /*! \internal */
-    property Component style: Qt.createComponent(Settings.theme() + "/TabViewStyle.qml", root)
+    property Component style: Qt.createComponent(Settings.style + "/TabViewStyle.qml", root)
 
     /*! \internal */
     property var __styleItem: loader.item
diff --git a/src/controls/TableView.qml b/src/controls/TableView.qml
index 5d7a3472f..6efee30db 100644
--- a/src/controls/TableView.qml
+++ b/src/controls/TableView.qml
@@ -279,7 +279,7 @@ ScrollView {
     }
 
 
-    style: Qt.createComponent(Settings.theme() + "/TableViewStyle.qml", root)
+    style: Qt.createComponent(Settings.style + "/TableViewStyle.qml", root)
 
 
     Accessible.role: Accessible.Table
diff --git a/src/controls/TextField.qml b/src/controls/TextField.qml
index e374c83dd..81c30fc14 100644
--- a/src/controls/TextField.qml
+++ b/src/controls/TextField.qml
@@ -533,7 +533,7 @@ Control {
     /*! \internal */
     property alias __contentWidth: textInput.contentWidth
 
-    style: Qt.createComponent(Settings.theme() + "/TextFieldStyle.qml", textInput)
+    style: Qt.createComponent(Settings.style + "/TextFieldStyle.qml", textInput)
 
     activeFocusOnTab: true
 
diff --git a/src/controls/ToolBar.qml b/src/controls/ToolBar.qml
index 71ef30a51..d2adea56a 100644
--- a/src/controls/ToolBar.qml
+++ b/src/controls/ToolBar.qml
@@ -76,7 +76,7 @@ Item {
     width: parent ? parent.width : implicitWidth
     implicitWidth: loader.item ? loader.item.implicitWidth : 0
     implicitHeight: loader.item ? loader.item.implicitHeight : 0
-    property Component style: Qt.createComponent(Settings.theme() + "/ToolBarStyle.qml", toolbar)
+    property Component style: Qt.createComponent(Settings.style + "/ToolBarStyle.qml", toolbar)
     Loader {
         id: loader
         anchors.fill: parent
diff --git a/src/controls/ToolButton.qml b/src/controls/ToolButton.qml
index 106a947f4..d6607d283 100644
--- a/src/controls/ToolButton.qml
+++ b/src/controls/ToolButton.qml
@@ -78,5 +78,5 @@ BasicButton {
 
     Accessible.name: text
 
-    style: Qt.createComponent(Settings.theme() + "/ToolButtonStyle.qml", button)
+    style: Qt.createComponent(Settings.style + "/ToolButtonStyle.qml", button)
 }
diff --git a/src/private/FocusFrame.qml b/src/private/FocusFrame.qml
index 52c114387..3a07701c5 100644
--- a/src/private/FocusFrame.qml
+++ b/src/private/FocusFrame.qml
@@ -62,6 +62,6 @@ Item {
         id: loader
         z: 2
         anchors.fill: parent
-        sourceComponent: Qt.createComponent( "../" + Settings.theme() + "/FocusFrameStyle.qml", root)
+        sourceComponent: Qt.createComponent(Settings.style + "/FocusFrameStyle.qml", root)
     }
 }
diff --git a/src/private/plugin.cpp b/src/private/plugin.cpp
index e45371b26..0392a2494 100644
--- a/src/private/plugin.cpp
+++ b/src/private/plugin.cpp
@@ -66,7 +66,7 @@ static QObject *registerSettingsModule(QQmlEngine *engine, QJSEngine *jsEngine)
 {
     Q_UNUSED(engine);
     Q_UNUSED(jsEngine);
-    return new QQuickControlSettings();
+    return new QQuickControlSettings(engine);
 }
 
 class QtQuickControlsPrivatePlugin : public QQmlExtensionPlugin
diff --git a/src/private/qquickcontrolsettings.cpp b/src/private/qquickcontrolsettings.cpp
index 01456b2a1..44db49c20 100644
--- a/src/private/qquickcontrolsettings.cpp
+++ b/src/private/qquickcontrolsettings.cpp
@@ -42,34 +42,95 @@
 #include "qquickcontrolsettings_p.h"
 #include <qquickitem.h>
 #include <qcoreapplication.h>
+#include <qqmlengine.h>
+#include <qdir.h>
 
 QT_BEGIN_NAMESPACE
 
-QQuickControlSettings::QQuickControlSettings(QObject *parent)
-    : QObject(parent)
+static QString defaultStyleName()
 {
+    //Only enable QStyle support when we are using QApplication
+    if (QCoreApplication::instance()->inherits("QApplication"))
+        return QLatin1String("Desktop");
+    return QLatin1String("Base");
 }
 
-QString QQuickControlSettings::theme()
+static QString styleImportName()
 {
-    static QString currentTheme;
-    if (currentTheme.isEmpty()) {
-        //Following variable is for internal use only. It is very possible
-        //that it will disappear in future releases.
-        currentTheme = qgetenv("QT_QUICK_CONTROLS_STYLE");
+    QString name = qgetenv("QT_QUICK_CONTROLS_STYLE");
+    if (name.isEmpty())
+        name = defaultStyleName();
+    return QFileInfo(name).fileName();
+}
 
-        if (currentTheme.isEmpty()) {
-            //Only enable QStyle support when we are using QApplication
-            if (QCoreApplication::instance()->inherits("QApplication"))
-                currentTheme = QLatin1String("Desktop");
-            else
-                currentTheme = QLatin1String("Base");
+static QString styleImportPath(QQmlEngine *engine, const QString &styleName)
+{
+    QString path = qgetenv("QT_QUICK_CONTROLS_STYLE");
+    QFileInfo info(path);
+    if (info.isRelative()) {
+        foreach (const QString &import, engine->importPathList()) {
+            QDir dir(import + QLatin1String("/QtQuick/Controls/Styles"));
+            if (dir.exists(styleName)) {
+                path = dir.absolutePath();
+                break;
+            }
         }
+    } else {
+        path = info.absolutePath();
+    }
+    return path;
+}
 
-        if (!currentTheme.startsWith(QLatin1String("Styles/")))
-            currentTheme.prepend(QLatin1String("Styles/"));
+QQuickControlSettings::QQuickControlSettings(QQmlEngine *engine)
+{
+    m_name = styleImportName();
+    m_path = styleImportPath(engine, m_name);
+
+    if (!QFile::exists(styleFilePath())) {
+        QString unknownStyle = m_name;
+        m_name = defaultStyleName();
+        m_path = styleImportPath(engine, m_name);
+        qWarning() << "WARNING: Cannot find style" << unknownStyle << "- fallback:" << styleFilePath();
     }
-    return currentTheme;
+
+    connect(this, SIGNAL(styleNameChanged()), SIGNAL(styleChanged()));
+    connect(this, SIGNAL(stylePathChanged()), SIGNAL(styleChanged()));
+}
+
+QUrl QQuickControlSettings::style() const
+{
+    return QUrl::fromLocalFile(styleFilePath());
+}
+
+QString QQuickControlSettings::styleName() const
+{
+    return m_name;
+}
+
+void QQuickControlSettings::setStyleName(const QString &name)
+{
+    if (m_name != name) {
+        m_name = name;
+        emit styleNameChanged();
+    }
+}
+
+QString QQuickControlSettings::stylePath() const
+{
+    return m_path;
+}
+
+void QQuickControlSettings::setStylePath(const QString &path)
+{
+    if (m_path != path) {
+        m_path = path;
+        emit stylePathChanged();
+    }
+}
+
+QString QQuickControlSettings::styleFilePath() const
+{
+    return m_path + QLatin1Char('/') + m_name;
 }
 
 QT_END_NAMESPACE
diff --git a/src/private/qquickcontrolsettings_p.h b/src/private/qquickcontrolsettings_p.h
index ea2811beb..98e851512 100644
--- a/src/private/qquickcontrolsettings_p.h
+++ b/src/private/qquickcontrolsettings_p.h
@@ -42,18 +42,41 @@
 #ifndef QQUICKCONTROLSETTINGS_P_H
 #define QQUICKCONTROLSETTINGS_P_H
 
+#include <QtCore/qurl.h>
 #include <QtCore/qobject.h>
 
 QT_BEGIN_NAMESPACE
 
+class QQmlEngine;
+
 class QQuickControlSettings : public QObject
 {
     Q_OBJECT
+    Q_PROPERTY(QUrl style READ style NOTIFY styleChanged)
+    Q_PROPERTY(QString styleName READ styleName WRITE setStyleName NOTIFY styleNameChanged)
+    Q_PROPERTY(QString stylePath READ stylePath WRITE setStylePath NOTIFY stylePathChanged)
 
 public:
-    QQuickControlSettings(QObject *parent = 0);
+    QQuickControlSettings(QQmlEngine *engine);
+
+    QUrl style() const;
+
+    QString styleName() const;
+    void setStyleName(const QString &name);
+
+    QString stylePath() const;
+    void setStylePath(const QString &path);
+
+signals:
+    void styleChanged();
+    void styleNameChanged();
+    void stylePathChanged();
+
+private:
+    QString styleFilePath() const;
 
-    Q_INVOKABLE QString theme();
+    QString m_name;
+    QString m_path;
 };
 
 QT_END_NAMESPACE
-- 
GitLab