From c1d88b95f97a18443c60d62626e86b619cd84f34 Mon Sep 17 00:00:00 2001
From: Jens Bache-Wiig <jens.bache-wiig@digia.com>
Date: Mon, 19 Aug 2013 17:26:29 +0200
Subject: [PATCH] BusyIndicator

A basic BusyIndicator to indicate activity while blocking
the UI.

Change-Id: Iec88b6a4c7f23b630ebdf445c4cb288684c24cb7
Reviewed-by: J-P Nurmi <jpnurmi@digia.com>
---
 .../controls/gallery/content/Controls.qml     |  13 +-
 examples/quick/controls/gallery/main.qml      |   2 +-
 src/controls/BusyIndicator.qml                |  76 +++++++++++
 .../Styles/Base/BusyIndicatorStyle.qml        | 128 ++++++++++++++++++
 .../Styles/Desktop/BusyIndicatorStyle.qml     |  42 ++++++
 src/controls/Styles/qmldir                    |   1 +
 src/controls/Styles/styles.pri                |   2 +
 src/controls/controls.pro                     |   1 +
 src/controls/plugin.cpp                       |   4 +-
 tests/auto/controls/controls.pro              |   1 +
 .../auto/controls/data/tst_busyindicator.qml  |  62 +++++++++
 tests/manual/testbench/content/Components.qml |   4 +
 tests/manual/testbench/main.qml               |   1 +
 13 files changed, 334 insertions(+), 3 deletions(-)
 create mode 100644 src/controls/BusyIndicator.qml
 create mode 100644 src/controls/Styles/Base/BusyIndicatorStyle.qml
 create mode 100644 src/controls/Styles/Desktop/BusyIndicatorStyle.qml
 create mode 100644 tests/auto/controls/data/tst_busyindicator.qml

diff --git a/examples/quick/controls/gallery/content/Controls.qml b/examples/quick/controls/gallery/content/Controls.qml
index 19251fea6..946dd374b 100644
--- a/examples/quick/controls/gallery/content/Controls.qml
+++ b/examples/quick/controls/gallery/content/Controls.qml
@@ -43,7 +43,7 @@
 
 
 import QtQuick 2.1
