Merge lp:~kalikiana/ubuntu-ui-toolkit/appname into lp:ubuntu-ui-toolkit

Proposed by Christian Dywan on 2013-08-16
Status: Merged
Approved by: Zoltan Balogh on 2013-09-23
Approved revision: 713
Merged at revision: 752
Proposed branch: lp:~kalikiana/ubuntu-ui-toolkit/appname
Merge into: lp:ubuntu-ui-toolkit
Diff against target: 376 lines (+286/-0)
9 files modified
modules/Ubuntu/Components/MainView.qml (+5/-0)
modules/Ubuntu/Components/plugin/plugin.cpp (+7/-0)
modules/Ubuntu/Components/plugin/plugin.pro (+2/-0)
modules/Ubuntu/Components/plugin/ucapplication.cpp (+57/-0)
modules/Ubuntu/Components/plugin/ucapplication.h (+53/-0)
tests/unit/tst_mainview/AppName.qml (+23/-0)
tests/unit/tst_mainview/tst_mainview.cpp (+132/-0)
tests/unit/tst_mainview/tst_mainview.pro (+6/-0)
tests/unit/unit.pro (+1/-0)
To merge this branch: bzr merge lp:~kalikiana/ubuntu-ui-toolkit/appname
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Approve on 2013-09-23
Zsombor Egri Approve on 2013-09-19
Tim Peeters 2013-08-16 Pending
Review via email: mp+180601@code.launchpad.net

Commit message

Set QCoreApplication::applicationName based on MainView

To post a comment you must log in.
Antti Kaijanmäki (kaijanmaki) wrote :

Should this be ApplicationIdentifier in our API? AFAIK we are using $APP_ID and "Application Identifier" in our docs and discussion.

Tim Peeters (tpeeters) wrote :

why do you need applicationName in i18n? Is it really something different than domain, and can you not use only one variables that combines these two?

Tim Peeters (tpeeters) wrote :

why do you need organizationName?

Christian Dywan (kalikiana) wrote :

> why do you need organizationName?

As the code says: "// Unset organization to skip an extra folder component"

Zsombor Egri (zsombi) wrote :

63 + qmlRegisterUncreatableType<UCApplication>(uri, 0, 1, "Application", "Singleton object");

This is not needed. Pls remove.

Zsombor Egri (zsombi) wrote :

35 + /* Set name and organization on Application which QStandardPaths
36 + honors to construct folders.
37 + This works across platforms. For confinement we rely on the fact
38 + that the folders are whitelisted based on the app name. Similar
39 + to how Unity uses it to distinguish running applications.
40 + */
41 + UbuntuApplication.applicationName = applicationName
42 + // Unset organization to skip an extra folder component
43 + UbuntuApplication.organizationName = ""

If we anyway set the organizationName to an empty string, shouldn't we do this in the UCApplication itself? Do we have to expose it? Or do you expect to use it at some point in QML?

Zsombor Egri (zsombi) wrote :

Nice one! Have you ran unit tests on the device?

Christian Dywan (kalikiana) wrote :

I'm not able to do anything with my device at the moment because it doesn't boot, so this is all tested on the desktop only, I'm still trying to figure out what the problem is.

Zsombor Egri (zsombi) wrote :

seems you have errors in documentation.

review: Needs Fixing
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Zsombor Egri (zsombi) wrote :

Good to go!

review: Approve
Zsombor Egri (zsombi) wrote :

Hold on, if I create a QSettings() object right after the application name is set, the path the setting file will be located will look as follows: ~/.config/qt-project.org/AppName.conf.
If I create it with QSetting("", UCApplication::instance().applicationName()), the file path will be ~/.config/Unknown Organization/AppName.conf.

Seems the QCoreApplication::organizationName = "" wasn't good enough. If I set the organizationName to the same as applicationName, then the setting file will be in ~/.config/AppName/AppName.conf

review: Needs Fixing
Christian Dywan (kalikiana) wrote :

The problem is in QSettings using its own mechanism to build the path which diverges from the rest of Qt as far as I can say - so either we can find a way to override it or we need to patch it. All other APIs will add another folder level when setting an organizationName even if it's the app name.

