on xenial help sign in
Range Input filter

Approved by: Andrea Cimitan

commit66ee6846292cc0c54bf76d4f7ae6069a2ad00d30 authorAlbert Astals Cid <albert.astals@canonical.com> dateWed 23 Mar 2016, 09:51 (11 years ago) parent5fda13f59bb048
13 files changed+730−21
qml/Dash/Filters/FilterOptionSelector.qml+1 qml/Dash/Filters/FilterRangeInput.qml+136 qml/Dash/Filters/FilterWidget.qml+1−1 qml/Dash/Filters/FilterWidgetFactory.qml+41−12 qml/Dash/FiltersPopover.qml+7 tests/mocks/Unity/CMakeLists.txt+2 tests/mocks/Unity/fake_filters.cpp+43−4 tests/mocks/Unity/fake_filters.h+3−3 tests/mocks/Unity/fake_rangeinputfilter.cpp+167 tests/mocks/Unity/fake_rangeinputfilter.h+79 tests/qmltests/CMakeLists.txt+1 tests/qmltests/Dash/Filters/tst_FilterRangeInput.qml+247 tests/qmltests/Dash/Filters/tst_FilterWidgetFactory.qml+2−1
qml/Dash/Filters/FilterOptionSelector.qml+1
@@ -31,6 +31,7 @@ FilterWidget {
3131
3232 expandedHeight: collapsedHeight + column.height
3333 width: parent.width
34+ showDivider: false
3435
3536 onClicked: {
3637 expanded = !expanded;
qml/Dash/Filters/FilterRangeInput.qmlnew file+136
@@ -0,0 +1,136 @@
1+/*
2+ * Copyright (C) 2015 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.4
18+import QtQuick.Layouts 1.1
19+import Ubuntu.Components 1.3
20+
21+/*! Range Input Filter Widget. */
22+
23+FilterWidget {
24+ id: root
25+
26+ implicitHeight: field1.height + units.gu(2)
27+
28+ function setFieldValue(field, hasValue, value) {
29+ if (hasValue) {
30+ // Need this othewise if we are on 4.5 and backspace instead of
31+ // having 4. in the text field we end up with 4 which is confusing
32+ if (field.text != value) {
33+ field.text = value;
34+ }
35+ } else {
36+ field.text = "";
37+ }
38+ }
39+
40+ Connections {
41+ target: widgetData
42+ onStartValueChanged: root.setFieldValue(field1, widgetData.hasStartValue, widgetData.startValue);
43+ onHasStartValueChanged: root.setFieldValue(field1, widgetData.hasStartValue, widgetData.startValue);
44+ onEndValueChanged: root.setFieldValue(field2, widgetData.hasEndValue, widgetData.endValue);
45+ onHasEndValueChanged: root.setFieldValue(field2, widgetData.hasEndValue, widgetData.endValue);
46+ }
47+
48+ onWidgetDataChanged: {
49+ if (widgetData) {
50+ root.setFieldValue(field1, widgetData.hasStartValue, widgetData.startValue);
51+ root.setFieldValue(field2, widgetData.hasEndValue, widgetData.endValue);
52+ } else {
53+ root.setFieldValue(field1, false, -1);
54+ root.setFieldValue(field2, false, -1);
55+ }
56+ }
57+
58+ RowLayout {
59+ anchors {
60+ fill: parent
61+ topMargin: units.gu(1)
62+ bottomMargin: units.gu(1)
63+ }
64+
65+ Item {
66+ Layout.fillWidth: true
67+ }
68+
69+ Label {
70+ text: widgetData.startPrefixLabel
71+ verticalAlignment: Text.AlignVCenter
72+ }
73+
74+ TextField {
75+ id: field1
76+ objectName: "startValueField"
77+ implicitWidth: units.gu(9)
78+ verticalAlignment: Text.AlignVCenter
79+ inputMethodHints: Qt.ImhFormattedNumbersOnly
80+ validator: DoubleValidator {
81+ notation: DoubleValidator.StandardNotation
82+ }
83+ onTextChanged: {
84+ if (text === "") widgetData.eraseStartValue();
85+ else widgetData.startValue = text;
86+ }
87+ }
88+
89+ Label {
90+ text: widgetData.startPostfixLabel
91+ verticalAlignment: Text.AlignVCenter
92+ }
93+
94+ Item {
95+ Layout.fillWidth: true
96+ }
97+
98+ Label {
99+ text: widgetData.centralLabel
100+ verticalAlignment: Text.AlignVCenter
101+ }
102+
103+ Item {
104+ Layout.fillWidth: true
105+ }
106+
107+ Label {
108+ text: widgetData.endPrefixLabel
109+ verticalAlignment: Text.AlignVCenter
110+ }
111+
112+ TextField {
113+ id: field2
114+ objectName: "endValueField"
115+ implicitWidth: units.gu(9)
116+ verticalAlignment: Text.AlignVCenter
117+ inputMethodHints: Qt.ImhFormattedNumbersOnly
118+ validator: DoubleValidator {
119+ notation: DoubleValidator.StandardNotation
120+ }
121+ onTextChanged: {
122+ if (text === "") widgetData.eraseEndValue();
123+ else widgetData.endValue = text;
124+ }
125+ }
126+
127+ Label {
128+ text: widgetData.endPostfixLabel
129+ verticalAlignment: Text.AlignVCenter
130+ }
131+
132+ Item {
133+ Layout.fillWidth: true
134+ }
135+ }
136+}
qml/Dash/Filters/FilterWidget.qml+1−1
@@ -23,7 +23,7 @@ Item {
2323 property string widgetId
2424
2525 //! Variable used to contain widget's data
26− property var widgetData
26+ property var widgetData: null
2727
2828 objectName: widgetId
2929}
qml/Dash/Filters/FilterWidgetFactory.qml+41−12
@@ -15,13 +15,13 @@
1515 */
1616
1717import QtQuick 2.4
18+import Ubuntu.Components 1.3
1819import Unity 0.2
1920
2021//! \brief This component loads the widgets based on widgetType.
2122
22−Loader {
23+Item {
2324 id: root
24−
2525 //! Identifier of the widget.
2626 property string widgetId: ""
2727
@@ -31,19 +31,48 @@ Loader {
3131 //! Widget data, forwarded to the widget as is.
3232 property var widgetData: null
3333
34− source: widgetSource
34+ implicitHeight: title.height + title.anchors.topMargin + loader.height
35+
36+ Label {
37+ id: title
38+ text: widgetData ? widgetData.title : ""
39+ height: text != "" ? implicitHeight : 0
40+
41+ anchors {
42+ top: parent.top
43+ left: parent.left
44+ right: parent.right
3545
36− //! \cond private
37− readonly property url widgetSource: {
38− switch (widgetType) {
39− case Filters.OptionSelectorFilter: return "FilterOptionSelector.qml";
40− default: return "";
46+ topMargin: height > 0 ? units.gu(1) : 0
47+ leftMargin: units.gu(2)
48+ rightMargin: anchors.leftMargin
4149 }
4250 }
43− //! \endcond
4451
45− onLoaded: {
46− item.widgetId = Qt.binding(function() { return root.widgetId } )
47− item.widgetData = Qt.binding(function() { return root.widgetData } )
52+ property alias active: loader.active
53+
54+ Loader {
55+ id: loader
56+
57+ anchors {
58+ top: title.bottom
59+ left: parent.left
60+ right: parent.right
61+ }
62+
63+ source: widgetSource
64+
65+ readonly property url widgetSource: {
66+ switch (widgetType) {
67+ case Filters.OptionSelectorFilter: return "FilterOptionSelector.qml";
68+ case Filters.RangeInputFilter: return "FilterRangeInput.qml";
69+ default: return "";
70+ }
71+ }
72+
73+ onLoaded: {
74+ item.widgetId = Qt.binding(function() { return root.widgetId } )
75+ item.widgetData = Qt.binding(function() { return root.widgetData } )
76+ }
4877 }
4978}
qml/Dash/FiltersPopover.qml+7
@@ -17,6 +17,7 @@
1717import QtQuick 2.4
1818import Ubuntu.Components 1.3
1919import Ubuntu.Components.Popups 1.3
20+import Ubuntu.Components.ListItems 1.3 as ListItems
2021import "Filters" as Filters
2122
2223Popover {
@@ -83,6 +84,7 @@ Popover {
8384 }
8485
8586 Repeater {
87+ id: repeater
8688 model: scopeView.scope.filters
8789
8890 delegate: Filters.FilterWidgetFactory {
@@ -91,6 +93,11 @@ Popover {
9193 widgetId: id
9294 widgetType: type
9395 widgetData: filter
96+
97+ ListItems.ThinDivider {
98+ anchors.bottom: parent.bottom
99+ visible: index != repeater.count - 1
100+ }
94101 }
95102 }
96103 }
tests/mocks/Unity/CMakeLists.txt+2
@@ -32,6 +32,7 @@ set(UnityQML_SOURCES
3232 fake_filters.cpp
3333 fake_optionselectorfilter.cpp
3434 fake_optionselectoroptions.cpp
35+ fake_rangeinputfilter.cpp
3536 fake_unity_plugin.cpp
3637 ${SCOPES_API_INCLUDEDIR}/unity/shell/scopes/CategoriesInterface.h
3738 ${SCOPES_API_INCLUDEDIR}/unity/shell/scopes/FilterBaseInterface.h
@@ -41,6 +42,7 @@ set(UnityQML_SOURCES
4142 ${SCOPES_API_INCLUDEDIR}/unity/shell/scopes/OptionSelectorOptionsInterface.h
4243 ${SCOPES_API_INCLUDEDIR}/unity/shell/scopes/PreviewModelInterface.h
4344 ${SCOPES_API_INCLUDEDIR}/unity/shell/scopes/PreviewWidgetModelInterface.h
45+ ${SCOPES_API_INCLUDEDIR}/unity/shell/scopes/RangeInputFilterInterface.h
4446 ${SCOPES_API_INCLUDEDIR}/unity/shell/scopes/ResultsModelInterface.h
4547 ${SCOPES_API_INCLUDEDIR}/unity/shell/scopes/ScopeInterface.h
4648 ${SCOPES_API_INCLUDEDIR}/unity/shell/scopes/ScopesInterface.h
tests/mocks/Unity/fake_filters.cpp+43−4
@@ -17,18 +17,42 @@
1717#include "fake_filters.h"
1818
1919#include "fake_optionselectorfilter.h"
20+#include "fake_rangeinputfilter.h"
2021#include "fake_scope.h"
2122
2223Filters::Filters(Scope* parent)
2324 : unity::shell::scopes::FiltersInterface(parent)
2425{
2526 addFilter(new FakeOptionSelectorFilter("OSF1", "Tag1", "Which Cake you like More", false, QStringList() << "cheese" << "carrot" << "chocolate", this));
27+
28+ FakeRangeInputFilter *rif = new FakeRangeInputFilter("RIF1", "Tag3", this);
29+ rif->setTitle("How much do you want to walk?");
30+ rif->setCentralLabel("to");
31+ rif->setStartPostfixLabel("m");
32+ rif->setEndPostfixLabel("m");
33+ addFilter(rif);
34+
2635 addFilter(new FakeOptionSelectorFilter("OSF2", "Tag2", "Which Countries have you been to?", true, QStringList() << "Germany" << "UK" << "New Zealand", this));
2736}
2837
29−void Filters::addFilter(FakeOptionSelectorFilter *f)
38+void Filters::addFilter(unity::shell::scopes::FilterBaseInterface *f)
3039{
31− connect(f, &FakeOptionSelectorFilter::isActiveChanged, this, &Filters::activeFiltersCountChanged);
40+ switch (f->filterType()) {
41+ case FiltersInterface::OptionSelectorFilter: {
42+ FakeOptionSelectorFilter *osf = static_cast<FakeOptionSelectorFilter *>(f);
43+ connect(osf, &FakeOptionSelectorFilter::isActiveChanged, this, &Filters::activeFiltersCountChanged);
44+ }
45+ break;
46+
47+ case FiltersInterface::RangeInputFilter: {
48+ FakeRangeInputFilter *rif = static_cast<FakeRangeInputFilter *>(f);
49+ connect(rif, &FakeRangeInputFilter::isActiveChanged, this, &Filters::activeFiltersCountChanged);
50+ }
51+ break;
52+
53+ case Invalid:
54+ break;
55+ }
3256 m_filters << f;
3357}
3458
@@ -63,8 +87,23 @@ QVariant Filters::data(const QModelIndex &index, int role) const
6387int Filters::activeFiltersCount() const
6488{
6589 int active = 0;
66− Q_FOREACH(FakeOptionSelectorFilter *f, m_filters) {
67− if (f->isActive()) ++active;
90+ Q_FOREACH(unity::shell::scopes::FilterBaseInterface *f, m_filters) {
91+ switch (f->filterType()) {
92+ case FiltersInterface::OptionSelectorFilter: {
93+ FakeOptionSelectorFilter *osf = static_cast<FakeOptionSelectorFilter *>(f);
94+ if (osf->isActive()) ++active;
95+ }
96+ break;
97+
98+ case FiltersInterface::RangeInputFilter: {
99+ FakeRangeInputFilter *rif = static_cast<FakeRangeInputFilter *>(f);
100+ if (rif->isActive()) ++active;
101+ }
102+ break;
103+
104+ case Invalid:
105+ break;
106+ }
68107 }
69108 return active;
70109}
tests/mocks/Unity/fake_filters.h+3−3
@@ -18,9 +18,9 @@
1818#define FAKE_FILTERS_H
1919
2020#include <unity/shell/scopes/FiltersInterface.h>
21+#include <unity/shell/scopes/FilterBaseInterface.h>
2122
2223class Scope;
23−class FakeOptionSelectorFilter;
2424
2525class Filters : public unity::shell::scopes::FiltersInterface
2626{
@@ -38,9 +38,9 @@ Q_SIGNALS:
3838 void activeFiltersCountChanged();
3939
4040private:
41− void addFilter(FakeOptionSelectorFilter* f);
41+ void addFilter(unity::shell::scopes::FilterBaseInterface* f);
4242
43− QVector<FakeOptionSelectorFilter*> m_filters;
43+ QVector<unity::shell::scopes::FilterBaseInterface*> m_filters;
4444};
4545
4646#endif
tests/mocks/Unity/fake_rangeinputfilter.cppnew file+167
@@ -0,0 +1,167 @@
1+/*
2+ * Copyright (C) 2015 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include "fake_rangeinputfilter.h"
18+
19+FakeRangeInputFilter::FakeRangeInputFilter(const QString &id, const QString &tag, QObject* parent)
20+ : unity::shell::scopes::RangeInputFilterInterface(parent),
21+ m_filterId(id),
22+ m_filterTag(tag),
23+ m_hasStartValue(false),
24+ m_hasEndValue(false),
25+ m_startValue(-1),
26+ m_endValue(-1)
27+{
28+ connect(this, &FakeRangeInputFilter::hasStartValueChanged, this, &FakeRangeInputFilter::isActiveChanged);
29+ connect(this, &FakeRangeInputFilter::hasEndValueChanged, this, &FakeRangeInputFilter::isActiveChanged);
30+}
31+
32+QString FakeRangeInputFilter::filterId() const
33+{
34+ return m_filterId;
35+}
36+
37+QString FakeRangeInputFilter::filterTag() const
38+{
39+ return m_filterTag;
40+}
41+
42+QString FakeRangeInputFilter::title() const
43+{
44+ return m_title;
45+}
46+
47+double FakeRangeInputFilter::startValue() const
48+{
49+ return m_startValue;
50+}
51+
52+double FakeRangeInputFilter::endValue() const
53+{
54+ return m_endValue;
55+}
56+
57+void FakeRangeInputFilter::setStartValue(double value)
58+{
59+ if (m_startValue != value) {
60+ m_startValue = value;
61+ Q_EMIT startValueChanged();
62+ }
63+ if (!m_hasStartValue) {
64+ m_hasStartValue = true;
65+ Q_EMIT hasStartValueChanged();
66+ }
67+}
68+
69+void FakeRangeInputFilter::setEndValue(double value)
70+{
71+ if (m_endValue != value) {
72+ m_endValue = value;
73+ Q_EMIT endValueChanged();
74+ }
75+ if (!m_hasEndValue) {
76+ m_hasEndValue = true;
77+ Q_EMIT hasEndValueChanged();
78+ }
79+}
80+
81+QString FakeRangeInputFilter::startPrefixLabel() const
82+{
83+ return m_startPrefixLabel;
84+}
85+
86+QString FakeRangeInputFilter::startPostfixLabel() const
87+{
88+ return m_startPostfixLabel;
89+}
90+
91+QString FakeRangeInputFilter::centralLabel() const
92+{
93+ return m_centralLabel;
94+}
95+
96+QString FakeRangeInputFilter::endPrefixLabel() const
97+{
98+ return m_endPrefixLabel;
99+}
100+
101+QString FakeRangeInputFilter::endPostfixLabel() const
102+{
103+ return m_endPostfixLabel;
104+}
105+
106+bool FakeRangeInputFilter::hasStartValue() const
107+{
108+ return m_hasStartValue;
109+}
110+
111+bool FakeRangeInputFilter::hasEndValue() const
112+{
113+ return m_hasEndValue;
114+}
115+
116+void FakeRangeInputFilter::eraseStartValue()
117+{
118+ m_hasStartValue = false;
119+ Q_EMIT hasStartValueChanged();
120+}
121+
122+void FakeRangeInputFilter::eraseEndValue()
123+{
124+ m_hasEndValue = false;
125+ Q_EMIT hasEndValueChanged();
126+}
127+
128+bool FakeRangeInputFilter::isActive() const
129+{
130+ return hasStartValue() && hasEndValue();
131+}
132+
133+void FakeRangeInputFilter::setTitle(const QString &title)
134+{
135+ m_title = title;
136+ Q_EMIT titleChanged();
137+}
138+
139+void FakeRangeInputFilter::setStartPrefixLabel(const QString &startPrefixLabel)
140+{
141+ m_startPrefixLabel = startPrefixLabel;
142+ Q_EMIT startPrefixLabelChanged();
143+}
144+
145+void FakeRangeInputFilter::setStartPostfixLabel(const QString &startPostfixLabel)
146+{
147+ m_startPostfixLabel = startPostfixLabel;
148+ Q_EMIT startPostfixLabelChanged();
149+}
150+
151+void FakeRangeInputFilter::setCentralLabel(const QString &centralLabel)
152+{
153+ m_centralLabel = centralLabel;
154+ Q_EMIT centralLabelChanged();
155+}
156+
157+void FakeRangeInputFilter::setEndPrefixLabel(const QString &endPrefixLabel)
158+{
159+ m_endPrefixLabel = endPrefixLabel;
160+ Q_EMIT endPrefixLabelChanged();
161+}
162+
163+void FakeRangeInputFilter::setEndPostfixLabel(const QString &endPostfixLabel)
164+{
165+ m_endPostfixLabel = endPostfixLabel;
166+ Q_EMIT endPostfixLabelChanged();
167+}
tests/mocks/Unity/fake_rangeinputfilter.hnew file+79
@@ -0,0 +1,79 @@
1+/*
2+ * Copyright (C) 2015 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#ifndef FAKE_RANGEINPUTFILTER_H
18+#define FAKE_RANGEINPUTFILTER_H
19+
20+#include <unity/shell/scopes/RangeInputFilterInterface.h>
21+
22+class FakeRangeInputFilter : public unity::shell::scopes::RangeInputFilterInterface
23+{
24+ Q_OBJECT
25+
26+public:
27+ FakeRangeInputFilter(const QString &id, const QString &tag, QObject* parent);
28+
29+ QString filterId() const override;
30+ QString filterTag() const override;
31+ QString title() const override;
32+
33+ double startValue() const override;
34+ double endValue() const override;
35+ void setStartValue(double value) override;
36+ void setEndValue(double value) override;
37+ QString startPrefixLabel() const override;
38+ QString startPostfixLabel() const override;
39+ QString centralLabel() const override;
40+ QString endPrefixLabel() const override;
41+ QString endPostfixLabel() const override;
42+ bool hasStartValue() const override;
43+ bool hasEndValue() const override;
44+
45+ void eraseStartValue() override;
46+ void eraseEndValue() override;
47+
48+ // Not part of the iface, for mock/testing purposes
49+ bool isActive() const;
50+
51+ void setTitle(const QString &title);
52+ void setStartPrefixLabel(const QString &startPrefixLabel);
53+ void setStartPostfixLabel(const QString &startPostfixLabel);
54+ void setCentralLabel(const QString &centralLabel);
55+ void setEndPrefixLabel(const QString &endPrefixLabel);
56+ void setEndPostfixLabel(const QString &endPostfixLabel);
57+
58+Q_SIGNALS:
59+ void isActiveChanged();
60+
61+private:
62+ QString m_filterId;
63+ QString m_filterTag;
64+ QString m_title;
65+
66+ bool m_hasStartValue;
67+ bool m_hasEndValue;
68+
69+ double m_startValue;
70+ double m_endValue;
71+
72+ QString m_startPrefixLabel;
73+ QString m_startPostfixLabel;
74+ QString m_centralLabel;
75+ QString m_endPrefixLabel;
76+ QString m_endPostfixLabel;
77+};
78+
79+#endif
tests/qmltests/CMakeLists.txt+1
@@ -54,6 +54,7 @@ add_unity8_qmltest(Dash/Previews PreviewVideoPlayback)
5454add_unity8_qmltest(Dash/Previews PreviewWidgetFactory)
5555add_unity8_qmltest(Dash/Previews PreviewZoomableImage)
5656add_unity8_qmltest(Dash/Filters FilterOptionSelector)
57+add_unity8_qmltest(Dash/Filters FilterRangeInput)
5758add_unity8_qmltest(Dash/Filters FilterWidgetFactory)
5859add_unity8_qmltest(Dash/ScopeSettings ScopeSettingBoolean)
5960add_unity8_qmltest(Dash/ScopeSettings ScopeSettingList)
tests/qmltests/Dash/Filters/tst_FilterRangeInput.qmlnew file+247
@@ -0,0 +1,247 @@
1+/*
2+ * Copyright 2015 Canonical Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.4
18+import QtTest 1.0
19+import Ubuntu.Components 1.3
20+import "../../../../qml/Dash/Filters"
21+import Unity.Test 0.1 as UT
22+import Unity 0.2
23+
24+Rectangle {
25+ id: root
26+ width: units.gu(60)
27+ height: units.gu(80)
28+ color: theme.palette.selected.background
29+
30+ QtObject {
31+ id: widgetData1
32+
33+ property string title
34+ property real startValue
35+ property real endValue
36+ property bool hasStartValue
37+ property bool hasEndValue
38+ property string startPrefixLabel
39+ property string startPostfixLabel
40+ property string centralLabel
41+ property string endPrefixLabel
42+ property string endPostfixLabel
43+
44+ onStartValueChanged: {
45+ hasStartValue = true;
46+ }
47+
48+ onEndValueChanged: {
49+ hasEndValue = true;
50+ }
51+
52+ function eraseStartValue() {
53+ hasStartValue = false;
54+ }
55+
56+ function eraseEndValue() {
57+ hasEndValue = false;
58+ }
59+ }
60+
61+ Component.onCompleted: {
62+ generateData();
63+ }
64+
65+ function generateData() {
66+ widgetData1.title = title.text
67+ widgetData1.startValue = startValue.text;
68+ widgetData1.endValue = endValue.text;
69+ widgetData1.hasStartValue = startValueHasValue.checked;
70+ widgetData1.hasEndValue = endValueHasValue.checked;
71+ widgetData1.startPrefixLabel = startValuePrefixLabel.text;
72+ widgetData1.startPostfixLabel = startValuePostfixLabel.text;
73+ widgetData1.centralLabel = centralLabel.text;
74+ widgetData1.endPrefixLabel = endValuePrefixLabel.text;
75+ widgetData1.endPostfixLabel = endValuePostfixLabel.text;
76+
77+ factory.widgetData = widgetData1;
78+ }
79+
80+ FilterWidgetFactory {
81+ id: factory
82+ widgetId: "testRangeInputFilter"
83+ widgetType: Filters.RangeInputFilter
84+ anchors {
85+ left: parent.left
86+ right: parent.right
87+ }
88+ clip: true
89+ }
90+
91+ Column {
92+ anchors.top: factory.bottom
93+ width: parent.width
94+ spacing: units.gu(1)
95+
96+ Text {
97+ text: "Values"
98+ }
99+
100+ Row {
101+ spacing: units.gu(1)
102+ Text {
103+ text: "Title"
104+ verticalAlignment: Text.AlignVCenter
105+ height: parent.height
106+ }
107+ TextField {
108+ id: title
109+ text: ""
110+ }
111+ }
112+
113+ Row {
114+ spacing: units.gu(1)
115+ Text {
116+ text: "Start Value Prefix Label"
117+ verticalAlignment: Text.AlignVCenter
118+ height: parent.height
119+ }
120+ TextField {
121+ id: startValuePrefixLabel
122+ text: "Pre1"
123+ }
124+ }
125+
126+ Row {
127+ spacing: units.gu(1)
128+ Text {
129+ text: "Start Value Postfix Label"
130+ verticalAlignment: Text.AlignVCenter
131+ height: parent.height
132+ }
133+ TextField {
134+ id: startValuePostfixLabel
135+ text: "Post1"
136+ }
137+ }
138+
139+ Row {
140+ spacing: units.gu(1)
141+ Text {
142+ text: "Central Label"
143+ verticalAlignment: Text.AlignVCenter
144+ height: parent.height
145+ }
146+ TextField {
147+ id: centralLabel
148+ text: "to"
149+ }
150+ }
151+
152+ Row {
153+ spacing: units.gu(1)
154+ Text {
155+ text: "End Value Prefix Label"
156+ verticalAlignment: Text.AlignVCenter
157+ height: parent.height
158+ }
159+ TextField {
160+ id: endValuePrefixLabel
161+ text: "Pre2"
162+ }
163+ }
164+
165+ Row {
166+ spacing: units.gu(1)
167+ Text {
168+ text: "End Value Postfix Label"
169+ verticalAlignment: Text.AlignVCenter
170+ height: parent.height
171+ }
172+ TextField {
173+ id: endValuePostfixLabel
174+ text: "Post2"
175+ }
176+ }
177+
178+ Row {
179+ spacing: units.gu(1)
180+ Text {
181+ text: "Start Value"
182+ verticalAlignment: Text.AlignVCenter
183+ height: parent.height
184+ }
185+ TextField {
186+ id: startValue
187+ text: "-1"
188+ }
189+ CheckBox {
190+ id: startValueHasValue
191+ }
192+ }
193+
194+
195+ Row {
196+ spacing: units.gu(1)
197+ Text {
198+ text: "End Value"
199+ verticalAlignment: Text.AlignVCenter
200+ height: parent.height
201+ }
202+ TextField {
203+ id: endValue
204+ text: "5"
205+ }
206+ CheckBox {
207+ id: endValueHasValue
208+ checked: true
209+ }
210+ }
211+
212+ Button {
213+ text: "Set Values"
214+ onClicked: root.generateData();
215+ }
216+ }
217+
218+ UT.UnityTestCase {
219+ name: "FilterRangeInput"
220+ when: windowShown
221+
222+ function init() {
223+ root.generateData();
224+ }
225+
226+ function test_initialStatus() {
227+ var startValueField = findChild(factory, "startValueField");
228+ compare(startValueField.text, "");
229+
230+ var endValueField = findChild(factory, "endValueField");
231+ compare(endValueField.text, "5");
232+ }
233+
234+ function test_dotStays() {
235+ var startValueField = findChild(factory, "startValueField");
236+ compare(startValueField.text, "");
237+
238+ startValueField.text = "4.5";
239+ compare(startValueField.text, "4.5");
240+ compare(widgetData1.startValue, 4.5);
241+
242+ startValueField.text = "4.";
243+ compare(startValueField.text, "4.");
244+ compare(widgetData1.startValue, 4);
245+ }
246+ }
247+}
tests/qmltests/Dash/Filters/tst_FilterWidgetFactory.qml+2−1
@@ -41,7 +41,8 @@ Rectangle {
4141
4242 function test_mapping_data() {
4343 return [
44− { tag: "OptionSelector", type: Filters.OptionSelectorFilter, source: "FilterOptionSelector.qml" }
44+ { tag: "OptionSelector", type: Filters.OptionSelectorFilter, source: "FilterOptionSelector.qml" },
45+ { tag: "RangeInputFilter", type: Filters.RangeInputFilter, source: "FilterRangeInput.qml" }
4546 ];
4647 }
4748