-import QtQuick.Controls 1.0
+import QtQuick.Controls 1.1
 import QtQuick.Controls.Styles 1.0
 
 Item {
@@ -119,6 +119,17 @@ Item {
                 tickmarksEnabled: tickmarkCheck.checked
                 stepSize: tickmarksEnabled ? 0.1 : 0
             }
+            MouseArea {
+                id: busyCheck
+                width: parent.width
+                height: 40
+                hoverEnabled:true
+                BusyIndicator {
+                    running: busyCheck.containsMouse
+                    anchors.horizontalCenter: parent.horizontalCenter
+                }
+            }
+
         }
         Column {
             id: rightcol
diff --git a/examples/quick/controls/gallery/main.qml b/examples/quick/controls/gallery/main.qml
index 32e04efd6..4e5bb3787 100644
--- a/examples/quick/controls/gallery/main.qml
+++ b/examples/quick/controls/gallery/main.qml
@@ -43,7 +43,7 @@
 
 
 import QtQuick 2.2
-import QtQuick.Controls 1.0
+import QtQuick.Controls 1.1
 import QtQuick.Layouts 1.0
 import QtQuick.Dialogs 1.0
 import "content"
diff --git a/src/controls/BusyIndicator.qml b/src/controls/BusyIndicator.qml
new file mode 100644
index 000000000..bf8b09524
--- /dev/null
+++ b/src/controls/BusyIndicator.qml
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Quick Controls module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+**   * Redistributions of source code must retain the above copyright
+**     notice, this list of conditions and the following disclaimer.
+**   * Redistributions in binary form must reproduce the above copyright
+**     notice, this list of conditions and the following disclaimer in
+**     the documentation and/or other materials provided with the
+**     distribution.
+**   * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
+**     of its contributors may be used to endorse or promote products derived
+**     from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.1
+import QtQuick.Controls 1.1
+import QtQuick.Controls.Private 1.0
+
+/*!
+    \qmltype BusyIndicator
+    \inqmlmodule QtQuick.Controls 1.1
+    \since QtQuick.Controls 1.1
+    \ingroup controls
+    \brief A busy indicator.
+
+    The busy indicator should be used to indicate activity while content is
+    being loaded or the UI is blocked waiting for a resource to become available.
+
+    You can create a custom appearance for a Busy Indicator by
+    assigning a \l BusyIndicatorStyle.
+ */
+Control {
+    id: indicator
+
+    /*! \qmlproperty bool BusyIndicator::running
+
+    This property holds whether the busy indicator is currently indicating
+    activity.
+
+    \note The indicator is only visible when this property is set to \c true.
+
+    The default value is \c true.
+    */
+    property bool running: true
+
+    Accessible.role: Accessible.Indicator
+    Accessible.name: "busy"
+
+    style: Qt.createComponent(Settings.style + "/BusyIndicatorStyle.qml", indicator)
+}
diff --git a/src/controls/Styles/Base/BusyIndicatorStyle.qml b/src/controls/Styles/Base/BusyIndicatorStyle.qml
new file mode 100644
index 000000000..e03748833
--- /dev/null
+++ b/src/controls/Styles/Base/BusyIndicatorStyle.qml
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Quick Controls module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+**   * Redistributions of source code must retain the above copyright
+**     notice, this list of conditions and the following disclaimer.
+**   * Redistributions in binary form must reproduce the above copyright
+**     notice, this list of conditions and the following disclaimer in
+**     the documentation and/or other materials provided with the
+**     distribution.
+**   * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
+**     of its contributors may be used to endorse or promote products derived
+**     from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+import QtQuick 2.1
+import QtQuick.Controls 1.1
+import QtQuick.Controls.Private 1.0
+
+/*!
+    \qmltype BusyIndicatorStyle
+    \inqmlmodule QtQuick.Controls.Styles 1.1
+    \since QtQuick.Controls.Styles 1.1
+    \ingroup controlsstyling
+    \brief Provides custom styling for BusyIndicatorStyle
+
+    You can create a busy indicator by replacing the "indicator" delegate
+    of the BusyIndicatorStyle with a custom design.
+
+    Example:
+    \qml
+    BusyIndicator {
+        style: BusyIndicatorStyle
+            indicator: Image {
+                visible: control.running
+                source: "spinner.png"
+                NumberAnimation on rotation {
+                    running: control.running
+                    loops: Animation.Infinite
+                    duration: 2000
+                    from: 0 ; to: 360
+                }
+            }
+        }
+    }
+    \endqml
+*/
+Style {
+    id: indicatorstyle
+
+    /*! The \l BusyIndicator attached to this style. */
+    readonly property BusyIndicator control: __control
+
+    /*! This defines the appearance of the busy indicator. */
+    property Component indicator: Item {
+        implicitWidth: 32
+        implicitHeight: 32
+
+        opacity: control.running ? 1 : 0
+        Behavior on opacity { NumberAnimation { duration: 250 } }
+
+        Timer {
+            interval: 16
+            running: control.running
+            repeat: true
+            onTriggered: { repeater.counter += 0.20 }
+        }
+
+        Repeater {
+            id: repeater
+            model: 9
+            anchors.fill: parent
+            property real counter: 0
+            Rectangle {
+                width: repeater.width/6 + 2
+                height: width
+                radius: width/2
+                x: repeater.width/2
+                transform: Rotation { origin.x: 0 ; origin.y: repeater.width/2 ; angle: 5 + (360/repeater.count) * index}
+                border.color: Qt.rgba(0, 0, 0, 0.24)
+                color: Qt.rgba(lum, lum, lum, lum/2 + 0.3)
+                property real lum: {
+                    var idx = ((repeater.count-index) + repeater.counter) % repeater.count
+                    return Math.max( 0.3, 1 - (idx/(repeater.count - 1)))
+                }
+            }
+        }
+    }
+
+    /*! \internal */
+    property Component panel: Item {
+        anchors.fill: parent
+        implicitWidth: indicatorLoader.implicitWidth
+        implicitHeight: indicatorLoader.implicitHeight
+
+        Loader {
+            id: indicatorLoader
+            sourceComponent: indicator
+            anchors.centerIn: parent
+            width: Math.min(parent.width, parent.height)
+            height: width
+        }
+    }
+}
diff --git a/src/controls/Styles/Desktop/BusyIndicatorStyle.qml b/src/controls/Styles/Desktop/BusyIndicatorStyle.qml
new file mode 100644
index 000000000..99f37919f
--- /dev/null
+++ b/src/controls/Styles/Desktop/BusyIndicatorStyle.qml
@@ -0,0 +1,42 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Quick Controls module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+**   * Redistributions of source code must retain the above copyright
+**     notice, this list of conditions and the following disclaimer.
+**   * Redistributions in binary form must reproduce the above copyright
+**     notice, this list of conditions and the following disclaimer in
+**     the documentation and/or other materials provided with the
+**     distribution.
+**   * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
+**     of its contributors may be used to endorse or promote products derived
+**     from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+import QtQuick.Controls.Styles 1.1
+
+BusyIndicatorStyle { }
diff --git a/src/controls/Styles/qmldir b/src/controls/Styles/qmldir
index 5077542a5..8080acaf4 100644
--- a/src/controls/Styles/qmldir
+++ b/src/controls/Styles/qmldir
@@ -1,5 +1,6 @@
 module QtQuick.Controls.Styles
 ButtonStyle 1.0 Base/ButtonStyle.qml
+BusyIndicatorStyle 1.1 Base/BusyIndicatorStyle.qml
 CheckBoxStyle 1.0 Base/CheckBoxStyle.qml
 ComboBoxStyle 1.0 Base/ComboBoxStyle.qml
 ProgressBarStyle 1.0 Base/ProgressBarStyle.qml
diff --git a/src/controls/Styles/styles.pri b/src/controls/Styles/styles.pri
index 10eb3e9b4..9cdd9c953 100644
--- a/src/controls/Styles/styles.pri
+++ b/src/controls/Styles/styles.pri
@@ -2,6 +2,7 @@
 # Base
 STYLES_QML_FILES = \
     $$PWD/Base/ButtonStyle.qml \
+    $$PWD/Base/BusyIndicatorStyle.qml \
     $$PWD/Base/CheckBoxStyle.qml \
     $$PWD/Base/ComboBoxStyle.qml \
     $$PWD/Base/FocusFrameStyle.qml \
@@ -23,6 +24,7 @@ STYLES_QML_FILES = \
 # Desktop
 STYLES_QML_FILES += \
     $$PWD/Desktop/ButtonStyle.qml \
+    $$PWD/Desktop/BusyIndicatorStyle.qml \
     $$PWD/Desktop/CheckBoxStyle.qml \
     $$PWD/Desktop/ComboBoxStyle.qml \
     $$PWD/Desktop/FocusFrameStyle.qml \
diff --git a/src/controls/controls.pro b/src/controls/controls.pro
index 380183530..37a5a32ab 100644
--- a/src/controls/controls.pro
+++ b/src/controls/controls.pro
@@ -9,6 +9,7 @@ QMAKE_DOCS = $$PWD/doc/qtquickcontrols.qdocconf
 CONTROLS_QML_FILES = \
     ApplicationWindow.qml \
     Button.qml \
+    BusyIndicator.qml \
     CheckBox.qml \
     ComboBox.qml \
     GroupBox.qml \
diff --git a/src/controls/plugin.cpp b/src/controls/plugin.cpp
index b98e79080..6e0e1b045 100644
--- a/src/controls/plugin.cpp
+++ b/src/controls/plugin.cpp
@@ -91,7 +91,9 @@ static const struct {
     { "TextArea", 1, 0 },
     { "TextField", 1, 0 },
     { "ToolBar", 1, 0 },
-    { "ToolButton", 1, 0 }
+    { "ToolButton", 1, 0 },
+
+    { "BusyIndicator", 1, 1 }
 };
 
 void QtQuickControlsPlugin::registerTypes(const char *uri)
diff --git a/tests/auto/controls/controls.pro b/tests/auto/controls/controls.pro
index e1da1d556..f4a7cc968 100644
--- a/tests/auto/controls/controls.pro
+++ b/tests/auto/controls/controls.pro
@@ -14,6 +14,7 @@ TESTDATA = $$PWD/data/*
 
 OTHER_FILES += \
     $$PWD/data/tst_button.qml \
+    $$PWD/data/tst_busyindicator.qml \
     $$PWD/data/tst_shortcuts.qml \
     $$PWD/data/tst_spinbox.qml \
     $$PWD/data/tst_tableview.qml \
diff --git a/tests/auto/controls/data/tst_busyindicator.qml b/tests/auto/controls/data/tst_busyindicator.qml
new file mode 100644
index 000000000..912ed7faf
--- /dev/null
+++ b/tests/auto/controls/data/tst_busyindicator.qml
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Quick Controls module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+**   * Redistributions of source code must retain the above copyright
+**     notice, this list of conditions and the following disclaimer.
+**   * Redistributions in binary form must reproduce the above copyright
+**     notice, this list of conditions and the following disclaimer in
+**     the documentation and/or other materials provided with the
+**     distribution.
+**   * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
+**     of its contributors may be used to endorse or promote products derived
+**     from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.1
+import QtTest 1.0
+
+Item {
+    id: container
+    width: 400
+    height: 400
+
+    TestCase {
+        id: testCase
+        name: "Tests_BusyIndicator"
+        when:windowShown
+        width:400
+        height:400
+
+        function test_createIndicator() {
+            var indicator = Qt.createQmlObject('import QtQuick.Controls 1.1; BusyIndicator {}', testCase, '');
+            indicator.running = true
+            indicator.destroy()
+        }
+    }
+}
diff --git a/tests/manual/testbench/content/Components.qml b/tests/manual/testbench/content/Components.qml
index 4d406d14f..af5dcd003 100644
--- a/tests/manual/testbench/content/Components.qml
+++ b/tests/manual/testbench/content/Components.qml
@@ -49,6 +49,7 @@ Item {
     property Component toolbutton: ToolButton { text: "A ToolButton" }
     property Component radiobutton: RadioButton { text: "A RadioButton" }
     property Component textfield: TextField { }
+    property Component busyIndicator: BusyIndicator { }
     property Component spinbox: SpinBox {}
     property Component slider : Slider {}
     property Component combobox: ComboBox { model: testDataModel }
@@ -114,6 +115,7 @@ Item {
     property var componentModel: ListModel {
         Component.onCompleted: {
             append({ name: "Button",        component: button});
+            append({ name: "BusyIndicator", component: busyIndicator});
             append({ name: "ToolButton",    component: toolbutton});
             append({ name: "CheckBox",      component: checkbox});
             append({ name: "ComboBox",      component: combobox});
@@ -149,11 +151,13 @@ Item {
     property Component scrollviewStyle: ScrollViewStyle {}
     property Component groupboxStyle: GroupBoxStyle {}
     property Component tabViewStyle: TabViewStyle {}
+    property Component busyIndicatorStyle: BusyIndicatorStyle {}
     property Component labelStyle: null
 
     property var customStyles: ListModel {
         Component.onCompleted: {
             append({ name: "Button",        component: buttonStyle});
+            append({ name: "BusyIndicator", component: busyIndicatorStyle});
             append({ name: "ToolButton",    component: toolbuttonStyle});
             append({ name: "CheckBox",      component: checkboxStyle});
             append({ name: "ComboBox",      component: comboboxStyle});
diff --git a/tests/manual/testbench/main.qml b/tests/manual/testbench/main.qml
index 5c1d4eb71..df7cea9bc 100644
--- a/tests/manual/testbench/main.qml
+++ b/tests/manual/testbench/main.qml
@@ -198,6 +198,7 @@ ApplicationWindow {
                                     case "visible":
                                     case "checkable":
                                     case "checked":
+                                    case "running":
                                     case "frameVisible":
                                     case "adjustToContentSize":
                                     case "flat":
-- 
GitLab