on xenial help sign in
Update fake/mock plugins so that "./run --fake" works well again
040db36Daniel d'Andrada
tests/mocks/Unity/CMakeLists.txt+2
@@ -17,6 +17,8 @@ add_definitions(-DQT_NO_KEYWORDS)
17
17
18set(UnityQML_SOURCES
18set(UnityQML_SOURCES
19 ${CMAKE_SOURCE_DIR}/plugins/Unity/categoryresults.cpp
19 ${CMAKE_SOURCE_DIR}/plugins/Unity/categoryresults.cpp
20+ fake_applications_scope.cpp
21+ fake_preview.cpp
20 fake_scope.cpp
22 fake_scope.cpp
21 fake_scopes.cpp
23 fake_scopes.cpp
22 fake_categories.cpp
24 fake_categories.cpp
tests/mocks/Unity/fake_applications_scope.cppnew file+68
@@ -0,0 +1,68 @@
1+/*
2+ * Copyright (C) 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+#include "fake_applications_scope.h"
18+
19+static const gchar * categories_model_schema[] = {
20+ "s", //ID
21+ "s", // DISPLAY_NAME
22+ "s", // ICON_HINT
23+ "s", // RENDERER_NAME
24+ "a{sv}" // HINTS
25+};
26+
27+ApplicationsScope::ApplicationsScope(bool visible, QObject* parent)
28+ : Scope(parent)
29+{
30+ m_id = "applications.scope";
31+ m_name = "Applications";
32+ m_visible = visible;
33+ m_categories->setModel(createCategoriesModel());
34+}
35+
36+DeeModel* ApplicationsScope::createCategoriesModel()
37+{
38+ DeeModel* category_model = dee_sequence_model_new();
39+ dee_model_set_schema_full(category_model, categories_model_schema, G_N_ELEMENTS(categories_model_schema));
40+ GVariant* hints = g_variant_new_array(g_variant_type_element(G_VARIANT_TYPE_VARDICT), NULL, 0);
41+
42+ GVariant* children[1];
43+ children[0] = g_variant_new_dict_entry(g_variant_new_string("content-type"),
44+ g_variant_new_variant(g_variant_new_string("apps")));
45+ GVariant* recentHints = g_variant_new_array(g_variant_type_element(G_VARIANT_TYPE_VARDICT), children, 1);
46+ dee_model_append(category_model,
47+ "recent",
48+ "Recent",
49+ "gtk-apply",
50+ "special",
51+ recentHints);
52+
53+ dee_model_append(category_model,
54+ "installed",
55+ "Installed",
56+ "gtk-apply",
57+ "grid",
58+ hints);
59+
60+ dee_model_append(category_model,
61+ "suggested",
62+ "Suggested",
63+ "gtk-apply",
64+ "grid",
65+ hints);
66+
67+ return category_model;
68+}
tests/mocks/Unity/fake_applications_scope.hnew file+33
@@ -0,0 +1,33 @@
1+/*
2+ * Copyright (C) 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+#ifndef FAKE_APPLICATIONS_SCOPE_H
18+#define FAKE_APPLICATIONS_SCOPE_H
19+
20+#include "fake_scope.h"
21+
22+class ApplicationsScope : public Scope
23+{
24+ Q_OBJECT
25+
26+public:
27+ ApplicationsScope(bool visible, QObject* parent = 0);
28+
29+private:
30+ DeeModel* createCategoriesModel();
31+};
32+
33+#endif // FAKE_APPLICATIONS_SCOPE_H
tests/mocks/Unity/fake_categories.cpp+84−9
@@ -24,11 +24,20 @@
24
24
25#define CATEGORY_COLUMN 2
25#define CATEGORY_COLUMN 2
26
26
27+// TODO: use something from libunity once it's public
28+enum CategoryColumn {
29+ ID,
30+ DISPLAY_NAME,
31+ ICON_HINT,
32+ RENDERER_NAME,
33+ HINTS
34+};
35+
27Categories::Categories(QObject* parent)
36Categories::Categories(QObject* parent)
28 : DeeListModel(parent)
37 : DeeListModel(parent)
29{
38{
30 // FIXME: need to clean up unused filters on countChanged
39 // FIXME: need to clean up unused filters on countChanged
31− m_roles[Categories::RoleId] = "id";
40+ m_roles[Categories::RoleCategoryId] = "categoryId";
32 m_roles[Categories::RoleName] = "name";
41 m_roles[Categories::RoleName] = "name";
33 m_roles[Categories::RoleIcon] = "icon";
42 m_roles[Categories::RoleIcon] = "icon";
34 m_roles[Categories::RoleRenderer] = "renderer";
43 m_roles[Categories::RoleRenderer] = "renderer";
@@ -74,6 +83,25 @@ Categories::onCountChanged()
74 }
83 }
75}
84}
76
85
86+void Categories::onRowCountChanged()
87+{
88+ QAbstractItemModel* model = qobject_cast<QAbstractItemModel*>(sender());
89+ // find the corresponding category index
90+ for (auto iter = m_overriddenCategories.begin(); iter != m_overriddenCategories.end(); ++iter) {
91+ if (iter.value() == model) {
92+ for (int i = 0; i < rowCount(); i++) {
93+ auto id = data(index(i), RoleCategoryId).toString();
94+ if (id != iter.key()) continue;
95+ QVector<int> roles;
96+ roles.append(RoleCount);
97+ QModelIndex changedIndex = index(i);
98+ Q_EMIT dataChanged(changedIndex, changedIndex, roles);
99+ break;
100+ }
101+ }
102+ }
103+}
104+
77void
105void
78Categories::onEmitCountChanged()
106Categories::onEmitCountChanged()
79{
107{
@@ -93,6 +121,41 @@ Categories::roleNames() const
93 return m_roles;
121 return m_roles;
94}
122}
95
123
124+void Categories::onOverrideModelDestroyed()
125+{
126+ QObject* model = sender();
127+ auto iter = m_overriddenCategories.begin();
128+ while (iter != m_overriddenCategories.end()) {
129+ if (iter.value() == model) {
130+ iter = m_overriddenCategories.erase(iter);
131+ continue;
132+ }
133+ ++iter;
134+ }
135+}
136+
137+void Categories::overrideResults(const QString& categoryId, QAbstractItemModel* model)
138+{
139+ m_overriddenCategories[categoryId] = model;
140+ // watch the model
141+ connect(model, &QObject::destroyed, this, &Categories::onOverrideModelDestroyed);
142+ connect(model, &QAbstractItemModel::rowsInserted, this, &Categories::onRowCountChanged);
143+ connect(model, &QAbstractItemModel::rowsRemoved, this, &Categories::onRowCountChanged);
144+ connect(model, &QAbstractItemModel::modelReset, this, &Categories::onRowCountChanged);
145+
146+ // emit the dataChanged signal if the category is already in the model
147+ for (int i = 0; i < rowCount(); i++) {
148+ auto id = data(index(i), RoleCategoryId).toString();
149+ if (id != categoryId) continue;
150+ QVector<int> roles;
151+ roles.append(RoleCount);
152+ roles.append(RoleResults);
153+ QModelIndex changedIndex = index(i);
154+ Q_EMIT dataChanged(changedIndex, changedIndex, roles);
155+ break;
156+ }
157+}
158+
96void Categories::setResultModel(DeeModel* model)
159void Categories::setResultModel(DeeModel* model)
97{
160{
98 // FIXME: should ref it
161 // FIXME: should ref it
@@ -154,24 +217,36 @@ Categories::data(const QModelIndex& index, int role) const
154 }
217 }
155
218
156 switch (role) {
219 switch (role) {
157− case RoleId:
220+ case RoleCategoryId:
158− return DeeListModel::data(index, 0); //ID
221+ return DeeListModel::data(index, CategoryColumn::ID);
159 case RoleName:
222 case RoleName:
160− return DeeListModel::data(index, 1); //DISPLAY_NAME
223+ return DeeListModel::data(index, CategoryColumn::DISPLAY_NAME);
161 case RoleIcon:
224 case RoleIcon:
162− return DeeListModel::data(index, 2); //ICON_HINT
225+ return DeeListModel::data(index, CategoryColumn::ICON_HINT);
163 case RoleRenderer:
226 case RoleRenderer:
164− return DeeListModel::data(index, 3); //RENDERER_NAME
227+ return DeeListModel::data(index, CategoryColumn::RENDERER_NAME);
165 case RoleContentType:
228 case RoleContentType:
166 {
229 {
167− auto hints = DeeListModel::data(index, 4).toHash();
230+ auto hints = DeeListModel::data(index, CategoryColumn::HINTS).toHash();
168− return hints.contains("content-type") ? hints["content-type"] : QVariant(QString("default"));
231+ return hints.contains("content-type") ? hints["content-type"] : QVariant(QString("default"));
169 }
232 }
170 case RoleHints:
233 case RoleHints:
171− return DeeListModel::data(index, 4); //HINTS
234+ return DeeListModel::data(index, CategoryColumn::HINTS);
172 case RoleResults:
235 case RoleResults:
236+ if (m_overriddenCategories.size() > 0)
237+ {
238+ auto id = DeeListModel::data(index, CategoryColumn::ID).toString();
239+ if (m_overriddenCategories.find(id) != m_overriddenCategories.end())
240+ return QVariant::fromValue(m_overriddenCategories[id]);
241+ }
173 return QVariant::fromValue(getFilter(index.row()));
242 return QVariant::fromValue(getFilter(index.row()));
174 case RoleCount:
243 case RoleCount:
244+ if (m_overriddenCategories.size() > 0)
245+ {
246+ auto id = DeeListModel::data(index, CategoryColumn::ID).toString();
247+ if (m_overriddenCategories.find(id) != m_overriddenCategories.end())
248+ return QVariant::fromValue(m_overriddenCategories[id]->rowCount());
249+ }
175 return QVariant::fromValue(getFilter(index.row())->rowCount());
250 return QVariant::fromValue(getFilter(index.row())->rowCount());
176 case RoleCategoryIndex:
251 case RoleCategoryIndex:
177 return QVariant::fromValue(index.row());
252 return QVariant::fromValue(index.row());
tests/mocks/Unity/fake_categories.h+6−1
@@ -34,7 +34,7 @@ class Categories : public DeeListModel
34public:
34public:
35 Categories(QObject* parent = 0);
35 Categories(QObject* parent = 0);
36 enum Roles {
36 enum Roles {
37− RoleId,
37+ RoleCategoryId,
38 RoleName,
38 RoleName,
39 RoleIcon,
39 RoleIcon,
40 RoleRenderer,
40 RoleRenderer,
@@ -45,6 +45,8 @@ public:
45 RoleCategoryIndex
45 RoleCategoryIndex
46 };
46 };
47
47
48+ Q_INVOKABLE void overrideResults(const QString& categoryId, QAbstractItemModel* model);
49+
48 QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
50 QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
49
51
50 QHash<int, QByteArray> roleNames() const;
52 QHash<int, QByteArray> roleNames() const;
@@ -54,7 +56,9 @@ public:
54
56
55private Q_SLOTS:
57private Q_SLOTS:
56 void onCountChanged();
58 void onCountChanged();
59+ void onRowCountChanged();
57 void onEmitCountChanged();
60 void onEmitCountChanged();
61+ void onOverrideModelDestroyed();
58
62
59private:
63private:
60 DeeModel* getResultsForCategory(unsigned index) const;
64 DeeModel* getResultsForCategory(unsigned index) const;
@@ -64,6 +68,7 @@ private:
64 QTimer m_timer;
68 QTimer m_timer;
65 QSet<DeeListModel*> m_timerFilters;
69 QSet<DeeListModel*> m_timerFilters;
66 QHash<int, QByteArray> m_roles;
70 QHash<int, QByteArray> m_roles;
71+ QMap<QString, QAbstractItemModel*> m_overriddenCategories;
67 mutable QMap<int, DeeListModel*> m_filters;
72 mutable QMap<int, DeeListModel*> m_filters;
68};
73};
69
74
tests/mocks/Unity/fake_preview.cppnew file+66
@@ -0,0 +1,66 @@
1+/*
2+ * Copyright (C) 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+#include "fake_preview.h"
18+
19+QString Preview::rendererName() const
20+{
21+ return "foo";
22+}
23+
24+QString Preview::title() const
25+{
26+ return "Title";
27+}
28+
29+QString Preview::subtitle() const
30+{
31+ return "Subtitle";
32+}
33+
34+QString Preview::description() const
35+{
36+ return "Description";
37+}
38+
39+QVariant Preview::actions()
40+{
41+ return QVariant();
42+}
43+
44+QVariant Preview::infoHints()
45+{
46+ return QVariant();
47+}
48+
49+QVariantMap Preview::infoHintsHash() const
50+{
51+ return QVariantMap();
52+}
53+
54+QString Preview::image() const
55+{
56+ return "";
57+}
58+
59+QString Preview::imageSourceUri() const
60+{
61+ return "";
62+}
63+
64+void Preview::execute(const QString& actionId, const QHash<QString, QVariant>& hints)
65+{
66+}
tests/mocks/Unity/fake_preview.hnew file+62
@@ -0,0 +1,62 @@
1+/*
2+ * Copyright (C) 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+#ifndef FAKE_PREVIEW_H
18+#define FAKE_PREVIEW_H
19+
20+// Qt
21+#include <QObject>
22+#include <QString>
23+#include <QMetaType>
24+#include <QList>
25+#include <QVariantMap>
26+
27+class Q_DECL_EXPORT Preview : public QObject
28+{
29+ Q_OBJECT
30+
31+ Q_PROPERTY(QString rendererName READ rendererName NOTIFY previewChanged)
32+ Q_PROPERTY(QString title READ title NOTIFY previewChanged)
33+ Q_PROPERTY(QString subtitle READ subtitle NOTIFY previewChanged)
34+ Q_PROPERTY(QString description READ description NOTIFY previewChanged)
35+ Q_PROPERTY(QVariant actions READ actions NOTIFY previewChanged)
36+ Q_PROPERTY(QVariant infoHints READ infoHints NOTIFY previewChanged)
37+ Q_PROPERTY(QVariantMap infoMap READ infoHintsHash NOTIFY previewChanged)
38+ Q_PROPERTY(QString image READ image NOTIFY previewChanged)
39+ Q_PROPERTY(QString imageSourceUri READ imageSourceUri NOTIFY previewChanged)
40+
41+public:
42+ explicit Preview(QObject *parent = 0);
43+
44+ QString rendererName() const;
45+ QString title() const;
46+ QString subtitle() const;
47+ QString description() const;
48+ QVariant actions();
49+ QVariant infoHints();
50+ QVariantMap infoHintsHash() const;
51+ QString image() const;
52+ QString imageSourceUri() const;
53+
54+ Q_INVOKABLE void execute(const QString& actionId, const QHash<QString, QVariant>& hints);
55+
56+Q_SIGNALS:
57+ void previewChanged();
58+};
59+
60+Q_DECLARE_METATYPE(Preview *)
61+
62+#endif // FAKE_PREVIEW_H
tests/mocks/Unity/fake_scope.cpp+33−9
@@ -20,6 +20,8 @@
20#include <dee.h>
20#include <dee.h>
21#include "paths.h"
21#include "paths.h"
22
22
23+#include "fake_preview.h"
24+
23static DeeModel* create_categories_model(unsigned category_count);
25static DeeModel* create_categories_model(unsigned category_count);
24static DeeModel* create_results_model(unsigned category_count, unsigned result_count);
26static DeeModel* create_results_model(unsigned category_count, unsigned result_count);
25
27
@@ -127,6 +129,36 @@ void Scope::setNoResultsHint(const QString& str) {
127 }
129 }
128}
130}
129
131
132+void Scope::activate(const QVariant &uri, const QVariant &icon_hint, const QVariant &category,
133+ const QVariant &result_type, const QVariant &mimetype, const QVariant &title,
134+ const QVariant &comment, const QVariant &dnd_uri, const QVariant &metadata)
135+{
136+ Q_UNUSED(uri);
137+ Q_UNUSED(icon_hint);
138+ Q_UNUSED(category);
139+ Q_UNUSED(result_type);
140+ Q_UNUSED(mimetype);
141+ Q_UNUSED(title);
142+ Q_UNUSED(comment);
143+ Q_UNUSED(dnd_uri);
144+ Q_UNUSED(metadata);
145+}
146+
147+void Scope::preview(const QVariant &uri, const QVariant &icon_hint, const QVariant &category,
148+ const QVariant &result_type, const QVariant &mimetype, const QVariant &title,
149+ const QVariant &comment, const QVariant &dnd_uri, const QVariant &metadata)
150+{
151+ Q_UNUSED(uri);
152+ Q_UNUSED(icon_hint);
153+ Q_UNUSED(category);
154+ Q_UNUSED(result_type);
155+ Q_UNUSED(mimetype);
156+ Q_UNUSED(title);
157+ Q_UNUSED(comment);
158+ Q_UNUSED(dnd_uri);
159+ Q_UNUSED(metadata);
160+}
161+
130static const gchar * categories_model_schema[] = {
162static const gchar * categories_model_schema[] = {
131 "s", //ID
163 "s", //ID
132 "s", // DISPLAY_NAME
164 "s", // DISPLAY_NAME
@@ -168,14 +200,6 @@ static const gchar * results_model_schema[] = {
168 "a{sv}" // METADATA
200 "a{sv}" // METADATA
169};
201};
170
202
171−static const gchar * icons[] = {
172− "Applications.png",
173− "Home.png",
174− "Music.png",
175− "People.png",
176− "Videos.png",
177−};
178−
179DeeModel* create_results_model(unsigned category_count, unsigned result_count) {
203DeeModel* create_results_model(unsigned category_count, unsigned result_count) {
180 DeeModel* results_model = dee_sequence_model_new();
204 DeeModel* results_model = dee_sequence_model_new();
181 dee_model_set_schema_full(results_model, results_model_schema, G_N_ELEMENTS(results_model_schema));
205 dee_model_set_schema_full(results_model, results_model_schema, G_N_ELEMENTS(results_model_schema));
@@ -187,7 +211,7 @@ DeeModel* create_results_model(unsigned category_count, unsigned result_count) {
187
211
188 dee_model_append(results_model,
212 dee_model_append(results_model,
189 ("uri://result."+std::to_string(i)).c_str(),
213 ("uri://result."+std::to_string(i)).c_str(),
190− (shellAppDirectory() + "Dash/graphics/scopeIcons/" + (icons[i%G_N_ELEMENTS(icons)])).toLatin1().data(),
214+ (shellAppDirectory() + "graphics/applicationIcons/dash.png").toLatin1().data(),
191 category,
215 category,
192 0,
216 0,
193 "application/x-desktop",
217 "application/x-desktop",
tests/mocks/Unity/fake_scope.h+15−1
@@ -21,6 +21,8 @@
21#include <QObject>
21#include <QObject>
22#include "fake_categories.h"
22#include "fake_categories.h"
23
23
24+class Preview;
25+
24class Scope : public QObject
26class Scope : public QObject
25{
27{
26 Q_OBJECT
28 Q_OBJECT
@@ -63,6 +65,13 @@ public:
63 void setNoResultsHint(const QString& hint);
65 void setNoResultsHint(const QString& hint);
64 void setFormFactor(const QString& form_factor);
66 void setFormFactor(const QString& form_factor);
65
67
68+ Q_INVOKABLE void activate(const QVariant &uri, const QVariant &icon_hint, const QVariant &category,
69+ const QVariant &result_type, const QVariant &mimetype, const QVariant &title,
70+ const QVariant &comment, const QVariant &dnd_uri, const QVariant &metadata);
71+ Q_INVOKABLE void preview(const QVariant &uri, const QVariant &icon_hint, const QVariant &category,
72+ const QVariant &result_type, const QVariant &mimetype, const QVariant &title,
73+ const QVariant &comment, const QVariant &dnd_uri, const QVariant &metadata);
74+
66Q_SIGNALS:
75Q_SIGNALS:
67 void idChanged(const QString&);
76 void idChanged(const QString&);
68 void nameChanged(const QString&);
77 void nameChanged(const QString&);
@@ -78,7 +87,12 @@ Q_SIGNALS:
78 void noResultsHintChanged();
87 void noResultsHintChanged();
79 void formFactorChanged();
88 void formFactorChanged();
80
89
81−private:
90+ // signals triggered by activate(..) or preview(..) requests.
91+ void previewReady(Preview *preview);
92+ void activateApplication(const QString &desktop);
93+
94+protected:
95+
82 QString m_id;
96 QString m_id;
83 QString m_iconHint;
97 QString m_iconHint;
84 QString m_description;
98 QString m_description;
tests/mocks/Unity/fake_scopes.cpp+4−1
@@ -19,6 +19,9 @@
19// Self
19// Self
20#include "fake_scopes.h"
20#include "fake_scopes.h"
21
21
22+// Local
23+#include "fake_applications_scope.h"
24+
22// TODO: Implement remaining pieces, like Categories (i.e. LensView now gives warnings)
25// TODO: Implement remaining pieces, like Categories (i.e. LensView now gives warnings)
23
26
24// Qt
27// Qt
@@ -53,7 +56,7 @@ void Scopes::updateScopes()
53 addScope(new Scope("MockScope1", "People", true, this));
56 addScope(new Scope("MockScope1", "People", true, this));
54 addScope(new Scope("MockScope2", "Music", false, this));
57 addScope(new Scope("MockScope2", "Music", false, this));
55 addScope(new Scope("home.scope", "Home", true, this));
58 addScope(new Scope("home.scope", "Home", true, this));
56− addScope(new Scope("applications.scope", "Applications", true, this));
59+ addScope(new ApplicationsScope(true, this));
57 addScope(new Scope("MockScope5", "Videos", true, this));
60 addScope(new Scope("MockScope5", "Videos", true, this));
58
61
59 if (!m_loaded) {
62 if (!m_loaded) {