on xenial help sign in
Support switching indicator profiles between normal and greeter versions
commitc2435700d68c044cbb21092538decc2db5e3cac0 authorMichael Terry <michael.terry@canonical.com> dateFri 3 Oct 2014, 10:08 (12 years ago) parente384844
15 files changed+129−26
plugins/Unity/Indicators/indicator.cpp+25−8 plugins/Unity/Indicators/indicator.h+4 plugins/Unity/Indicators/indicatorsmanager.cpp+15−1 plugins/Unity/Indicators/indicatorsmanager.h+5 plugins/Unity/Indicators/indicatorsmodel.cpp+23 plugins/Unity/Indicators/indicatorsmodel.h+5 plugins/Unity/Indicators/rootactionstate.cpp+3−1 plugins/Unity/Indicators/unitymenumodelcache.cpp+6−7 qml/Panel/IndicatorItem.qml+9−1 qml/Panel/Indicators.qml+1−2 qml/Panel/Indicators/DefaultIndicatorPage.qml−1 qml/Panel/Indicators/DefaultIndicatorWidget.qml+2−1 qml/Panel/Indicators/VisibleIndicators.qml+13−2 qml/Panel/MenuContent.qml+15−2 qml/Shell.qml+3
plugins/Unity/Indicators/indicator.cpp+25−8
@@ -33,23 +33,27 @@ Indicator::~Indicator()
3333
3434void Indicator::init(const QString &profile, const QString& busName, const QSettings& settings)
3535{
36− setId(settings.value("Indicator Service/Name").toString());
36+ // Save all keys we care about from the QSettings object. It's annoying
37+ // that we can't just copy the object.
38+ m_settings.clear();
39+ Q_FOREACH(const QString& key, settings.allKeys()) {
40+ if (key.endsWith("/Position") || key.endsWith("/ObjectPath")) {
41+ m_settings.insert(key, settings.value(key));
42+ }
43+ }
3744
38− QVariant pos = settings.value(profile + "/Position");
39− if (!pos.isValid())
40− pos = settings.value("Indicator Service/Position", QVariant::fromValue(0));
41− setPosition(pos.toInt());
45+ setId(settings.value("Indicator Service/Name").toString());
4246
4347 QString actionObjectPath = settings.value("Indicator Service/ObjectPath").toString();
44− QString menuObjectPath = settings.value(profile + "/ObjectPath").toString();
4548
4649 QVariantMap properties;
4750 properties.clear();
4851 properties.insert("busType", 1);
4952 properties.insert("busName", busName);
5053 properties.insert("actionsObjectPath", actionObjectPath);
51− properties.insert("menuObjectPath", menuObjectPath);
52− setIndicatorProperties(properties);
54+
55+ m_properties = properties;
56+ setProfile(profile); // will emit changed signals for us and set position
5357}
5458
5559QString Indicator::identifier() const
@@ -78,6 +82,19 @@ void Indicator::setPosition(int position)
7882 }
7983}
8084
85+void Indicator::setProfile(const QString& profile)
86+{
87+ QVariant pos = m_settings.value(profile + "/Position");
88+ if (!pos.isValid())
89+ pos = m_settings.value("Indicator Service/Position", QVariant::fromValue(0));
90+ setPosition(pos.toInt());
91+
92+ QString menuObjectPath = m_settings.value(profile + "/ObjectPath").toString();
93+ QVariantMap map = m_properties.toMap();
94+ map.insert("menuObjectPath", menuObjectPath);
95+ setIndicatorProperties(map);
96+}
97+
8198QVariant Indicator::indicatorProperties() const
8299{
83100 return m_properties;
plugins/Unity/Indicators/indicator.h+4
@@ -41,6 +41,9 @@ public:
4141 int position() const;
4242 QVariant indicatorProperties() const;
4343
44+public Q_SLOTS:
45+ void setProfile(const QString& profile);
46+
4447Q_SIGNALS:
4548 void identifierChanged(const QString &identifier);
4649 void positionChanged(int position);
@@ -55,6 +58,7 @@ private:
5558 QString m_identifier;
5659 int m_position;
5760 QVariant m_properties;
61+ QVariantMap m_settings;
5862};
5963
6064#endif // INDICATOR_H
plugins/Unity/Indicators/indicatorsmanager.cpp+15−1
@@ -57,7 +57,7 @@ IndicatorsManager::~IndicatorsManager()
5757void IndicatorsManager::load(const QString& profile)
5858{
5959 unload();
60− m_profile = profile;
60+ setProfile(profile);
6161
6262 QStringList xdgLocations = shellDataDirs();//QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation);
6363
@@ -216,6 +216,19 @@ void IndicatorsManager::setLoaded(bool loaded)
216216 }
217217}
218218
219+QString IndicatorsManager::profile() const
220+{
221+ return m_profile;
222+}
223+
224+void IndicatorsManager::setProfile(const QString& profile)
225+{
226+ if (m_profile != profile) {
227+ m_profile = profile;
228+ Q_EMIT profileChanged(m_profile);
229+ }
230+}
231+
219232void IndicatorsManager::startVerify(const QString& path)
220233{
221234 QHashIterator<QString, IndicatorData*> iter(m_indicatorsData);
@@ -269,6 +282,7 @@ Indicator::Ptr IndicatorsManager::indicator(const QString& indicator_name)
269282 data->m_indicator = new_indicator;
270283 QSettings settings(data->m_fileInfo.absoluteFilePath(), QSettings::IniFormat, this);
271284 new_indicator->init(m_profile, data->m_fileInfo.fileName(), settings);
285+ QObject::connect(this, SIGNAL(profileChanged(const QString&)), new_indicator.data(), SLOT(setProfile(const QString&)));
272286 return new_indicator;
273287}
274288
plugins/Unity/Indicators/indicatorsmanager.h+5
@@ -32,6 +32,7 @@ class UNITYINDICATORS_EXPORT IndicatorsManager : public QObject
3232{
3333 Q_OBJECT
3434 Q_PROPERTY(bool loaded READ isLoaded NOTIFY loadedChanged)
35+ Q_PROPERTY(QString profile READ profile WRITE setProfile NOTIFY profileChanged)
3536public:
3637 explicit IndicatorsManager(QObject* parent = 0);
3738 ~IndicatorsManager();
@@ -39,6 +40,9 @@ public:
3940 Q_INVOKABLE void load(const QString& profile);
4041 Q_INVOKABLE void unload();
4142
43+ QString profile() const;
44+ void setProfile(const QString& profile);
45+
4246 Indicator::Ptr indicator(const QString& indicator_name);
4347
4448 QList<Indicator::Ptr> indicators();
@@ -47,6 +51,7 @@ public:
4751
4852Q_SIGNALS:
4953 void loadedChanged(bool);
54+ void profileChanged(const QString&);
5055
5156 void indicatorLoaded(const QString& indicator_name);
5257 void indicatorAboutToBeUnloaded(const QString& indicator_name);
plugins/Unity/Indicators/indicatorsmodel.cpp+23
@@ -56,6 +56,7 @@ IndicatorsModel::IndicatorsModel(QObject *parent)
5656 m_manager = new IndicatorsManager(this);
5757 QObject::connect(m_manager, SIGNAL(indicatorLoaded(const QString&)), this, SLOT(onIndicatorLoaded(const QString&)));
5858 QObject::connect(m_manager, SIGNAL(indicatorAboutToBeUnloaded(const QString&)), this, SLOT(onIndicatorAboutToBeUnloaded(const QString&)));
59+ QObject::connect(m_manager, SIGNAL(profileChanged(const QString&)), this, SIGNAL(profileChanged()));
5960
6061 QObject::connect(this, SIGNAL(rowsInserted(const QModelIndex &, int, int)), this, SIGNAL(countChanged()));
6162 QObject::connect(this, SIGNAL(rowsRemoved(const QModelIndex &, int, int)), this, SIGNAL(countChanged()));
@@ -80,6 +81,28 @@ int IndicatorsModel::count() const
8081 return rowCount();
8182}
8283
84+/*!
85+ \qmlproperty IndicatorsModel::profile
86+ The indicator profile to use for the model.
87+
88+ \b Note: methods should only be called after the Component has completed.
89+*/
90+QString IndicatorsModel::profile() const
91+{
92+ return m_manager->profile();
93+}
94+
95+/*!
96+ \qmlproperty IndicatorsModel::setProfile
97+ Set the indicator profile to use for the model.
98+
99+ \b Note: methods should only be called after the Component has completed.
100+*/
101+void IndicatorsModel::setProfile(const QString &profile)
102+{
103+ m_manager->setProfile(profile);
104+}
105+
83106/*!
84107 \qmlmethod IndicatorsModel::unload()
85108
plugins/Unity/Indicators/indicatorsmodel.h+5
@@ -34,6 +34,7 @@ class UNITYINDICATORS_EXPORT IndicatorsModel : public QAbstractListModel
3434 Q_OBJECT
3535 Q_ENUMS(Roles)
3636 Q_PROPERTY(int count READ count NOTIFY countChanged)
37+ Q_PROPERTY(QString profile READ profile WRITE setProfile NOTIFY profileChanged)
3738
3839public:
3940
@@ -45,6 +46,9 @@ public:
4546
4647 Q_INVOKABLE QVariant data(int row, int role) const;
4748
49+ QString profile() const;
50+ void setProfile(const QString& profile);
51+
4852 /* QAbstractItemModel */
4953 QHash<int, QByteArray> roleNames() const;
5054 int columnCount(const QModelIndex &parent = QModelIndex()) const;
@@ -55,6 +59,7 @@ public:
5559
5660Q_SIGNALS:
5761 void countChanged();
62+ void profileChanged();
5863 void indicatorDataChanged(const QVariant& data);
5964
6065private Q_SLOTS:
plugins/Unity/Indicators/rootactionstate.cpp+3−1
@@ -110,9 +110,11 @@ void RootActionState::updateActionState()
110110 m_cachedState = m_menu->get(0, "actionState").toMap();
111111
112112 m_menu->setActionStateParser(oldParser);
113− } else {
113+ } else if (!m_menu) {
114114 m_cachedState.clear();
115115 }
116+ // else if m_menu->rowCount() == 0, let's leave existing cache in place
117+ // until the new menu comes in, to avoid flashing the UI empty for a moment
116118 Q_EMIT updated();
117119}
118120
plugins/Unity/Indicators/unitymenumodelcache.cpp+6−7
@@ -36,13 +36,12 @@ UnityMenuModel* UnityMenuModelCache::model(const QByteArray& bus,
3636 if (m_registry.contains(path))
3737 return m_registry[path];
3838
39− UnityMenuModel* menuModel = new UnityMenuModel;
40− connect(menuModel, &QObject::destroyed, this, [menuModel, this](QObject*) {
41− QList<QByteArray> keys = m_registry.keys(menuModel);
42− Q_FOREACH(const QByteArray& key, keys) {
43− m_registry.remove(key);
44− }
45− });
39+ // Parent the model to us, so it is not deleted by Qml. We want to keep
40+ // all models cached, because when we switch indicator profiles, we will
41+ // be switching paths often. And we want to keep the old model around,
42+ // ready to be used. Otherwise the UI might momentarily wait as we
43+ // populate the model from DBus yet again.
44+ UnityMenuModel* menuModel = new UnityMenuModel(this);
4645 m_registry[path] = menuModel;
4746
4847 menuModel->setBusName(bus);
qml/Panel/IndicatorItem.qml+9−1
@@ -31,7 +31,7 @@ Loader {
3131 opacity: dimmed ? 0.4 : 1
3232 Behavior on opacity { UbuntuNumberAnimation { duration: UbuntuAnimation.BriskDuration } }
3333
34− onLoaded: {
34+ function updateProperties() {
3535 for(var pName in indicatorProperties) {
3636 if (item.hasOwnProperty(pName)) {
3737 item[pName] = indicatorProperties[pName];
@@ -39,6 +39,14 @@ Loader {
3939 }
4040 }
4141
42+ onLoaded: updateProperties()
43+
44+ onIndicatorPropertiesChanged: {
45+ if (status === Loader.Ready) {
46+ updateProperties()
47+ }
48+ }
49+
4250 Binding {
4351 target: item
4452 property: "identifier"
qml/Panel/Indicators.qml+1−2
@@ -30,8 +30,7 @@ Showable {
3030 property int panelHeight: units.gu(3)
3131 property alias overFlowWidth: indicatorRow.overFlowWidth
3232 property alias showAll: indicatorRow.showAll
33− // TODO: This should be sourced by device type (eg "desktop", "tablet", "phone"...)
34− property string profile: indicatorProfile
33+ property alias profile: visibleIndicators.profile
3534
3635 readonly property real hintValue: panelHeight + menuContent.headerHeight
3736 readonly property int lockThreshold: openedHeight / 2
qml/Panel/Indicators/DefaultIndicatorPage.qml−1
@@ -125,7 +125,6 @@ IndicatorBase {
125125 delegate: Loader {
126126 id: loader
127127 objectName: "menuItem" + index
128− asynchronous: true
129128 width: ListView.view.width
130129 visible: status == Loader.Ready
131130
qml/Panel/Indicators/DefaultIndicatorWidget.qml+2−1
@@ -113,7 +113,8 @@ IndicatorBase {
113113
114114 leftLabel = rootActionState.leftLabel ? rootActionState.leftLabel : "";
115115 rightLabel = rootActionState.rightLabel ? rootActionState.rightLabel : "";
116− icons = rootActionState.icons;
116+ if (icons !== rootActionState.icons) // don't reset visual unless we need to
117+ icons = rootActionState.icons;
117118 enabled = rootActionState.visible;
118119 }
119120}
qml/Panel/Indicators/VisibleIndicators.qml+13−2
@@ -23,6 +23,7 @@ import Utils 0.1
2323
2424Item {
2525 property SortFilterProxyModel model: filterModel
26+ property alias profile: indicatorsModel.profile
2627
2728 SortFilterProxyModel {
2829 id: filterModel
@@ -56,13 +57,23 @@ Item {
5657 id: item
5758 objectName: model.identifier + "-delegate"
5859 identifier: model.identifier
59− Component.onCompleted: {
60+
61+ function updateProperties() {
6062 for(var pName in indicatorProperties) {
6163 if (item.hasOwnProperty(pName)) {
6264 item[pName] = indicatorProperties[pName];
6365 }
6466 }
65− updateVisibility();
67+ }
68+
69+ Component.onCompleted: {
70+ updateProperties()
71+ updateVisibility()
72+ }
73+
74+ Connections {
75+ target: indicatorsModel
76+ onDataChanged: item.updateProperties()
6677 }
6778
6879 onEnabledChanged: {
qml/Panel/MenuContent.qml+15−2
@@ -69,13 +69,20 @@ Rectangle {
6969
7070 IndicatorDelegate {
7171 id: indicatorDelegate
72− Component.onCompleted: {
72+
73+ function updateProperties() {
7374 for(var pName in indicatorProperties) {
7475 if (indicatorDelegate.hasOwnProperty(pName)) {
7576 indicatorDelegate[pName] = indicatorProperties[pName];
7677 }
7778 }
7879 }
80+
81+ Component.onCompleted: updateProperties()
82+ Connections {
83+ target: content.indicatorsModel
84+ onDataChanged: indicatorDelegate.updateProperties()
85+ }
7986 }
8087 }
8188 }
@@ -115,7 +122,7 @@ Rectangle {
115122 }
116123 }
117124
118− onLoaded: {
125+ function updateProperties() {
119126 for(var pName in indicatorProperties) {
120127 if (item.hasOwnProperty(pName)) {
121128 item[pName] = indicatorProperties[pName]
@@ -123,6 +130,12 @@ Rectangle {
123130 }
124131 }
125132
133+ onLoaded: updateProperties()
134+ Connections {
135+ target: content.indicatorsModel
136+ onDataChanged: if (loader.status === Loader.Ready) loader.updateProperties()
137+ }
138+
126139 Binding {
127140 target: loader.item
128141 property: "identifier"
qml/Shell.qml+3
@@ -574,6 +574,9 @@ Item {
574574 contentEnabled: edgeDemo.panelContentEnabled
575575 width: parent.width > units.gu(60) ? units.gu(40) : parent.width
576576 panelHeight: units.gu(3)
577+
578+ // TODO: This should be sourced by device type (eg "desktop", "tablet", "phone"...)
579+ profile: LightDM.Greeter.active ? (indicatorProfile + "_greeter") : indicatorProfile
577580 }
578581
579582 property bool topmostApplicationIsFullscreen: