on xenial help sign in
implement onlyPinned property
commit191c091ea0e99a4c3af477e8d1680be5623cbfb3 authorMichael Zanetti <michael.zanetti@canonical.com> dateMon 9 Feb 2015, 18:17 (12 years ago) parent4c28595
11 files changed+131−42
debian/control+1−1 plugins/Greeter/Unity/Launcher/launchermodelas.cpp+41−13 plugins/Greeter/Unity/Launcher/launchermodelas.h+4 plugins/Unity/Launcher/asadapter.cpp+1 plugins/Unity/Launcher/launchermodel.cpp+9 plugins/Unity/Launcher/launchermodel.h+3 tests/mocks/Unity/Launcher/MockLauncherModel.cpp+10 tests/mocks/Unity/Launcher/MockLauncherModel.h+3 tests/plugins/Greeter/Unity/Launcher/AccountsServiceDBusAdaptor.cpp+2−3 tests/plugins/Greeter/Unity/Launcher/AccountsServiceDBusAdaptor.h+2−3 tests/plugins/Greeter/Unity/Launcher/launchermodelastest.cpp+55−22
debian/control+1−1
@@ -27,7 +27,7 @@ Build-Depends: cmake,
2727 libqmenumodel-dev (>= 0.2.9),
2828 libqt5xmlpatterns5-dev,
2929 libsystemsettings-dev,
30− libunity-api-dev (>= 7.94),
30+ libunity-api-dev (>= 7.95),
3131 libusermetricsoutput1-dev,
3232 libxcb1-dev,
3333 pkg-config,
plugins/Greeter/Unity/Launcher/launchermodelas.cpp+41−13
@@ -30,7 +30,8 @@ using namespace unity::shell::application;
3030
3131LauncherModel::LauncherModel(QObject *parent):
3232 LauncherModelInterface(parent),
33− m_accounts(new AccountsServiceDBusAdaptor(this))
33+ m_accounts(new AccountsServiceDBusAdaptor(this)),
34+ m_onlyPinned(true)
3435{
3536 connect(m_accounts, &AccountsServiceDBusAdaptor::propertiesChanged, this, &LauncherModel::propertiesChanged);
3637 refresh();
@@ -162,6 +163,20 @@ void LauncherModel::setApplicationManager(unity::shell::application::Application
162163 return;
163164}
164165
166+bool LauncherModel::onlyPinned() const
167+{
168+ return m_onlyPinned;
169+}
170+
171+void LauncherModel::setOnlyPinned(bool onlyPinned)
172+{
173+ if (m_onlyPinned != onlyPinned) {
174+ m_onlyPinned = onlyPinned;
175+ Q_EMIT onlyPinnedChanged();
176+ refresh();
177+ }
178+}
179+
165180int LauncherModel::findApplication(const QString &appId)
166181{
167182 for (int i = 0; i < m_list.count(); ++i) {
@@ -189,13 +204,17 @@ void LauncherModel::refresh()
189204 bool found = false;
190205 Q_FOREACH(const QVariant &asItem, items) {
191206 if (asItem.toMap().value("id").toString() == item->appId()) {
192− found = true;
193− item->setName(asItem.toMap().value("name").toString());
194− item->setIcon(asItem.toMap().value("icon").toString());
195− item->setCount(asItem.toMap().value("count").toInt());
196− item->setCountVisible(asItem.toMap().value("countVisible").toBool());
197− int idx = m_list.indexOf(item);
198− Q_EMIT dataChanged(index(idx), index(idx), QVector<int>() << RoleName << RoleIcon);
207+ // Only keep and update it if we either show unpinned or it is pinned
208+ if (!m_onlyPinned || asItem.toMap().value("pinned").toBool()) {
209+ found = true;
210+ item->setName(asItem.toMap().value("name").toString());
211+ item->setIcon(asItem.toMap().value("icon").toString());
212+ item->setCount(asItem.toMap().value("count").toInt());
213+ item->setCountVisible(asItem.toMap().value("countVisible").toBool());
214+ int idx = m_list.indexOf(item);
215+ Q_EMIT dataChanged(index(idx), index(idx), QVector<int>() << RoleName << RoleIcon);
216+ }
217+ break;
199218 }
200219 }
201220 if (!found) {
@@ -211,8 +230,17 @@ void LauncherModel::refresh()
211230 }
212231
213232 // Now walk through list and see if we need to add something
233+ int skipped = 0;
214234 for (int asIndex = 0; asIndex < items.count(); ++asIndex) {
215235 QVariant entry = items.at(asIndex);
236+
237+ if (m_onlyPinned && !entry.toMap().value("pinned").toBool()) {
238+ // Skipping it as we only show pinned and it is not
239+ skipped++;
240+ continue;
241+ }
242+ int newPosition = asIndex - skipped;
243+
216244 int itemIndex = -1;
217245 for (int i = 0; i < m_list.count(); ++i) {
218246 if (m_list.at(i)->appId() == entry.toMap().value("id").toString()) {
@@ -230,14 +258,14 @@ void LauncherModel::refresh()
230258 item->setPinned(true);
231259 item->setCount(entry.toMap().value("count").toInt());
232260 item->setCountVisible(entry.toMap().value("countVisible").toBool());
233− beginInsertRows(QModelIndex(), asIndex, asIndex);
234− m_list.insert(asIndex, item);
261+ beginInsertRows(QModelIndex(), newPosition, newPosition);
262+ m_list.insert(newPosition, item);
235263 endInsertRows();
236− } else if (itemIndex != asIndex) {
264+ } else if (itemIndex != newPosition) {
237265 // The item is already there, but it is in a different place than in the settings.
238266 // Move it to the addedIndex
239− beginMoveRows(QModelIndex(), itemIndex, itemIndex, QModelIndex(), asIndex);
240− m_list.move(itemIndex, asIndex);
267+ beginMoveRows(QModelIndex(), itemIndex, itemIndex, QModelIndex(), newPosition);
268+ m_list.move(itemIndex, newPosition);
241269 endMoveRows();
242270 }
243271 }
plugins/Greeter/Unity/Launcher/launchermodelas.h+4
@@ -54,6 +54,9 @@ public:
5454 unity::shell::application::ApplicationManagerInterface* applicationManager() const;
5555 void setApplicationManager(unity::shell::application::ApplicationManagerInterface *appManager);
5656
57+ bool onlyPinned() const override;
58+ void setOnlyPinned(bool onlyPinned) override;
59+
5760 int findApplication(const QString &appId);
5861
5962public Q_SLOTS:
@@ -67,6 +70,7 @@ private:
6770 QString m_user;
6871 QList<LauncherItem*> m_list;
6972 AccountsServiceDBusAdaptor *m_accounts;
73+ bool m_onlyPinned;
7074
7175 friend class LauncherModelASTest;
7276};
plugins/Unity/Launcher/asadapter.cpp+1
@@ -58,5 +58,6 @@ QVariantMap ASAdapter::itemToVariant(LauncherItem *item) const
5858 details.insert("icon", item->icon());
5959 details.insert("count", item->count());
6060 details.insert("countVisible", item->countVisible());
61+ details.insert("pinned", item->pinned());
6162 return details;
6263}
plugins/Unity/Launcher/launchermodel.cpp+9
@@ -265,6 +265,15 @@ void LauncherModel::setApplicationManager(unity::shell::application::Application
265265 }
266266}
267267
268+bool LauncherModel::onlyPinned() const
269+{
270+ return false;
271+}
272+
273+void LauncherModel::setOnlyPinned(bool onlyPinned) {
274+ Q_UNUSED(onlyPinned);
275+ qWarning() << "This launcher implementation does not support showing only pinned apps";
276+}
268277
269278void LauncherModel::storeAppList()
270279{
plugins/Unity/Launcher/launchermodel.h+3
@@ -55,6 +55,9 @@ public:
5555 unity::shell::application::ApplicationManagerInterface* applicationManager() const;
5656 void setApplicationManager(unity::shell::application::ApplicationManagerInterface *appManager);
5757
58+ bool onlyPinned() const override;
59+ void setOnlyPinned(bool onlyPinned) override;
60+
5861 int findApplication(const QString &appId);
5962
6063public Q_SLOTS:
tests/mocks/Unity/Launcher/MockLauncherModel.cpp+10
@@ -209,6 +209,16 @@ void MockLauncherModel::setApplicationManager(unity::shell::application::Applica
209209 Q_UNUSED(applicationManager)
210210}
211211
212+bool MockLauncherModel::onlyPinned() const
213+{
214+ return false;
215+}
216+
217+void MockLauncherModel::setOnlyPinned(bool onlyPinned)
218+{
219+ Q_UNUSED(onlyPinned)
220+}
221+
212222void MockLauncherModel::emitHint()
213223{
214224 Q_EMIT hint();
tests/mocks/Unity/Launcher/MockLauncherModel.h+3
@@ -49,6 +49,9 @@ public:
4949 unity::shell::application::ApplicationManagerInterface *applicationManager() const;
5050 void setApplicationManager(unity::shell::application::ApplicationManagerInterface *applicationManager);
5151
52+ bool onlyPinned() const override;
53+ void setOnlyPinned(bool onlyPinned) override;
54+
5255 // For testing
5356 Q_INVOKABLE void emitHint();
5457
tests/plugins/Greeter/Unity/Launcher/AccountsServiceDBusAdaptor.cpp+2−3
@@ -31,12 +31,11 @@ AccountsServiceDBusAdaptor::AccountsServiceDBusAdaptor(QObject* parent)
3131
3232QVariant AccountsServiceDBusAdaptor::getUserProperty(const QString &user, const QString &interface, const QString &property)
3333{
34− Q_UNUSED(user)
3534 Q_UNUSED(interface)
3635 Q_UNUSED(property) // We only fake one property here (LauncherItems)
3736
3837 QDBusMessage msg;
39− QVariant v = QVariant::fromValue(properties);
38+ QVariant v = QVariant::fromValue(mockProperties.value(user));
4039 QDBusVariant dv(v);
4140 QVariant packed = QVariant::fromValue(dv);
4241 msg << packed;
@@ -47,6 +46,6 @@ QVariant AccountsServiceDBusAdaptor::getUserProperty(const QString &user, const
4746void AccountsServiceDBusAdaptor::simulatePropertyChange(const QString &user, const QString &property, const QVariant &value)
4847{
4948 Q_ASSERT(property == "LauncherItems");
50− properties = value.value<QList<QVariantMap>>();
49+ mockProperties[user] = value.value<QList<QVariantMap>>();
5150 Q_EMIT propertiesChanged(user, "com.canonical.unity.AccountsService", QStringList() << property);
5251}
tests/plugins/Greeter/Unity/Launcher/AccountsServiceDBusAdaptor.h+2−3
@@ -26,7 +26,7 @@
2626#include <QHash>
2727#include <QDBusArgument>
2828
29−extern QList<QVariantMap> properties;
29+extern QHash<QString, QList<QVariantMap>> mockProperties;
3030
3131class AccountsServiceDBusAdaptor: public QObject
3232{
@@ -38,10 +38,9 @@ public:
3838 Q_INVOKABLE QVariant getUserProperty(const QString &user, const QString &interface, const QString &property);
3939 template <typename T>
4040 inline T getUserProperty(const QString &user, const QString &interface, const QString &property) {
41− Q_UNUSED(user)
4241 Q_UNUSED(interface)
4342 Q_ASSERT(property == "LauncherItems");
44− T ret = properties;
43+ T ret = mockProperties[user];
4544 return ret;
4645 }
4746
tests/plugins/Greeter/Unity/Launcher/launchermodelastest.cpp+55−22
@@ -27,7 +27,7 @@
2727
2828#include <QtTest>
2929
30−QList<QVariantMap> properties;
30+QHash<QString, QList<QVariantMap>> mockProperties;
3131
3232class LauncherModelASTest : public QObject
3333{
@@ -47,22 +47,30 @@ private Q_SLOTS:
4747 item.insert("icon", "fake.svg");
4848 item.insert("count", 0);
4949 item.insert("countVisible", false);
50+ item.insert("pinned", true);
5051 list.append(item);
5152 item["id"] = "appId2";
5253 item["name"] = "Item 2";
5354 list.append(item);
54− properties = list;
55+ mockProperties["user1"] = list;
5556 }
5657
57− bool isInSync(LauncherModel *model) {
58− // Verify after startup the items are in there
59− bool inSync = model->rowCount() == properties.count();
60− for (int i = 0; i < model->rowCount(); i++) {
61− inSync &= model->get(i)->appId() == properties.at(i).value("id").toString();
62− inSync &= model->get(i)->name() == properties.at(i).value("name").toString();
63− inSync &= model->get(i)->icon() == properties.at(i).value("icon").toString();
64− inSync &= model->get(i)->count() == properties.at(i).value("count").toInt();
65− inSync &= model->get(i)->countVisible() == properties.at(i).value("countVisible").toBool();
58+ bool isInSync(LauncherModel *model, const QList<QVariantMap> &properties) {
59+ QList<QVariantMap> list;
60+ // Strip unpinned if onlyPinned is set
61+ Q_FOREACH (const QVariantMap &map, properties) {
62+ if (!model->onlyPinned() || map.value("pinned").toBool()) {
63+ list << map;
64+ }
65+ }
66+
67+ bool inSync = model->rowCount() == list.count();
68+ for (int i = 0; inSync && i < model->rowCount(); i++) {
69+ inSync &= model->get(i)->appId() == list.at(i).value("id").toString();
70+ inSync &= model->get(i)->name() == list.at(i).value("name").toString();
71+ inSync &= model->get(i)->icon() == list.at(i).value("icon").toString();
72+ inSync &= model->get(i)->count() == list.at(i).value("count").toInt();
73+ inSync &= model->get(i)->countVisible() == list.at(i).value("countVisible").toBool();
6674 }
6775 return inSync;
6876 }
@@ -74,9 +82,9 @@ private Q_SLOTS:
7482 // We didn't set a user yet. model should be empty
7583 QCOMPARE(model->rowCount(), 0);
7684
77− model->setUser("dummy");
85+ model->setUser("user1");
7886
79− QCOMPARE(isInSync(model), true);
87+ QCOMPARE(isInSync(model, mockProperties["user1"]), true);
8088 model->deleteLater();
8189 }
8290
@@ -85,8 +93,8 @@ private Q_SLOTS:
8593 QTest::addColumn<QString>("changedUser");
8694 QTest::addColumn<bool>("inSync");
8795
88− QTest::newRow("this user changed") << "dummy" << "dummy" << true;
89− QTest::newRow("other user changed") << "dummy" << "fred" << false;
96+ QTest::newRow("this user changed") << "user1" << "user1" << true;
97+ QTest::newRow("other user changed") << "user1" << "user2" << false;
9098 }
9199
92100 void testASChangedUpdatesModel() {
@@ -97,42 +105,67 @@ private Q_SLOTS:
97105 LauncherModel* model = new LauncherModel(this);
98106 model->setUser(modelUser);
99107
100− int oldCount = properties.count();
108+ int oldCount = mockProperties[modelUser].count();
101109 QCOMPARE(model->rowCount(), oldCount);
102110
103− QList<QVariantMap> newList = properties;
111+ QList<QVariantMap> newList;
104112 QVariantMap newEntry;
105113 newEntry.insert("id", "newappId");
106114 newEntry.insert("name", "New app");
107115 newEntry.insert("icon", "some-icon.svg");
108116 newEntry.insert("count", 0);
109117 newEntry.insert("countVisible", false);
118+ newEntry.insert("pinned", true);
110119 newList.append(newEntry);
111120 model->m_accounts->simulatePropertyChange(changedUser, "LauncherItems", QVariant::fromValue(newList));
112121
113− QCOMPARE(isInSync(model), inSync);
122+ QCOMPARE(isInSync(model, mockProperties[modelUser]), true);
123+ QCOMPARE(isInSync(model, mockProperties[changedUser]), inSync);
114124
115125 model->deleteLater();
116126 }
117127
118128 void testUpdateCount() {
119129 LauncherModel* model = new LauncherModel(this);
120− model->setUser("dummy");
130+ model->setUser("user1");
121131
122132 QCOMPARE(model->get(0)->countVisible(), false);
123133 QCOMPARE(model->get(0)->count(), 0);
124134
125− QList<QVariantMap> newList = properties;
135+ QList<QVariantMap> newList = mockProperties["user1"];
126136 QVariantMap entry = newList.at(0);
127137 entry["countVisible"] = true;
128138 entry["count"] = 55;
129139 newList[0] = entry;
130− model->m_accounts->simulatePropertyChange("dummy", "LauncherItems", QVariant::fromValue(newList));
140+ model->m_accounts->simulatePropertyChange("user1", "LauncherItems", QVariant::fromValue(newList));
131141
132− QCOMPARE(isInSync(model), true);
142+ QCOMPARE(isInSync(model, mockProperties["user1"]), true);
133143
134144 model->deleteLater();
135145 }
146+
147+ void testOnlyPinned() {
148+ LauncherModel *model = new LauncherModel(this);
149+ model->setUser("user1");
150+ model->setOnlyPinned(true);
151+
152+ QCOMPARE(isInSync(model, mockProperties["user1"]), true);
153+
154+ // Let's unpin one item
155+ QList<QVariantMap> newList = mockProperties["user1"];
156+ QVariantMap entry = newList.at(0);
157+ entry["pinned"] = false;
158+ newList[0] = entry;
159+ model->m_accounts->simulatePropertyChange("user1", "LauncherItems", QVariant::fromValue(newList));
160+ QCOMPARE(isInSync(model, mockProperties["user1"]), true);
161+
162+ // Now toggle onlyPinned and make sure the model keeps up
163+ model->setOnlyPinned(false);
164+ QCOMPARE(isInSync(model, mockProperties["user1"]), true);
165+
166+ model->setOnlyPinned(true);
167+ QCOMPARE(isInSync(model, mockProperties["user1"]), true);
168+ }
136169};
137170
138171QTEST_GUILESS_MAIN(LauncherModelASTest)