on xenial help sign in
Indicator visibility based on connection with backend service.
6fca692Nick Dedekind
Panel/IndicatorItem.qml+2−3
@@ -26,13 +26,12 @@ Item {
26 property bool highlighted: false
26 property bool highlighted: false
27 property bool dimmed: false
27 property bool dimmed: false
28 property var indicatorProperties: undefined
28 property var indicatorProperties: undefined
29+ property bool indicatorVisible: loader.item ? loader.item.enabled : false
29
30
30 opacity: dimmed ? 0.4 : 1
31 opacity: dimmed ? 0.4 : 1
31 Behavior on opacity { StandardAnimation {} }
32 Behavior on opacity { StandardAnimation {} }
32
33
33− // only visible when non-empty
34− visible: loader.item != undefined && loader.status == Loader.Ready ? loader.item.enabled : false
35− width: visible ? loader.item.width : 0
34+ width: loader.item ? loader.item.width : 0
36
35
37 Loader {
36 Loader {
38 id: loader
37 id: loader
Panel/IndicatorRow.qml+19−1
@@ -16,6 +16,7 @@
16
16
17import QtQuick 2.0
17import QtQuick 2.0
18import Ubuntu.Components 0.1
18import Ubuntu.Components 0.1
19+import Unity.Indicators 0.1 as Indicators
19import "../Components"
20import "../Components"
20
21
21Item {
22Item {
@@ -25,6 +26,7 @@ Item {
25 readonly property int currentItemIndex: currentItem ? currentItem.ownIndex : -1
26 readonly property int currentItemIndex: currentItem ? currentItem.ownIndex : -1
26 property alias row: row
27 property alias row: row
27 property QtObject indicatorsModel: null
28 property QtObject indicatorsModel: null
29+ property var visibleIndicators: defined
28
30
29 width: units.gu(40)
31 width: units.gu(40)
30 height: units.gu(3)
32 height: units.gu(3)
@@ -55,7 +57,8 @@ Item {
55 Item {
57 Item {
56 id: itemWrapper
58 id: itemWrapper
57 height: indicatorRow.height
59 height: indicatorRow.height
58− width: childrenRect.width
60+ width: indicatorItem.width
61+ visible: indicatorItem.indicatorVisible
59
62
60 property int ownIndex: index
63 property int ownIndex: index
61 property alias highlighted: indicatorItem.highlighted
64 property alias highlighted: indicatorItem.highlighted
@@ -70,6 +73,21 @@ Item {
70
73
71 widgetSource: model.widgetSource
74 widgetSource: model.widgetSource
72 indicatorProperties : model.indicatorProperties
75 indicatorProperties : model.indicatorProperties
76+
77+ Component.onCompleted: {
78+ if (visibleIndicators == undefined) {
79+ visibleIndicators = {}
80+ }
81+ indicatorRow.visibleIndicators[model.identifier] = indicatorVisible;
82+ indicatorRow.visibleIndicatorsChanged();
83+ }
84+ onIndicatorVisibleChanged: {
85+ if (visibleIndicators == undefined) {
86+ visibleIndicators = {}
87+ }
88+ indicatorRow.visibleIndicators[model.identifier] = indicatorVisible;
89+ indicatorRow.visibleIndicatorsChanged();
90+ }
73 }
91 }
74
92
75 opacity: {
93 opacity: {
Panel/Indicators.qml+17−2
@@ -180,11 +180,19 @@ Showable {
180 clip: !indicators.fullyOpened
180 clip: !indicators.fullyOpened
181 activeHeader: indicators.state == "hint" || indicators.state == "reveal"
181 activeHeader: indicators.state == "hint" || indicators.state == "reveal"
182 enabled: contentEnabled
182 enabled: contentEnabled
183+ visibleIndicators: indicatorRow.visibleIndicators
183
184
184 Connections {
185 Connections {
186+ property bool enableIndexChangeSignal: true
187+
185− target: indicatorRow
188+ target: enableIndexChangeSignal ? indicatorRow : null
186 onCurrentItemIndexChanged: {
189 onCurrentItemIndexChanged: {
190+ var oldActive = enableIndexChangeSignal;
191+ enableIndexChangeSignal = false;
192+
187 menuContent.setCurrentMenuIndex(indicatorRow.currentItemIndex);
193 menuContent.setCurrentMenuIndex(indicatorRow.currentItemIndex);
194+
195+ enableIndexChangeSignal = oldActive;
188 }
196 }
189 }
197 }
190
198
@@ -256,9 +264,16 @@ Showable {
256 state: indicators.state
264 state: indicators.state
257
265
258 Connections {
266 Connections {
267+ property bool enableIndexChangeSignal: true
268+
259− target: menuContent
269+ target: enableIndexChangeSignal ? menuContent : null
260 onCurrentMenuIndexChanged: {
270 onCurrentMenuIndexChanged: {
271+ var oldActive = enableIndexChangeSignal;
272+ enableIndexChangeSignal = false;
273+
261 indicatorRow.setCurrentItem(menuContent.currentMenuIndex);
274 indicatorRow.setCurrentItem(menuContent.currentMenuIndex);
275+
276+ enableIndexChangeSignal = oldActive;
262 }
277 }
263 }
278 }
264 }
279 }
Panel/Indicators/DatetimeIndicatorWidget.qml+4−2
@@ -25,6 +25,7 @@ Indicators.IndicatorWidget {
25 id: indicatorWidget
25 id: indicatorWidget
26
26
27 width: timeLabel.width + units.gu(1)
27 width: timeLabel.width + units.gu(1)
28+ rootMenuType: "com.canonical.indicator.root.time"
28
29
29 property alias label: timeLabel.text
30 property alias label: timeLabel.text
30
31
@@ -52,14 +53,15 @@ Indicators.IndicatorWidget {
52
53
53 onActionStateChanged: {
54 onActionStateChanged: {
54 if (action == undefined || !action.valid) {
55 if (action == undefined || !action.valid) {
56+ enabled = false;
55 return;
57 return;
56 }
58 }
57
59
58 if (action.state == undefined) {
60 if (action.state == undefined) {
59− visible = false;
61+ enabled = false;
60 return;
62 return;
61 }
63 }
62
64
63− indicatorWidget.visible = action.state[3];
65+ enabled = action.state[3];
64 }
66 }
65}
67}
Panel/Indicators/DefaultIndicatorWidget.qml+1
@@ -63,6 +63,7 @@ Indicators.IndicatorWidget {
63
63
64 onActionStateChanged: {
64 onActionStateChanged: {
65 if (action == undefined || !action.valid) {
65 if (action == undefined || !action.valid) {
66+ enabled = false;
66 return;
67 return;
67 }
68 }
68
69
Panel/Indicators/NetworkIndicatorWidget.qml+3
@@ -43,14 +43,17 @@ Indicators.IndicatorWidget {
43
43
44 onActionStateChanged: {
44 onActionStateChanged: {
45 if (action == undefined || !action.valid) {
45 if (action == undefined || !action.valid) {
46+ enabled = false;
46 return;
47 return;
47 }
48 }
48
49
49 if (action.state == undefined) {
50 if (action.state == undefined) {
51+ enabled = false;
50 connectionState = 0;
52 connectionState = 0;
51 return;
53 return;
52 }
54 }
53
55
56+ enabled = true;
54 connectionState = action.state[Indicators.NetworkActionState.Connection];
57 connectionState = action.state[Indicators.NetworkActionState.Connection];
55 if (connectionState == Indicators.NetworkConnection.Activated) {
58 if (connectionState == Indicators.NetworkConnection.Activated) {
56 signalStrength = action.state[Indicators.NetworkActionState.SignalStrength];
59 signalStrength = action.state[Indicators.NetworkActionState.SignalStrength];
Panel/Indicators/SoundIndicatorWidget.qml+1
@@ -22,4 +22,5 @@ import QtQuick 2.0
22DefaultIndicatorWidget {
22DefaultIndicatorWidget {
23 // default the icon so we have something to show when we don't have the bus.
23 // default the icon so we have something to show when we don't have the bus.
24 iconSource: "image://gicon/audio-volume-high"
24 iconSource: "image://gicon/audio-volume-high"
25+ enabled: true
25}
26}
Panel/MenuContent.qml+25−7
@@ -17,6 +17,7 @@
17import QtQuick 2.0
17import QtQuick 2.0
18import Ubuntu.Components 0.1
18import Ubuntu.Components 0.1
19import Unity.Indicators 0.1 as Indicators
19import Unity.Indicators 0.1 as Indicators
20+import Utils 0.1
20import "../Components"
21import "../Components"
21
22
22// FIXME : We dont want to use MainView.
23// FIXME : We dont want to use MainView.
@@ -27,20 +28,23 @@ MainView {
27
28
28 property QtObject indicatorsModel: null
29 property QtObject indicatorsModel: null
29 property bool __contentActive: false
30 property bool __contentActive: false
30− readonly property int currentMenuIndex : tabs.selectedTabIndex
31+ readonly property int currentMenuIndex : filteredIndicators.mapToSource(tabs.selectedTabIndex)
31 backgroundColor: "#221e1c" // FIXME not in palette yet
32 backgroundColor: "#221e1c" // FIXME not in palette yet
32 property int contentReleaseInterval: 20000
33 property int contentReleaseInterval: 20000
33 property bool activeHeader: false
34 property bool activeHeader: false
35+ property alias visibleIndicators: visibleIndicatorsModel.visible
34
36
35 width: units.gu(40)
37 width: units.gu(40)
36 height: units.gu(42)
38 height: units.gu(42)
37
39
38 function setCurrentMenuIndex(index) {
40 function setCurrentMenuIndex(index) {
39− if (currentMenuIndex !== index) {
41+ var filteredIndex = filteredIndicators.mapFromSource(index)
40− if (currentMenuIndex == -1) {
42+
43+ if (tabs.selectedTabIndex !== filteredIndex) {
44+ if (tabs.selectedTabIndex == -1) {
41 tabs.tabBar.animate = false;
45 tabs.tabBar.animate = false;
42 }
46 }
43− tabs.selectedTabIndex = index;
47+ tabs.selectedTabIndex = filteredIndex;
44 tabs.tabBar.animate = true;
48 tabs.tabBar.animate = true;
45 }
49 }
46 }
50 }
@@ -61,6 +65,20 @@ MainView {
61 tabs.tabBar.alwaysSelectionMode = activeHeader;
65 tabs.tabBar.alwaysSelectionMode = activeHeader;
62 }
66 }
63
67
68+ SortFilterProxyModel {
69+ id: filteredIndicators
70+ model: visibleIndicatorsModel
71+ dynamicSortFilter: true
72+
73+ filterRole: Indicators.IndicatorsModelRole.IsVisible
74+ filterRegExp: RegExp("^true$")
75+ }
76+
77+ Indicators.VisibleIndicatorsModel {
78+ id: visibleIndicatorsModel
79+ model: indicatorsModel
80+ }
81+
64 Tabs {
82 Tabs {
65 id: tabs
83 id: tabs
66 objectName: "tabs"
84 objectName: "tabs"
@@ -69,8 +87,8 @@ MainView {
69
87
70 Repeater {
88 Repeater {
71 id: repeater
89 id: repeater
72− model: indicatorsModel
90+ model: filteredIndicators
73− objectName: "menus"
91+ objectName: "tabsRepeater"
74
92
75 // FIXME: This is needed because tabs dont handle repeaters well.
93 // FIXME: This is needed because tabs dont handle repeaters well.
76 // Due to the child ordering happening after child insertion.
94 // Due to the child ordering happening after child insertion.
@@ -114,7 +132,7 @@ MainView {
114 item[pName] = indicatorProperties[pName]
132 item[pName] = indicatorProperties[pName]
115 }
133 }
116 }
134 }
117− if (contentActive && menus.visible) {
135+ if (contentActive && tabs.visible) {
118 item.start()
136 item.start()
119 }
137 }
120 }
138 }
plugins/Unity/Indicators/CMakeLists.txt+1
@@ -34,6 +34,7 @@ set(IndicatorsQML_SOURCES
34 rootactionstate.cpp
34 rootactionstate.cpp
35 unitymenumodelcache.cpp
35 unitymenumodelcache.cpp
36 unitymenumodelstack.cpp
36 unitymenumodelstack.cpp
37+ visibleindicatorsmodel.cpp
37)
38)
38add_definitions(-DUNITYINDICATORS_LIBRARY)
39add_definitions(-DUNITYINDICATORS_LIBRARY)
39
40
plugins/Unity/Indicators/indicator.cpp−2
@@ -51,7 +51,6 @@ void Indicator::init(const QString& busName, const QSettings& settings)
51 }
51 }
52 }
52 }
53
53
54−
55 QVariantMap properties;
54 QVariantMap properties;
56 properties.clear();
55 properties.clear();
57 properties.insert("busType", 1);
56 properties.insert("busType", 1);
@@ -87,7 +86,6 @@ void Indicator::setPosition(int position)
87 }
86 }
88}
87}
89
88
90−
91QVariant Indicator::indicatorProperties() const
89QVariant Indicator::indicatorProperties() const
92{
90{
93 return m_properties;
91 return m_properties;
plugins/Unity/Indicators/indicator.h−4
@@ -29,10 +29,6 @@
29class UNITYINDICATORS_EXPORT Indicator : public QObject
29class UNITYINDICATORS_EXPORT Indicator : public QObject
30{
30{
31 Q_OBJECT
31 Q_OBJECT
32− Q_PROPERTY(QString identifier READ identifier NOTIFY identifierChanged)
33− Q_PROPERTY(int position READ position NOTIFY positionChanged)
34− Q_PROPERTY(QVariant indicatorProperties READ indicatorProperties NOTIFY indicatorPropertiesChanged)
35−
36public:
32public:
37 typedef QSharedPointer<Indicator> Ptr;
33 typedef QSharedPointer<Indicator> Ptr;
38
34
plugins/Unity/Indicators/indicators.h+1−1
@@ -79,7 +79,7 @@ public:
79 WidgetSource,
79 WidgetSource,
80 PageSource,
80 PageSource,
81 IndicatorProperties,
81 IndicatorProperties,
82− IsValid
82+ IsVisible
83 };
83 };
84
84
85 IndicatorsModelRole(QObject*parent=0):QObject(parent) {}
85 IndicatorsModelRole(QObject*parent=0):QObject(parent) {}
plugins/Unity/Indicators/indicatorsmodel.cpp−3
@@ -206,7 +206,6 @@ QHash<int, QByteArray> IndicatorsModel::roleNames() const
206 roles[IndicatorsModelRole::WidgetSource] = "widgetSource";
206 roles[IndicatorsModelRole::WidgetSource] = "widgetSource";
207 roles[IndicatorsModelRole::PageSource] = "pageSource";
207 roles[IndicatorsModelRole::PageSource] = "pageSource";
208 roles[IndicatorsModelRole::IndicatorProperties] = "indicatorProperties";
208 roles[IndicatorsModelRole::IndicatorProperties] = "indicatorProperties";
209− roles[IndicatorsModelRole::IsValid] = "isValid";
210 }
209 }
211 return roles;
210 return roles;
212}
211}
@@ -269,8 +268,6 @@ QVariant IndicatorsModel::data(const QModelIndex &index, int role) const
269 return QVariant(indicator->indicatorProperties());
268 return QVariant(indicator->indicatorProperties());
270 }
269 }
271 break;
270 break;
272− case IndicatorsModelRole::IsValid:
273− return (indicator ? true : false);
274 case IndicatorsModelRole::Title:
271 case IndicatorsModelRole::Title:
275 case IndicatorsModelRole::Description:
272 case IndicatorsModelRole::Description:
276 case IndicatorsModelRole::WidgetSource:
273 case IndicatorsModelRole::WidgetSource:
plugins/Unity/Indicators/indicatorsmodel.h+2−1
@@ -44,7 +44,7 @@ public:
44 Q_INVOKABLE void load();
44 Q_INVOKABLE void load();
45 Q_INVOKABLE void unload();
45 Q_INVOKABLE void unload();
46
46
47− Q_INVOKABLE QVariant data(int row, int role = Qt::DisplayRole) const;
47+ Q_INVOKABLE QVariant data(int row, int role) const;
48
48
49 /* QAbstractItemModel */
49 /* QAbstractItemModel */
50 QHash<int, QByteArray> roleNames() const;
50 QHash<int, QByteArray> roleNames() const;
@@ -56,6 +56,7 @@ public:
56 void setIndicatorData(const QVariant& data);
56 void setIndicatorData(const QVariant& data);
57 QVariant indicatorData() const;
57 QVariant indicatorData() const;
58
58
59+
59Q_SIGNALS:
60Q_SIGNALS:
60 void countChanged();
61 void countChanged();
61 void indicatorDataChanged(const QVariant& data);
62 void indicatorDataChanged(const QVariant& data);
plugins/Unity/Indicators/plugin.cpp+2
@@ -32,6 +32,7 @@
32#include "rootactionstate.h"
32#include "rootactionstate.h"
33#include "unitymenumodelcache.h"
33#include "unitymenumodelcache.h"
34#include "unitymenumodelstack.h"
34#include "unitymenumodelstack.h"
35+#include "visibleindicatorsmodel.h"
35
36
36static QObject* menuModelCacheSingleton(QQmlEngine* engine, QJSEngine* scriptEngine) {
37static QObject* menuModelCacheSingleton(QQmlEngine* engine, QJSEngine* scriptEngine) {
37 Q_UNUSED(engine);
38 Q_UNUSED(engine);
@@ -47,6 +48,7 @@ void Indicators2Plugin::registerTypes(const char *uri)
47 qmlRegisterType<UnityMenuModelStack>(uri, 0, 1, "UnityMenuModelStack");
48 qmlRegisterType<UnityMenuModelStack>(uri, 0, 1, "UnityMenuModelStack");
48 qmlRegisterType<RootActionState>(uri, 0, 1, "RootActionState");
49 qmlRegisterType<RootActionState>(uri, 0, 1, "RootActionState");
49 qmlRegisterType<ModelPrinter>(uri, 0, 1, "ModelPrinter");
50 qmlRegisterType<ModelPrinter>(uri, 0, 1, "ModelPrinter");
51+ qmlRegisterType<VisibleIndicatorsModel>(uri, 0, 1, "VisibleIndicatorsModel");
50
52
51 qmlRegisterSingletonType<UnityMenuModelCache>(uri, 0, 1, "UnityMenuModelCache", menuModelCacheSingleton);
53 qmlRegisterSingletonType<UnityMenuModelCache>(uri, 0, 1, "UnityMenuModelCache", menuModelCacheSingleton);
52
54
plugins/Unity/Indicators/qml/IndicatorBase.qml−5
@@ -24,8 +24,6 @@ import Unity.Indicators 0.1 as Indicators
24Item {
24Item {
25 id: indicatorItem
25 id: indicatorItem
26
26
27− // FIXME : should be disabled until bus available when we have desktop indicators
28− // for now, disable when we dont habe the correct profile.
29 enabled: menuObjectPaths.hasOwnProperty(device)
27 enabled: menuObjectPaths.hasOwnProperty(device)
30
28
31 //const
29 //const
@@ -39,9 +37,6 @@ Item {
39
37
40 property string deviceMenuObjectPath: menuObjectPaths.hasOwnProperty(device) ? menuObjectPaths[device] : ""
38 property string deviceMenuObjectPath: menuObjectPaths.hasOwnProperty(device) ? menuObjectPaths[device] : ""
41
39
42− signal actionGroupUpdated()
43− signal modelUpdated()
44−
45 property alias menuModel: cachedModel.model
40 property alias menuModel: cachedModel.model
46
41
47 CachedUnityMenuModel {
42 CachedUnityMenuModel {
plugins/Unity/Indicators/qml/IndicatorWidget.qml+1
@@ -24,6 +24,7 @@ IndicatorBase {
24 id: indicatorWidget
24 id: indicatorWidget
25
25
26 active: true
26 active: true
27+ enabled: false
27 property int iconSize: height - units.gu(0.5)
28 property int iconSize: height - units.gu(0.5)
28
29
29 property var actionState: Indicators.RootActionState {
30 property var actionState: Indicators.RootActionState {
plugins/Unity/Indicators/visibleindicatorsmodel.cppnew file+94
@@ -0,0 +1,94 @@
1+/*
2+ * Copyright (C) 2012, 2013 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+// self
18+#include "visibleindicatorsmodel.h"
19+#include "indicators.h"
20+
21+VisibleIndicatorsModel::VisibleIndicatorsModel(QObject *parent)
22+ : QIdentityProxyModel(parent),
23+ m_inserting(false)
24+{
25+ QObject::connect(this, SIGNAL(rowsAboutToBeInserted(QModelIndex, int, int)), this, SLOT(onBeginRowInserted(QModelIndex, int, int)));
26+ QObject::connect(this, SIGNAL(rowsInserted(QModelIndex, int, int)), this, SLOT(onRowInserted(QModelIndex, int, int)));
27+}
28+
29+QHash<int, QByteArray> VisibleIndicatorsModel::roleNames() const
30+{
31+ static QHash<int, QByteArray> roles;
32+ if (roles.isEmpty())
33+ {
34+ roles[IndicatorsModelRole::Identifier] = "identifier";
35+ roles[IndicatorsModelRole::Position] = "position";
36+ roles[IndicatorsModelRole::Title] = "title";
37+ roles[IndicatorsModelRole::Description] = "description";
38+ roles[IndicatorsModelRole::WidgetSource] = "widgetSource";
39+ roles[IndicatorsModelRole::PageSource] = "pageSource";
40+ roles[IndicatorsModelRole::IndicatorProperties] = "indicatorProperties";
41+ roles[IndicatorsModelRole::IsVisible] = "isVisible";
42+ }
43+ return roles;
44+}
45+
46+void VisibleIndicatorsModel::setSourceModel(QAbstractItemModel *model)
47+{
48+ if (sourceModel() != model) {
49+ QIdentityProxyModel::setSourceModel(model);
50+ Q_EMIT modelChanged();
51+ }
52+}
53+
54+QVariantMap VisibleIndicatorsModel::visible() const
55+{
56+ return m_visible;
57+}
58+
59+void VisibleIndicatorsModel::onBeginRowInserted(const QModelIndex&, int, int)
60+{
61+ m_inserting = true;
62+}
63+
64+void VisibleIndicatorsModel::onRowInserted(const QModelIndex&, int, int)
65+{
66+ m_inserting = false;
67+}
68+
69+void VisibleIndicatorsModel::setVisible(const QVariantMap& visible)
70+{
71+ if (m_visible != visible) {
72+ m_visible = visible;
73+ Q_EMIT visibleChanged();
74+
75+ // need to tell the view that the visible data has changed.
76+ if (!m_inserting && rowCount() > 0) {
77+ Q_EMIT dataChanged(index(0, 0), index(rowCount() - 1, 0), QVector<int>() << IndicatorsModelRole::IsVisible);
78+ }
79+ }
80+}
81+
82+QVariant VisibleIndicatorsModel::data(const QModelIndex &index, int role) const
83+{
84+ if (role != IndicatorsModelRole::IsVisible) {
85+ return QIdentityProxyModel::data(index, role);
86+ }
87+
88+ if (!index.isValid()) {
89+ return false;
90+ }
91+
92+ QString ident = QIdentityProxyModel::data(index, IndicatorsModelRole::Identifier).toString();
93+ return m_visible.value(ident, false).toBool();
94+}
plugins/Unity/Indicators/visibleindicatorsmodel.hnew file+56
@@ -0,0 +1,56 @@
1+/*
2+ * Copyright (C) 2012, 2013 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+ * Authors:
17+ * Nick Dedekind <nick.dedekind@canonical.com>
18+ */
19+
20+#ifndef VISIBLEINDICATORSMODEL_H
21+#define VISIBLEINDICATORSMODEL_H
22+
23+#include <QIdentityProxyModel>
24+
25+class VisibleIndicatorsModel : public QIdentityProxyModel
26+{
27+ Q_OBJECT
28+
29+ Q_PROPERTY(QAbstractItemModel* model READ sourceModel WRITE setSourceModel NOTIFY modelChanged)
30+ Q_PROPERTY(QVariantMap visible READ visible WRITE setVisible NOTIFY visibleChanged)
31+
32+public:
33+ explicit VisibleIndicatorsModel(QObject *parent = 0);
34+
35+ virtual void setSourceModel(QAbstractItemModel *model);
36+ virtual QHash<int, QByteArray> roleNames() const;
37+ virtual QVariant data(const QModelIndex &index, int role) const;
38+
39+ QVariantMap visible() const;
40+ void setVisible(const QVariantMap& visible);
41+
42+public Q_SLOTS:
43+ void onBeginRowInserted(const QModelIndex&, int start, int end);
44+ void onRowInserted(const QModelIndex&, int start, int end);
45+
46+Q_SIGNALS:
47+ void totalCountChanged();
48+ void modelChanged();
49+ void visibleChanged();
50+
51+private:
52+ QVariantMap m_visible;
53+ bool m_inserting;
54+};
55+
56+#endif // VISIBLEINDICATORSMODEL_H
plugins/Unity/IndicatorsLegacy/qml/IndicatorWidget.qml+2−2
@@ -23,7 +23,7 @@ import Unity.IndicatorsLegacy 0.1 as Indicators
23IndicatorBase {
23IndicatorBase {
24 id: indicatorWidget
24 id: indicatorWidget
25
25
26−// enabled: false // FIXME : should be disabled until bus available when we have desktop indicators
26+ enabled: false
27 property var action: undefined
27 property var action: undefined
28 property bool started: (busType != 0) && (busName != "") && (deviceMenuObjectPath != "")
28 property bool started: (busType != 0) && (busName != "") && (deviceMenuObjectPath != "")
29 property int iconSize: height - units.gu(0.5)
29 property int iconSize: height - units.gu(0.5)
@@ -40,7 +40,6 @@ IndicatorBase {
40 actionGroup.stop();
40 actionGroup.stop();
41 }
41 }
42 }
42 }
43− onActionChanged: actionStateChanged()
44 onActionGroupUpdated: update_state()
43 onActionGroupUpdated: update_state()
45 onModelUpdated: update_state()
44 onModelUpdated: update_state()
46
45
@@ -57,6 +56,7 @@ IndicatorBase {
57
56
58 if (extra.canonical_type === rootMenuType) {
57 if (extra.canonical_type === rootMenuType) {
59 action = actionGroup.action(proxyModel.data(0, Indicators.FlatMenuProxyModelRole.Action));
58 action = actionGroup.action(proxyModel.data(0, Indicators.FlatMenuProxyModelRole.Action));
59+ actionStateChanged();
60 }
60 }
61 }
61 }
62
62
plugins/Utils/qsortfilterproxymodelqml.cpp+20
@@ -121,3 +121,23 @@ QSortFilterProxyModelQML::findFirst(int role, const QVariant& value) const
121 return -1;
121 return -1;
122 }
122 }
123}
123}
124+
125+int
126+QSortFilterProxyModelQML::mapFromSource(int row)
127+{
128+ if (sourceModel() != NULL) {
129+ return QSortFilterProxyModel::mapFromSource(sourceModel()->index(row, 0)).row();
130+ } else {
131+ return -1;
132+ }
133+}
134+
135+int
136+QSortFilterProxyModelQML::mapToSource(int row)
137+{
138+ if (sourceModel() != NULL) {
139+ return QSortFilterProxyModel::mapToSource(index(row, 0)).row();
140+ } else {
141+ return -1;
142+ }
143+}
plugins/Utils/qsortfilterproxymodelqml.h+3
@@ -45,6 +45,9 @@ public:
45 void setModel(QAbstractItemModel *model);
45 void setModel(QAbstractItemModel *model);
46 void setInvertMatch(bool invertMatch);
46 void setInvertMatch(bool invertMatch);
47
47
48+ Q_INVOKABLE int mapFromSource(int row);
49+ Q_INVOKABLE int mapToSource(int row);
50+
48Q_SIGNALS:
51Q_SIGNALS:
49 void totalCountChanged();
52 void totalCountChanged();
50 void countChanged();
53 void countChanged();
tests/mocks/Unity/Indicators/CMakeLists.txt+1
@@ -13,6 +13,7 @@ set(IndicatorsFakeQml_SOURCES
13 fakeplugin.cpp
13 fakeplugin.cpp
14 ${CMAKE_SOURCE_DIR}/plugins/Unity/Indicators/indicators.h
14 ${CMAKE_SOURCE_DIR}/plugins/Unity/Indicators/indicators.h
15 ${CMAKE_SOURCE_DIR}/plugins/Unity/Indicators/menucontentactivator.cpp
15 ${CMAKE_SOURCE_DIR}/plugins/Unity/Indicators/menucontentactivator.cpp
16+ ${CMAKE_SOURCE_DIR}/plugins/Unity/Indicators/visibleindicatorsmodel.cpp
16)
17)
17
18
18set(IndicatorsFakeQml_RESOURCES
19set(IndicatorsFakeQml_RESOURCES
tests/mocks/Unity/Indicators/IndicatorsModel.qml+47−76
@@ -23,82 +23,53 @@ ListModel {
23
23
24 function load() {}
24 function load() {}
25
25
26− ListElement {
26+ // Need to do this dynamically.
27+ // Apparently ListModels dont order roles visually when using ListElement
28+ // which throws off the filter for non-visible indicators.
29+ Component.onCompleted: {
27− identifier: "indicator-fake1";
30+ append({ "identifier": "indicator-fake1",
28− priority: 0
31+ "priority": 0,
29− title: "Menu1";
32+ "title": "Menu1",
30− description: "";
33+ "description": "",
31− widgetSource: "qrc:/tests/indciators/qml/fake_menu_widget1.qml";
34+ "widgetSource": "qrc:/tests/indciators/qml/fake_menu_widget1.qml",
32− pageSource: "qrc:/tests/indciators/qml/fake_menu_page1.qml";
35+ "pageSource": "qrc:/tests/indciators/qml/fake_menu_page1.qml",
33− indicatorProperties: "";
34− isValid: "";
35− }
36− ListElement {
37− identifier: "indicator-fake2";
38− priority: 1
39− title: "Menu2";
40− description: "";
41− widgetSource: "qrc:/tests/indciators/qml/fake_menu_widget2.qml";
42− pageSource: "qrc:/tests/indciators/qml/fake_menu_page2.qml";
43− indicatorProperties: "";
36+ "indicatorProperties": ""
44− isValid: "";
45− }
46− ListElement {
47− identifier: "indicator-fake3";
48− priority: 2
49− title: "Menu3";
50− description: "";
51− widgetSource: "qrc:/tests/indciators/qml/fake_menu_widget3.qml";
52− pageSource: "qrc:/tests/indciators/qml/fake_menu_page3.qml";
53− indicatorProperties: "";
54− isValid: "";
55− }
37+ });
56− ListElement {
57− identifier: "indicator-fake4";
58− priority: 3
59− title: "Menu4";
60− description: "";
61− widgetSource: "qrc:/tests/indciators/qml/fake_menu_widget4.qml";
62− pageSource: "qrc:/tests/indciators/qml/fake_menu_page4.qml";
63− indicatorProperties: "";
64− isValid: "";
65− }
66− ListElement {
67− identifier: "indicator-fake5";
68− priority: 4
69− title: "Menu5";
70− description: "";
71− widgetSource: "qrc:/tests/indciators/qml/fake_menu_widget5.qml";
72− pageSource: "qrc:/tests/indciators/qml/fake_menu_page5.qml";
73− indicatorProperties: "";
74− isValid: "";
75− }
76
38
77− function data(row, role) {
39+ append({ "identifier": "indicator-fake2",
78− if (role == Indicators.IndicatorsModelRole.Identifier) {
40+ "priority": 1,
79− return get(row).identifier;
41+ "title": "Menu2",
80− }
42+ "description": "",
81− else if (role == Indicators.IndicatorsModelRole.Priority) {
43+ "widgetSource": "qrc:/tests/indciators/qml/fake_menu_widget2.qml",
82− return get(row).priority
44+ "pageSource": "qrc:/tests/indciators/qml/fake_menu_page2.qml",
83− }
45+ "indicatorProperties": ""
84− else if (role == Indicators.IndicatorsModelRole.Title) {
85− return get(row).title
86− }
46+ });
87− else if (role == Indicators.IndicatorsModelRole.Description) {
47+
88− return get(row).description
48+ append({ "identifier": "indicator-fake3",
89− }
49+ "priority": 2,
90− else if (role == Indicators.IndicatorsModelRole.WidgetSource) {
50+ "title": "Menu3",
91− return get(row).widgetSource
51+ "description": "",
92− }
52+ "widgetSource": "qrc:/tests/indciators/qml/fake_menu_widget3.qml",
93− else if (role == Indicators.IndicatorsModelRole.PageSource) {
53+ "pageSource": "qrc:/tests/indciators/qml/fake_menu_page3.qml",
94− return get(row).pageSource
54+ "indicatorProperties": ""
95− }
96− else if (role == Indicators.IndicatorsModelRole.IndicatorProperties) {
97− return get(row).indicatorProperties
98− }
99− else if (role == Indicators.IndicatorsModelRole.IsValid) {
100− return get(row).isValid
101− }
102− }
55+ });
103
56
57+ append({ "identifier": "indicator-fake4",
58+ "priority": 3,
59+ "title": "Menu4",
60+ "description": "",
61+ "widgetSource": "qrc:/tests/indciators/qml/fake_menu_widget4.qml",
62+ "pageSource": "qrc:/tests/indciators/qml/fake_menu_page4.qml",
63+ "indicatorProperties": ""
64+ });
65+
66+ append({ "identifier": "indicator-fake5",
67+ "priority": 4,
68+ "title": "Menu5",
69+ "description": "",
70+ "widgetSource": "qrc:/tests/indciators/qml/fake_menu_widget5.qml",
71+ "pageSource": "qrc:/tests/indciators/qml/fake_menu_page5.qml",
72+ "indicatorProperties": ""
73+ });
74+ }
104}
75}
tests/mocks/Unity/Indicators/fakeplugin.cpp+2
@@ -25,12 +25,14 @@
25// local
25// local
26#include "indicators.h"
26#include "indicators.h"
27#include "menucontentactivator.h"
27#include "menucontentactivator.h"
28+#include "visibleindicatorsmodel.h"
28
29
29void IndicatorsFakePlugin::registerTypes(const char * uri)
30void IndicatorsFakePlugin::registerTypes(const char * uri)
30{
31{
31 Q_INIT_RESOURCE(indicators_fake);
32 Q_INIT_RESOURCE(indicators_fake);
32
33
33 qmlRegisterType<MenuContentActivator>(uri, 0, 1, "MenuContentActivator");
34 qmlRegisterType<MenuContentActivator>(uri, 0, 1, "MenuContentActivator");
35+ qmlRegisterType<VisibleIndicatorsModel>(uri, 0, 1, "VisibleIndicatorsModel");
34
36
35 qmlRegisterUncreatableType<MenuContentState>(uri, 0, 1, "MenuContentState", "Can't create MenuContentState class");
37 qmlRegisterUncreatableType<MenuContentState>(uri, 0, 1, "MenuContentState", "Can't create MenuContentState class");
36 qmlRegisterUncreatableType<ActionState>(uri, 0, 1, "ActionState", "Can't create ActionState class");
38 qmlRegisterUncreatableType<ActionState>(uri, 0, 1, "ActionState", "Can't create ActionState class");
tests/mocks/Unity/Indicators/qml/fake_menu_widget2.qml+2
@@ -20,4 +20,6 @@ Rectangle {
20 width: 40
20 width: 40
21 height: 40
21 height: 40
22 color : "yellow"
22 color : "yellow"
23+
24+ enabled: false
23}
25}
tests/qmltests/CMakeLists.txt+1−1
@@ -66,7 +66,7 @@ add_qml_test(Launcher Launcher IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltes
66add_qml_test(Notifications Notifications IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_SOURCE_DIR}/tests/mocks)
66add_qml_test(Notifications Notifications IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_SOURCE_DIR}/tests/mocks)
67add_qml_test(Panel IndicatorRow)
67add_qml_test(Panel IndicatorRow)
68add_qml_test(Panel Indicators IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
68add_qml_test(Panel Indicators IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
69−add_qml_test(Panel MenuContent)
69+add_qml_test(Panel MenuContent IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
70add_qml_test(Panel Panel IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
70add_qml_test(Panel Panel IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
71add_qml_test(Panel SearchIndicator)
71add_qml_test(Panel SearchIndicator)
72add_qml_test(SideStage SideStage IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS}
72add_qml_test(SideStage SideStage IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS}
tests/qmltests/Panel/tst_IndicatorItem.qml+2−2
@@ -53,9 +53,9 @@ Rectangle {
53 }
53 }
54
54
55 function test_empty() {
55 function test_empty() {
56− compare(indicatorItem.visible, false, "IndicatorItem should not be visible.");
56+ compare(indicatorItem.indicatorVisible, false, "IndicatorItem should not be visible.");
57 indicatorItem.widgetSource = "qrc:/tests/indciators/qml/fake_menu_widget1.qml";
57 indicatorItem.widgetSource = "qrc:/tests/indciators/qml/fake_menu_widget1.qml";
58− tryCompare(indicatorItem, "visible", true);
58+ tryCompare(indicatorItem, "indicatorVisible", true);
59 }
59 }
60 }
60 }
61}
61}
tests/qmltests/Panel/tst_Indicators.qml+30−11
@@ -100,26 +100,29 @@ Item {
100 {
100 {
101 // tests changing the lateral position of the revealer activates the correct indicator items.
101 // tests changing the lateral position of the revealer activates the correct indicator items.
102
102
103− var indicator_row = findChild(indicators, "indicatorRow")
103+ var indicatorRow = findChild(indicators, "indicatorRow")
104− var row_repeater = findChild(indicators, "rowRepeater")
104+ var rowRepeater = findChild(indicators, "rowRepeater")
105
105
106− for (var i = 0; i < row_repeater.count; i++) {
106+ for (var i = 0; i < rowRepeater.count; i++) {
107− var indicator_item = row_repeater.itemAt(i);
107+ var indicatorItem = rowRepeater.itemAt(i);
108
108
109+ if (!indicatorItem.visible)
110+ continue;
111+
109− var indicator_position = indicators.mapFromItem(indicator_item,
112+ var indicatorPosition = indicators.mapFromItem(indicatorItem,
110− indicator_item.width/2, indicator_item.height/2)
113+ indicatorItem.width/2, indicatorItem.height/2)
111
114
112 touchFlick(indicators,
115 touchFlick(indicators,
113− indicator_position.x, indicator_position.y,
116+ indicatorPosition.x, indicatorPosition.y,
114− indicator_position.x, indicators.openedHeight * 0.4,
117+ indicatorPosition.x, indicators.openedHeight * 0.4,
115 true /* beginTouch */, false /* endTouch */)
118 true /* beginTouch */, false /* endTouch */)
116
119
117− compare(indicator_row.currentItem, indicator_item,
120+ compare(indicatorRow.currentItem, indicatorItem,
118 "Incorrect item activated at position " + i);
121 "Incorrect item activated at position " + i);
119
122
120 touchFlick(indicators,
123 touchFlick(indicators,
121− indicator_position.x, indicators.openedHeight * 0.4,
124+ indicatorPosition.x, indicators.openedHeight * 0.4,
122− indicator_position.x, indicator_position.y,
125+ indicatorPosition.x, indicatorPosition.y,
123 false /* beginTouch */, true /* endTouch */)
126 false /* beginTouch */, true /* endTouch */)
124
127
125 // wait until fully closed
128 // wait until fully closed
@@ -158,5 +161,21 @@ Item {
158 compare(indicators.fullyOpened, true);
161 compare(indicators.fullyOpened, true);
159 }
162 }
160
163
164+ function test_row_visible_menuContent_visible_data() { return [
165+ {tag: "visible", index: 0, name: "indicator-fake1", visible: true },
166+ {tag: "invisible", index: 1, name: "indicator-fake2", visible: false }]
167+ }
168+
169+ function test_row_visible_menuContent_visible(data) {
170+ var indicatorTabs = findChild(indicators, "tabs");
171+ var rowRepeater = findChild(indicators, "rowRepeater");
172+
173+ var indicatorItem = rowRepeater.itemAt(data.index);
174+ tryCompareFunction(function() { return indicatorItem.width > 0}, true);
175+ tryCompare(indicatorItem, "visible", data.visible);
176+
177+ var indicatorTab = findChild(indicatorTabs, data.name)
178+ tryCompareFunction(function() { return indicatorTab !== undefined }, data.visible);
179+ }
161 }
180 }
162}
181}
tests/qmltests/Panel/tst_MenuContent.qml+9−2
@@ -48,8 +48,15 @@ Item {
48 id: menuContent
48 id: menuContent
49 indicatorsModel: indicatorsModel
49 indicatorsModel: indicatorsModel
50 contentReleaseInterval: 50
50 contentReleaseInterval: 50
51−
52 height: parent.height - 50
51 height: parent.height - 50
52+
53+ visibleIndicators: {
54+ 'indicator-fake1': true,
55+ 'indicator-fake2': true,
56+ 'indicator-fake3': true,
57+ 'indicator-fake4': true,
58+ 'indicator-fake5': true
59+ }
53 }
60 }
54
61
55 Rectangle {
62 Rectangle {
@@ -134,7 +141,7 @@ Item {
134 var menuIndex = i%menuCount;
141 var menuIndex = i%menuCount;
135
142
136 activate_content(menuIndex);
143 activate_content(menuIndex);
137− testTabObjectName = indicatorsModel.data(menuIndex, Indicators.IndicatorsModelRole.Identifier);
144+ testTabObjectName = indicatorsModel.get(menuIndex).identifier;
138 compare(tabs.selectedTabIndex, menuIndex, "Current tab index does not match selected tab index");
145 compare(tabs.selectedTabIndex, menuIndex, "Current tab index does not match selected tab index");
139 tryCompareFunction(selected_tab_equals_test_tab, true);
146 tryCompareFunction(selected_tab_equals_test_tab, true);
140 }
147 }
tests/qmltests/Panel/tst_Panel.qml+3
@@ -159,6 +159,9 @@ Item {
159 var indicatorItem = get_indicator_item(i);
159 var indicatorItem = get_indicator_item(i);
160 verify(indicatorItem != undefined);
160 verify(indicatorItem != undefined);
161
161
162+ if (!indicatorItem.visible)
163+ continue;
164+
162 var indicatorItemCoord = get_indicator_item_position(i);
165 var indicatorItemCoord = get_indicator_item_position(i);
163
166
164 touchPress(panel,
167 touchPress(panel,