summaryrefslogtreecommitdiff
path: root/src/controls
diff options
context:
space:
mode:
Diffstat (limited to 'src/controls')
-rw-r--r--src/controls/ApplicationWindow.qml2
-rw-r--r--src/controls/BusyIndicator.qml2
-rw-r--r--src/controls/Button.qml2
-rw-r--r--src/controls/Calendar.qml2
-rw-r--r--src/controls/CheckBox.qml2
-rw-r--r--src/controls/ComboBox.qml2
-rw-r--r--src/controls/GroupBox.qml2
-rw-r--r--src/controls/Menu.qml2
-rw-r--r--src/controls/MenuBar.qml2
-rw-r--r--src/controls/Private/FocusFrame.qml2
-rw-r--r--src/controls/Private/qquickcontrolsettings.cpp190
-rw-r--r--src/controls/Private/qquickcontrolsettings_p.h19
-rw-r--r--src/controls/ProgressBar.qml2
-rw-r--r--src/controls/RadioButton.qml2
-rw-r--r--src/controls/ScrollView.qml2
-rw-r--r--src/controls/Slider.qml2
-rw-r--r--src/controls/SpinBox.qml2
-rw-r--r--src/controls/StatusBar.qml2
-rw-r--r--src/controls/Styles/Base/CircularButtonStyle.qml84
-rw-r--r--src/controls/Styles/Base/CircularGaugeStyle.qml494
-rw-r--r--src/controls/Styles/Base/CircularTickmarkLabelStyle.qml304
-rw-r--r--src/controls/Styles/Base/CommonStyleHelper.qml56
-rw-r--r--src/controls/Styles/Base/DelayButtonStyle.qml230
-rw-r--r--src/controls/Styles/Base/DialStyle.qml360
-rw-r--r--src/controls/Styles/Base/GaugeStyle.qml541
-rw-r--r--src/controls/Styles/Base/HandleStyle.qml73
-rw-r--r--src/controls/Styles/Base/HandleStyleHelper.qml91
-rw-r--r--src/controls/Styles/Base/PieMenuStyle.qml388
-rw-r--r--src/controls/Styles/Base/StatusIndicatorStyle.qml233
-rw-r--r--src/controls/Styles/Base/ToggleButtonStyle.qml291
-rw-r--r--src/controls/Styles/Base/TumblerStyle.qml328
-rw-r--r--src/controls/Styles/Base/images/knob.pngbin0 -> 5495 bytes
-rw-r--r--src/controls/Styles/Base/images/needle.pngbin0 -> 4354 bytes
-rw-r--r--src/controls/Styles/qmldir15
-rw-r--r--src/controls/Styles/styles.pri20
-rw-r--r--src/controls/Switch.qml2
-rw-r--r--src/controls/TabView.qml2
-rw-r--r--src/controls/TableView.qml2
-rw-r--r--src/controls/TextArea.qml2
-rw-r--r--src/controls/TextField.qml2
-rw-r--r--src/controls/ToolBar.qml2
-rw-r--r--src/controls/ToolButton.qml2
-rw-r--r--src/controls/TreeView.qml2
-rw-r--r--src/controls/controls.pro2
-rw-r--r--src/controls/doc/images/circulargauge-angles.pngbin0 -> 19719 bytes
-rw-r--r--src/controls/doc/images/circulargauge-needle-example-2.pngbin0 -> 12680 bytes
-rw-r--r--src/controls/doc/images/circulargauge-needle.pngbin0 -> 1561 bytes
-rw-r--r--src/controls/doc/images/circulargauge-reversed.pngbin0 -> 21836 bytes
-rw-r--r--src/controls/doc/images/circulargauge-tickmark-indices-values.pngbin0 -> 40132 bytes
-rw-r--r--src/controls/doc/images/gauge-minorTickmark-example.pngbin0 -> 4780 bytes
-rw-r--r--src/controls/doc/images/gauge-temperature.pngbin0 -> 6055 bytes
-rw-r--r--src/controls/doc/images/gauge-tickmark-example.pngbin0 -> 4882 bytes
-rw-r--r--src/controls/doc/images/piemenu-menuitem-example.pngbin0 -> 10606 bytes
-rw-r--r--src/controls/doc/images/styling-circulargauge-background-example.pngbin0 -> 13071 bytes
-rw-r--r--src/controls/doc/images/styling-circulargauge-knob-example.pngbin0 -> 13209 bytes
-rw-r--r--src/controls/doc/images/styling-circulargauge-minorTickmark-example.pngbin0 -> 11770 bytes
-rw-r--r--src/controls/doc/images/styling-circulargauge-needle-example.pngbin0 -> 13472 bytes
-rw-r--r--src/controls/doc/images/styling-circulargauge-tickmark-example.pngbin0 -> 12179 bytes
-rw-r--r--src/controls/doc/images/styling-circulargauge-tickmarkLabel-example.pngbin0 -> 12171 bytes
-rw-r--r--src/controls/doc/images/styling-gauge-font-size.pngbin0 -> 4410 bytes
-rw-r--r--src/controls/doc/images/styling-gauge-foreground.pngbin0 -> 3557 bytes
-rw-r--r--src/controls/doc/images/styling-gauge-minorTickmark.pngbin0 -> 3527 bytes
-rw-r--r--src/controls/doc/images/styling-gauge-tickmark.pngbin0 -> 3547 bytes
-rw-r--r--src/controls/doc/images/styling-gauge-valueBar.pngbin0 -> 3691 bytes
-rw-r--r--src/controls/doc/qtquickcontrols.qdocconf8
-rw-r--r--src/controls/doc/snippets/circulargauge-background-range.qml121
-rw-r--r--src/controls/doc/snippets/circulargauge-tickmark-indices-values.qml85
-rw-r--r--src/controls/doc/snippets/styling-gauge.qml93
-rw-r--r--src/controls/doc/src/qtquickcontrolsstyles-index.qdoc41
-rw-r--r--src/controls/doc/src/styling-circulargauge.qdoc145
-rw-r--r--src/controls/doc/src/styling-gauge.qdoc129
71 files changed, 4323 insertions, 66 deletions
diff --git a/src/controls/ApplicationWindow.qml b/src/controls/ApplicationWindow.qml
index 51e08316..542cfe4e 100644
--- a/src/controls/ApplicationWindow.qml
+++ b/src/controls/ApplicationWindow.qml
@@ -145,7 +145,7 @@ Window {
/*! The style Component for the window.
\sa {Qt Quick Controls Styles QML Types}
*/
- property Component style: Qt.createComponent(Settings.style + "/ApplicationWindowStyle.qml", root)
+ property Component style: Settings.styleComponent(Settings.style, "ApplicationWindowStyle.qml", root)
/*! \internal */
property alias __style: styleLoader.item
diff --git a/src/controls/BusyIndicator.qml b/src/controls/BusyIndicator.qml
index 4922ecd0..fbd6d665 100644
--- a/src/controls/BusyIndicator.qml
+++ b/src/controls/BusyIndicator.qml
@@ -78,5 +78,5 @@ Control {
Accessible.role: Accessible.Indicator
Accessible.name: "busy"
- style: Qt.createComponent(Settings.style + "/BusyIndicatorStyle.qml", indicator)
+ style: Settings.styleComponent(Settings.style, "BusyIndicatorStyle.qml", indicator)
}
diff --git a/src/controls/Button.qml b/src/controls/Button.qml
index 00ccfa4e..6daf595c 100644
--- a/src/controls/Button.qml
+++ b/src/controls/Button.qml
@@ -88,7 +88,7 @@ BasicButton {
Accessible.name: text
- style: Qt.createComponent(Settings.style + "/ButtonStyle.qml", button)
+ style: Settings.styleComponent(Settings.style, "ButtonStyle.qml", button)
Binding {
target: menu
diff --git a/src/controls/Calendar.qml b/src/controls/Calendar.qml
index ba40893a..f6a779db 100644
--- a/src/controls/Calendar.qml
+++ b/src/controls/Calendar.qml
@@ -218,7 +218,7 @@ Control {
visibleDate: new Date(visibleYear, visibleMonth, 1)
}
- style: Qt.createComponent(Settings.style + "/CalendarStyle.qml", calendar)
+ style: Settings.styleComponent(Settings.style, "CalendarStyle.qml", calendar)
/*!
\qmlsignal Calendar::hovered(date date)
diff --git a/src/controls/CheckBox.qml b/src/controls/CheckBox.qml
index 0d27c1ac..b5df8846 100644
--- a/src/controls/CheckBox.qml
+++ b/src/controls/CheckBox.qml
@@ -139,7 +139,7 @@ AbstractCheckable {
*/
property bool __ignoreCheckedState: false
- style: Qt.createComponent(Settings.style + "/CheckBoxStyle.qml", checkBox)
+ style: Settings.styleComponent(Settings.style, "CheckBoxStyle.qml", checkBox)
activeFocusOnTab: true
diff --git a/src/controls/ComboBox.qml b/src/controls/ComboBox.qml
index f0067822..81d56030 100644
--- a/src/controls/ComboBox.qml
+++ b/src/controls/ComboBox.qml
@@ -332,7 +332,7 @@ Control {
/*! \internal */
property var __popup: popup
- style: Qt.createComponent(Settings.style + "/ComboBoxStyle.qml", comboBox)
+ style: Settings.styleComponent(Settings.style, "ComboBoxStyle.qml", comboBox)
activeFocusOnTab: true
diff --git a/src/controls/GroupBox.qml b/src/controls/GroupBox.qml
index f51ac757..99d520fe 100644
--- a/src/controls/GroupBox.qml
+++ b/src/controls/GroupBox.qml
@@ -154,7 +154,7 @@ FocusScope {
readonly property alias contentItem: container
/*! \internal */
- property Component style: Qt.createComponent(Settings.style + "/GroupBoxStyle.qml", groupbox)
+ property Component style: Settings.styleComponent(Settings.style, "GroupBoxStyle.qml", groupbox)
/*! \internal */
property alias __checkbox: check
diff --git a/src/controls/Menu.qml b/src/controls/Menu.qml
index 2ab229ab..17b27977 100644
--- a/src/controls/Menu.qml
+++ b/src/controls/Menu.qml
@@ -132,7 +132,7 @@ MenuPrivate {
Component.onCompleted: {
if (!style) {
__usingDefaultStyle = true
- style = Qt.binding(function() { return Qt.createComponent(Settings.style + "/MenuStyle.qml", root) })
+ style = Qt.binding(function() { return Settings.styleComponent(Settings.style, "MenuStyle.qml", root) })
}
}
diff --git a/src/controls/MenuBar.qml b/src/controls/MenuBar.qml
index 5f444dac..0c0a2004 100644
--- a/src/controls/MenuBar.qml
+++ b/src/controls/MenuBar.qml
@@ -77,7 +77,7 @@ import QtQuick.Controls.Private 1.0
MenuBarPrivate {
id: root
- property Component style: Qt.createComponent(Settings.style + "/MenuBarStyle.qml", root)
+ property Component style: Settings.styleComponent(Settings.style, "MenuBarStyle.qml", root)
/*! \internal */
property QtObject __style: styleLoader.item
diff --git a/src/controls/Private/FocusFrame.qml b/src/controls/Private/FocusFrame.qml
index d1205708..66090038 100644
--- a/src/controls/Private/FocusFrame.qml
+++ b/src/controls/Private/FocusFrame.qml
@@ -59,6 +59,6 @@ Item {
id: loader
z: 2
anchors.fill: parent
- sourceComponent: Qt.createComponent(Settings.style + "/FocusFrameStyle.qml", root)
+ sourceComponent: Settings.styleComponent(Settings.style, "FocusFrameStyle.qml", root)
}
}
diff --git a/src/controls/Private/qquickcontrolsettings.cpp b/src/controls/Private/qquickcontrolsettings.cpp
index 017a0714..c000a658 100644
--- a/src/controls/Private/qquickcontrolsettings.cpp
+++ b/src/controls/Private/qquickcontrolsettings.cpp
@@ -106,6 +106,57 @@ bool QQuickControlSettings::hoverEnabled() const
return !isMobile() || !hasTouchScreen();
}
+QString QQuickControlSettings::makeStyleComponentPath(const QString &controlStyleName, const QString &styleDirPath)
+{
+ return styleDirPath + QStringLiteral("/") + controlStyleName;
+}
+
+QUrl QQuickControlSettings::makeStyleComponentUrl(const QString &controlStyleName, QString styleDirPath)
+{
+ QString styleFilePath = makeStyleComponentPath(controlStyleName, styleDirPath);
+
+ if (styleDirPath.startsWith(QStringLiteral(":/")))
+ return QUrl(QStringLiteral("qrc") + styleFilePath);
+
+ return QUrl::fromLocalFile(styleFilePath);
+}
+
+QQmlComponent *QQuickControlSettings::styleComponent(const QUrl &styleDirUrl, const QString &controlStyleName, QObject *control)
+{
+ Q_UNUSED(styleDirUrl); // required for hack that forces this function to be re-called from within QML when style changes
+
+ // QUrl doesn't consider qrc-based URLs as local files, so bypass it here.
+ QString styleFilePath = makeStyleComponentPath(controlStyleName, m_styleMap.value(m_name).m_styleDirPath);
+ QUrl styleFileUrl;
+ if (QFile::exists(styleFilePath)) {
+ styleFileUrl = makeStyleComponentUrl(controlStyleName, m_styleMap.value(m_name).m_styleDirPath);
+ } else {
+ // It's OK for a style to pick and choose which controls it wants to provide style files for.
+ styleFileUrl = makeStyleComponentUrl(controlStyleName, m_styleMap.value(QStringLiteral("Base")).m_styleDirPath);
+ }
+
+ return new QQmlComponent(qmlEngine(control), styleFileUrl);
+}
+
+static QString relativeStyleImportPath(QQmlEngine *engine, const QString &styleName)
+{
+ QString path;
+ bool found = false;
+ foreach (const QString &import, engine->importPathList()) {
+ QDir dir(import + QStringLiteral("/QtQuick/Controls/Styles"));
+ if (dir.exists(styleName)) {
+ found = true;
+ path = dir.absolutePath();
+ break;
+ }
+ if (found)
+ break;
+ }
+ if (!found)
+ path = ":/QtQuick/Controls/Styles";
+ return path;
+}
+
static QString styleImportPath(QQmlEngine *engine, const QString &styleName)
{
QString path = qgetenv("QT_QUICK_CONTROLS_STYLE");
@@ -113,19 +164,7 @@ static QString styleImportPath(QQmlEngine *engine, const QString &styleName)
if (fromResource(path)) {
path = info.path();
} else if (info.isRelative()) {
- bool found = false;
- foreach (const QString &import, engine->importPathList()) {
- QDir dir(import + QLatin1String("/QtQuick/Controls/Styles"));
- if (dir.exists(styleName)) {
- found = true;
- path = dir.absolutePath();
- break;
- }
- if (found)
- break;
- }
- if (!found)
- path = ":/QtQuick/Controls/Styles";
+ path = relativeStyleImportPath(engine, styleName);
} else {
path = info.absolutePath();
}
@@ -134,40 +173,109 @@ static QString styleImportPath(QQmlEngine *engine, const QString &styleName)
QQuickControlSettings::QQuickControlSettings(QQmlEngine *engine)
{
+ // First, register all style paths in the default style location.
+ QDir dir;
+ const QString defaultStyle = defaultStyleName();
+ dir.setPath(relativeStyleImportPath(engine, defaultStyle));
+ dir.setFilter(QDir::Dirs | QDir::NoDotAndDotDot);
+ foreach (const QString &styleDirectory, dir.entryList()) {
+ findStyle(engine, styleDirectory);
+ }
+
m_name = styleImportName();
- m_path = styleImportPath(engine, m_name);
- QString path = styleFilePath();
+ // If the style name is a path..
+ const QString styleNameFromEnvVar = qgetenv("QT_QUICK_CONTROLS_STYLE");
+ if (QFile::exists(styleNameFromEnvVar)) {
+ StyleData styleData;
+ styleData.m_styleDirPath = styleNameFromEnvVar;
+ m_styleMap[m_name] = styleData;
+ }
- QDir dir(path);
- if (!dir.exists()) {
+ // Then check if the style the user wanted is known to us. Otherwise, use the fallback style.
+ if (m_styleMap.contains(m_name)) {
+ m_path = m_styleMap.value(m_name).m_styleDirPath;
+ } else {
QString unknownStyle = m_name;
- m_name = defaultStyleName();
- m_path = styleImportPath(engine, m_name);
+ m_name = defaultStyle;
+ m_path = m_styleMap.value(defaultStyle).m_styleDirPath;
qWarning() << "WARNING: Cannot find style" << unknownStyle << "- fallback:" << styleFilePath();
- } else {
- typedef bool (*StyleInitFunc)();
- typedef const char *(*StylePathFunc)();
-
- foreach (const QString &fileName, dir.entryList()) {
- if (QLibrary::isLibrary(fileName)) {
- QLibrary lib(dir.absoluteFilePath(fileName));
- StyleInitFunc initFunc = (StyleInitFunc) lib.resolve("qt_quick_controls_style_init");
- if (initFunc)
- initFunc();
- StylePathFunc pathFunc = (StylePathFunc) lib.resolve("qt_quick_controls_style_path");
- if (pathFunc)
- m_path = QString::fromLocal8Bit(pathFunc());
- if (initFunc || pathFunc)
- break;
- }
- }
}
+ // Can't really do anything about this failing here, so don't bother checking...
+ resolveCurrentStylePath();
+
connect(this, SIGNAL(styleNameChanged()), SIGNAL(styleChanged()));
connect(this, SIGNAL(stylePathChanged()), SIGNAL(styleChanged()));
}
+bool QQuickControlSettings::resolveCurrentStylePath()
+{
+ if (!m_styleMap.contains(m_name)) {
+ qWarning() << "WARNING: Cannot find style" << m_name;
+ return false;
+ }
+
+ StyleData styleData = m_styleMap.value(m_name);
+
+ if (styleData.m_stylePluginPath.isEmpty())
+ return true; // It's not a plugin; don't have to do anything.
+
+ typedef bool (*StyleInitFunc)();
+ typedef const char *(*StylePathFunc)();
+
+ QLibrary lib(styleData.m_stylePluginPath);
+ if (!lib.load()) {
+ qWarning().nospace() << "WARNING: Cannot load plugin " << styleData.m_stylePluginPath
+ << " for style " << m_name << ": " << lib.errorString();
+ return false;
+ }
+
+ // Check for the existence of this first, as we don't want to init if this doesn't exist.
+ StylePathFunc pathFunc = (StylePathFunc) lib.resolve("qt_quick_controls_style_path");
+ if (!pathFunc) {
+ qWarning() << "WARNING: Style" << m_name << "is a plugin but does not expose qt_quick_controls_style_path";
+ return false;
+ }
+
+ StyleInitFunc initFunc = (StyleInitFunc) lib.resolve("qt_quick_controls_style_init");
+ if (initFunc)
+ initFunc();
+
+ styleData.m_styleDirPath = QString::fromLocal8Bit(pathFunc());
+ m_styleMap[m_name] = styleData;
+ return true;
+}
+
+void QQuickControlSettings::findStyle(QQmlEngine *engine, const QString &styleName)
+{
+ QString path = styleImportPath(engine, styleName);
+ QDir dir;
+ dir.setFilter(QDir::Files | QDir::NoDotAndDotDot);
+ dir.setPath(path);
+ dir.cd(styleName);
+
+ StyleData styleData;
+
+ foreach (const QString &fileName, dir.entryList()) {
+ // This assumes that there is only one library in the style directory,
+ // which should be a safe assumption. If at some point it's determined
+ // not to be safe, we'll have to resolve the init and path functions
+ // here, to be sure that it is the correct library.
+ if (QLibrary::isLibrary(fileName)) {
+ styleData.m_stylePluginPath = dir.absoluteFilePath(fileName);
+ break;
+ }
+ }
+
+ // If there's no plugin for the style, then the style's files are
+ // contained in this directory (which contains a qmldir file instead).
+ if (styleData.m_stylePluginPath.isEmpty())
+ styleData.m_styleDirPath = dir.absolutePath();
+
+ m_styleMap[styleName] = styleData;
+}
+
QUrl QQuickControlSettings::style() const
{
QUrl result;
@@ -189,8 +297,14 @@ QString QQuickControlSettings::styleName() const
void QQuickControlSettings::setStyleName(const QString &name)
{
if (m_name != name) {
+ QString oldName = m_name;
m_name = name;
- emit styleNameChanged();
+
+ // Don't change the style if it can't be resolved.
+ if (!resolveCurrentStylePath())
+ m_name = oldName;
+ else
+ emit styleNameChanged();
}
}
@@ -209,7 +323,7 @@ void QQuickControlSettings::setStylePath(const QString &path)
QString QQuickControlSettings::styleFilePath() const
{
- return m_path + QLatin1Char('/') + m_name;
+ return m_path;
}
extern Q_GUI_EXPORT int qt_defaultDpiX();
diff --git a/src/controls/Private/qquickcontrolsettings_p.h b/src/controls/Private/qquickcontrolsettings_p.h
index ed21101d..1b99fd3e 100644
--- a/src/controls/Private/qquickcontrolsettings_p.h
+++ b/src/controls/Private/qquickcontrolsettings_p.h
@@ -39,6 +39,9 @@
#include <QtCore/qurl.h>
#include <QtCore/qobject.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qhash.h>
+#include <QtQml/qqmlcomponent.h>
QT_BEGIN_NAMESPACE
@@ -74,6 +77,9 @@ public:
bool isMobile() const;
bool hoverEnabled() const;
+ Q_INVOKABLE QQmlComponent *styleComponent(const QUrl &styleDirUrl,
+ const QString &controlStyleName, QObject *control);
+
signals:
void styleChanged();
void styleNameChanged();
@@ -81,9 +87,22 @@ signals:
private:
QString styleFilePath() const;
+ void findStyle(QQmlEngine *engine, const QString &styleName);
+ bool resolveCurrentStylePath();
+ QString makeStyleComponentPath(const QString &controlStyleName, const QString &styleDirPath);
+ QUrl makeStyleComponentUrl(const QString &controlStyleName, QString styleDirPath);
+
+ struct StyleData
+ {
+ // Path to the style's plugin or qmldir file.
+ QString m_stylePluginPath;
+ // Path to the directory containing the style's files.
+ QString m_styleDirPath;
+ };
QString m_name;
QString m_path;
+ QHash<QString, StyleData> m_styleMap;
};
QT_END_NAMESPACE
diff --git a/src/controls/ProgressBar.qml b/src/controls/ProgressBar.qml
index 7bc3bec5..681cb135 100644
--- a/src/controls/ProgressBar.qml
+++ b/src/controls/ProgressBar.qml
@@ -114,7 +114,7 @@ Control {
readonly property alias hovered: hoverArea.containsMouse
/*! \internal */
- style: Qt.createComponent(Settings.style + "/ProgressBarStyle.qml", progressbar)
+ style: Settings.styleComponent(Settings.style, "ProgressBarStyle.qml", progressbar)
/*! \internal */
property bool __initialized: false
diff --git a/src/controls/RadioButton.qml b/src/controls/RadioButton.qml
index d24a5d44..b03028a1 100644
--- a/src/controls/RadioButton.qml
+++ b/src/controls/RadioButton.qml
@@ -90,7 +90,7 @@ AbstractCheckable {
\codeline Qt.createComponent("path/to/style.qml", radioButtonId);
*/
- style: Qt.createComponent(Settings.style + "/RadioButtonStyle.qml", radioButton)
+ style: Settings.styleComponent(Settings.style, "RadioButtonStyle.qml", radioButton)
__cycleStatesHandler: function() { checked = !checked; }
}
diff --git a/src/controls/ScrollView.qml b/src/controls/ScrollView.qml
index 05f33b84..c82bb7e5 100644
--- a/src/controls/ScrollView.qml
+++ b/src/controls/ScrollView.qml
@@ -180,7 +180,7 @@ FocusScope {
\sa {Qt Quick Controls Styles QML Types}
*/
- property Component style: Qt.createComponent(Settings.style + "/ScrollViewStyle.qml", root)
+ property Component style: Settings.styleComponent(Settings.style, "ScrollViewStyle.qml", root)
/*! \internal */
property Style __style: styleLoader.item
diff --git a/src/controls/Slider.qml b/src/controls/Slider.qml
index 8bce7e8f..437749eb 100644
--- a/src/controls/Slider.qml
+++ b/src/controls/Slider.qml
@@ -189,7 +189,7 @@ Control {
range.decreaseSingleStep()
}
- style: Qt.createComponent(Settings.style + "/SliderStyle.qml", slider)
+ style: Settings.styleComponent(Settings.style, "SliderStyle.qml", slider)
Keys.onRightPressed: if (__horizontal) range.increaseSingleStep()
Keys.onLeftPressed: if (__horizontal) range.decreaseSingleStep()
diff --git a/src/controls/SpinBox.qml b/src/controls/SpinBox.qml
index 95ce2b47..96d8d0a2 100644
--- a/src/controls/SpinBox.qml
+++ b/src/controls/SpinBox.qml
@@ -208,7 +208,7 @@ Control {
*/
property Component menu: input.editMenu.defaultMenu
- style: Qt.createComponent(Settings.style + "/SpinBoxStyle.qml", spinbox)
+ style: Settings.styleComponent(Settings.style, "SpinBoxStyle.qml", spinbox)
/*! \internal */
function __increment() {
diff --git a/src/controls/StatusBar.qml b/src/controls/StatusBar.qml
index 4f0dd374..74df9439 100644
--- a/src/controls/StatusBar.qml
+++ b/src/controls/StatusBar.qml
@@ -82,7 +82,7 @@ FocusScope {
+ Math.max(container.layoutHeight, __panel ? __panel.implicitHeight : 0)
/*! \internal */
- property Component style: Qt.createComponent(Settings.style + "/StatusBarStyle.qml", statusbar)
+ property Component style: Settings.styleComponent(Settings.style, "StatusBarStyle.qml", statusbar)
/*! \internal */
property alias __style: styleLoader.item
diff --git a/src/controls/Styles/Base/CircularButtonStyle.qml b/src/controls/Styles/Base/CircularButtonStyle.qml
new file mode 100644
index 00000000..e4576226
--- /dev/null
+++ b/src/controls/Styles/Base/CircularButtonStyle.qml
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Extras module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtQuick.Controls.Styles 1.4
+import QtQuick.Extras.Private 1.0
+
+ButtonStyle {
+ id: buttonStyle
+
+ label: Text {
+ anchors.fill: parent
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ text: control.text
+ font.pixelSize: TextSingleton.font.pixelSize * 1.25
+ color: control.pressed || control.checked ? __buttonHelper.textColorDown : __buttonHelper.textColorUp
+ styleColor: control.pressed || control.checked ? __buttonHelper.textRaisedColorDown : __buttonHelper.textRaisedColorUp
+ style: Text.Raised
+ wrapMode: Text.Wrap
+ fontSizeMode: Text.Fit
+ }
+
+ /*! \internal */
+ property alias __buttonHelper: buttonHelper
+
+ CircularButtonStyleHelper {
+ id: buttonHelper
+ control: buttonStyle.control
+ }
+
+ background: Item {
+ implicitWidth: __buttonHelper.implicitWidth
+ implicitHeight: __buttonHelper.implicitHeight
+
+ Canvas {
+ id: backgroundCanvas
+ anchors.fill: parent
+
+ Connections {
+ target: control
+ onPressedChanged: backgroundCanvas.requestPaint()
+ }
+
+ onPaint: {
+ var ctx = getContext("2d");
+ __buttonHelper.paintBackground(ctx);
+ }
+ }
+ }
+}
diff --git a/src/controls/Styles/Base/CircularGaugeStyle.qml b/src/controls/Styles/Base/CircularGaugeStyle.qml
new file mode 100644
index 00000000..99b0091b
--- /dev/null
+++ b/src/controls/Styles/Base/CircularGaugeStyle.qml
@@ -0,0 +1,494 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Extras module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtGraphicalEffects 1.0
+import QtQuick.Controls 1.4
+import QtQuick.Controls.Styles 1.4
+import QtQuick.Controls.Private 1.0
+import QtQuick.Extras 1.4
+import QtQuick.Extras.Private 1.0
+
+/*!
+ \qmltype CircularGaugeStyle
+ \inqmlmodule QtQuick.Controls.Styles
+ \since 5.5
+ \ingroup controlsstyling
+ \brief Provides custom styling for CircularGauge.
+
+ You can create a custom circular gauge by replacing the following delegates:
+ \list
+ \li \l background
+ \li \l tickmark
+ \li \l minorTickmark
+ \li \l tickmarkLabel
+ \li \l needle
+ \li \l foreground
+ \endlist
+
+ Below is an example that changes the needle to a basic orange \l Rectangle:
+ \code
+ CircularGauge {
+ style: CircularGaugeStyle {
+ needle: Rectangle {
+ y: outerRadius * 0.15
+ implicitWidth: outerRadius * 0.03
+ implicitHeight: outerRadius * 0.9
+ antialiasing: true
+ color: Qt.rgba(0.66, 0.3, 0, 1)
+ }
+ }
+ }
+ \endcode
+
+ The result:
+ \image circulargauge-needle-example-2.png CircularGaugeStyle example
+
+ \section2 Direction
+
+ \l minimumValueAngle and \l maximumValueAngle determine not only the
+ position of the tickmarks, labels and needle, but the direction in which
+ they are displayed around the gauge. For example, if \l minimumValueAngle
+ is greater than \l maximumValueAngle, the gauge will be anti-clockwise.
+ Below, there are two gauges: the top gauge has a \l minimumValueAngle of
+ \c -90 degrees and a \l maximumValueAngle of \c 90 degrees, and the bottom
+ gauge has the opposite.
+
+ \image circulargauge-reversed.png Reversed CircularGauge
+
+ \sa {Styling CircularGauge}
+*/
+
+Style {
+ id: circularGaugeStyle
+
+ /*!
+ The \l CircularGauge that this style is attached to.
+ */
+ readonly property CircularGauge control: __control
+
+ /*!
+ The distance from the center of the gauge to the outer edge of the
+ gauge.
+
+ This property is useful for determining the size of the various
+ components of the style, in order to ensure that they are scaled
+ proportionately when the gauge is resized.
+ */
+ readonly property real outerRadius: Math.min(control.width, control.height) * 0.5
+
+ /*!
+ This property determines the angle at which the minimum value is
+ displayed on the gauge.
+
+ The angle set affects the following components of the gauge:
+ \list
+ \li The angle of the needle
+ \li The position of the tickmarks and labels
+ \endlist
+
+ The angle origin points north:
+
+ \image circulargauge-angles.png
+
+ There is no minimum or maximum angle for this property, but the default
+ style only supports angles whose absolute range is less than or equal
+ to \c 360 degrees. This is because ranges higher than \c 360 degrees
+ will cause the tickmarks and labels to overlap each other.
+
+ The default value is \c -145.
+ */
+ property real minimumValueAngle: -145
+
+ /*!
+ This property determines the angle at which the maximum value is
+ displayed on the gauge.
+
+ The angle set affects the following components of the gauge:
+ \list
+ \li The angle of the needle
+ \li The position of the tickmarks and labels
+ \endlist
+
+ The angle origin points north:
+
+ \image circulargauge-angles.png
+
+ There is no minimum or maximum angle for this property, but the default
+ style only supports angles whose absolute range is less than or equal
+ to \c 360 degrees. This is because ranges higher than \c 360 degrees
+ will cause the tickmarks and labels to overlap each other.
+
+ The default value is \c 145.
+ */
+ property real maximumValueAngle: 145
+
+ /*!
+ The range between \l minimumValueAngle and \l maximumValueAngle, in
+ degrees. This value will always be positive.
+ */
+ readonly property real angleRange: control.__panel.circularTickmarkLabel.angleRange
+
+ /*!
+ This property holds the rotation of the needle in degrees.
+ */
+ property real needleRotation: {
+ var percentage = (control.value - control.minimumValue) / (control.maximumValue - control.minimumValue);
+ minimumValueAngle + percentage * angleRange;
+ }
+
+ /*!
+ The interval at which tickmarks are displayed.
+
+ For example, if this property is set to \c 10 (the default),
+ control.minimumValue to \c 0, and control.maximumValue to \c 100,
+ the tickmarks displayed will be 0, 10, 20, etc., to 100,
+ around the gauge.
+ */
+ property real tickmarkStepSize: 10
+
+ /*!
+ The distance in pixels from the outside of the gauge (outerRadius) at
+ which the outermost point of the tickmark line is drawn.
+ */
+ property real tickmarkInset: 0
+
+
+ /*!
+ The amount of tickmarks displayed by the gauge, calculated from
+ \l tickmarkStepSize and the control's
+ \l {CircularGauge::minimumValue}{minimumValue} and
+ \l {CircularGauge::maximumValue}{maximumValue}.
+
+ \sa minorTickmarkCount
+ */
+ readonly property int tickmarkCount: control.__panel.circularTickmarkLabel.tickmarkCount
+
+ /*!
+ The amount of minor tickmarks between each tickmark.
+
+ The default value is \c 4.
+
+ \sa tickmarkCount
+ */
+ property int minorTickmarkCount: 4
+
+ /*!
+ The distance in pixels from the outside of the gauge (outerRadius) at
+ which the outermost point of the minor tickmark line is drawn.
+ */
+ property real minorTickmarkInset: 0
+
+ /*!
+ The distance in pixels from the outside of the gauge (outerRadius) at
+ which the center of the value marker text is drawn.
+ */
+ property real labelInset: __protectedScope.toPixels(0.19)
+
+ /*!
+ The interval at which tickmark labels are displayed.
+
+ For example, if this property is set to \c 10 (the default),
+ control.minimumValue to \c 0, and control.maximumValue to \c 100, the
+ tickmark labels displayed will be 0, 10, 20, etc., to 100,
+ around the gauge.
+ */
+ property real labelStepSize: tickmarkStepSize
+
+ /*!
+ The amount of tickmark labels displayed by the gauge, calculated from
+ \l labelStepSize and the control's
+ \l {CircularGauge::minimumValue}{minimumValue} and
+ \l {CircularGauge::maximumValue}{maximumValue}.
+
+ \sa tickmarkCount, minorTickmarkCount
+ */
+ readonly property int labelCount: control.__panel.circularTickmarkLabel.labelCount
+
+ /*!
+ Returns \a value as an angle in degrees.
+
+ This function is useful for custom drawing or positioning of items in
+ the style's components. For example, it can be used to calculate the
+ angles at which to draw an arc around the gauge indicating the safe
+ area for the needle to be within.
+
+ For example, if minimumValueAngle is set to \c 270 and
+ maximumValueAngle is set to \c 90, this function will return \c 270
+ when passed minimumValue and \c 90 when passed maximumValue.
+
+ \sa {Styling CircularGauge#styling-circulargauge-background}{
+ Styling CircularGauge's background}
+ */
+ function valueToAngle(value) {
+ return control.__panel.circularTickmarkLabel.valueToAngle(value);
+ }
+
+ property QtObject __protectedScope: QtObject {
+ /*!
+ Converts a value expressed as a percentage of \l outerRadius to
+ a pixel value.
+ */
+ function toPixels(percentageOfOuterRadius) {
+ return percentageOfOuterRadius * outerRadius;
+ }
+ }
+
+ /*!
+ The background of the gauge.
+
+ If set, the background determines the implicit size of the gauge.
+
+ By default, there is no background defined.
+
+ \sa {Styling CircularGauge#styling-circulargauge-background}{
+ Styling CircularGauge's background}
+ */
+ property Component background
+
+ /*!
+ This component defines each individual tickmark. The position of each
+ tickmark is already set; only the
+ \l {Item::implicitWidth}{implicitWidth} and
+ \l {Item::implicitHeight}{implicitHeight} need to be specified.
+
+ Each instance of this component has access to the following properties:
+
+ \table
+ \row \li \c {readonly property int} \b styleData.index
+ \li The index of this tickmark.
+ \row \li \c {readonly property real} \b styleData.value
+ \li The value that this tickmark represents.
+ \endtable
+
+ To illustrate what these properties refer to, we can use the following
+ example:
+
+ \snippet circulargauge-tickmark-indices-values.qml tickmarks
+
+ We've replaced the conventional \e line tickmarks with \l Text items
+ and have hidden the tickmarkLabel component in order to make the
+ association clearer:
+
+ \image circulargauge-tickmark-indices-values.png Tickmarks
+
+ The index property can be useful if you have another model that
+ contains images to display for each index, for example.
+
+ The value property is useful for drawing lower and upper limits around
+ the gauge to indicate the recommended value ranges. For example, speeds
+ above 200 kilometers an hour in a car's speedometer could be indicated
+ as dangerous using this property.
+
+ \sa {Styling CircularGauge#styling-circulargauge-tickmark}{
+ Styling CircularGauge's tickmark}
+ */
+ property Component tickmark: Rectangle {
+ implicitWidth: outerRadius * 0.02
+ antialiasing: true
+ implicitHeight: outerRadius * 0.06
+ color: "#c8c8c8"
+ }
+
+ /*!
+ This component defines each individual minor tickmark. The position of
+ each minor tickmark is already set; only the
+ \l {Item::implicitWidth}{implicitWidth} and
+ \l {Item::implicitHeight}{implicitHeight} need to be specified.
+
+ Each instance of this component has access to the following properties:
+
+ \table
+ \row \li \c {readonly property int} \b styleData.index
+ \li The index of this tickmark.
+ \row \li \c {readonly property real} \b styleData.value
+ \li The value that this tickmark represents.
+ \endtable
+
+ \sa {Styling CircularGauge#styling-circulargauge-minorTickmark}{
+ Styling CircularGauge's minorTickmark}
+ */
+ property Component minorTickmark: Rectangle {
+ implicitWidth: outerRadius * 0.01
+ antialiasing: true
+ implicitHeight: outerRadius * 0.03
+ color: "#c8c8c8"
+ }
+
+ /*!
+ This defines the text of each tickmark label on the gauge.
+
+ Each instance of this component has access to the following properties:
+
+ \table
+ \row \li \c {readonly property int} \b styleData.index
+ \li The index of this label.
+ \row \li \c {readonly property real} \b styleData.value
+ \li The value that this label represents.
+ \endtable
+
+ \sa {Styling CircularGauge#styling-circulargauge-tickmarkLabel}{
+ Styling CircularGauge's tickmarkLabel}
+ */
+ property Component tickmarkLabel: Text {
+ font.pixelSize: Math.max(6, __protectedScope.toPixels(0.12))
+ text: styleData.value
+ color: "#c8c8c8"
+ antialiasing: true
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ }
+
+ /*!
+ The needle that points to the gauge's current value.
+
+ This component is drawn below the \l foreground component.
+
+ The style expects the needle to be pointing up at a rotation of \c 0,
+ in order for the rotation to be correct. For example:
+
+ \image circulargauge-needle.png CircularGauge's needle
+
+ When defining your own needle component, the only properties that the
+ style requires you to set are the
+ \l {Item::implicitWidth}{implicitWidth} and
+ \l {Item::implicitHeight}{implicitHeight}.
+
+ Optionally, you can set \l {Item::x}{x} and \l {Item::y}{y} to change
+ the needle's transform origin. Setting the \c x position can be useful
+ for needle images where the needle is not centered exactly
+ horizontally. Setting the \c y position allows you to make the base of
+ the needle hang over the center of the gauge.
+
+ \sa {Styling CircularGauge#styling-circulargauge-needle}{
+ Styling CircularGauge's needle}
+ */
+ property Component needle: Item {
+ implicitWidth: __protectedScope.toPixels(0.08)
+ implicitHeight: 0.9 * outerRadius
+
+ Image {
+ anchors.fill: parent
+ source: "images/needle.png"
+ }
+ }
+
+ /*!
+ The foreground of the gauge. This component is drawn above all others.
+
+ Like \l background, the foreground component fills the entire gauge.
+
+ By default, the knob of the gauge is defined here.
+
+ \sa {Styling CircularGauge#styling-circulargauge-foreground}{
+ Styling CircularGauge's foreground}
+ */
+ property Component foreground: Item {
+ Image {
+ source: "images/knob.png"
+ anchors.centerIn: parent
+ scale: {
+ var idealHeight = __protectedScope.toPixels(0.2);
+ var originalImageHeight = sourceSize.height;
+ idealHeight / originalImageHeight;
+ }
+ }
+ }
+
+ /*! \internal */
+ property Component panel: Item {
+ id: panelItem
+ implicitWidth: backgroundLoader.item ? backgroundLoader.implicitWidth : TextSingleton.implicitHeight * 16
+ implicitHeight: backgroundLoader.item ? backgroundLoader.implicitHeight : TextSingleton.implicitHeight * 16
+
+ property alias background: backgroundLoader.item
+ property alias circularTickmarkLabel: circularTickmarkLabel_
+
+ Loader {
+ id: backgroundLoader
+ sourceComponent: circularGaugeStyle.background
+ width: outerRadius * 2
+ height: outerRadius * 2
+ anchors.centerIn: parent
+ }
+
+ CircularTickmarkLabel {
+ id: circularTickmarkLabel_
+ anchors.fill: backgroundLoader
+
+ minimumValue: control.minimumValue
+ maximumValue: control.maximumValue
+ stepSize: control.stepSize
+ tickmarksVisible: control.tickmarksVisible
+ minimumValueAngle: circularGaugeStyle.minimumValueAngle
+ maximumValueAngle: circularGaugeStyle.maximumValueAngle
+ tickmarkStepSize: circularGaugeStyle.tickmarkStepSize
+ tickmarkInset: circularGaugeStyle.tickmarkInset
+ minorTickmarkCount: circularGaugeStyle.minorTickmarkCount
+ minorTickmarkInset: circularGaugeStyle.minorTickmarkInset
+ labelInset: circularGaugeStyle.labelInset
+ labelStepSize: circularGaugeStyle.labelStepSize
+
+ style: CircularTickmarkLabelStyle {
+ tickmark: circularGaugeStyle.tickmark
+ minorTickmark: circularGaugeStyle.minorTickmark
+ tickmarkLabel: circularGaugeStyle.tickmarkLabel
+ }
+ }
+
+ Loader {
+ id: needleLoader
+ sourceComponent: circularGaugeStyle.needle
+ transform: [
+ Rotation {
+ angle: needleRotation
+ origin.x: needleLoader.width / 2
+ origin.y: needleLoader.height
+ },
+ Translate {
+ x: panelItem.width / 2 - needleLoader.width / 2
+ y: panelItem.height / 2 - needleLoader.height
+ }
+ ]
+ }
+
+ Loader {
+ id: foreground
+ sourceComponent: circularGaugeStyle.foreground
+ anchors.fill: backgroundLoader
+ }
+ }
+}
diff --git a/src/controls/Styles/Base/CircularTickmarkLabelStyle.qml b/src/controls/Styles/Base/CircularTickmarkLabelStyle.qml
new file mode 100644
index 00000000..010e9245
--- /dev/null
+++ b/src/controls/Styles/Base/CircularTickmarkLabelStyle.qml
@@ -0,0 +1,304 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Extras module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtQuick.Controls.Private 1.0
+import QtQuick.Extras.Private 1.0
+import QtQuick.Extras.Private.CppUtils 1.0
+
+Style {
+ id: circularTickmarkLabelStyle
+
+ /*!
+ The distance from the center of the control to the outer edge.
+ */
+ readonly property real outerRadius: Math.min(control.width, control.height) * 0.5
+
+ property QtObject __protectedScope: QtObject {
+ /*!
+ Converts a value expressed as a percentage of \l outerRadius to
+ a pixel value.
+ */
+ function toPixels(percentageOfOuterRadius) {
+ return percentageOfOuterRadius * outerRadius;
+ }
+ }
+
+ /*!
+ This component defines each individual tickmark. The position of each
+ tickmark is already set; only the size needs to be specified.
+ */
+ property Component tickmark: Rectangle {
+ width: outerRadius * 0.02
+ antialiasing: true
+ height: outerRadius * 0.06
+ color: "#c8c8c8"
+ }
+
+ /*!
+ This component defines each individual minor tickmark. The position of
+ each minor tickmark is already set; only the size needs to be specified.
+ */
+ property Component minorTickmark: Rectangle {
+ width: outerRadius * 0.01
+ antialiasing: true
+ height: outerRadius * 0.03
+ color: "#c8c8c8"
+ }
+
+ /*!
+ This defines the text of each tickmark label on the gauge.
+ */
+ property Component tickmarkLabel: Text {
+ font.pixelSize: Math.max(6, __protectedScope.toPixels(0.12))
+ text: styleData.value
+ color: "#c8c8c8"
+ antialiasing: true
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ }
+
+ /*! \internal */
+ property Component panel: Item {
+ id: panelItem
+ implicitWidth: 250
+ implicitHeight: 250
+
+ function rangeUsed(count, stepSize) {
+ return (((count - 1) * stepSize) / (control.maximumValue - control.minimumValue)) * control.angleRange;
+ }
+
+ readonly property real tickmarkSectionSize: rangeUsed(control.tickmarkCount, control.tickmarkStepSize) / (control.tickmarkCount - 1)
+ readonly property real tickmarkSectionValue: (control.maximumValue - control.minimumValue) / (control.tickmarkCount - 1)
+ readonly property real minorTickmarkSectionSize: tickmarkSectionSize / (control.minorTickmarkCount + 1)
+ readonly property real minorTickmarkSectionValue: tickmarkSectionValue / (control.minorTickmarkCount + 1)
+ readonly property int totalMinorTickmarkCount: {
+ // The size of each section within two major tickmarks, expressed as a percentage.
+ var minorSectionPercentage = 1 / (control.minorTickmarkCount + 1);
+ // The amount of major tickmarks not able to be displayed; will be 0 if they all fit.
+ var tickmarksNotDisplayed = control.__tickmarkCount - control.tickmarkCount;
+ var count = control.minorTickmarkCount * (control.tickmarkCount - 1);
+ // We'll try to display as many minor tickmarks as we can to fill up the space.
+ count + tickmarksNotDisplayed / minorSectionPercentage;
+ }
+ readonly property real labelSectionSize: rangeUsed(control.labelCount, control.labelStepSize) / (control.labelCount - 1)
+
+ function toPixels(percentageOfOuterRadius) {
+ return percentageOfOuterRadius * outerRadius;
+ }
+
+ /*!
+ Returns the angle of \a marker (in the range 0 ... n - 1, where n
+ is the amount of markers) on the gauge where sections are of size
+ tickmarkSectionSize.
+ */
+ function tickmarkAngleFromIndex(tickmarkIndex) {
+ return tickmarkIndex * tickmarkSectionSize + control.minimumValueAngle;
+ }
+
+ function labelAngleFromIndex(labelIndex) {
+ return labelIndex * labelSectionSize + control.minimumValueAngle;
+ }
+
+ function labelPosFromIndex(index, labelWidth, labelHeight) {
+ return MathUtils.centerAlongCircle(outerRadius, outerRadius, labelWidth, labelHeight,
+ MathUtils.degToRadOffset(labelAngleFromIndex(index)),
+ outerRadius - control.labelInset)
+ }
+
+ function minorTickmarkAngleFromIndex(minorTickmarkIndex) {
+ var baseAngle = tickmarkAngleFromIndex(Math.floor(minorTickmarkIndex / control.minorTickmarkCount));
+ // + minorTickmarkSectionSize because we don't want the first minor tickmark to start on top of its "parent" tickmark.
+ var relativeMinorAngle = (minorTickmarkIndex % control.minorTickmarkCount * minorTickmarkSectionSize) + minorTickmarkSectionSize;
+ return baseAngle + relativeMinorAngle;
+ }
+
+ function tickmarkValueFromIndex(majorIndex) {
+ return (majorIndex * tickmarkSectionValue) + control.minimumValue;
+ }
+
+ function tickmarkValueFromMinorIndex(minorIndex) {
+ var majorIndex = Math.floor(minorIndex / control.minorTickmarkCount);
+ var relativeMinorIndex = minorIndex % control.minorTickmarkCount;
+ return tickmarkValueFromIndex(majorIndex) + ((relativeMinorIndex * minorTickmarkSectionValue) + minorTickmarkSectionValue);
+ }
+
+ Loader {
+ active: control.tickmarksVisible && tickmark != null
+ width: outerRadius * 2
+ height: outerRadius * 2
+ anchors.centerIn: parent
+
+ sourceComponent: Repeater {
+ id: tickmarkRepeater
+ model: control.tickmarkCount
+ delegate: Loader {
+ id: tickmarkLoader
+ objectName: "tickmark" + styleData.index
+ x: tickmarkRepeater.width / 2
+ y: tickmarkRepeater.height / 2
+
+ transform: [
+ Translate {
+ y: -outerRadius + control.tickmarkInset
+ },
+ Rotation {
+ angle: panelItem.tickmarkAngleFromIndex(styleData.index) - __tickmarkWidthAsAngle / 2
+ }
+ ]
+
+ sourceComponent: tickmark
+
+ property int __index: index
+ property QtObject styleData: QtObject {
+ readonly property alias index: tickmarkLoader.__index
+ readonly property real value: tickmarkValueFromIndex(index)
+ }
+
+ readonly property real __tickmarkWidthAsAngle: MathUtils.radToDeg((width / (MathUtils.pi2 * outerRadius)) * MathUtils.pi2)
+ }
+ }
+ }
+ Loader {
+ active: control.tickmarksVisible && minorTickmark != null
+ width: outerRadius * 2
+ height: outerRadius * 2
+ anchors.centerIn: parent
+
+ sourceComponent: Repeater {
+ id: minorRepeater
+ anchors.fill: parent
+ model: totalMinorTickmarkCount
+ delegate: Loader {
+ id: minorTickmarkLoader
+ objectName: "minorTickmark" + styleData.index
+ x: minorRepeater.width / 2
+ y: minorRepeater.height / 2
+ transform: [
+ Translate {
+ y: -outerRadius + control.minorTickmarkInset
+ },
+ Rotation {
+ angle: panelItem.minorTickmarkAngleFromIndex(styleData.index) - __minorTickmarkWidthAsAngle / 2
+ }
+ ]
+
+ sourceComponent: minorTickmark
+
+ property int __index: index
+ property QtObject styleData: QtObject {
+ readonly property alias index: minorTickmarkLoader.__index
+ readonly property real value: tickmarkValueFromMinorIndex(index)
+ }
+
+ readonly property real __minorTickmarkWidthAsAngle: MathUtils.radToDeg((width / (MathUtils.pi2 * outerRadius)) * MathUtils.pi2)
+ }
+ }
+ }
+ Loader {
+ id: labelLoader
+ active: control.tickmarksVisible && tickmarkLabel != null
+ width: outerRadius * 2
+ height: outerRadius * 2
+ anchors.centerIn: parent
+
+ sourceComponent: Item {
+ id: labelItem
+ width: outerRadius * 2
+ height: outerRadius * 2
+ anchors.centerIn: parent
+
+ Connections {
+ target: control
+ onMinimumValueChanged: valueTextModel.update()
+ onMaximumValueChanged: valueTextModel.update()
+ onTickmarkStepSizeChanged: valueTextModel.update()
+ onLabelStepSizeChanged: valueTextModel.update()
+ }
+
+ Repeater {
+ id: labelItemRepeater
+
+ Component.onCompleted: valueTextModel.update();
+
+ model: ListModel {
+ id: valueTextModel
+
+ function update() {
+ if (control.labelStepSize === 0) {
+ return;
+ }
+
+ // Make bigger if it's too small and vice versa.
+ // +1 because we want to show 11 values, with, for example: 0, 10, 20... 100.
+ var difference = control.labelCount - count;
+ if (difference > 0) {
+ for (; difference > 0; --difference) {
+ append({ value: 0 });
+ }
+ } else if (difference < 0) {
+ for (; difference < 0; ++difference) {
+ remove(count - 1);
+ }
+ }
+
+ var index = 0;
+ for (var value = control.minimumValue;
+ value <= control.maximumValue && index < count;
+ value += control.labelStepSize, ++index) {
+ setProperty(index, "value", value);
+ }
+ }
+ }
+ delegate: Loader {
+ id: tickmarkLabelDelegateLoader
+ sourceComponent: tickmarkLabel
+ x: pos.x
+ y: pos.y
+
+ readonly property point pos: panelItem.labelPosFromIndex(index, width, height);
+
+ readonly property int __index: index
+ property QtObject styleData: QtObject {
+ readonly property var value: index != -1 ? labelItemRepeater.model.get(index).value : 0
+ readonly property alias index: tickmarkLabelDelegateLoader.__index
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/controls/Styles/Base/CommonStyleHelper.qml b/src/controls/Styles/Base/CommonStyleHelper.qml
new file mode 100644
index 00000000..4263a743
--- /dev/null
+++ b/src/controls/Styles/Base/CommonStyleHelper.qml
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Extras module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+
+QtObject {
+ property Item control
+
+ property color buttonColorUpTop: "#e3e3e3"
+ property color buttonColorUpBottom: "#b3b3b3"
+ property color buttonColorDownTop: "#d3d3d3"
+ property color buttonColorDownBottom: "#939393"
+ property color textColorUp: "#4e4e4e"
+ property color textColorDown: "#303030"
+ property color textRaisedColorUp: "#ffffff"
+ property color textRaisedColorDown: "#e3e3e3"
+ property color offColor: "#ff0000"
+ property color offColorShine: "#ff6666"
+ property color onColor: "#00cc00"
+ property color onColorShine: "#66ff66"
+ property color inactiveColor: "#1f1f1f"
+ property color inactiveColorShine: "#666666"
+}
diff --git a/src/controls/Styles/Base/DelayButtonStyle.qml b/src/controls/Styles/Base/DelayButtonStyle.qml
new file mode 100644
index 00000000..447932b7
--- /dev/null
+++ b/src/controls/Styles/Base/DelayButtonStyle.qml
@@ -0,0 +1,230 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Extras module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtGraphicalEffects 1.0
+import QtQuick.Controls.Styles 1.4
+import QtQuick.Extras 1.4
+import QtQuick.Extras.Private.CppUtils 1.1
+
+/*!
+ \qmltype DelayButtonStyle
+ \inqmlmodule QtQuick.Controls.Styles
+ \since 5.5
+ \ingroup controlsstyling
+ \brief Provides custom styling for DelayButton.
+
+ You can create a custom DelayButton by replacing the following delegates:
+ \list
+ \li \l foreground
+ \li \l {QtQuick.Controls.Styles::ButtonStyle::label}{label}
+ \endlist
+*/
+
+CircularButtonStyle {
+ id: delayButtonStyle
+
+ /*!
+ The \l DelayButton that this style is attached to.
+ */
+ readonly property DelayButton control: __control
+
+ /*!
+ The gradient of the progress bar around the button.
+ */
+ property Gradient progressBarGradient: Gradient {
+ GradientStop {
+ position: 0
+ color: "#ff6666"
+ }
+ GradientStop {
+ position: 1
+ color: "#ff0000"
+ }
+ }
+
+ /*!
+ The color of the drop shadow under the progress bar.
+ */
+ property color progressBarDropShadowColor: "#ff6666"
+
+ background: Item {
+ implicitWidth: __buttonHelper.implicitWidth
+ implicitHeight: __buttonHelper.implicitHeight
+
+ Canvas {
+ id: backgroundCanvas
+ anchors.fill: parent
+
+ Connections {
+ target: control
+ onPressedChanged: backgroundCanvas.requestPaint()
+ onCheckedChanged: backgroundCanvas.requestPaint()
+ }
+
+ onPaint: {
+ var ctx = getContext("2d");
+ __buttonHelper.paintBackground(ctx);
+ }
+ }
+ }
+
+ /*!
+ The foreground of the button.
+
+ The progress bar is drawn here.
+ */
+ property Component foreground: Item {
+ id: foregroundItem
+
+ state: "normal"
+ states: [
+ State {
+ name: "normal"
+
+ PropertyChanges {
+ target: foregroundItem
+ opacity: 1
+ }
+ },
+ State {
+ name: "activated"
+ }
+ ]
+
+ transitions: [
+ Transition {
+ from: "normal"
+ to: "activated"
+ SequentialAnimation {
+ loops: Animation.Infinite
+
+ NumberAnimation {
+ target: foregroundItem
+ property: "opacity"
+ from: 0.8
+ to: 0
+ duration: 500
+ easing.type: Easing.InOutSine
+ }
+ NumberAnimation {
+ target: foregroundItem
+ property: "opacity"
+ from: 0
+ to: 0.8
+ duration: 500
+ easing.type: Easing.InOutSine
+ }
+ }
+ }
+ ]
+
+ Connections {
+ target: control
+ onActivated: state = "activated"
+ onCheckedChanged: if (!control.checked) state = "normal"
+ }
+
+ CircularProgressBar {
+ id: progressBar
+ visible: false
+ width: Math.min(parent.width, parent.height) + progressBarDropShadow.radius * 3 * 2
+ height: width
+ anchors.centerIn: parent
+ antialiasing: true
+ barWidth: __buttonHelper.outerArcLineWidth
+ inset: progressBarDropShadow.radius * 3
+ minimumValueAngle: -180
+ maximumValueAngle: 180
+
+ progress: control.progress
+
+ // TODO: Add gradient property if/when we drop support for building with 5.1.
+ function updateGradient() {
+ clearStops();
+ for (var i = 0; i < progressBarGradient.stops.length; ++i) {
+ addStop(progressBarGradient.stops[i].position, progressBarGradient.stops[i].color);
+ }
+ }
+
+ Component.onCompleted: updateGradient()
+
+ Connections {
+ target: delayButtonStyle
+ onProgressBarGradientChanged: progressBar.updateGradient()
+ }
+ }
+
+ DropShadow {
+ id: progressBarDropShadow
+ anchors.fill: progressBar
+ fast: true
+ // QTBUG-33747
+// cached: !control.pressed
+ radius: 4
+ samples: radius * 2
+ color: progressBarDropShadowColor
+ source: progressBar
+ }
+ }
+
+ panel: Item {
+ implicitWidth: backgroundLoader.implicitWidth
+ implicitHeight: backgroundLoader.implicitHeight
+
+ Loader {
+ id: backgroundLoader
+ anchors.fill: parent
+ sourceComponent: background
+ }
+
+ Loader {
+ id: foregroundLoader
+ anchors.fill: parent
+ sourceComponent: foreground
+ }
+
+ Loader {
+ id: labelLoader
+ sourceComponent: label
+ anchors.fill: parent
+ anchors.leftMargin: padding.left
+ anchors.topMargin: padding.top
+ anchors.rightMargin: padding.right
+ anchors.bottomMargin: padding.bottom
+ }
+ }
+}
diff --git a/src/controls/Styles/Base/DialStyle.qml b/src/controls/Styles/Base/DialStyle.qml
new file mode 100644
index 00000000..dc4f370d
--- /dev/null
+++ b/src/controls/Styles/Base/DialStyle.qml
@@ -0,0 +1,360 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Extras module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtQuick.Controls 1.4
+import QtQuick.Controls.Styles 1.4
+import QtQuick.Controls.Private 1.0
+import QtQuick.Extras 1.4
+import QtQuick.Extras.Private 1.0
+import QtQuick.Extras.Private.CppUtils 1.0
+
+/*!
+ \qmltype DialStyle
+ \inqmlmodule QtQuick.Controls.Styles
+ \since 5.5
+ \ingroup controlsstyling
+ \brief Provides custom styling for Dial.
+
+ You can create a custom dial by replacing the following delegates:
+ \list
+ \li \l background
+ \endlist
+*/
+
+Style {
+ id: dialStyle
+
+ /*!
+ The \l Dial that this style is attached to.
+ */
+ readonly property Dial control: __control
+
+ /*!
+ The distance from the center of the dial to the outer edge of the dial.
+
+ This property is useful for determining the size of the various
+ components of the style, in order to ensure that they are scaled
+ proportionately when the dial is resized.
+ */
+ readonly property real outerRadius: Math.min(control.height, control.width) / 2
+
+ /*!
+ The distance in pixels from the outside of the dial (outerRadius)
+ to the center of the handle.
+ */
+ property real handleInset: (__tickmarkRadius * 4) + ((__handleRadius * 2) * 0.55)
+
+ /*!
+ The interval at which tickmarks are displayed.
+
+ For example, if this property is set to \c 10,
+ control.minimumValue to \c 0, and control.maximumValue to \c 100,
+ the tickmarks displayed will be 0, 10, 20, etc., to 100, along
+ the circumference of the dial.
+ */
+ property real tickmarkStepSize: 1
+
+ /*!
+ The distance in pixels from the outside of the dial (outerRadius) at
+ which the outermost point of the tickmark line is drawn.
+ */
+ property real tickmarkInset: 0
+
+
+ /*!
+ The amount of tickmarks displayed by the dial, calculated from
+ \l tickmarkStepSize and the control's
+ \l {Dial::minimumValue}{minimumValue} and
+ \l {Dial::maximumValue}{maximumValue}.
+
+ \sa minorTickmarkCount
+ */
+ readonly property int tickmarkCount: control.__panel.circularTickmarkLabel.tickmarkCount
+
+ /*!
+ The amount of minor tickmarks between each tickmark.
+
+ \sa tickmarkCount
+ */
+ property int minorTickmarkCount: 0
+
+ /*!
+ The distance in pixels from the outside of the dial (outerRadius) at
+ which the outermost point of the minor tickmark line is drawn.
+ */
+ property real minorTickmarkInset: 0
+
+ /*!
+ The distance in pixels from the outside of the dial (outerRadius) at
+ which the center of the value marker text is drawn.
+ */
+ property real labelInset: 0
+
+ /*!
+ The interval at which tickmark labels are displayed.
+
+ For example, if this property is set to \c 10 (the default),
+ control.minimumValue to \c 0, and control.maximumValue to \c 100, the
+ tickmark labels displayed will be 0, 10, 20, etc., to 100,
+ along the circumference of the dial.
+ */
+ property real labelStepSize: tickmarkStepSize
+
+ /*!
+ The amount of tickmark labels displayed by the dial, calculated from
+ \l labelStepSize and the control's
+ \l {Dial::minimumValue}{minimumValue} and
+ \l {Dial::maximumValue}{maximumValue}.
+
+ \sa tickmarkCount, minorTickmarkCount
+ */
+ readonly property int labelCount: control.__panel.circularTickmarkLabel.labelCount
+
+ /*!
+ Returns \a value as an angle in degrees.
+
+ This function is useful for custom drawing or positioning of items in
+ the style's components. For example, it can be used to calculate the
+ angles at which to draw an arc around the dial indicating the safe
+ range of values.
+
+ For example, if minimumValueAngle is set to \c 270 and
+ maximumValueAngle is set to \c 90, this function will return \c 270
+ when passed minimumValue and \c 90 when passed maximumValue.
+ */
+ function valueToAngle(value) {
+ return control.__panel.circularTickmarkLabel.valueToAngle(value);
+ }
+
+ /*! \internal */
+ readonly property real __tickmarkRadius: outerRadius * 0.06
+
+ /*! \internal */
+ readonly property real __handleRadius: outerRadius * 0.15
+
+ /*!
+ \internal
+
+ This property determines whether it is possible to change the value of
+ the dial simply by pressing/tapping.
+
+ If \c false, the user must drag to rotate the dial and hence change the
+ value.
+
+ This property is useful for touch devices, where it is easy to
+ accidentally tap while flicking, for example.
+ */
+ property bool __dragToSet: Settings.hasTouchScreen && Settings.isMobile
+
+ /*!
+ The background of the dial.
+
+ The implicit size of the dial is taken from this component.
+ */
+ property Component background: Item {
+ id: backgroundItem
+ implicitWidth: backgroundHelper.implicitWidth
+ implicitHeight: backgroundHelper.implicitHeight
+
+ CircularButtonStyleHelper {
+ id: backgroundHelper
+ control: dialStyle.control
+ property color zeroMarkerColor: "#a8a8a8"
+ property color zeroMarkerColorTransparent: "transparent"
+ property real zeroMarkerLength: outerArcLineWidth * 1.25
+ property real zeroMarkerWidth: outerArcLineWidth * 0.3
+
+ smallestAxis: Math.min(backgroundItem.width, backgroundItem.height) - __tickmarkRadius * 4
+ }
+
+ Canvas {
+ id: backgroundCanvas
+ anchors.fill: parent
+
+ readonly property real xCenter: width / 2
+ readonly property real yCenter: height / 2
+
+ onPaint: {
+ var ctx = getContext("2d");
+ backgroundHelper.paintBackground(ctx);
+ }
+ }
+ }
+
+ /*!
+ The handle of the dial.
+
+ The handle is automatically positioned within the dial, based on the
+ \l handleInset and the implicit width and height of the handle itself.
+ */
+ property Component handle: Canvas {
+ implicitWidth: __handleRadius * 2
+ implicitHeight: __handleRadius * 2
+
+ HandleStyleHelper {
+ id: handleHelper
+ }
+
+ onPaint: {
+ var ctx = getContext("2d");
+ handleHelper.paintHandle(ctx, 1, 1, width - 2, height - 2);
+ }
+ }
+
+ /*!
+ This component defines each individual tickmark. The position of each
+ tickmark is already set; only the
+ \l {Item::implicitWidth}{implicitWidth} and
+ \l {Item::implicitHeight}{implicitHeight} need to be specified.
+
+ Each instance of this component has access to the following properties:
+
+ \table
+ \row \li \c {readonly property int} \b styleData.index
+ \li The index of this tickmark.
+ \row \li \c {readonly property real} \b styleData.value
+ \li The value that this tickmark represents.
+ \endtable
+ */
+ property Component tickmark: Rectangle {
+ implicitWidth: outerRadius * 0.015 + (styleData.index === 0 || styleData.index === tickmarkCount ? 1 : (styleData.index) / tickmarkCount) * __tickmarkRadius * 0.75
+ implicitHeight: implicitWidth
+ radius: height / 2
+ color: styleData.index === 0 ? "transparent" : Qt.rgba(0, 0, 0, 0.266)
+ antialiasing: true
+ border.width: styleData.index === 0 ? Math.max(1, outerRadius * 0.0075) : 0
+ border.color: Qt.rgba(0, 0, 0, 0.266)
+ }
+
+ /*!
+ This component defines each individual minor tickmark. The position of each
+ minor tickmark is already set; only the
+ \l {Item::implicitWidth}{implicitWidth} and
+ \l {Item::implicitHeight}{implicitHeight} need to be specified.
+
+ Each instance of this component has access to the following properties:
+
+ \table
+ \row \li \c {readonly property int} \b styleData.index
+ \li The index of this tickmark.
+ \row \li \c {readonly property real} \b styleData.value
+ \li The value that this tickmark represents.
+ \endtable
+
+ By default, no minor tickmark is defined.
+ */
+ property Component minorTickmark
+
+ /*!
+ This defines the text of each tickmark label on the dial.
+
+ Each instance of this component has access to the following properties:
+
+ \table
+ \row \li \c {readonly property int} \b styleData.index
+ \li The index of this label.
+ \row \li \c {readonly property real} \b styleData.value
+ \li The value that this label represents.
+ \endtable
+
+ By default, no label is defined.
+ */
+ property Component tickmarkLabel
+
+ /*! \internal */
+ property Component panel: Item {
+ implicitWidth: backgroundLoader.implicitWidth
+ implicitHeight: backgroundLoader.implicitHeight
+
+ property alias background: backgroundLoader.item
+ property alias circularTickmarkLabel: circularTickmarkLabel_
+
+ Loader {
+ id: backgroundLoader
+ sourceComponent: dialStyle.background
+ width: outerRadius * 2
+ height: width
+ anchors.centerIn: parent
+ }
+
+ Loader {
+ id: handleLoader
+ sourceComponent: dialStyle.handle
+ x: backgroundLoader.x + __pos.x - width / 2
+ y: backgroundLoader.y + __pos.y - height / 2
+
+ readonly property point __pos: {
+ var radians = 0;
+ if (control.__wrap) {
+ radians = (control.value - control.minimumValue) /
+ (control.maximumValue - control.minimumValue) *
+ (MathUtils.pi2) + backgroundHelper.zeroAngle;
+ } else {
+ radians = -(Math.PI * 8 - (control.value - control.minimumValue) * 10 *
+ Math.PI / (control.maximumValue - control.minimumValue)) / 6;
+ }
+
+ return MathUtils.centerAlongCircle(backgroundLoader.width / 2, backgroundLoader.height / 2,
+ 0, 0, radians, outerRadius - handleInset)
+ }
+ }
+
+ CircularTickmarkLabel {
+ id: circularTickmarkLabel_
+ anchors.fill: backgroundLoader
+
+ minimumValue: control.minimumValue
+ maximumValue: control.maximumValue
+ stepSize: control.stepSize
+ tickmarksVisible: control.tickmarksVisible
+ minimumValueAngle: -150
+ maximumValueAngle: 150
+ tickmarkStepSize: dialStyle.tickmarkStepSize
+ tickmarkInset: dialStyle.tickmarkInset
+ minorTickmarkCount: dialStyle.minorTickmarkCount
+ minorTickmarkInset: dialStyle.minorTickmarkInset
+ labelInset: dialStyle.labelInset
+ labelStepSize: dialStyle.labelStepSize
+
+ style: CircularTickmarkLabelStyle {
+ tickmark: dialStyle.tickmark
+ minorTickmark: dialStyle.minorTickmark
+ tickmarkLabel: dialStyle.tickmarkLabel
+ }
+ }
+ }
+}
diff --git a/src/controls/Styles/Base/GaugeStyle.qml b/src/controls/Styles/Base/GaugeStyle.qml
new file mode 100644
index 00000000..35da65d5
--- /dev/null
+++ b/src/controls/Styles/Base/GaugeStyle.qml
@@ -0,0 +1,541 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Extras module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtQuick.Controls 1.4
+import QtQuick.Controls.Styles 1.4
+import QtQuick.Controls.Private 1.0
+import QtQuick.Extras 1.4
+import QtQuick.Extras.Private 1.0
+
+/*!
+ \qmltype GaugeStyle
+ \inqmlmodule QtQuick.Controls.Styles
+ \since 5.5
+ \ingroup controlsstyling
+ \brief Provides custom styling for Gauge.
+
+ You can create a custom gauge by replacing the following delegates:
+ \list
+ \li \l background
+ \li valueBar
+ \li tickmarkLabel
+ \endlist
+
+ Below, you'll find an example of how to create a temperature gauge that
+ changes color as its value increases:
+
+ \code
+ import QtQuick 2.2
+ import QtQuick.Controls 1.4
+ import QtQuick.Controls.Styles 1.4
+ import QtQuick.Extras 1.4
+
+ Rectangle {
+ width: 80
+ height: 200
+
+ Timer {
+ running: true
+ repeat: true
+ interval: 2000
+ onTriggered: gauge.value = gauge.value == gauge.maximumValue ? 5 : gauge.maximumValue
+ }
+
+ Gauge {
+ id: gauge
+ anchors.fill: parent
+ anchors.margins: 10
+
+ value: 5
+ Behavior on value {
+ NumberAnimation {
+ duration: 1000
+ }
+ }
+
+ style: GaugeStyle {
+ valueBar: Rectangle {
+ implicitWidth: 16
+ color: Qt.rgba(gauge.value / gauge.maximumValue, 0, 1 - gauge.value / gauge.maximumValue, 1)
+ }
+ }
+ }
+ }
+ \endcode
+
+ \image gauge-temperature.png
+ The gauge displaying values at various points during the animation.
+
+ \sa {Styling Gauge}
+*/
+
+Style {
+ id: gaugeStyle
+
+ /*!
+ The \l Gauge that this style is attached to.
+ */
+ readonly property Gauge control: __control
+
+ /*!
+ This property holds the value displayed by the gauge as a position in
+ pixels.
+
+ It is useful for custom styling.
+ */
+ readonly property real valuePosition: control.__panel.valuePosition
+
+ /*!
+ The background of the gauge, displayed behind the \l valueBar.
+
+ By default, no background is defined.
+ */
+ property Component background
+
+ /*!
+ Each tickmark displayed by the gauge.
+
+ To set the size of the tickmarks, specify an
+ \l {Item::implicitWidth}{implicitWidth} and
+ \l {Item::implicitHeight}{implicitHeight}.
+
+ The widest tickmark will determine the space set aside for all
+ tickmarks. For this reason, the \c implicitWidth of each tickmark
+ should be greater than or equal to that of each minor tickmark. If you
+ need minor tickmarks to have greater widths than the major tickmarks,
+ set the larger width in a child item of the \l minorTickmark component.
+
+ For layouting reasons, each tickmark should have the same
+ \c implicitHeight. If different heights are needed for individual
+ tickmarks, specify those heights in a child item of the component.
+
+ In the example below, we decrease the height of the tickmarks:
+
+ \code
+ tickmark: Item {
+ implicitWidth: 18
+ implicitHeight: 1
+
+ Rectangle {
+ color: "#c8c8c8"
+ anchors.fill: parent
+ anchors.leftMargin: 3
+ anchors.rightMargin: 3
+ }
+ }
+ \endcode
+
+ \image gauge-tickmark-example.png Gauge tickmark example
+
+ Each instance of this component has access to the following properties:
+
+ \table
+ \row \li \c {readonly property int} \b styleData.index
+ \li The index of this tickmark.
+ \row \li \c {readonly property real} \b styleData.value
+ \li The value that this tickmark represents.
+ \row \li \c {readonly property real} \b styleData.valuePosition
+ \li The value that this tickmark represents as a position in
+ pixels, with 0 being at the bottom of the gauge.
+ \endtable
+
+ \sa minorTickmark
+ */
+ property Component tickmark: Item {
+ implicitWidth: Math.round(TextSingleton.height * 1.1)
+ implicitHeight: Math.max(2, Math.round(TextSingleton.height * 0.1))
+
+ Rectangle {
+ color: "#c8c8c8"
+ anchors.fill: parent
+ anchors.leftMargin: Math.round(TextSingleton.implicitHeight * 0.2)
+ anchors.rightMargin: Math.round(TextSingleton.implicitHeight * 0.2)
+ }
+ }
+
+ /*!
+ Each minor tickmark displayed by the gauge.
+
+ To set the size of the minor tickmarks, specify an
+ \l {Item::implicitWidth}{implicitWidth} and
+ \l {Item::implicitHeight}{implicitHeight}.
+
+ For layouting reasons, each minor tickmark should have the same
+ \c implicitHeight. If different heights are needed for individual
+ tickmarks, specify those heights in a child item of the component.
+
+ In the example below, we decrease the width of the minor tickmarks:
+
+ \code
+ minorTickmark: Item {
+ implicitWidth: 8
+ implicitHeight: 1
+
+ Rectangle {
+ color: "#cccccc"
+ anchors.fill: parent
+ anchors.leftMargin: 2
+ anchors.rightMargin: 4
+ }
+ }
+ \endcode
+
+ \image gauge-minorTickmark-example.png Gauge minorTickmark example
+
+ Each instance of this component has access to the following property:
+
+ \table
+ \row \li \c {readonly property int} \b styleData.index
+ \li The index of this minor tickmark.
+ \row \li \c {readonly property real} \b styleData.value
+ \li The value that this minor tickmark represents.
+ \row \li \c {readonly property real} \b styleData.valuePosition
+ \li The value that this minor tickmark represents as a
+ position in pixels, with 0 being at the bottom of the
+ gauge.
+ \endtable
+
+ \sa tickmark
+ */
+ property Component minorTickmark: Item {
+ implicitWidth: Math.round(TextSingleton.implicitHeight * 0.65)
+ implicitHeight: Math.max(1, Math.round(TextSingleton.implicitHeight * 0.05))
+
+ Rectangle {
+ color: "#c8c8c8"
+ anchors.fill: parent
+ anchors.leftMargin: control.__tickmarkAlignment === Qt.AlignBottom || control.__tickmarkAlignment === Qt.AlignRight
+ ? Math.max(3, Math.round(TextSingleton.implicitHeight * 0.2))
+ : 0
+ anchors.rightMargin: control.__tickmarkAlignment === Qt.AlignBottom || control.__tickmarkAlignment === Qt.AlignRight
+ ? 0
+ : Math.max(3, Math.round(TextSingleton.implicitHeight * 0.2))
+ }
+ }
+
+ /*!
+ This defines the text of each tickmark label on the gauge.
+
+ Each instance of this component has access to the following properties:
+
+ \table
+ \row \li \c {readonly property int} \b styleData.index
+ \li The index of this label.
+ \row \li \c {readonly property real} \b styleData.value
+ \li The value that this label represents.
+ \endtable
+ */
+ property Component tickmarkLabel: Text {
+ text: control.formatValue(styleData.value)
+ font: control.font
+ color: "#c8c8c8"
+ antialiasing: true
+ }
+
+ /*!
+ The bar that represents the value of the gauge.
+
+ To height of the value bar is automatically resized according to
+ \l {Gauge::value}{value}, and does not need to be specified.
+
+ When a custom valueBar is defined, its
+ \l {Item::implicitWidth}{implicitWidth} property must be set.
+ */
+ property Component valueBar: Rectangle {
+ color: "#00bbff"
+ implicitWidth: TextSingleton.implicitHeight
+ }
+
+ /*!
+ The bar that represents the foreground of the gauge.
+
+ This component is drawn above every other component.
+ */
+ property Component foreground: Canvas {
+ readonly property real xCenter: width / 2
+ readonly property real yCenter: height / 2
+ property real shineLength: height * 0.95
+
+ onPaint: {
+ var ctx = getContext("2d");
+ ctx.reset();
+
+ ctx.beginPath();
+ ctx.rect(0, 0, width, height);
+
+ var gradient = ctx.createLinearGradient(0, yCenter, width, yCenter);
+
+ gradient.addColorStop(0, Qt.rgba(1, 1, 1, 0.08));
+ gradient.addColorStop(1, Qt.rgba(1, 1, 1, 0.20));
+ ctx.fillStyle = gradient;
+ ctx.fill();
+ }
+ }
+
+ /*! \internal */
+ property Component panel: Item {
+ id: panelComponent
+ implicitWidth: control.orientation === Qt.Vertical ? tickmarkLabelBoundsWidth + rawBarWidth : TextSingleton.height * 14
+ implicitHeight: control.orientation === Qt.Vertical ? TextSingleton.height * 14 : tickmarkLabelBoundsWidth + rawBarWidth
+
+ readonly property int tickmarkCount: (control.maximumValue - control.minimumValue) / control.tickmarkStepSize + 1
+ readonly property real tickmarkSpacing: (tickmarkLabelBounds.height - tickmarkWidth * tickmarkCount) / (tickmarkCount - 1)
+
+ property real tickmarkLength: tickmarkColumn.width
+ // Can't deduce this from the column, so we set it from within the first tickmark delegate loader.
+ property real tickmarkWidth: 2
+
+ readonly property real tickmarkOffset: control.orientation === Qt.Vertical ? control.__hiddenText.height / 2 : control.__hiddenText.width / 2
+
+ readonly property real minorTickmarkStep: control.tickmarkStepSize / (control.minorTickmarkCount + 1);
+
+ /*!
+ Returns the marker text that should be displayed based on
+ \a markerPos (\c 0 to \c 1.0).
+ */
+ function markerTextFromPos(markerPos) {
+ return markerPos * (control.maximumValue - control.minimumValue) + control.minimumValue;
+ }
+
+ readonly property real rawBarWidth: valueBarLoader.item.implicitWidth
+ readonly property real barLength: (control.orientation === Qt.Vertical ? control.height : control.width) - (tickmarkOffset * 2 - 2)
+
+ readonly property real tickmarkLabelBoundsWidth: tickmarkLength + (control.orientation === Qt.Vertical ? control.__hiddenText.width : control.__hiddenText.height)
+ readonly property int valuePosition: valueBarLoader.height
+
+ Item {
+ id: container
+
+ width: control.orientation === Qt.Vertical ? parent.width : parent.height
+ height: control.orientation === Qt.Vertical ? parent.height : parent.width
+ rotation: control.orientation === Qt.Horizontal ? 90 : 0
+ transformOrigin: Item.Center
+ anchors.centerIn: parent
+
+ Item {
+ id: valueBarItem
+
+ x: control.__tickmarkAlignment === Qt.AlignLeft || control.__tickmarkAlignment === Qt.AlignTop ? tickmarkLabelBounds.x + tickmarkLabelBounds.width : 0
+ width: rawBarWidth
+ height: barLength
+ anchors.verticalCenter: parent.verticalCenter
+
+ Loader {
+ id: backgroundLoader
+ sourceComponent: background
+ anchors.fill: parent
+ }
+
+ Loader {
+ id: valueBarLoader
+ sourceComponent: valueBar
+
+ readonly property real valueAsPercentage: (control.value - control.minimumValue) / (control.maximumValue - control.minimumValue)
+
+ y: Math.round(parent.height - height)
+ height: Math.round(valueAsPercentage * parent.height)
+ }
+ }
+ Item {
+ id: tickmarkLabelBounds
+
+ x: control.__tickmarkAlignment === Qt.AlignLeft || control.__tickmarkAlignment === Qt.AlignTop ? 0 : valueBarItem.width
+ width: tickmarkLabelBoundsWidth
+ height: barLength
+ anchors.verticalCenter: parent.verticalCenter
+ // We want our items to be laid out from bottom to top, but Column can't do that, so we flip
+ // the whole item containing the tickmarks and labels vertically. Then, we flip each tickmark
+ // and label back again.
+ transform: Rotation {
+ axis.x: 1
+ axis.y: 0
+ axis.z: 0
+ origin.x: tickmarkLabelBounds.width / 2
+ origin.y: tickmarkLabelBounds.height / 2
+ angle: 180
+ }
+
+ Column {
+ id: tickmarkColumn
+ x: control.__tickmarkAlignment === Qt.AlignRight || control.__tickmarkAlignment === Qt.AlignBottom ? 0 : tickmarkLabelBounds.width - width
+ spacing: tickmarkSpacing
+ anchors.verticalCenter: parent.verticalCenter
+
+ Repeater {
+ id: tickmarkRepeater
+ model: tickmarkCount
+ delegate: Loader {
+ id: tickmarkDelegateLoader
+
+ sourceComponent: gaugeStyle.tickmark
+ transform: Rotation {
+ axis.x: 1
+ axis.y: 0
+ axis.z: 0
+ origin.x: tickmarkDelegateLoader.width / 2
+ origin.y: tickmarkDelegateLoader.height / 2
+ angle: 180
+ }
+
+ onHeightChanged: {
+ if (index == 0)
+ tickmarkWidth = height;
+ }
+
+ readonly property int __index: index
+ property QtObject styleData: QtObject {
+ readonly property alias index: tickmarkDelegateLoader.__index
+ readonly property real value: (index / (tickmarkCount - 1)) * (control.maximumValue - control.minimumValue) + control.minimumValue
+ readonly property int valuePosition: Math.round(tickmarkDelegateLoader.y)
+ }
+ }
+ }
+ }
+
+ // Doesn't need to be in a column, since we assume that the major tickmarks will always be longer than us.
+ Repeater {
+ id: minorTickmarkRepeater
+ model: (tickmarkCount - 1) * control.minorTickmarkCount
+ delegate: Loader {
+ id: minorTickmarkDelegateLoader
+
+ x: control.__tickmarkAlignment === Qt.AlignRight || control.__tickmarkAlignment === Qt.AlignBottom ? 0 : tickmarkLabelBounds.width - width
+ y: {
+ var tickmarkWidthOffset = Math.floor(index / control.minorTickmarkCount) * tickmarkWidth + tickmarkWidth;
+ var relativePosition = (index % control.minorTickmarkCount + 1) * (tickmarkSpacing / (control.minorTickmarkCount + 1));
+ var clusterOffset = Math.floor(index / control.minorTickmarkCount) * tickmarkSpacing;
+ // We assume that each minorTickmark's height is the same.
+ return clusterOffset + tickmarkWidthOffset + relativePosition - height / 2;
+ }
+
+ transform: Rotation {
+ axis.x: 1
+ axis.y: 0
+ axis.z: 0
+ origin.x: minorTickmarkDelegateLoader.width / 2
+ origin.y: minorTickmarkDelegateLoader.height / 2
+ angle: 180
+ }
+
+ sourceComponent: gaugeStyle.minorTickmark
+
+ readonly property int __index: index
+ property QtObject styleData: QtObject {
+ readonly property alias index: minorTickmarkDelegateLoader.__index
+ readonly property real value: {
+ var tickmarkIndex = Math.floor(index / control.minorTickmarkCount);
+ return index * minorTickmarkStep + minorTickmarkStep * tickmarkIndex + minorTickmarkStep + control.minimumValue;
+ }
+ readonly property int valuePosition: Math.round(minorTickmarkDelegateLoader.y)
+ }
+ }
+ }
+
+ Item {
+ id: tickmarkLabelItem
+ x: control.__tickmarkAlignment === Qt.AlignRight || control.__tickmarkAlignment === Qt.AlignBottom
+ ? tickmarkLength
+ : tickmarkLabelBounds.width - tickmarkLength - width
+ width: control.__hiddenText.width
+ // Use the bar height instead of the container's, as the labels seem to be translated by 1 when we
+ // flip the control vertically, and this fixes that.
+ height: parent.height
+ anchors.verticalCenter: parent.verticalCenter
+
+ Repeater {
+ id: tickmarkTextRepeater
+ model: tickmarkCount
+ delegate: Item {
+ x: {
+ if (control.orientation === Qt.Vertical)
+ return 0;
+
+ // Align the text to the edge of the tickmarks.
+ return ((width - height) / 2) * (control.__tickmarkAlignment === Qt.AlignBottom ? -1 : 1);
+ }
+ y: index * labelDistance - height / 2
+
+ width: control.__hiddenText.width
+ height: control.__hiddenText.height
+
+ transformOrigin: Item.Center
+ rotation: control.orientation === Qt.Vertical ? 0 : 90
+
+ readonly property real labelDistance: tickmarkLabelBounds.height / (tickmarkCount - 1)
+
+ Loader {
+ id: tickmarkTextRepeaterDelegate
+
+ x: {
+ if (control.orientation === Qt.Horizontal) {
+ return parent.width / 2 - width / 2;
+ }
+
+ return control.__tickmarkAlignment === Qt.AlignRight || control.__tickmarkAlignment === Qt.AlignBottom
+ ? 0
+ : parent.width - width;
+ }
+
+ transform: Rotation {
+ axis.x: 1
+ axis.y: 0
+ axis.z: 0
+ origin.x: tickmarkTextRepeaterDelegate.width / 2
+ origin.y: tickmarkTextRepeaterDelegate.height / 2
+ angle: 180
+ }
+
+ sourceComponent: tickmarkLabel
+
+ readonly property int __index: index
+ property QtObject styleData: QtObject {
+ readonly property alias index: tickmarkTextRepeaterDelegate.__index
+ readonly property real value: markerTextFromPos(index / (tickmarkTextRepeater.count - 1))
+ }
+ }
+ }
+ }
+ }
+ }
+ Loader {
+ id: foregroundLoader
+ sourceComponent: foreground
+ anchors.fill: valueBarItem
+ }
+ }
+ }
+}
diff --git a/src/controls/Styles/Base/HandleStyle.qml b/src/controls/Styles/Base/HandleStyle.qml
new file mode 100644
index 00000000..fd89ecac
--- /dev/null
+++ b/src/controls/Styles/Base/HandleStyle.qml
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Extras module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtQuick.Controls.Private 1.0
+import QtQuick.Extras 1.4
+
+Style {
+ id: handleStyle
+ property alias handleColorTop: __helper.handleColorTop
+ property alias handleColorBottom: __helper.handleColorBottom
+ property alias handleColorBottomStop: __helper.handleColorBottomStop
+
+ HandleStyleHelper {
+ id: __helper
+ }
+
+ property Component handle: Item {
+ implicitWidth: 50
+ implicitHeight: 50
+
+ Canvas {
+ id: handleCanvas
+ anchors.fill: parent
+
+ onPaint: {
+ var ctx = getContext("2d");
+ __helper.paintHandle(ctx);
+ }
+ }
+ }
+
+ property Component panel: Item {
+ Loader {
+ id: handleLoader
+ sourceComponent: handle
+ anchors.fill: parent
+ }
+ }
+}
diff --git a/src/controls/Styles/Base/HandleStyleHelper.qml b/src/controls/Styles/Base/HandleStyleHelper.qml
new file mode 100644
index 00000000..61ad3bb3
--- /dev/null
+++ b/src/controls/Styles/Base/HandleStyleHelper.qml
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Extras module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+
+QtObject {
+ id: handleStyleHelper
+
+ property color handleColorTop: "#969696"
+ property color handleColorBottom: Qt.rgba(0.9, 0.9, 0.9, 0.298)
+ property real handleColorBottomStop: 0.7
+
+ property color handleRingColorTop: "#b0b0b0"
+ property color handleRingColorBottom: "transparent"
+
+ /*!
+ If \a ctx is the only argument, this is equivalent to calling
+ paintHandle(\c ctx, \c 0, \c 0, \c ctx.canvas.width, \c ctx.canvas.height).
+ */
+ function paintHandle(ctx, handleX, handleY, handleWidth, handleHeight) {
+ ctx.reset();
+
+ if (handleWidth < 0)
+ return;
+
+ if (arguments.length == 1) {
+ handleX = 0;
+ handleY = 0;
+ handleWidth = ctx.canvas.width;
+ handleHeight = ctx.canvas.height;
+ }
+
+ ctx.beginPath();
+ var gradient = ctx.createRadialGradient(handleX, handleY, handleWidth / 2,
+ handleX, handleY, handleWidth);
+ gradient.addColorStop(0, handleColorTop);
+ gradient.addColorStop(handleColorBottomStop, handleColorBottom);
+ ctx.ellipse(handleX, handleY, handleWidth, handleHeight);
+ ctx.fillStyle = gradient;
+ ctx.fill();
+
+ /* Draw the ring gradient around the handle. */
+ // Clip first, so we only draw inside the ring.
+ ctx.beginPath();
+ ctx.ellipse(handleX, handleY, handleWidth, handleHeight);
+ ctx.ellipse(handleX + 2, handleY + 2, handleWidth - 4, handleHeight - 4);
+ ctx.clip();
+
+ ctx.beginPath();
+ gradient = ctx.createLinearGradient(handleX + handleWidth / 2, handleY,
+ handleX + handleWidth / 2, handleY + handleHeight);
+ gradient.addColorStop(0, handleRingColorTop);
+ gradient.addColorStop(1, handleRingColorBottom);
+ ctx.ellipse(handleX, handleY, handleWidth, handleHeight);
+ ctx.fillStyle = gradient;
+ ctx.fill();
+ }
+}
diff --git a/src/controls/Styles/Base/PieMenuStyle.qml b/src/controls/Styles/Base/PieMenuStyle.qml
new file mode 100644
index 00000000..916a0c9e
--- /dev/null
+++ b/src/controls/Styles/Base/PieMenuStyle.qml
@@ -0,0 +1,388 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Extras module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtGraphicalEffects 1.0
+import QtQuick.Controls 1.4
+import QtQuick.Controls.Styles 1.4
+import QtQuick.Controls.Private 1.0
+import QtQuick.Extras 1.4
+import QtQuick.Extras.Private 1.0
+import QtQuick.Extras.Private.CppUtils 1.0
+
+/*!
+ \qmltype PieMenuStyle
+ \inqmlmodule QtQuick.Controls.Styles
+ \since 5.5
+ \ingroup controlsstyling
+ \brief Provides custom styling for PieMenu.
+
+ PieMenuStyle is a style for PieMenu that draws each section of the menu as a
+ filled "slice".
+
+ You can create a custom pie menu by replacing the following delegates:
+ \list
+ \li \l background
+ \li \l cancel
+ \li \l menuItem
+ \li \l title
+ \endlist
+
+ To customize the appearance of each menuItem without having to define your
+ own, you can use the \l backgroundColor and \l selectionColor properties.
+ To customize the drop shadow, use the \l shadowColor, \l shadowRadius and
+ \l shadowSpread properties.
+
+ Icons that are too large for the section that they are in will be scaled
+ down appropriately.
+
+ To style individual sections of the menu, use the menuItem component:
+ \code
+ PieMenuStyle {
+ shadowRadius: 0
+
+ menuItem: Item {
+ id: item
+ rotation: -90 + sectionCenterAngle(styleData.index)
+
+ Rectangle {
+ width: parent.height * 0.2
+ height: width
+ color: "darkorange"
+ radius: width / 2
+ anchors.right: parent.right
+ anchors.verticalCenter: parent.verticalCenter
+
+ Text {
+ id: textItem
+ text: control.menuItems[styleData.index].text
+ anchors.centerIn: parent
+ color: control.currentIndex === styleData.index ? "red" : "white"
+ rotation: -item.rotation
+ }
+ }
+ }
+ }
+ \endcode
+
+ \image piemenu-menuitem-example.png A custom PieMenu
+*/
+
+Style {
+ id: pieMenuStyle
+
+ /*!
+ The \l PieMenu that this style is attached to.
+ */
+ readonly property PieMenu control: __control
+
+ /*! The background color. */
+ property color backgroundColor: Qt.rgba(0.6, 0.6, 0.6, 0.66)
+
+ /*! The selection color. */
+ property color selectionColor: "#eee"
+
+ /*! The shadow color. */
+ property color shadowColor: Qt.rgba(0, 0, 0, 0.26)
+
+ /*! The shadow radius. */
+ property real shadowRadius: 50
+
+ /*! The shadow spread. */
+ property real shadowSpread: 0.3
+
+ /*!
+ The distance from the center of the menu to the outer edge of the menu.
+
+ \sa cancelRadius
+ */
+ readonly property real radius: Math.min(control.width, control.height) * 0.5
+
+ /*!
+ The radius of the area that is used to cancel the menu.
+
+ \sa radius
+ */
+ property real cancelRadius: radius * 0.4
+
+ /*!
+ The angle (in degrees) at which the first menu item will be drawn.
+
+ The absolute range formed by \a startAngle and \l endAngle must be
+ less than or equal to \c 360 degrees.
+
+ Menu items are displayed clockwise when \a startAngle is less than
+ \l endAngle, otherwise they are displayed anti-clockwise.
+
+ \sa endAngle
+ */
+ property real startAngle: -90
+
+ /*!
+ The angle (in degrees) at which the last menu item will be drawn.
+
+ The absolute range formed by \l startAngle and \a endAngle must be
+ less than or equal to \c 360 degrees.
+
+ Menu items are displayed clockwise when \l startAngle is less than
+ \a endAngle, otherwise they are displayed anti-clockwise.
+
+ \sa startAngle
+ */
+ property real endAngle: 90
+
+ /*!
+ Returns the start of the section at \a itemIndex as an angle in degrees.
+ */
+ function sectionStartAngle(itemIndex) {
+ return MathUtils.radToDegOffset(control.__protectedScope.sectionStartAngle(itemIndex));
+ }
+
+ /*!
+ Returns the center of the section at \a itemIndex as an angle in
+ degrees.
+ */
+ function sectionCenterAngle(itemIndex) {
+ return MathUtils.radToDegOffset(control.__protectedScope.sectionCenterAngle(itemIndex));
+ }
+
+ /*!
+ Returns the end of the section at \a itemIndex as an angle in degrees.
+ */
+ function sectionEndAngle(itemIndex) {
+ return MathUtils.radToDegOffset(control.__protectedScope.sectionEndAngle(itemIndex));
+ }
+
+ /*!
+ \internal
+
+ The distance in pixels from the center of each menu item's icon to the
+ center of the menu. A higher value means that the icons will be further
+ from the center of the menu.
+ */
+ readonly property real __iconOffset: cancelRadius + ((radius - cancelRadius) / 2)
+
+ /*! \internal */
+ readonly property real __selectableRadius: radius - cancelRadius
+
+ /*! \internal */
+ property int __implicitWidth: Math.round(TextSingleton.implicitHeight * 12.5)
+
+ /*! \internal */
+ property int __implicitHeight: __implicitWidth
+
+ /*!
+ The background of the menu.
+
+ By default, there is no background defined.
+ */
+ property Component background
+
+ /*!
+ The cancel component of the menu.
+
+ This is an area in the center of the menu that closes the menu when
+ clicked.
+
+ By default, it is not visible.
+ */
+ property Component cancel: null
+
+ /*!
+ The component that displays the text of the currently selected menu
+ item, or the title if there is no current item.
+
+ The current item's text is available via the \c styleData.text
+ property.
+ */
+ property Component title: Text {
+ font.pointSize: 20
+ text: styleData.text
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ color: "#ccc"
+ antialiasing: true
+ }
+
+ /*!
+ This component defines each section of the pie menu.
+
+ This component covers the width and height of the control.
+
+ No mouse events are propagated to this component, which means that
+ controls like Button will not function when used within it. You can
+ check if the mouse is over this section by comparing
+ \c control.currentIndex to \c styleData.index.
+
+ Each instance of this component has access to the following properties:
+
+ \table
+ \row \li \c {readonly property int} \b styleData.index
+ \li The index of this menu item.
+ \row \li \c {readonly property bool} \b styleData.hovered
+ \li \c true if this menu item is under the mouse.
+ \row \li \c {readonly property bool} \b styleData.pressed
+ \li \c true if the mouse is pressed down on this menu item.
+ \endtable
+ */
+ property Component menuItem: Item {
+ id: actionRootDelegateItem
+
+ function drawRingSection(ctx, x, y, section, r, ringWidth, ringColor) {
+ ctx.fillStyle = ringColor;
+
+ // Draw one section.
+ ctx.beginPath();
+ ctx.moveTo(x,y);
+
+ // Canvas draws 0 degrees at 3 o'clock, whereas we want it to draw it at 12.
+ var start = control.__protectedScope.sectionStartAngle(section);
+ var end = control.__protectedScope.sectionEndAngle(section);
+ ctx.arc(x, y, r, start, end, start > end);
+ ctx.fill();
+
+ // Either change this to the background color, or use the global composition.
+ ctx.fillStyle = "black";
+ ctx.globalCompositeOperation = "destination-out";
+ ctx.beginPath();
+ ctx.moveTo(x, y);
+ ctx.arc(x, y, ringWidth, 0, Math.PI * 2);
+ ctx.closePath();
+ ctx.fill();
+
+ // If using the global composition method, make sure to change it back to default.
+ ctx.globalCompositeOperation = "source-over";
+ }
+
+ Canvas {
+ id: actionCanvas
+ anchors.fill: parent
+ property color currentColor: control.currentIndex === styleData.index ? selectionColor : backgroundColor
+
+ Connections {
+ target: pieMenuStyle
+ onStartAngleChanged: actionCanvas.requestPaint()
+ onEndAngleChanged: actionCanvas.requestPaint()
+ }
+
+ Connections {
+ target: control
+ onCurrentIndexChanged: actionCanvas.requestPaint()
+ }
+
+ onPaint: {
+ var ctx = getContext("2d");
+ ctx.reset();
+ drawRingSection(ctx, width / 2, height / 2, styleData.index, radius, cancelRadius, currentColor);
+ }
+ }
+
+ readonly property var __styleData: styleData
+
+ PieMenuIcon {
+ control: pieMenuStyle.control
+ styleData: __styleData
+ }
+ }
+
+ /*! \internal */
+ property Component panel: Item {
+ implicitWidth: __implicitWidth
+ implicitHeight: __implicitHeight
+
+ property alias titleItem: titleLoader.item
+
+ Item {
+ id: itemgroup
+ anchors.fill: parent
+ visible: false
+
+ Loader {
+ id: backgroundLoader
+ sourceComponent: background
+ anchors.fill: parent
+ }
+
+ Loader {
+ id: cancelLoader
+ sourceComponent: cancel
+ anchors.centerIn: parent
+ }
+
+ Repeater {
+ id: menuItemRepeater
+ model: control.__protectedScope.visibleItems
+
+ delegate: Loader {
+ id: menuItemLoader
+ anchors.fill: parent
+ sourceComponent: menuItem
+
+ readonly property int __index: index
+ property QtObject styleData: QtObject {
+ readonly property alias index: menuItemLoader.__index
+ readonly property bool hovered: control.currentIndex === index
+ readonly property bool pressed: control.__protectedScope.pressedIndex === index
+ }
+ }
+ }
+ }
+ DropShadow {
+ id: dropShadow
+ anchors.fill: itemgroup
+ fast: true
+ radius: shadowRadius
+ spread: shadowSpread
+ transparentBorder: true
+ samples: 12
+ color: shadowColor
+ source: itemgroup
+ }
+
+ Loader {
+ id: titleLoader
+ sourceComponent: title
+ x: parent.x + parent.width / 2 - width / 2
+ y: -height - 10
+
+ property QtObject styleData: QtObject {
+ property string text: control.currentIndex !== -1
+ ? control.__protectedScope.visibleItems[control.currentIndex].text
+ : control.title
+ }
+ }
+ }
+}
diff --git a/src/controls/Styles/Base/StatusIndicatorStyle.qml b/src/controls/Styles/Base/StatusIndicatorStyle.qml
new file mode 100644
index 00000000..62ed1038
--- /dev/null
+++ b/src/controls/Styles/Base/StatusIndicatorStyle.qml
@@ -0,0 +1,233 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Extras module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtGraphicalEffects 1.0
+import QtQuick.Controls.Private 1.0
+import QtQuick.Extras 1.4
+
+/*!
+ \qmltype StatusIndicatorStyle
+ \inqmlmodule QtQuick.Controls.Styles
+ \since 5.5
+ \ingroup controlsstyling
+ \brief Provides custom styling for StatusIndicatorStyle.
+
+ You can create a custom status indicator by defining the \l indicator
+ component.
+*/
+
+Style {
+ id: pieMenuStyle
+
+ /*!
+ The \l StatusIndicator that this style is attached to.
+ */
+ readonly property StatusIndicator control: __control
+
+ /*!
+ The color that instances of
+ \l {QtQuick.Extras::}{StatusIndicator} will have.
+ The \l {QtQuick.Extras::StatusIndicator::}{color}
+ property in \l {QtQuick.Extras::}{StatusIndicator}
+ will override this property when set.
+ */
+ property color color: "red"
+
+ /*!
+ This defines the indicator in both its on and off status.
+ */
+ property Component indicator: Item {
+ readonly property real shineStep: 0.05
+ readonly property real smallestAxis: Math.min(control.width, control.height)
+ readonly property real shadowRadius: smallestAxis * 0.4
+ readonly property real outerRecessPercentage: 0.11
+ readonly property color offColor: Qt.rgba(0.13, 0.13, 0.13)
+ readonly property color baseColor: control.active ? control.color : offColor
+
+ implicitWidth: TextSingleton.implicitHeight * 2
+ implicitHeight: implicitWidth
+
+ Canvas {
+ id: backgroundCanvas
+ width: Math.min(parent.width, parent.height)
+ // height: width --- QTBUG-42878
+ height: Math.min(parent.width, parent.height)
+ anchors.centerIn: parent
+
+ Connections {
+ target: control
+ onActiveChanged: backgroundCanvas.requestPaint()
+ onColorChanged: backgroundCanvas.requestPaint()
+ }
+
+ onPaint: {
+ var ctx = getContext("2d");
+ ctx.reset();
+
+ // Draw the semi-transparent background.
+ ctx.beginPath();
+ var gradient = ctx.createLinearGradient(width / 2, 0, width / 2, height * 0.75);
+ gradient.addColorStop(0.0, Qt.rgba(0, 0, 0, control.active ? 0.1 : 0.25));
+ gradient.addColorStop(1.0, control.active ? Qt.rgba(0, 0, 0, 0.1) : Qt.rgba(0.74, 0.74, 0.74, 0.25));
+
+ ctx.fillStyle = gradient;
+ ctx.ellipse(0, 0, width, height);
+ ctx.fill();
+ }
+ }
+
+ Item {
+ id: shadowGuard
+ anchors.fill: backgroundCanvas
+ anchors.margins: -shadowRadius
+
+ Canvas {
+ id: colorCanvas
+ anchors.fill: parent
+ anchors.margins: shadowRadius
+
+ Connections {
+ target: control
+ onActiveChanged: colorCanvas.requestPaint()
+ onColorChanged: colorCanvas.requestPaint()
+ }
+
+ onPaint: {
+ var ctx = getContext("2d");
+ ctx.reset();
+
+ // Draw the actual color within the circle.
+ ctx.beginPath();
+ ctx.fillStyle = baseColor;
+ var recess = smallestAxis * outerRecessPercentage;
+ ctx.ellipse(recess, recess, width - recess * 2, height - recess * 2);
+ ctx.fill();
+ }
+ }
+ }
+
+ DropShadow {
+ id: shadow
+ source: shadowGuard
+ color: control.color
+ // Don't set fast here because Qt < 5.3 will run into QTBUG-36931
+ radius: shadowRadius
+ samples: Math.min(32, radius)
+ cached: true
+ anchors.fill: shadowGuard
+ visible: control.active
+ }
+
+ Canvas {
+ id: foregroundCanvas
+ anchors.fill: backgroundCanvas
+
+ Connections {
+ target: control
+ onActiveChanged: foregroundCanvas.requestPaint()
+ onColorChanged: foregroundCanvas.requestPaint()
+ }
+
+ onPaint: {
+ var ctx = getContext("2d");
+ ctx.reset();
+
+ // Draw the first shine.
+ ctx.beginPath();
+ ctx.fillStyle = Qt.rgba(1, 1, 1, 0.03);
+ var recessPercentage = outerRecessPercentage + shineStep * 0.65;
+ var recess = smallestAxis * recessPercentage;
+ ctx.ellipse(recess, recess, width - recess * 2, height - recess * 2);
+ ctx.fill();
+
+ // Draw the second, inner shine.
+ ctx.beginPath();
+ ctx.fillStyle = Qt.rgba(1, 1, 1, 0.06);
+ recessPercentage += shineStep;
+ recess = smallestAxis * recessPercentage;
+ ctx.ellipse(recess, recess, width - recess * 2, height - recess * 2);
+ ctx.fill();
+
+ // Now draw the final arced shine that goes over the first and second shines.
+ // First, clip the entire shine area.
+ ctx.beginPath();
+ recessPercentage -= shineStep;
+ recess = smallestAxis * recessPercentage;
+ ctx.ellipse(recess, recess, width - recess * 2, height - recess * 2);
+ ctx.clip();
+
+ if (!control.active) {
+ // Then, clip the bottom area out of the shine.
+ ctx.ellipse(recess, height * 0.425, width - recess * 2, height - recess * 2);
+ ctx.clip();
+ }
+
+ ctx.beginPath();
+ var gradient;
+ if (!control.active) {
+ // Draw the shine arc.
+ gradient = ctx.createLinearGradient(width / 2, height * 0.2, width / 2, height * 0.65);
+ gradient.addColorStop(0.0, Qt.rgba(1, 1, 1, 0.05));
+ gradient.addColorStop(1.0, "transparent");
+ } else {
+ // Draw the radial shine.
+ gradient = ctx.createRadialGradient(width / 2, height / 2, width * 0.25, width / 2, height / 2, width * 0.25);
+ gradient.addColorStop(0.0, Qt.lighter(baseColor, 1.4));
+ gradient.addColorStop(1.0, "transparent");
+ }
+
+ ctx.fillStyle = gradient;
+ ctx.ellipse(recess, recess, width - recess * 2, height - recess * 2);
+ ctx.fill();
+ }
+ }
+ }
+
+ /*! \internal */
+ property Component panel: Item {
+ implicitWidth: indicatorLoader.implicitWidth
+ implicitHeight: indicatorLoader.implicitHeight
+
+ Loader {
+ id: indicatorLoader
+ width: Math.max(1, parent.width)
+ height: Math.max(1, parent.height)
+ anchors.centerIn: parent
+ sourceComponent: indicator
+ }
+ }
+}
diff --git a/src/controls/Styles/Base/ToggleButtonStyle.qml b/src/controls/Styles/Base/ToggleButtonStyle.qml
new file mode 100644
index 00000000..de06d72b
--- /dev/null
+++ b/src/controls/Styles/Base/ToggleButtonStyle.qml
@@ -0,0 +1,291 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Extras module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtGraphicalEffects 1.0
+import QtQuick.Controls.Styles 1.4
+import QtQuick.Extras 1.4
+import QtQuick.Extras.Private 1.0
+import QtQuick.Extras.Private.CppUtils 1.0
+
+/*!
+ \qmltype ToggleButtonStyle
+ \inqmlmodule QtQuick.Controls.Styles
+ \since 5.5
+ \ingroup controlsstyling
+ \brief Provides custom styling for ToggleButton.
+
+ You can create a custom toggle button by replacing the same delegates that
+ \l {QtQuick.Controls.Styles::ButtonStyle}{ButtonStyle} provides.
+*/
+
+CircularButtonStyle {
+ id: circularButtonStyle
+
+ /*!
+ The \l ToggleButton that this style is attached to.
+ */
+ readonly property ToggleButton control: __control
+
+ /*!
+ The gradient that is displayed on the inactive state indicator. The
+ inactive state indicator will be the checked gradient when the button
+ is unchecked, and the unchecked gradient when the button is checked.
+
+ \sa checkedGradient, uncheckedGradient
+ */
+ property Gradient inactiveGradient: Gradient {
+ GradientStop {
+ position: 0
+ color: commonStyleHelper.inactiveColor
+ }
+ GradientStop {
+ position: 1
+ color: commonStyleHelper.inactiveColorShine
+ }
+ }
+
+ /*!
+ The gradient that is displayed on the checked state indicator.
+
+ \sa uncheckedGradient, inactiveGradient
+ */
+ property Gradient checkedGradient: Gradient {
+ GradientStop {
+ position: 0
+ color: commonStyleHelper.onColor
+ }
+ GradientStop {
+ position: 1
+ color: commonStyleHelper.onColorShine
+ }
+ }
+
+ /*!
+ The gradient that is displayed on the unchecked state indicator.
+
+ \sa checkedGradient, inactiveGradient
+ */
+ property Gradient uncheckedGradient: Gradient {
+ GradientStop {
+ position: 0
+ color: commonStyleHelper.offColor
+ }
+ GradientStop {
+ position: 1
+ color: commonStyleHelper.offColorShine
+ }
+ }
+
+ /*!
+ The color that is used for the drop shadow below the checked state
+ indicator.
+
+ \sa uncheckedDropShadowColor
+ */
+ property color checkedDropShadowColor: commonStyleHelper.onColor
+
+ /*!
+ The color that is used for the drop shadow below the checked state
+ indicator.
+
+ \sa checkedDropShadowColor
+ */
+ property color uncheckedDropShadowColor: commonStyleHelper.offColor
+
+ CommonStyleHelper {
+ id: commonStyleHelper
+ }
+
+ background: Item {
+ implicitWidth: __buttonHelper.implicitWidth
+ implicitHeight: __buttonHelper.implicitHeight
+
+ Connections {
+ target: control
+ onPressedChanged: {
+ backgroundCanvas.requestPaint();
+ }
+
+ onCheckedChanged: {
+ uncheckedCanvas.requestPaint();
+ checkedCanvas.requestPaint();
+ }
+ }
+
+ Connections {
+ target: circularButtonStyle
+
+ onCheckedGradientChanged: checkedCanvas.requestPaint()
+ onCheckedDropShadowColorChanged: checkedCanvas.requestPaint()
+ onUncheckedGradientChanged: uncheckedCanvas.requestPaint()
+ onUncheckedDropShadowColorChanged: uncheckedCanvas.requestPaint()
+ onInactiveGradientChanged: {
+ checkedCanvas.requestPaint();
+ uncheckedCanvas.requestPaint();
+ }
+ }
+
+ Connections {
+ target: circularButtonStyle.checkedGradient
+ onUpdated: checkedCanvas.requestPaint()
+ }
+
+ Connections {
+ target: circularButtonStyle.uncheckedGradient
+ onUpdated: uncheckedCanvas.requestPaint()
+ }
+
+ Connections {
+ target: circularButtonStyle.inactiveGradient
+ onUpdated: {
+ uncheckedCanvas.requestPaint();
+ checkedCanvas.requestPaint();
+ }
+ }
+
+ Canvas {
+ id: backgroundCanvas
+ anchors.fill: parent
+
+ onPaint: {
+ var ctx = getContext("2d");
+ __buttonHelper.paintBackground(ctx);
+ }
+ }
+
+ Canvas {
+ id: uncheckedCanvas
+ anchors.fill: parent
+ anchors.margins: -(__buttonHelper.radius * 3)
+ visible: control.checked
+
+ readonly property real xCenter: width / 2
+ readonly property real yCenter: height / 2
+
+ onPaint: {
+ var ctx = getContext("2d");
+ ctx.reset();
+
+ /* Draw unchecked indicator */
+ ctx.beginPath();
+ ctx.lineWidth = __buttonHelper.outerArcLineWidth - __buttonHelper.innerArcLineWidth;
+ ctx.arc(xCenter, yCenter, __buttonHelper.outerArcRadius + __buttonHelper.innerArcLineWidth / 2,
+ MathUtils.degToRad(180), MathUtils.degToRad(270), false);
+ var gradient = ctx.createLinearGradient(xCenter, yCenter + __buttonHelper.radius,
+ xCenter, yCenter - __buttonHelper.radius);
+ var relevantGradient = control.checked ? inactiveGradient : uncheckedGradient;
+ for (var i = 0; i < relevantGradient.stops.length; ++i) {
+ gradient.addColorStop(relevantGradient.stops[i].position, relevantGradient.stops[i].color);
+ }
+ ctx.strokeStyle = gradient;
+ ctx.stroke();
+ }
+ }
+
+ Canvas {
+ id: checkedCanvas
+ anchors.fill: parent
+ anchors.margins: -(__buttonHelper.radius * 3)
+ visible: !control.checked
+
+ readonly property real xCenter: width / 2
+ readonly property real yCenter: height / 2
+
+ onPaint: {
+ var ctx = getContext("2d");
+ ctx.reset();
+
+ /* Draw checked indicator */
+ ctx.beginPath();
+ ctx.lineWidth = __buttonHelper.outerArcLineWidth - __buttonHelper.innerArcLineWidth;
+ ctx.arc(xCenter, yCenter, __buttonHelper.outerArcRadius + __buttonHelper.innerArcLineWidth / 2,
+ MathUtils.degToRad(270), MathUtils.degToRad(0), false);
+ var gradient = ctx.createLinearGradient(xCenter, yCenter + __buttonHelper.radius,
+ xCenter, yCenter - __buttonHelper.radius);
+ var relevantGradient = control.checked ? checkedGradient : inactiveGradient;
+ for (var i = 0; i < relevantGradient.stops.length; ++i) {
+ gradient.addColorStop(relevantGradient.stops[i].position, relevantGradient.stops[i].color);
+ }
+ ctx.strokeStyle = gradient;
+ ctx.stroke();
+ }
+ }
+
+ DropShadow {
+ id: uncheckedDropShadow
+ anchors.fill: uncheckedCanvas
+ cached: true
+ radius: 4
+ samples: 8
+ color: uncheckedDropShadowColor
+ source: uncheckedCanvas
+ visible: !control.checked
+ }
+
+ DropShadow {
+ id: checkedDropShadow
+ anchors.fill: checkedCanvas
+ cached: true
+ radius: 4
+ samples: 8
+ color: checkedDropShadowColor
+ source: checkedCanvas
+ visible: control.checked
+ }
+ }
+
+ panel: Item {
+ implicitWidth: backgroundLoader.implicitWidth
+ implicitHeight: backgroundLoader.implicitHeight
+
+ Loader {
+ id: backgroundLoader
+ anchors.fill: parent
+ sourceComponent: background
+ }
+
+ Loader {
+ id: labelLoader
+ sourceComponent: label
+ anchors.fill: parent
+ anchors.leftMargin: padding.left
+ anchors.topMargin: padding.top
+ anchors.rightMargin: padding.right
+ anchors.bottomMargin: padding.bottom
+ }
+ }
+}
diff --git a/src/controls/Styles/Base/TumblerStyle.qml b/src/controls/Styles/Base/TumblerStyle.qml
new file mode 100644
index 00000000..2661837e
--- /dev/null
+++ b/src/controls/Styles/Base/TumblerStyle.qml
@@ -0,0 +1,328 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Extras module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtGraphicalEffects 1.0
+import QtQuick.Controls 1.4
+import QtQuick.Controls.Styles 1.4
+import QtQuick.Controls.Private 1.0
+import QtQuick.Extras 1.4
+import QtQuick.Extras.Private 1.0
+
+/*!
+ \qmltype TumblerStyle
+ \inqmlmodule QtQuick.Controls.Styles
+ \since 5.5
+ \ingroup controlsstyling
+ \brief Provides custom styling for Tumbler.
+
+ \note TumblerStyle requires Qt 5.3.2 or later.
+
+ You can create a custom tumbler by replacing the following delegates:
+ \list
+ \li \l background
+ \li \l foreground
+ \li \l separator
+ \li \l delegate
+ \li \l highlight
+ \li \l frame
+ \endlist
+*/
+
+Style {
+ id: tumblerStyle
+
+ padding.left: __padding
+ padding.right: __padding
+ padding.top: __padding
+ padding.bottom: __padding
+
+ /*!
+ The \l Tumbler that this style is attached to.
+ */
+ readonly property Tumbler control: __control
+
+ /*!
+ This property holds the spacing between each delegate.
+ */
+ property real spacing: 0
+
+ /*!
+ This property holds the amount of items visible in each column.
+
+ This value should be an odd number.
+ */
+ property int visibleItemCount: 3
+
+ /*!
+ \internal
+
+ TODO: how do we handle differing padding values?
+ */
+ readonly property real __padding: Math.max(6, Math.round(TextSingleton.implicitHeight * 0.4))
+ /*! \internal */
+ property real __delegateHeight: 0
+ /*! \internal */
+ property real __separatorWidth: 0
+
+ /*!
+ The background of the tumbler.
+ */
+ property Component background: Rectangle {
+ gradient: Gradient {
+ GradientStop { position: 0.00; color: "#acacac" }
+ GradientStop { position: 0.12; color: "#d5d5d5" }
+ GradientStop { position: 0.24; color: "#e8e8e8" }
+ GradientStop { position: 0.39; color: "#ffffff" }
+ GradientStop { position: 0.61; color: "#ffffff" }
+ GradientStop { position: 0.76; color: "#e8e8e8" }
+ GradientStop { position: 0.88; color: "#d5d5d5" }
+ GradientStop { position: 1.00; color: "#acacac" }
+ }
+ }
+
+ /*!
+ The foreground of the tumbler.
+ */
+ property Component foreground: Item {
+ clip: true
+
+ Rectangle {
+ id: rect
+ anchors.fill: parent
+ // Go one pixel larger than our parent so that we can hide our one pixel frame
+ // that the shadow is created from.
+ anchors.margins: -1
+ color: "transparent"
+ border.color: "black"
+ visible: false
+ }
+
+ DropShadow {
+ anchors.fill: rect
+ source: rect
+ radius: __padding
+ samples: Math.min(32, radius * 2)
+ }
+ }
+
+ /*!
+ The separator between each column.
+
+ The \l {Item::}{implicitWidth} property must be set, and should be the
+ same value for each separator.
+ */
+ property Component separator: Canvas {
+ implicitWidth: Math.max(10, Math.round(TextSingleton.implicitHeight * 0.4))
+
+ onPaint: {
+ var ctx = getContext("2d");
+ ctx.reset();
+
+ ctx.fillStyle = "#11000000";
+ ctx.fillRect(0, 0, width, height);
+ ctx.fillStyle = "#11000000";
+ ctx.fillRect(width * 0.2, 0, width * 0.6, height);
+ ctx.fillStyle = "#66000000";
+ ctx.fillRect(width * 0.4, 0, width * 0.2, height);
+ }
+ }
+
+ /*!
+ The foreground of each column.
+
+ In terms of stacking order, this component is displayed above the
+ delegate and highlight components, but below the foreground component.
+
+ \table
+ \row \li \c {readonly property int} \b styleData.column
+ \li The index of the column that contains this item.
+ \row \li \c {readonly property bool} \b styleData.activeFocus
+ \li \c true if the column that contains this item has active focus.
+
+ \endtable
+
+ Delegates for items in specific columns can be defined using
+ TumblerColumn's \l {TumblerColumn::columnForeground}{columnForeground}
+ property, which will be used instead of this component.
+ */
+ property Component columnForeground
+
+ /*!
+ The frame around the tumbler.
+
+ The \l {Item::}{implicitWidth} property must be set, and should be the
+ same value for each separator.
+ */
+ property Component frame: Canvas {
+ onPaint: {
+ // workaround for QTBUG-40792
+ var ctx = getContext("2d");
+ ctx.reset();
+
+ var cornerRadius = Math.max(2, Math.round(TextSingleton.implicitHeight * 0.2));
+ var outerLineWidth = Math.max(1, Math.round(TextSingleton.implicitHeight * 0.05));
+ var innerLineWidth = __padding - outerLineWidth;
+
+ ctx.save();
+ ctx.lineWidth = outerLineWidth;
+ ctx.beginPath();
+ ctx.roundedRect(0, 0, width, height, cornerRadius, cornerRadius);
+ ctx.roundedRect(outerLineWidth, outerLineWidth, width - outerLineWidth * 2, height - outerLineWidth * 2,
+ cornerRadius - outerLineWidth, cornerRadius - outerLineWidth);
+ ctx.clip();
+
+ ctx.beginPath();
+ ctx.rect(0, 0, width, height);
+ var gradient = ctx.createLinearGradient(width / 2, 0, width / 2, height);
+ gradient.addColorStop(0, "#33b3b3b3");
+ gradient.addColorStop(1, "#4ce6e6e6");
+ ctx.fillStyle = gradient;
+ ctx.fill();
+ ctx.restore();
+
+ // The inner stroke must account for its corner radius.
+ cornerRadius -= outerLineWidth;
+
+ ctx.save();
+ ctx.lineWidth = innerLineWidth;
+ ctx.beginPath();
+ ctx.roundedRect(outerLineWidth, outerLineWidth, width - outerLineWidth * 2, height - outerLineWidth * 2,
+ cornerRadius, cornerRadius);
+ ctx.roundedRect(outerLineWidth + innerLineWidth, outerLineWidth + innerLineWidth,
+ width - outerLineWidth * 2 - innerLineWidth * 2, height - outerLineWidth * 2 - innerLineWidth * 2,
+ cornerRadius - innerLineWidth, cornerRadius - innerLineWidth);
+ ctx.clip();
+
+ ctx.beginPath();
+ ctx.rect(0, 0, width, height);
+ gradient = ctx.createLinearGradient(width / 2, 0, width / 2, height);
+ gradient.addColorStop(0, "#4c666666");
+ gradient.addColorStop(1, "#40cccccc");
+ ctx.fillStyle = gradient;
+ ctx.fill();
+ ctx.restore();
+ }
+ }
+
+ /*!
+ The delegate provides a template defining each item instantiated in the
+ column. Each instance of this component has access to the following properties:
+
+ \table
+ \row \li \c {readonly property int} \b styleData.index
+ \li The index of this delegate in the model.
+ \row \li \c {readonly property int} \b styleData.column
+ \li The index of the column that contains this item.
+ \row \li \c {readonly property real} \b styleData.value
+ \li The value for this delegate from the model.
+ \row \li \c {readonly property bool} \b styleData.current
+ \li \c true if this delegate is the current item.
+ \row \li \c {readonly property real} \b styleData.displacement
+ \li \c A value from \c {-visibleItemCount / 2} to
+ \c {visibleItemCount / 2} which represents how far away
+ this item is from being the current item, with \c 0 being
+ completely current.
+
+ For example, the item below will be 40% opaque when
+ it is not the current item, and transition to 100%
+ opacity when it becomes the current item:
+
+ \code
+ delegate: Text {
+ text: styleData.value
+ opacity: 0.4 + Math.max(0, 1 - Math.abs(styleData.displacement)) * 0.6
+ }
+ \endcode
+ \row \li \c {readonly property bool} \b styleData.activeFocus
+ \li \c true if the column that contains this item has active focus.
+
+ \endtable
+
+ Properties of the model are also available depending upon the type of
+ \l {qml-data-models}{Data Model}.
+
+ Delegates for items in specific columns can be defined using
+ TumblerColumn's \l {TumblerColumn::delegate}{delegate} property, which
+ will be used instead of this delegate.
+
+ The \l {Item::}{implicitHeight} property must be set, and it must be
+ the same for each delegate.
+ */
+ property Component delegate: Item {
+ implicitHeight: (control.height - padding.top - padding.bottom) / tumblerStyle.visibleItemCount
+
+ Text {
+ id: label
+ text: styleData.value
+ color: "#666666"
+ opacity: 0.4 + Math.max(0, 1 - Math.abs(styleData.displacement)) * 0.6
+ font.pixelSize: Math.round(TextSingleton.font.pixelSize * 1.25)
+ anchors.centerIn: parent
+ }
+ }
+
+ /*!
+ The delegate for the highlight of each column.
+
+ Delegates for the highlight of specific columns can be defined using
+ TumblerColumn's \l {TumblerColumn::highlight}{highlight} property,
+ which will be used instead of this delegate.
+
+ Each instance of this component has access to the following properties:
+
+ \table
+ \row \li \c {readonly property int} \b styleData.index
+ \li The index of this column in the tumbler.
+ \row \li \c {readonly property int} \b styleData.columnIndex
+ \li The index of the column that contains this highlight.
+ \row \li \c {readonly property bool} \b styleData.activeFocus
+ \li \c true if the column that contains this highlight has active focus.
+ \endtable
+ */
+ property Component highlight
+
+ /*! \internal */
+ property Component panel: Item {
+ implicitWidth: {
+ var w = (__separatorWidth * (control.columnCount - 1)) + tumblerStyle.padding.left + tumblerStyle.padding.right;
+ for (var i = 0; i < control.columnCount; ++i)
+ w += control.getColumn(i).width;
+ return w;
+ }
+ implicitHeight: TextSingleton.implicitHeight * 10 + tumblerStyle.padding.top + tumblerStyle.padding.bottom
+ }
+}
diff --git a/src/controls/Styles/Base/images/knob.png b/src/controls/Styles/Base/images/knob.png
new file mode 100644
index 00000000..ecac4d09
--- /dev/null
+++ b/src/controls/Styles/Base/images/knob.png
Binary files differ
diff --git a/src/controls/Styles/Base/images/needle.png b/src/controls/Styles/Base/images/needle.png
new file mode 100644
index 00000000..8237e516
--- /dev/null
+++ b/src/controls/Styles/Base/images/needle.png
Binary files differ
diff --git a/src/controls/Styles/qmldir b/src/controls/Styles/qmldir
index 582a7898..4b2f9844 100644
--- a/src/controls/Styles/qmldir
+++ b/src/controls/Styles/qmldir
@@ -20,4 +20,19 @@ TextAreaStyle 1.1 Base/TextAreaStyle.qml
TextFieldStyle 1.0 Base/TextFieldStyle.qml
ToolBarStyle 1.0 Base/ToolBarStyle.qml
StatusBarStyle 1.0 Base/StatusBarStyle.qml
+
+CircularGaugeStyle 1.0 Base/CircularGaugeStyle.qml
+CircularButtonStyle 1.0 Base/CircularButtonStyle.qml
+CircularTickmarkLabelStyle 1.0 Base/CircularTickmarkLabelStyle.qml
+CommonStyleHelper 1.0 Base/CommonStyleHelper.qml
+DelayButtonStyle 1.0 Base/DelayButtonStyle.qml
+DialStyle 1.1 Base/DialStyle.qml
+GaugeStyle 1.0 Base/GaugeStyle.qml
+HandleStyle 1.0 Base/HandleStyle.qml
+HandleStyleHelper 1.0 Base/HandleStyleHelper.qml
+PieMenuStyle 1.3 Base/PieMenuStyle.qml
+StatusIndicatorStyle 1.1 Base/StatusIndicatorStyle.qml
+ToggleButtonStyle 1.0 Base/ToggleButtonStyle.qml
+TumblerStyle 1.2 Base/TumblerStyle.qml
+
designersupported
diff --git a/src/controls/Styles/styles.pri b/src/controls/Styles/styles.pri
index f91a9d1a..eaad43ea 100644
--- a/src/controls/Styles/styles.pri
+++ b/src/controls/Styles/styles.pri
@@ -27,6 +27,22 @@ STYLES_QML_FILES = \
$$PWD/Base/ToolBarStyle.qml \
$$PWD/Base/ToolButtonStyle.qml
+# Extras
+STYLES_QML_FILES += \
+ $$PWD/Base/CircularGaugeStyle.qml \
+ $$PWD/Base/CircularButtonStyle.qml \
+ $$PWD/Base/CircularTickmarkLabelStyle.qml \
+ $$PWD/Base/CommonStyleHelper.qml \
+ $$PWD/Base/DelayButtonStyle.qml \
+ $$PWD/Base/DialStyle.qml \
+ $$PWD/Base/GaugeStyle.qml \
+ $$PWD/Base/HandleStyle.qml \
+ $$PWD/Base/HandleStyleHelper.qml \
+ $$PWD/Base/PieMenuStyle.qml \
+ $$PWD/Base/StatusIndicatorStyle.qml \
+ $$PWD/Base/ToggleButtonStyle.qml \
+ $$PWD/Base/TumblerStyle.qml
+
# Desktop
!no_desktop {
STYLES_QML_FILES += \
@@ -88,7 +104,9 @@ STYLES_QML_FILES += \
$$PWD/Base/images/spinner_medium.png \
$$PWD/Base/images/spinner_large.png \
$$PWD/Base/images/check.png \
- $$PWD/Base/images/check@2x.png
+ $$PWD/Base/images/check@2x.png \
+ $$PWD/Base/images/knob.png \
+ $$PWD/Base/images/needle.png
STYLES_QML_FILES += $$PWD/qmldir
diff --git a/src/controls/Switch.qml b/src/controls/Switch.qml
index abfb79b0..d416b7f3 100644
--- a/src/controls/Switch.qml
+++ b/src/controls/Switch.qml
@@ -159,5 +159,5 @@ Control {
\codeline Qt.createComponent("path/to/style.qml", switchId);
*/
- style: Qt.createComponent(Settings.style + "/SwitchStyle.qml", root)
+ style: Settings.styleComponent(Settings.style, "SwitchStyle.qml", root)
}
diff --git a/src/controls/TabView.qml b/src/controls/TabView.qml
index ebab068a..ea8bf4bd 100644
--- a/src/controls/TabView.qml
+++ b/src/controls/TabView.qml
@@ -176,7 +176,7 @@ FocusScope {
property ListModel __tabs: ListModel { }
/*! \internal */
- property Component style: Qt.createComponent(Settings.style + "/TabViewStyle.qml", root)
+ property Component style: Settings.styleComponent(Settings.style, "TabViewStyle.qml", root)
/*! \internal */
property var __styleItem: loader.item
diff --git a/src/controls/TableView.qml b/src/controls/TableView.qml
index 198ec3c7..e4357739 100644
--- a/src/controls/TableView.qml
+++ b/src/controls/TableView.qml
@@ -281,7 +281,7 @@ BasicTableView {
onModelChanged: selection.clear()
- style: Qt.createComponent(Settings.style + "/TableViewStyle.qml", root)
+ style: Settings.styleComponent(Settings.style, "TableViewStyle.qml", root)
Accessible.role: Accessible.Table
diff --git a/src/controls/TextArea.qml b/src/controls/TextArea.qml
index 0199cc81..c141f9e2 100644
--- a/src/controls/TextArea.qml
+++ b/src/controls/TextArea.qml
@@ -695,7 +695,7 @@ ScrollView {
Accessible.role: Accessible.EditableText
- style: Qt.createComponent(Settings.style + "/TextAreaStyle.qml", area)
+ style: Settings.styleComponent(Settings.style, "TextAreaStyle.qml", area)
/*!
\qmlproperty TextDocument TextArea::textDocument
diff --git a/src/controls/TextField.qml b/src/controls/TextField.qml
index 078fee2d..db42cfb7 100644
--- a/src/controls/TextField.qml
+++ b/src/controls/TextField.qml
@@ -611,7 +611,7 @@ Control {
/*! \internal */
property alias __baselineOffset: textInput.baselineOffset
- style: Qt.createComponent(Settings.style + "/TextFieldStyle.qml", textInput)
+ style: Settings.styleComponent(Settings.style, "TextFieldStyle.qml", textInput)
activeFocusOnTab: true
diff --git a/src/controls/ToolBar.qml b/src/controls/ToolBar.qml
index 796d25dd..48f62f16 100644
--- a/src/controls/ToolBar.qml
+++ b/src/controls/ToolBar.qml
@@ -100,7 +100,7 @@ FocusScope {
+ Math.max(container.layoutHeight, __panel ? __panel.implicitHeight : 0)
/*! \internal */
- property Component style: Qt.createComponent(Settings.style + "/ToolBarStyle.qml", toolbar)
+ property Component style: Settings.styleComponent(Settings.style, "ToolBarStyle.qml", toolbar)
/*! \internal */
property alias __style: styleLoader.item
diff --git a/src/controls/ToolButton.qml b/src/controls/ToolButton.qml
index e98f7ffd..a9904e11 100644
--- a/src/controls/ToolButton.qml
+++ b/src/controls/ToolButton.qml
@@ -80,5 +80,5 @@ import QtQuick.Controls.Private 1.0
Button {
id: button
- style: Qt.createComponent(Settings.style + "/ToolButtonStyle.qml", button)
+ style: Settings.styleComponent(Settings.style, "ToolButtonStyle.qml", button)
}
diff --git a/src/controls/TreeView.qml b/src/controls/TreeView.qml
index 8aaf3bbf..f1175b72 100644
--- a/src/controls/TreeView.qml
+++ b/src/controls/TreeView.qml
@@ -252,7 +252,7 @@ BasicTableView {
modelAdaptor.expand(index)
}
- style: Qt.createComponent(Settings.style + "/TreeViewStyle.qml", root)
+ style: Settings.styleComponent(Settings.style, "TreeViewStyle.qml", root)
// Internal stuff. Do not look
diff --git a/src/controls/controls.pro b/src/controls/controls.pro
index 151ccb4b..7261b5c6 100644
--- a/src/controls/controls.pro
+++ b/src/controls/controls.pro
@@ -43,6 +43,8 @@ QML_FILES += $$CONTROLS_QML_FILES
SOURCES += $$PWD/plugin.cpp
HEADERS += $$PWD/plugin.h
+OTHER_FILES += doc/src/*
+
include(plugin.pri)
include(Private/private.pri)
include(Styles/styles.pri)
diff --git a/src/controls/doc/images/circulargauge-angles.png b/src/controls/doc/images/circulargauge-angles.png
new file mode 100644
index 00000000..fb93bcaa
--- /dev/null
+++ b/src/controls/doc/images/circulargauge-angles.png
Binary files differ
diff --git a/src/controls/doc/images/circulargauge-needle-example-2.png b/src/controls/doc/images/circulargauge-needle-example-2.png
new file mode 100644
index 00000000..a2b5f322
--- /dev/null
+++ b/src/controls/doc/images/circulargauge-needle-example-2.png
Binary files differ
diff --git a/src/controls/doc/images/circulargauge-needle.png b/src/controls/doc/images/circulargauge-needle.png
new file mode 100644
index 00000000..b2780b41
--- /dev/null
+++ b/src/controls/doc/images/circulargauge-needle.png
Binary files differ
diff --git a/src/controls/doc/images/circulargauge-reversed.png b/src/controls/doc/images/circulargauge-reversed.png
new file mode 100644
index 00000000..aeadfbcc
--- /dev/null
+++ b/src/controls/doc/images/circulargauge-reversed.png
Binary files differ
diff --git a/src/controls/doc/images/circulargauge-tickmark-indices-values.png b/src/controls/doc/images/circulargauge-tickmark-indices-values.png
new file mode 100644
index 00000000..d117f483
--- /dev/null
+++ b/src/controls/doc/images/circulargauge-tickmark-indices-values.png
Binary files differ
diff --git a/src/controls/doc/images/gauge-minorTickmark-example.png b/src/controls/doc/images/gauge-minorTickmark-example.png
new file mode 100644
index 00000000..591120d6
--- /dev/null
+++ b/src/controls/doc/images/gauge-minorTickmark-example.png
Binary files differ
diff --git a/src/controls/doc/images/gauge-temperature.png b/src/controls/doc/images/gauge-temperature.png
new file mode 100644
index 00000000..95fc1679
--- /dev/null
+++ b/src/controls/doc/images/gauge-temperature.png
Binary files differ
diff --git a/src/controls/doc/images/gauge-tickmark-example.png b/src/controls/doc/images/gauge-tickmark-example.png
new file mode 100644
index 00000000..c46fb8a5
--- /dev/null
+++ b/src/controls/doc/images/gauge-tickmark-example.png
Binary files differ
diff --git a/src/controls/doc/images/piemenu-menuitem-example.png b/src/controls/doc/images/piemenu-menuitem-example.png
new file mode 100644
index 00000000..57a2f956
--- /dev/null
+++ b/src/controls/doc/images/piemenu-menuitem-example.png
Binary files differ
diff --git a/src/controls/doc/images/styling-circulargauge-background-example.png b/src/controls/doc/images/styling-circulargauge-background-example.png
new file mode 100644
index 00000000..e816c6f6
--- /dev/null
+++ b/src/controls/doc/images/styling-circulargauge-background-example.png
Binary files differ
diff --git a/src/controls/doc/images/styling-circulargauge-knob-example.png b/src/controls/doc/images/styling-circulargauge-knob-example.png
new file mode 100644
index 00000000..793a36c2
--- /dev/null
+++ b/src/controls/doc/images/styling-circulargauge-knob-example.png
Binary files differ
diff --git a/src/controls/doc/images/styling-circulargauge-minorTickmark-example.png b/src/controls/doc/images/styling-circulargauge-minorTickmark-example.png
new file mode 100644
index 00000000..f3f2d8d7
--- /dev/null
+++ b/src/controls/doc/images/styling-circulargauge-minorTickmark-example.png
Binary files differ
diff --git a/src/controls/doc/images/styling-circulargauge-needle-example.png b/src/controls/doc/images/styling-circulargauge-needle-example.png
new file mode 100644
index 00000000..08049fc9
--- /dev/null
+++ b/src/controls/doc/images/styling-circulargauge-needle-example.png
Binary files differ
diff --git a/src/controls/doc/images/styling-circulargauge-tickmark-example.png b/src/controls/doc/images/styling-circulargauge-tickmark-example.png
new file mode 100644
index 00000000..01c71cd1
--- /dev/null
+++ b/src/controls/doc/images/styling-circulargauge-tickmark-example.png
Binary files differ
diff --git a/src/controls/doc/images/styling-circulargauge-tickmarkLabel-example.png b/src/controls/doc/images/styling-circulargauge-tickmarkLabel-example.png
new file mode 100644
index 00000000..7520827e
--- /dev/null
+++ b/src/controls/doc/images/styling-circulargauge-tickmarkLabel-example.png
Binary files differ
diff --git a/src/controls/doc/images/styling-gauge-font-size.png b/src/controls/doc/images/styling-gauge-font-size.png
new file mode 100644
index 00000000..97d7ebb2
--- /dev/null
+++ b/src/controls/doc/images/styling-gauge-font-size.png
Binary files differ
diff --git a/src/controls/doc/images/styling-gauge-foreground.png b/src/controls/doc/images/styling-gauge-foreground.png
new file mode 100644
index 00000000..5a4f65b9
--- /dev/null
+++ b/src/controls/doc/images/styling-gauge-foreground.png
Binary files differ
diff --git a/src/controls/doc/images/styling-gauge-minorTickmark.png b/src/controls/doc/images/styling-gauge-minorTickmark.png
new file mode 100644
index 00000000..34e36192
--- /dev/null
+++ b/src/controls/doc/images/styling-gauge-minorTickmark.png
Binary files differ
diff --git a/src/controls/doc/images/styling-gauge-tickmark.png b/src/controls/doc/images/styling-gauge-tickmark.png
new file mode 100644
index 00000000..1cd4fb8b
--- /dev/null
+++ b/src/controls/doc/images/styling-gauge-tickmark.png
Binary files differ
diff --git a/src/controls/doc/images/styling-gauge-valueBar.png b/src/controls/doc/images/styling-gauge-valueBar.png
new file mode 100644
index 00000000..581b8240
--- /dev/null
+++ b/src/controls/doc/images/styling-gauge-valueBar.png
Binary files differ
diff --git a/src/controls/doc/qtquickcontrols.qdocconf b/src/controls/doc/qtquickcontrols.qdocconf
index 6b4b14c7..8d41247e 100644
--- a/src/controls/doc/qtquickcontrols.qdocconf
+++ b/src/controls/doc/qtquickcontrols.qdocconf
@@ -28,12 +28,13 @@ qhp.QtQuickControls.subprojects.qtquickcontrolsstyles.title = Qt Quick Cont
qhp.QtQuickControls.subprojects.qtquickcontrolsstyles.indexTitle = Qt Quick Controls Styles Structure
qhp.QtQuickControls.subprojects.qtquickcontrolsstyles.type = manual
-depends = qtqml qtquick qtgui qtwidgets qtdoc qtquicklayouts qtquickdialogs qtcore
+depends = qtcore qtdoc qtgui qtwidgets qtqml qtquick qtquicklayouts qtquickdialogs qtquickextras
# Specify the install path under QT_INSTALL_EXAMPLES
# Examples will be installed under quick/controls - 'controls' subdirectory
# is given as part of \example commands
-exampledirs += ../../../examples/quick/controls
+exampledirs += ../../../examples/quick/controls \
+ snippets
examplesinstallpath = quick/controls
headerdirs += ../ \
@@ -54,7 +55,8 @@ sources += ../Private/AbstractCheckable.qml \
../Private/qquickabstractstyle.h \
../Private/qquickabstractstyle.cpp
-imagedirs += images
+imagedirs += images \
+ ../../extras/doc/images
navigation.landingpage = "Qt Quick Controls"
navigation.qmltypespage = "Qt Quick Controls QML Types"
diff --git a/src/controls/doc/snippets/circulargauge-background-range.qml b/src/controls/doc/snippets/circulargauge-background-range.qml
new file mode 100644
index 00000000..f218e916
--- /dev/null
+++ b/src/controls/doc/snippets/circulargauge-background-range.qml
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//! [range]
+import QtQuick 2.0
+import QtQuick.Controls 1.4
+import QtQuick.Controls.Styles 1.4
+import QtQuick.Extras 1.4
+import QtQuick.Extras.Private 1.0
+
+Rectangle {
+ width: 300
+ height: 300
+ color: "#494d53"
+
+ CircularGauge {
+ id: gauge
+ anchors.centerIn: parent
+ style: CircularGaugeStyle {
+ id: style
+
+ //! [background]
+ function degreesToRadians(degrees) {
+ return degrees * (Math.PI / 180);
+ }
+
+
+ background: Canvas {
+ onPaint: {
+ var ctx = getContext("2d");
+ ctx.reset();
+
+ ctx.beginPath();
+ ctx.strokeStyle = "#e34c22";
+ ctx.lineWidth = outerRadius * 0.02;
+
+ ctx.arc(outerRadius, outerRadius, outerRadius - ctx.lineWidth / 2,
+ degreesToRadians(valueToAngle(80) - 90), degreesToRadians(valueToAngle(100) - 90));
+ ctx.stroke();
+ }
+ }
+ //! [background]
+
+ //! [tickmark]
+ tickmark: Rectangle {
+ visible: styleData.value < 80 || styleData.value % 10 == 0
+ implicitWidth: outerRadius * 0.02
+ antialiasing: true
+ implicitHeight: outerRadius * 0.06
+ color: styleData.value >= 80 ? "#e34c22" : "#e5e5e5"
+ }
+ //! [tickmark]
+
+ //! [minorTickmark]
+ minorTickmark: Rectangle {
+ visible: styleData.value < 80
+ implicitWidth: outerRadius * 0.01
+ antialiasing: true
+ implicitHeight: outerRadius * 0.03
+ color: "#e5e5e5"
+ }
+ //! [minorTickmark]
+
+ //! [tickmarkLabel]
+ tickmarkLabel: Text {
+ font.pixelSize: Math.max(6, outerRadius * 0.1)
+ text: styleData.value
+ color: styleData.value >= 80 ? "#e34c22" : "#e5e5e5"
+ antialiasing: true
+ }
+ //! [tickmarkLabel]
+
+ //! [needle]
+ needle: Rectangle {
+ y: outerRadius * 0.15
+ implicitWidth: outerRadius * 0.03
+ implicitHeight: outerRadius * 0.9
+ antialiasing: true
+ color: "#e5e5e5"
+ }
+ //! [needle]
+
+ //! [foreground]
+ foreground: Item {
+ Rectangle {
+ width: outerRadius * 0.2
+ height: width
+ radius: width / 2
+ color: "#e5e5e5"
+ anchors.centerIn: parent
+ }
+ }
+ //! [foreground]
+ }
+ }
+}
+//! [range]
diff --git a/src/controls/doc/snippets/circulargauge-tickmark-indices-values.qml b/src/controls/doc/snippets/circulargauge-tickmark-indices-values.qml
new file mode 100644
index 00000000..d3afd6f4
--- /dev/null
+++ b/src/controls/doc/snippets/circulargauge-tickmark-indices-values.qml
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//! [tickmarks]
+import QtQuick 2.0
+import QtQuick.Controls.Styles 1.4
+import QtQuick.Extras 1.4
+
+Rectangle {
+ width: 400
+ height: 400
+
+ CircularGauge {
+ id: gauge
+ anchors.fill: parent
+ style: CircularGaugeStyle {
+ labelInset: outerRadius * 0.2
+
+ tickmarkLabel: null
+
+ tickmark: Text {
+ text: styleData.value
+
+ Text {
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.top: parent.bottom
+ text: styleData.index
+ color: "blue"
+ }
+ }
+
+ minorTickmark: Text {
+ text: styleData.value
+ font.pixelSize: 8
+
+ Text {
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.top: parent.bottom
+ text: styleData.index
+ font.pixelSize: 8
+ color: "blue"
+ }
+ }
+ }
+
+ Text {
+ id: indexText
+ text: "Major and minor indices"
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.bottom: valueText.top
+ color: "blue"
+ }
+ Text {
+ id: valueText
+ text: "Major and minor values"
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.bottom: parent.bottom
+ }
+ }
+}
+//! [tickmarks]
diff --git a/src/controls/doc/snippets/styling-gauge.qml b/src/controls/doc/snippets/styling-gauge.qml
new file mode 100644
index 00000000..e999832b
--- /dev/null
+++ b/src/controls/doc/snippets/styling-gauge.qml
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//! [all]
+import QtQuick 2.2
+import QtQuick.Controls 1.4
+import QtQuick.Controls.Styles 1.4
+import QtQuick.Extras 1.4
+
+Rectangle {
+ width: 100
+ height: 220
+ color: "#494d53"
+
+ Gauge {
+ value: 50
+ tickmarkStepSize: 20
+ minorTickmarkCount: 1
+ //! [font-size]
+ font.pixelSize: 15
+ //! [font-size]
+ anchors.centerIn: parent
+ anchors.horizontalCenterOffset: -4
+
+ style: GaugeStyle {
+ //! [valueBar]
+ valueBar: Rectangle {
+ color: "#e34c22"
+ implicitWidth: 28
+ }
+ //! [valueBar]
+
+ //! [foreground]
+ foreground: null
+ //! [foreground]
+
+ //! [tickmark]
+ tickmark: Item {
+ implicitWidth: 8
+ implicitHeight: 4
+
+ Rectangle {
+ x: control.tickmarkAlignment === Qt.AlignLeft
+ || control.tickmarkAlignment === Qt.AlignTop ? parent.implicitWidth : -28
+ width: 28
+ height: parent.height
+ color: "#ffffff"
+ }
+ }
+ //! [tickmark]
+
+ //! [minorTickmark]
+ minorTickmark: Item {
+ implicitWidth: 8
+ implicitHeight: 2
+
+ Rectangle {
+ x: control.tickmarkAlignment === Qt.AlignLeft
+ || control.tickmarkAlignment === Qt.AlignTop ? parent.implicitWidth : -28
+ width: 28
+ height: parent.height
+ color: "#ffffff"
+ }
+ }
+ //! [minorTickmark]
+ }
+ }
+}
+//! [all]
diff --git a/src/controls/doc/src/qtquickcontrolsstyles-index.qdoc b/src/controls/doc/src/qtquickcontrolsstyles-index.qdoc
index d9c813e4..59951190 100644
--- a/src/controls/doc/src/qtquickcontrolsstyles-index.qdoc
+++ b/src/controls/doc/src/qtquickcontrolsstyles-index.qdoc
@@ -48,6 +48,11 @@
\internal
*/
+/*!
+ \group stylingtutorials
+ \title Styling Tutorials
+*/
+
/*!
\page qtquickcontrolsstyles-index.html
@@ -66,12 +71,48 @@
import QtQuick.Controls.Styles 1.4
\endcode
+ \section1 Styles
+
+ \section2 Base Style
+
+ The Base Style is the default style used when none is specified. It is also
+ used as a fallback when the specified style cannot be found.
+
+ \image tumbler.png
+ \caption The Base Style Tumbler.
+
+ \section2 Flat Style
+
+ The Flat Style is designed for touch devices.
+
+ \image tumbler-flat-style.png
+ \caption The Flat Style Tumbler.
+
+ \section2 Selecting Styles
+
+ You can apply a different style to the controls by setting the
+ \e QT_QUICK_CONTROLS_STYLE environment variable to the name of the style.
+ For example, to use the Flat style, you can do the following:
+
+ \code
+ QT_QUICK_CONTROLS_STYLE=Flat ./app
+ \endcode
+
+ This can also be done in C++, using qputenv():
+
+ \code
+ qputenv("QT_QUICK_CONTROLS_STYLE", "Flat");
+ \endcode
+
\section1 Styling Views
\annotatedlist viewsstyling
\section1 Styling Controls
\annotatedlist controlsstyling
+ \section1 Styling Tutorials
+ \annotatedlist stylingtutorials
+
\section1 Related information
\list
diff --git a/src/controls/doc/src/styling-circulargauge.qdoc b/src/controls/doc/src/styling-circulargauge.qdoc
new file mode 100644
index 00000000..e0260db4
--- /dev/null
+++ b/src/controls/doc/src/styling-circulargauge.qdoc
@@ -0,0 +1,145 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \page styling-circulargauge.html
+ \title Styling CircularGauge
+ \brief Tutorial for styling CircularGauge.
+ \ingroup stylingtutorials
+
+ \target styling-circulargauge-needle
+ \section2 The Needle Component
+
+ The \l {QtQuick.Controls.Styles::CircularGaugeStyle::}{needle}
+ component is rotated around the gauge to represent the current value.
+
+ Starting from the default style, we'll add a very basic white needle:
+
+ \snippet circulargauge-background-range.qml needle
+
+ \image styling-circulargauge-needle-example.png
+
+ As mentioned in the documentation for \l {QtQuick.Controls.Styles::}
+ {CircularGaugeStyle}, \c implicitWidth
+ and \c implicitHeight properties need to be set. This is so that the needle
+ can be positioned properly. We always scale items by the
+ \l {QtQuick.Controls.Styles::CircularGaugeStyle::}{outerRadius}
+ property of the style, ensuring the control resizes gracefully.
+
+ We offset the needle vertically so that its back sits beyond the knob.
+
+ \target styling-circulargauge-foreground
+ \section2 The Foreground Component
+
+ We've now changed the needle, but the default knob is still there; let's
+ replace it. The \l {QtQuick.Controls.Styles::CircularGaugeStyle::}
+ {foreground} component defines the default knob, so we can specify our own by
+ overriding it (note that we could also set it to \c null if we didn't want a
+ foreground):
+
+ \snippet circulargauge-background-range.qml foreground
+
+ \image styling-circulargauge-knob-example.png
+
+ Firstly, we create a circle from the Rectangle item by setting the radius to
+ be half the width (either width or height will work here; they are always
+ equal in this case). We make it a child of the Item, because the foreground
+ fills the gauge. We then center it within the Item.
+
+ We set the color of the knob to the same white that we used before.
+
+ \target styling-circulargauge-tickmarkLabel
+ \section2 The Tickmark Label Component
+
+ Suppose we want to caution the user if the value displayed by the gauge goes
+ above or below a certain range. We could present this range to the user in
+ several ways:
+
+ \list A
+ \li Change the color of the tickmarks depending on \c styleData.value
+ \li Add an image to the background
+ \li Draw it with \l {QtQuick::}{Canvas}
+ \endlist
+
+ We'll choose options 1 and 3, as they are more flexible than using an
+ image.
+
+ Firstly, let's change the color of the three highest tickmark labels:
+
+ \snippet circulargauge-background-range.qml tickmarkLabel
+
+ \image styling-circulargauge-tickmarkLabel-example.png tickmarkLabel
+
+ We also change the color of the rest of the labels to the same white that
+ we used for the needle and knob.
+
+ \target styling-circulargauge-tickmark
+ \section2 The Tickmark Component
+
+ Now let's do the same for the three highest tickmarks:
+
+ \snippet circulargauge-background-range.qml tickmark
+
+ \image styling-circulargauge-tickmark-example.png tickmark
+
+ \target styling-circulargauge-minorTickmark
+ \section2 The Minor Tickmark Component
+
+ For the minor tickmarks, we'll only show those which are not higher than
+ \c 80:
+
+ \snippet circulargauge-background-range.qml minorTickmark
+
+ \image styling-circulargauge-minorTickmark-example.png minorTickmark
+
+ This is because we'll draw something between that range in the next section.
+
+ \target styling-circulargauge-background
+ \section2 The Background Component
+
+ We'll display the range that indicates caution with an orange arc:
+
+ \snippet circulargauge-background-range.qml background
+
+ We define a function to convert degrees to radians, which are the
+ units used by \l {QtQuick::}{Canvas}.
+
+ Next, we do the drawing of the range using Canvas. We draw an arc between
+ \c 80 and \c 100, using the
+ \l {QtQuick.Controls.Styles::CircularGaugeStyle::}{valueToAngle()}
+ function provided by CircularGaugeStyle. Note that we subtract \c 90 degrees
+ before converting to radians, as our origin is north and Canvas' is east.
+
+ The finished product:
+
+ \image styling-circulargauge-background-example.png background
+
+ The complete code for this example is as follows:
+
+ \snippet circulargauge-background-range.qml range
+*/
+
diff --git a/src/controls/doc/src/styling-gauge.qdoc b/src/controls/doc/src/styling-gauge.qdoc
new file mode 100644
index 00000000..195cc4c8
--- /dev/null
+++ b/src/controls/doc/src/styling-gauge.qdoc
@@ -0,0 +1,129 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \page styling-gauge.html
+ \title Styling Gauge
+ \brief Tutorial for styling the Gauge control.
+ \ingroup stylingtutorials
+
+ As GaugeStyle's documentation adequately covers common use cases, this
+ tutorial will cover a different scenario: one where the gauge's tickmarks
+ cover the value bar, instead of being aligned to the left or right of it.
+
+ \target styling-gauge-valueBar
+ \section2 The Value Bar Component
+
+ The \l {QtQuick.Controls.Styles::GaugeStyle::}{valueBar}
+ component is resized according to the gauge's value; if the value is low,
+ the bar will be small, and vice versa.
+
+ Starting from the default style, we'll change the color of the value bar to
+ orange, and increase its width slightly:
+
+ \snippet styling-gauge.qml valueBar
+
+ \image styling-gauge-valueBar.png
+
+ As mentioned in the documentation for GaugeStyle, \c implicitWidth needs to
+ be set when defining your own value bar.
+
+ \target styling-gauge-foreground
+ \section2 The Foreground Component
+
+ The \l {QtQuick.Controls.Styles::GaugeStyle::}{foreground}
+ component covers the full width and height of the value bar, even when the
+ value bar is not at its highest. By default, the foreground component
+ provides a "sheen". We'll choose to discard this, and leave it empty
+ instead:
+
+ \snippet styling-gauge.qml foreground
+
+ \image styling-gauge-foreground.png
+
+ \target styling-gauge-tickmark
+ \section2 The Tickmark Component
+
+ The \l {QtQuick.Controls.Styles::GaugeStyle::}{tickmark}
+ component sits to the left or right of the value bar, depending on the
+ control's \l {Gauge::tickmarkAlignment}{tickmarkAlignment}. In order to
+ have the tickmarks cover the width of the value bar instead, we need to do
+ two things:
+ \list 1
+ \li Remove the space the tickmarks previously assumed so that there is
+ just enough space for margins between the tickmarks and value bar.
+ \li Position the tickmarks according to the control's orientation and
+ tickmark alignment.
+ \endlist
+
+ \snippet styling-gauge.qml tickmark
+
+ In this case we chose \c 8 pixel margins, so we set the \c implicitWidth of
+ the tickmarks to that.
+
+ We account for every possible orientation and tickmark alignment, something
+ that is not necessary if the gauge will only ever have one orientation and
+ alignment. For example, if the gauge will always be of a vertical
+ orientation and the tickmarks left-aligned, then it is enough to set the
+ \c x property of the \c Rectangle to the following:
+
+ \code
+ x: parent.implicitWidth
+ \endcode
+
+ The value bar is \c 28 pixels wide, so we give the same width to our
+ tickmarks so that they cover the width of it.
+
+ \image styling-gauge-tickmark.png
+
+ \target styling-gauge-minorTickmark
+ \section2 The Minor Tickmark Component
+
+ The \l {QtQuick.Controls.Styles::GaugeStyle::}{minorTickmark}
+ component is almost identical to its larger counterpart, except that its
+ width does not affect the layout of the gauge's components. We'll do
+ similar adjustments to the ones in the previous section - the only
+ difference being the height:
+
+ \snippet styling-gauge.qml minorTickmark
+
+ \image styling-gauge-minorTickmark.png
+
+ \target styling-gauge-font-size
+ \section2 Adjusting Font Size
+
+ Finally, we increase the \l {Gauge::font}{font} size to \c 15 pixels:
+
+ \snippet styling-gauge.qml font-size
+ \image styling-gauge-font-size.png
+
+ \target styling-gauge-complete
+ \section2 Complete Source Code
+
+ \snippet styling-gauge.qml all
+*/
+