Zsombor Egri (zsombi) wrote :

OK, then let's forget about this. We will use QSetting with custom
constructor.

On Wed, Sep 18, 2013 at 7:09 PM, Christian Dywan <email address hidden>wrote:

> The problem is in QSettings using its own mechanism to build the path
> which diverges from the rest of Qt as far as I can say - so either we can
> find a way to override it or we need to patch it. All other APIs will add
> another folder level when setting an organizationName even if it's the app
> name.
> --
>
> https://code.launchpad.net/~kalikiana/ubuntu-ui-toolkit/appname/+merge/180601
> You are reviewing the proposed merge of
> lp:~kalikiana/ubuntu-ui-toolkit/appname into lp:ubuntu-ui-toolkit.
>

Zsombor Egri (zsombi) :
review: Approve
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Christian Dywan (kalikiana) wrote :

Affected by bug 1229110

review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'modules/Ubuntu/Components/MainView.qml'
2--- modules/Ubuntu/Components/MainView.qml 2013-08-22 17:15:35 +0000
3+++ modules/Ubuntu/Components/MainView.qml 2013-09-23 08:32:16 +0000
4@@ -133,6 +133,10 @@
5 \preliminary
6 The property holds the application's name, which must be the same as the
7 desktop file's name.
8+ The name also sets the name of the QCoreApplication and defaults for data
9+ and cache folders that work on the desktop and under confinement.
10+ C++ code that writes files may use QStandardPaths::writableLocation with
11+ QStandardPaths::DataLocation or QStandardPaths::CacheLocation.
12 */
13 property string applicationName: ""
14
15@@ -334,6 +338,7 @@
16 onApplicationNameChanged: {
17 if (applicationName !== "") {
18 i18n.domain = applicationName;
19+ UbuntuApplication.applicationName = applicationName
20 }
21 }
22 }
23
24=== modified file 'modules/Ubuntu/Components/plugin/plugin.cpp'
25--- modules/Ubuntu/Components/plugin/plugin.cpp 2013-08-23 11:13:21 +0000
26+++ modules/Ubuntu/Components/plugin/plugin.cpp 2013-09-23 08:32:16 +0000
27@@ -42,6 +42,7 @@
28 #include "ucfontutils.h"
29 #include "ucarguments.h"
30 #include "ucargument.h"
31+#include "ucapplication.h"
32 #include "ucalarm.h"
33 #include "ucalarmmodel.h"
34 #include "unitythemeiconprovider.h"
35@@ -167,6 +168,12 @@
36 QObject::connect(&UbuntuI18n::instance(), SIGNAL(languageChanged()),
37 &i18nChangeListener, SLOT(updateContextProperty()));
38
39+ // We can't use 'Application' because it exists (undocumented)
40+ context->setContextProperty("UbuntuApplication", &UCApplication::instance());
41+ static ContextPropertyChangeListener applicationChangeListener(context, "UbuntuApplication");
42+ QObject::connect(&UCApplication::instance(), SIGNAL(applicationNameChanged()),
43+ &applicationChangeListener, SLOT(updateContextProperty()));
44+
45 context->setContextProperty("units", &UCUnits::instance());
46 static ContextPropertyChangeListener unitsChangeListener(context, "units");
47 QObject::connect(&UCUnits::instance(), SIGNAL(gridUnitChanged()),
48
49=== modified file 'modules/Ubuntu/Components/plugin/plugin.pro'
50--- modules/Ubuntu/Components/plugin/plugin.pro 2013-08-28 14:07:46 +0000
51+++ modules/Ubuntu/Components/plugin/plugin.pro 2013-09-23 08:32:16 +0000
52@@ -40,6 +40,7 @@
53 qquickclipboard_p.h \
54 ucubuntuanimation.h \
55 ucfontutils.h \
56+ ucapplication.h \
57 ucarguments.h \
58 ucargument.h \
59 ucalarm.h \
60@@ -68,6 +69,7 @@
61 qquickmimedata.cpp \
62 ucubuntuanimation.cpp \
63 ucfontutils.cpp \
64+ ucapplication.cpp \
65 ucarguments.cpp \
66 ucargument.cpp \
67 ucalarm.cpp \
68
69=== added file 'modules/Ubuntu/Components/plugin/ucapplication.cpp'
70--- modules/Ubuntu/Components/plugin/ucapplication.cpp 1970-01-01 00:00:00 +0000
71+++ modules/Ubuntu/Components/plugin/ucapplication.cpp 2013-09-23 08:32:16 +0000
72@@ -0,0 +1,57 @@
73+/*
74+ * Copyright 2013 Canonical Ltd.
75+ *
76+ * This program is free software; you can redistribute it and/or modify
77+ * it under the terms of the GNU Lesser General Public License as published by
78+ * the Free Software Foundation; version 3.
79+ *
80+ * This program is distributed in the hope that it will be useful,
81+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
82+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
83+ * GNU Lesser General Public License for more details.
84+ *
85+ * You should have received a copy of the GNU Lesser General Public License
86+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
87+ *
88+ * Author: Christian Dywan <christian.dywan@canonical.om>
89+ */
90+
91+#include "ucapplication.h"
92+
93+#include <QtCore/QCoreApplication>
94+#include <QDebug>
95+
96+/*!
97+ * \qmltype UbuntuApplication
98+ * \instantiates UCApplication
99+ * \inqmlmodule Ubuntu.Components 0.1
100+ * \ingroup ubuntu
101+ * \brief UbuntuApplication is a QML binding for a subset of QCoreApplication.
102+ *
103+ * UbuntuApplication is a context property in QML.
104+ */
105+UCApplication::UCApplication(QObject* parent) : QObject(parent)
106+{
107+}
108+
109+/*!
110+ * \qmlproperty string Application::applicationName
111+ * \internal
112+ * The name of the application, see QCoreApplication::applicationName
113+ */
114+QString UCApplication::applicationName() {
115+ return QCoreApplication::applicationName();
116+}
117+
118+void UCApplication::setApplicationName(QString applicationName) {
119+ /* QStandardPaths uses the name to build folder names.
120+ This works across platforms. For confinement we rely on the fact
121+ that the folders are whitelisted based on the app name. Similar
122+ to how Unity uses it to distinguish running applications.
123+ */
124+ QCoreApplication::setApplicationName(applicationName);
125+ // Unset organization to skip an extra folder component
126+ QCoreApplication::setOrganizationName("");
127+ Q_EMIT applicationNameChanged();
128+}
129+
130
131=== added file 'modules/Ubuntu/Components/plugin/ucapplication.h'
132--- modules/Ubuntu/Components/plugin/ucapplication.h 1970-01-01 00:00:00 +0000
133+++ modules/Ubuntu/Components/plugin/ucapplication.h 2013-09-23 08:32:16 +0000
134@@ -0,0 +1,53 @@
135+/*
136+ * Copyright 2013 Canonical Ltd.
137+ *
138+ * This program is free software; you can redistribute it and/or modify
139+ * it under the terms of the GNU Lesser General Public License as published by
140+ * the Free Software Foundation; version 3.
141+ *
142+ * This program is distributed in the hope that it will be useful,
143+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
144+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
145+ * GNU Lesser General Public License for more details.
146+ *
147+ * You should have received a copy of the GNU Lesser General Public License
148+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
149+ *
150+ * Author: Christian Dywan <christian.dywan@canonical.om>
151+ */
152+
153+#ifndef UBUNTU_COMPONENTS_APPLICATION_H
154+#define UBUNTU_COMPONENTS_APPLICATION_H
155+
156+#include <QtCore/QObject>
157+
158+class QQmlContext;
159+class QQmlEngine;
160+
161+class UCApplication : public QObject
162+{
163+ Q_OBJECT
164+ Q_PROPERTY(QString applicationName READ applicationName WRITE setApplicationName NOTIFY applicationNameChanged)
165+
166+private:
167+ Q_DISABLE_COPY(UCApplication)
168+ explicit UCApplication(QObject* parent = 0);
169+
170+
171+public:
172+ static UCApplication& instance() {
173+ static UCApplication instance;
174+ return instance;
175+ }
176+
177+ // getter
178+ QString applicationName();
179+
180+ // setter
181+ void setApplicationName(QString applicationName);
182+
183+Q_SIGNALS:
184+ void applicationNameChanged();
185+};
186+
187+#endif // UBUNTU_COMPONENTS_I18N_H
188
189=== added directory 'tests/unit/tst_mainview'
190=== added file 'tests/unit/tst_mainview/AppName.qml'
191--- tests/unit/tst_mainview/AppName.qml 1970-01-01 00:00:00 +0000
192+++ tests/unit/tst_mainview/AppName.qml 2013-09-23 08:32:16 +0000
193@@ -0,0 +1,23 @@
194+/*
195+ * Copyright 2013 Canonical Ltd.
196+ *
197+ * This program is free software; you can redistribute it and/or modify
198+ * it under the terms of the GNU Lesser General Public License as published by
199+ * the Free Software Foundation; version 3.
200+ *
201+ * This program is distributed in the hope that it will be useful,
202+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
203+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
204+ * GNU Lesser General Public License for more details.
205+ *
206+ * You should have received a copy of the GNU Lesser General Public License
207+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
208+ */
209+
210+import QtQuick 2.0
211+import Ubuntu.Components 0.1
212+
213+MainView {
214+ objectName: "appName"
215+ applicationName: "org.gnu.wildebeest"
216+}
217
218=== added file 'tests/unit/tst_mainview/tst_mainview.cpp'
219--- tests/unit/tst_mainview/tst_mainview.cpp 1970-01-01 00:00:00 +0000
220+++ tests/unit/tst_mainview/tst_mainview.cpp 2013-09-23 08:32:16 +0000
221@@ -0,0 +1,132 @@
222+/*
223+ * Copyright 2012-2013 Canonical Ltd.
224+ *
225+ * This program is free software; you can redistribute it and/or modify
226+ * it under the terms of the GNU Lesser General Public License as published by
227+ * the Free Software Foundation; version 3.
228+ *
229+ * This program is distributed in the hope that it will be useful,
230+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
231+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
232+ * GNU Lesser General Public License for more details.
233+ *
234+ * You should have received a copy of the GNU Lesser General Public License
235+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
236+ *
237+ * Author: Christian Dywan <christian.dywan@canonical.com>
238+ */
239+
240+#include <QtCore/QString>
241+#include <QtCore/QTextCodec>
242+#include <QtCore/QStandardPaths>
243+#include <QtCore/QProcessEnvironment>
244+#include <QtCore/QDebug>
245+#include <QtTest/QTest>
246+#include <QtTest/QSignalSpy>
247+#include <QtCore/QCoreApplication>
248+#include <QtQml/QQmlEngine>
249+#include <QtQuick/QQuickView>
250+#include <QtQuick/QQuickItem>
251+#include <QtCore/QThread>
252+#include <QtCore/QFileInfo>
253+#include <QtCore/QDir>
254+
255+#include "ucapplication.h"
256+#include "ucunits.h"
257+
258+class tst_MainView : public QObject
259+{
260+ Q_OBJECT
261+
262+private:
263+ QQuickView *view;
264+
265+public:
266+ tst_MainView() :
267+ view(0)
268+ {
269+ }
270+
271+ QQuickItem *loadTest(const QString &document)
272+ {
273+ // load the document
274+ view->setSource(QUrl::fromLocalFile(document));
275+ QTest::waitForEvents();
276+
277+ return view->rootObject();
278+ }
279+
280+ QQuickItem *testItem(QQuickItem *that, const QString &identifier)
281+ {
282+ if (that->property(identifier.toLocal8Bit()).isValid())
283+ return that->property(identifier.toLocal8Bit()).value<QQuickItem*>();
284+
285+ QList<QQuickItem*> children = that->findChildren<QQuickItem*>(identifier);
286+ return (children.count() > 0) ? children[0] : 0;
287+ }
288+
289+private Q_SLOTS:
290+
291+ void initTestCase()
292+ {
293+ QString modules("../../../modules");
294+ QVERIFY(QDir(modules).exists());
295+
296+ view = new QQuickView;
297+ QQmlEngine *quickEngine = view->engine();
298+
299+ view->setGeometry(0,0, UCUnits::instance().gu(40), UCUnits::instance().gu(30));
300+ //add modules folder so we have access to the plugin from QML
301+ QStringList imports = quickEngine->importPathList();
302+ imports.prepend(QDir(modules).absolutePath());
303+ quickEngine->setImportPathList(imports);
304+ }
305+
306+ void cleanupTestCase()
307+ {
308+ delete view;
309+ }
310+
311+ void testCase_AppName()
312+ {
313+ QQuickItem *root = loadTest("AppName.qml");
314+ QVERIFY(root);
315+ QQuickItem *mainView = root;
316+ QString applicationName(mainView->property("applicationName").toString());
317+ QCOMPARE(applicationName, QString("org.gnu.wildebeest"));
318+ QCOMPARE(applicationName, QCoreApplication::applicationName());
319+ QCOMPARE(QString(""), QCoreApplication::organizationName());
320+ }
321+
322+ void testSetApplicationName() {
323+ QString appName("com.ubuntu.foo");
324+ UCApplication::instance().setApplicationName(appName);
325+ QCOMPARE(UCApplication::instance().applicationName(), appName);
326+ QCOMPARE(QCoreApplication::applicationName(), appName);
327+ QCOMPARE(QString(""), QCoreApplication::organizationName());
328+ }
329+
330+ void testExpectedDataFolder() {
331+ QString appName("net.weight.gain");
332+ UCApplication::instance().setApplicationName(appName);
333+ QString dataFolder(QStandardPaths::writableLocation(QStandardPaths::DataLocation));
334+ QString xdgDataHome(QProcessEnvironment::systemEnvironment().value("XDG_DATA_HOME",
335+ QProcessEnvironment::systemEnvironment().value("HOME") + "/.local/share"));
336+ QString expectedDataFolder(xdgDataHome + "/" + appName);
337+ QCOMPARE(dataFolder, expectedDataFolder);
338+ }
339+
340+ void testExpectedCacheFolder() {
341+ QString appName("cat.long.very");
342+ UCApplication::instance().setApplicationName(appName);
343+ QString cacheFolder(QStandardPaths::writableLocation(QStandardPaths::CacheLocation));
344+ QString xdgCacheHome(QProcessEnvironment::systemEnvironment().value("XDG_CACHE_HOME",
345+ QProcessEnvironment::systemEnvironment().value("HOME") + "/.cache"));
346+ QString expectedCacheFolder(xdgCacheHome + "/" + appName);
347+ QCOMPARE(cacheFolder, expectedCacheFolder);
348+ }
349+};
350+
351+QTEST_MAIN(tst_MainView)
352+
353+#include "tst_mainview.moc"
354
355=== added file 'tests/unit/tst_mainview/tst_mainview.pro'
356--- tests/unit/tst_mainview/tst_mainview.pro 1970-01-01 00:00:00 +0000
357+++ tests/unit/tst_mainview/tst_mainview.pro 2013-09-23 08:32:16 +0000
358@@ -0,0 +1,6 @@
359+include(../test-include.pri)
360+
361+QT += gui
362+SOURCES += tst_mainview.cpp
363+
364+OTHER_FILES += $$system(ls tst_*.qml)
365
366=== modified file 'tests/unit/unit.pro'
367--- tests/unit/unit.pro 2013-08-28 09:49:02 +0000
368+++ tests/unit/unit.pro 2013-09-23 08:32:16 +0000
369@@ -20,6 +20,7 @@
370 tst_qquick_image_extension \
371 tst_performance \
372 tst_ubuntu_shape \
373+ tst_mainview \
374 tst_arguments \
375 tst_argument \
376 tst_layouts \

Subscribers

People subscribed via source and target branches

to status/vote changes: