Merge lp:~mardy/ubuntu-system-settings-online-accounts/lp1373279 into lp:~online-accounts/ubuntu-system-settings-online-accounts/master

Proposed by Alberto Mardegan
Status: Merged
Merged at revision: 227
Proposed branch: lp:~mardy/ubuntu-system-settings-online-accounts/lp1373279
Merge into: lp:~online-accounts/ubuntu-system-settings-online-accounts/master
Diff against target: 580 lines (+505/-8)
8 files modified
.bzrignore (+1/-0)
system-settings-plugin/online-accounts.settings (+2/-6)
system-settings-plugin/plugin.cpp (+116/-0)
system-settings-plugin/plugin.h (+36/-0)
system-settings-plugin/system-settings-plugin.pro (+24/-1)
tests/system-settings-plugin/system-settings-plugin.pro (+32/-0)
tests/system-settings-plugin/tst_plugin.cpp (+292/-0)
tests/tests.pro (+2/-1)
To merge this branch: bzr merge lp:~mardy/ubuntu-system-settings-online-accounts/lp1373279
Reviewer Review Type Date Requested Status
Alexandre Abreu (community) Approve
Review via email: mp+247453@code.launchpad.net

Commit message

Add account data as search keywords

Description of the change

Add account data as search keywords

To post a comment you must log in.
Revision history for this message
Alexandre Abreu (abreu-alexandre) wrote :

small comment inline

review: Needs Fixing
226. By Alberto Mardegan

Avoid inserting duplicate keywords

227. By Alberto Mardegan

Added tests

228. By Alberto Mardegan

Remove unnecessary friend

Revision history for this message
Alberto Mardegan (mardy) wrote :

I fixed the code as suggested by Alex, and added some unit tests.

Revision history for this message
Alexandre Abreu (abreu-alexandre) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file '.bzrignore'
--- .bzrignore 2014-12-11 12:51:46 +0000
+++ .bzrignore 2015-02-02 15:22:49 +0000
@@ -57,3 +57,4 @@
57/tests/online-accounts-ui/tst_notification57/tests/online-accounts-ui/tst_notification
58/tests/online-accounts-ui/tst_signonui_request58/tests/online-accounts-ui/tst_signonui_request
59/tests/plugin/tst_application_manager59/tests/plugin/tst_application_manager
60/tests/system-settings-plugin/tst_plugin
6061
=== modified file 'system-settings-plugin/online-accounts.settings'
--- system-settings-plugin/online-accounts.settings 2014-09-24 19:05:32 +0000
+++ system-settings-plugin/online-accounts.settings 2015-02-02 15:22:49 +0000
@@ -14,14 +14,10 @@
14 "access",14 "access",
15 "authorize",15 "authorize",
16 "revoke",16 "revoke",
17 "web",17 "web"
18 "facebook",
19 "twitter",
20 "flickr",
21 "google",
22 "gmail"
23 ],18 ],
24 "has-dynamic-keywords": true,19 "has-dynamic-keywords": true,
25 "has-dynamic-visibility": false,20 "has-dynamic-visibility": false,
21 "plugin": "online-accounts",
26 "page-component": "MainPage.qml"22 "page-component": "MainPage.qml"
27}23}
2824
=== added file 'system-settings-plugin/plugin.cpp'
--- system-settings-plugin/plugin.cpp 1970-01-01 00:00:00 +0000
+++ system-settings-plugin/plugin.cpp 2015-02-02 15:22:49 +0000
@@ -0,0 +1,116 @@
1/*
2 * Copyright (C) 2015 Canonical Ltd.
3 *
4 * Contact: Alberto Mardegan <alberto.mardegan@canonical.com>
5 *
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 3, as published
8 * by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranties of
12 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
13 * PURPOSE. See the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include "plugin.h"
20
21#include <Accounts/Account>
22#include <Accounts/Manager>
23#include <Accounts/Provider>
24#include <Accounts/Service>
25#include <QDebug>
26#include <QStringList>
27#include <SystemSettings/ItemBase>
28#include <libintl.h>
29
30using namespace SystemSettings;
31
32class Item: public ItemBase
33{
34 Q_OBJECT
35
36public:
37 Item(const QVariantMap &staticData, QObject *parent = 0);
38 ~Item();
39
40private:
41 void computeKeywords();
42};
43
44Item::Item(const QVariantMap &staticData, QObject *parent):
45 ItemBase(staticData, parent)
46{
47 computeKeywords();
48}
49
50Item::~Item()
51{
52}
53
54static QStringList translations(const QString &text, const QString &domain)
55{
56 /* Return a list of keywords based on a translatable name:
57 * - the untranslated text (lowercase, split into words)
58 * - the translated text (lowercase, split into words)
59 */
60 QStringList keys;
61 keys = text.toLower().split(" ", QString::SkipEmptyParts);
62 if (!domain.isEmpty()) {
63 QByteArray baText = text.toUtf8();
64 QByteArray baDomain = domain.toUtf8();
65 QString translated = QString::fromUtf8(dgettext(baDomain.constData(),
66 baText.constData()));
67 if (translated != text) {
68 keys.append(translated.toLower().split(" ",
69 QString::SkipEmptyParts));
70 }
71 }
72 return keys;
73}
74
75void Item::computeKeywords()
76{
77 Accounts::Manager *manager = new Accounts::Manager;
78
79 QStringList keywords;
80
81 /* List available providers, and add their names to the search keywords */
82 Q_FOREACH(const Accounts::Provider &provider, manager->providerList()) {
83 keywords.append(provider.name().toLower());
84 keywords.append(translations(provider.displayName(),
85 provider.trCatalog()));
86 }
87
88 /* Same for services */
89 Q_FOREACH(const Accounts::Service &service, manager->serviceList()) {
90 keywords.append(service.name().toLower());
91 keywords.append(translations(service.displayName(),
92 service.trCatalog()));
93 }
94
95 /* Also add the account display names */
96 Q_FOREACH(Accounts::AccountId id, manager->accountList()) {
97 Accounts::Account *account = manager->account(id);
98 if (Q_UNLIKELY(!account)) continue;
99 QString name = account->displayName().toLower();
100 if (!name.isEmpty()) {
101 keywords.append(name);
102 }
103 }
104
105 delete manager;
106
107 setKeywords(keywords);
108}
109
110ItemBase *Plugin::createItem(const QVariantMap &staticData,
111 QObject *parent)
112{
113 return new Item(staticData, parent);
114}
115
116#include "plugin.moc"
0117
=== added file 'system-settings-plugin/plugin.h'
--- system-settings-plugin/plugin.h 1970-01-01 00:00:00 +0000
+++ system-settings-plugin/plugin.h 2015-02-02 15:22:49 +0000
@@ -0,0 +1,36 @@
1/*
2 * Copyright (C) 2015 Canonical Ltd.
3 *
4 * Contact: Alberto Mardegan <alberto.mardegan@canonical.com>
5 *
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 3, as published
8 * by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranties of
12 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
13 * PURPOSE. See the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#ifndef ONLINE_ACCOUNTS_SYSTEM_SETTINGS_PLUGIN_H
20#define ONLINE_ACCOUNTS_SYSTEM_SETTINGS_PLUGIN_H
21
22#include <QObject>
23#include <SystemSettings/PluginInterface>
24
25class Plugin: public QObject, public SystemSettings::PluginInterface2
26{
27 Q_OBJECT
28 Q_PLUGIN_METADATA(IID "com.ubuntu.SystemSettings.PluginInterface/2.0")
29 Q_INTERFACES(SystemSettings::PluginInterface2)
30
31public:
32 SystemSettings::ItemBase *createItem(const QVariantMap &staticData,
33 QObject *parent = 0);
34};
35
36#endif // ONLINE_ACCOUNTS_SYSTEM_SETTINGS_PLUGIN_H
037
=== modified file 'system-settings-plugin/system-settings-plugin.pro'
--- system-settings-plugin/system-settings-plugin.pro 2014-08-13 13:11:06 +0000
+++ system-settings-plugin/system-settings-plugin.pro 2015-02-02 15:22:49 +0000
@@ -1,7 +1,27 @@
1include(../common-project-config.pri)1include(../common-project-config.pri)
2include($${TOP_SRC_DIR}/common-vars.pri)2include($${TOP_SRC_DIR}/common-vars.pri)
33
4TEMPLATE=aux4TEMPLATE=lib
5TARGET = online-accounts
6
7CONFIG += \
8 link_pkgconfig \
9 plugin \
10 qt
11
12QT += \
13 core \
14 qml
15
16PKGCONFIG += \
17 SystemSettings \
18 accounts-qt5
19
20SOURCES += \
21 plugin.cpp
22
23HEADERS += \
24 plugin.h
525
6QML_SOURCES = \26QML_SOURCES = \
7 AccountEditPage.qml \27 AccountEditPage.qml \
@@ -19,6 +39,9 @@
19settings.path = $${PLUGIN_MANIFEST_DIR}39settings.path = $${PLUGIN_MANIFEST_DIR}
20INSTALLS += settings40INSTALLS += settings
2141
42target.path = $${PLUGIN_MODULE_DIR}
43INSTALLS += target
44
22image.files = settings-accounts.svg45image.files = settings-accounts.svg
23image.path = $${PLUGIN_MANIFEST_DIR}/icons46image.path = $${PLUGIN_MANIFEST_DIR}/icons
24INSTALLS += image47INSTALLS += image
2548
=== added directory 'tests/system-settings-plugin'
=== added file 'tests/system-settings-plugin/system-settings-plugin.pro'
--- tests/system-settings-plugin/system-settings-plugin.pro 1970-01-01 00:00:00 +0000
+++ tests/system-settings-plugin/system-settings-plugin.pro 2015-02-02 15:22:49 +0000
@@ -0,0 +1,32 @@
1include(../../common-project-config.pri)
2
3TARGET = tst_plugin
4
5CONFIG += \
6 debug \
7 link_pkgconfig
8
9QT += \
10 core \
11 qml \
12 testlib
13
14PKGCONFIG += \
15 SystemSettings \
16 accounts-qt5
17
18SYSTEM_SETTINGS_PLUGIN_DIR = $${TOP_SRC_DIR}/system-settings-plugin
19
20INCLUDEPATH += \
21 $${SYSTEM_SETTINGS_PLUGIN_DIR}
22
23SOURCES += \
24 $${SYSTEM_SETTINGS_PLUGIN_DIR}/plugin.cpp \
25 tst_plugin.cpp
26
27HEADERS += \
28 $${SYSTEM_SETTINGS_PLUGIN_DIR}/plugin.h
29
30check.commands = "xvfb-run -s '-screen 0 640x480x24' -a dbus-test-runner -t ./$${TARGET}"
31check.depends = $${TARGET}
32QMAKE_EXTRA_TARGETS += check
033
=== added file 'tests/system-settings-plugin/tst_plugin.cpp'
--- tests/system-settings-plugin/tst_plugin.cpp 1970-01-01 00:00:00 +0000
+++ tests/system-settings-plugin/tst_plugin.cpp 2015-02-02 15:22:49 +0000
@@ -0,0 +1,292 @@
1/*
2 * Copyright (C) 2014 Canonical Ltd.
3 *
4 * Contact: Alberto Mardegan <alberto.mardegan@canonical.com>
5 *
6 * This file is part of online-accounts-ui
7 *
8 * This program is free software: you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License version 3, as published
10 * by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranties of
14 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#include <Accounts/Account>
22#include <Accounts/Manager>
23
24#include <QDebug>
25#include <QDir>
26#include <QDomDocument>
27#include <QDomElement>
28#include <QFile>
29#include <QSignalSpy>
30#include <QTemporaryDir>
31#include <QTest>
32
33#include <SystemSettings/ItemBase>
34
35#include "plugin.h"
36
37namespace QTest {
38template<>
39char *toString(const QSet<QString> &set)
40{
41 QByteArray ba = "QSet<QString>(";
42 QStringList list = set.toList();
43 ba += list.join(", ");
44 ba += ")";
45 return qstrdup(ba.data());
46}
47} // QTest namespace
48
49/* mocking libintl { */
50static QHash<QString,QHash<QByteArray,QByteArray> > m_translations;
51extern "C" {
52char *dgettext(const char *domainname, const char *msgid)
53{
54 return (char *)m_translations[domainname].value(msgid).data();
55}
56char *dcgettext(const char *__domainname, const char *__msgid, int __category)
57{
58 Q_UNUSED(__category);
59 return dgettext(__domainname, __msgid);
60}
61} // extern C
62/* } mocking libintl */
63
64class PluginTest: public QObject
65{
66 Q_OBJECT
67
68 struct FileData {
69 FileData() {}
70 FileData(const QString &name, const QString &domain):
71 name(name), domain(domain) {}
72 QString name;
73 QString domain;
74 };
75
76public:
77 PluginTest();
78
79private Q_SLOTS:
80 void testKeywords_data();
81 void testKeywords();
82
83private:
84 void setDataDir(const QTemporaryDir &dir);
85 void writeProvider(const QString &id, const QString &name,
86 const QString &domain);
87 void writeService(const QString &id, const QString &name,
88 const QString &domain);
89 void writeLibaccountsFile(const QString &type, const QString &id,
90 const QString &name, const QString &domain);
91 void createAccount(const QString &name);
92
93private:
94 QHash<QString,FileData> m_providersData;
95 QHash<QString,FileData> m_servicesData;
96 QDir m_dataDir;
97};
98
99PluginTest::PluginTest():
100 QObject(0)
101{
102 m_providersData["provider_noname"] = FileData("", "");
103 m_providersData["provider_nodomain"] = FileData("Happy", "");
104 m_providersData["provider_translated"] = FileData("Joyful", "translations1");
105
106 m_servicesData["service_nodomain"] = FileData("Sad", "");
107 m_servicesData["service_translated"] = FileData("Depressed", "translations1");
108 m_servicesData["service_translated2"] = FileData("Depressed", "translations2");
109
110 m_translations["translations1"]["Happy"] = "Contento";
111 m_translations["translations1"]["Joyful"] = "Gioioso";
112 m_translations["translations1"]["Sad"] = "Triste";
113 m_translations["translations1"]["Depressed"] = "Depresso1";
114 m_translations["translations1"]["Black"] = "Nero";
115 m_translations["translations1"]["White"] = "Bianco";
116
117 m_translations["translations2"]["Depressed"] = "Depresso2";
118}
119
120void PluginTest::setDataDir(const QTemporaryDir &dir)
121{
122 QVERIFY(dir.isValid());
123
124 m_dataDir = QDir(dir.path());
125
126 QByteArray dataPath = dir.path().toUtf8();
127 qputenv("ACCOUNTS", dataPath);
128 qputenv("AG_PROVIDERS", dataPath);
129 qputenv("AG_SERVICES", dataPath);
130}
131
132void PluginTest::writeProvider(const QString &id, const QString &name,
133 const QString &domain)
134{
135 writeLibaccountsFile("provider", id, name, domain);
136}
137
138void PluginTest::writeService(const QString &id, const QString &name,
139 const QString &domain)
140{
141 writeLibaccountsFile("service", id, name, domain);
142}
143
144void PluginTest::writeLibaccountsFile(const QString &type, const QString &id,
145 const QString &name, const QString &domain)
146{
147 QDomDocument doc;
148 QDomElement root = doc.createElement(type);
149 root.setAttribute("id", id);
150 doc.appendChild(root);
151
152 QDomElement nameTag = doc.createElement("name");
153 nameTag.appendChild(doc.createTextNode(name));
154 root.appendChild(nameTag);
155
156 QDomElement domainTag = doc.createElement("translations");
157 domainTag.appendChild(doc.createTextNode(domain));
158 root.appendChild(domainTag);
159
160 if (type == "service") {
161 QDomElement typeTag = doc.createElement("type");
162 typeTag.appendChild(doc.createTextNode("something"));
163 root.appendChild(typeTag);
164 }
165
166 QFile file(m_dataDir.filePath(id + "." + type));
167 if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
168 qWarning() << "Could not write file" << file.fileName();
169 return;
170 }
171
172 file.write(doc.toString().toUtf8());
173}
174
175void PluginTest::createAccount(const QString &name)
176{
177 Accounts::Manager *manager = new Accounts::Manager;
178
179 Accounts::Account *account = manager->createAccount("any");
180 account->setDisplayName(name);
181 account->syncAndBlock();
182
183 delete manager;
184}
185
186void PluginTest::testKeywords_data()
187{
188 QTest::addColumn<QStringList>("providers");
189 QTest::addColumn<QStringList>("services");
190 QTest::addColumn<QStringList>("accountNames");
191 QTest::addColumn<QStringList>("keywords");
192
193 QTest::newRow("provider, no name") <<
194 (QStringList() << "provider_noname") <<
195 QStringList() <<
196 QStringList() <<
197 (QStringList() << "provider_noname");
198
199 QTest::newRow("provider, untranslated") <<
200 (QStringList() << "provider_nodomain") <<
201 QStringList() <<
202 QStringList() <<
203 (QStringList() << "provider_nodomain" << "happy");
204
205 QTest::newRow("provider, translated") <<
206 (QStringList() << "provider_translated") <<
207 QStringList() <<
208 QStringList() <<
209 (QStringList() << "provider_translated" << "joyful" << "gioioso");
210
211 QTest::newRow("service, untranslated") <<
212 QStringList() <<
213 (QStringList() << "service_nodomain") <<
214 QStringList() <<
215 (QStringList() << "service_nodomain" << "sad");
216
217 QTest::newRow("service, translated 1") <<
218 QStringList() <<
219 (QStringList() << "service_translated") <<
220 QStringList() <<
221 (QStringList() << "service_translated" << "depressed" << "depresso1");
222
223 QTest::newRow("service, translated 2") <<
224 QStringList() <<
225 (QStringList() << "service_translated2") <<
226 QStringList() <<
227 (QStringList() << "service_translated2" << "depressed" << "depresso2");
228
229 QTest::newRow("one account, one word") <<
230 QStringList() <<
231 QStringList() <<
232 (QStringList() << "tom@example.com") <<
233 (QStringList() << "tom@example.com");
234
235 QTest::newRow("one account, many words") <<
236 QStringList() <<
237 QStringList() <<
238 (QStringList() << "My little sweet account") <<
239 (QStringList() << "my little sweet account");
240
241 QTest::newRow("combined") <<
242 (QStringList() << "provider_translated" << "provider_nodomain") <<
243 (QStringList() << "service_translated" << "service_translated2") <<
244 (QStringList() << "john@invalid" << "harry@mysite.com") <<
245 (QStringList() << "provider_translated" << "joyful" << "gioioso" <<
246 "provider_nodomain" << "happy" <<
247 "service_translated" << "depressed" << "depresso1" <<
248 "service_translated2" << "depressed" << "depresso2" <<
249 "john@invalid" << "harry@mysite.com");
250}
251
252void PluginTest::testKeywords()
253{
254 QFETCH(QStringList, providers);
255 QFETCH(QStringList, services);
256 QFETCH(QStringList, accountNames);
257 QFETCH(QStringList, keywords);
258
259 QTemporaryDir dataDir;
260
261 setDataDir(dataDir);
262
263 /* Create the needed files */
264 Q_FOREACH(const QString &providerId, providers) {
265 writeProvider(providerId,
266 m_providersData[providerId].name,
267 m_providersData[providerId].domain);
268 }
269
270 Q_FOREACH(const QString &serviceId, services) {
271 writeService(serviceId,
272 m_servicesData[serviceId].name,
273 m_servicesData[serviceId].domain);
274 }
275
276 /* create the accounts */
277 Q_FOREACH(const QString &displayName, accountNames) {
278 createAccount(displayName);
279 }
280
281 /* Now do the actual test */
282 Plugin plugin;
283
284 SystemSettings::ItemBase *item = plugin.createItem(QVariantMap());
285 QStringList pluginKeywords = item->keywords();
286
287 QCOMPARE(pluginKeywords.toSet(), keywords.toSet());
288}
289
290QTEST_MAIN(PluginTest);
291
292#include "tst_plugin.moc"
0293
=== modified file 'tests/tests.pro'
--- tests/tests.pro 2014-10-03 14:56:11 +0000
+++ tests/tests.pro 2015-02-02 15:22:49 +0000
@@ -5,4 +5,5 @@
5 client \5 client \
6 online-accounts-service \6 online-accounts-service \
7 online-accounts-ui \7 online-accounts-ui \
8 plugin8 plugin \
9 system-settings-plugin

Subscribers

People subscribed via source and target branches