Merge lp:~mterry/unity8/wizard-import into lp:unity8

Proposed by Michael Terry
Status: Merged
Approved by: Andrea Cimitan
Approved revision: 1435
Merged at revision: 1474
Proposed branch: lp:~mterry/unity8/wizard-import
Merge into: lp:unity8
Diff against target: 3078 lines (+2822/-1)
44 files modified
CMakeLists.txt (+1/-0)
debian/control (+13/-0)
debian/rules (+1/-1)
debian/ubuntu-system-settings-wizard.install (+5/-0)
debian/ubuntu-system-settings-wizard.lintian-overrides (+1/-0)
tests/CMakeLists.txt (+1/-0)
tests/wizard/CMakeLists.txt (+5/-0)
tests/wizard/tst_pagelist.cpp (+156/-0)
wizard/50-com.ubuntu.system-settings.wizard.pkla (+6/-0)
wizard/CMakeLists.txt (+65/-0)
wizard/PageList.cpp (+111/-0)
wizard/PageList.h (+55/-0)
wizard/Unity/Application/CMakeLists.txt (+3/-0)
wizard/Unity/Application/OSKController.qml (+20/-0)
wizard/Unity/Application/qmldir (+2/-0)
wizard/Unity/CMakeLists.txt (+1/-0)
wizard/Utils/CMakeLists.txt (+27/-0)
wizard/Utils/plugin.cpp (+41/-0)
wizard/Utils/plugin.h (+33/-0)
wizard/Utils/qmldir (+2/-0)
wizard/Utils/qsortfilterproxymodelqml.cpp (+167/-0)
wizard/Utils/qsortfilterproxymodelqml.h (+63/-0)
wizard/Utils/system.cpp (+118/-0)
wizard/Utils/system.h (+57/-0)
wizard/main.cpp (+93/-0)
wizard/qml/Components/CheckableSetting.qml (+85/-0)
wizard/qml/Components/InputMethod.qml (+113/-0)
wizard/qml/Components/Page.qml (+107/-0)
wizard/qml/Components/StackButton.qml (+47/-0)
wizard/qml/Pages/10-welcome.qml (+93/-0)
wizard/qml/Pages/20-sim.qml (+71/-0)
wizard/qml/Pages/30-passwd-type.qml (+119/-0)
wizard/qml/Pages/40-wifi.qml (+200/-0)
wizard/qml/Pages/50-location.qml (+149/-0)
wizard/qml/Pages/60-reporting.qml (+52/-0)
wizard/qml/Pages/80-finished.qml (+55/-0)
wizard/qml/Pages/here-terms.qml (+117/-0)
wizard/qml/Pages/passwd-confirm.qml (+85/-0)
wizard/qml/Pages/passwd-set.qml (+93/-0)
wizard/qml/main.qml (+246/-0)
wizard/test.sh (+18/-0)
wizard/ubuntu-system-settings-wizard-cleanup.conf (+20/-0)
wizard/ubuntu-system-settings-wizard-set-lang.conf (+30/-0)
wizard/ubuntu-system-settings-wizard.conf (+75/-0)
To merge this branch: bzr merge lp:~mterry/unity8/wizard-import
Reviewer Review Type Date Requested Status
Andrea Cimitan (community) Approve
PS Jenkins bot (community) continuous-integration Needs Fixing
Unity Team Pending
Review via email: mp+242245@code.launchpad.net

Commit message

Import wizard code from ubuntu-system-settings.

This branch does not guarantee it works, just that it builds and ships the right stuff. I wanted a baseline with as few changes as possible, so my actual changes to the code could be reviewed on their own.

Description of the change

Import wizard code from ubuntu-system-settings.

This branch does not guarantee it works, just that it builds and ships the right stuff. I wanted a baseline with as few changes as possible, so my actual changes to the code could be reviewed on their own.

This should not be landed without the 'wizard-plugin' (done) and 'wizard-tests' (not done yet) branches.

== Checklist ==

 * Are there any related MPs required for this MP to build/function as expected? Please list.
 Yesish. https://code.launchpad.net/~mterry/unity8/wizard-plugin/+merge/241912 will be needed to make actual functional use of this. But this is a baseline.

 It also expects https://code.launchpad.net/~mterry/ubuntu-system-settings/drop-wizard/+merge/242244 to be approved and in the same silo.

 * Did you perform an exploratory manual test run of your code change and any related functionality?
 Yesish. It builds and ships.

 * Did you make sure that your branch does not contain spurious tags?
 Yes

 * If you changed the packaging (debian), did you subscribe the ubuntu-unity team to this MP?
 I'm on that team.

 * If you changed the UI, has there been a design review?
 NA

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Andrea Cimitan (cimi) wrote :

 * Did you perform an exploratory manual test run of the code change and any related functionality?
Not of this, but following branch
 * Did CI run pass? If not, please explain why.
AP
 * Did you make sure that the branch does not contain spurious tags?
yes

review: Approve
lp:~mterry/unity8/wizard-import updated
1436. By Michael Terry

Merge from trunk

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2014-11-26 08:30:12 +0000
3+++ CMakeLists.txt 2014-12-02 18:43:43 +0000
4@@ -117,6 +117,7 @@
5 add_subdirectory(qml)
6 add_subdirectory(tests)
7 add_subdirectory(plugins)
8+add_subdirectory(wizard)
9
10 #
11 # Data files
12
13=== modified file 'debian/control'
14--- debian/control 2014-12-02 09:25:23 +0000
15+++ debian/control 2014-12-02 18:43:43 +0000
16@@ -24,6 +24,7 @@
17 libpulse-dev,
18 libqmenumodel-dev (>= 0.2.8),
19 libqt5xmlpatterns5-dev,
20+ libsystemsettings-dev,
21 libunity-api-dev (>= 7.93),
22 libusermetricsoutput1-dev,
23 libxcb1-dev,
24@@ -191,3 +192,15 @@
25 Depends: ${misc:Depends},
26 Description: Documentation for Unity8
27 The Unity 8 shell is the primary user interface for Ubuntu devices. (documentation)
28+
29+Package: ubuntu-system-settings-wizard
30+Architecture: any
31+Depends: unity8 (= ${binary:Version}),
32+ ${misc:Depends},
33+ ${shlibs:Depends},
34+Recommends: qtdeclarative5-qtmir-plugin (>= 0.4),
35+Breaks: ubuntu-system-settings (<< 0.4),
36+Replaces: ubuntu-system-settings (<< 0.4),
37+Description: Welcome Wizard for Ubuntu Touch
38+ This package contains the Welcome Wizard used on the Ubuntu Touch images,
39+ it's designed for phones, tablets and convergent devices.
40
41=== modified file 'debian/rules'
42--- debian/rules 2014-07-23 15:30:38 +0000
43+++ debian/rules 2014-12-02 18:43:43 +0000
44@@ -40,7 +40,7 @@
45
46 # use private lib directories
47 override_dh_makeshlibs:
48- dh_makeshlibs -Nunity8-private -Nunity8-fake-env
49+ dh_makeshlibs -Nunity8-private -Nunity8-fake-env -Nubuntu-system-settings-wizard
50
51 # libMockLightDM-qml.so links against liblightdm-qt5-2.so which doesn't exist
52 override_dh_shlibdeps:
53
54=== added file 'debian/ubuntu-system-settings-wizard.install'
55--- debian/ubuntu-system-settings-wizard.install 1970-01-01 00:00:00 +0000
56+++ debian/ubuntu-system-settings-wizard.install 2014-12-02 18:43:43 +0000
57@@ -0,0 +1,5 @@
58+usr/bin/system-settings-wizard
59+usr/share/ubuntu/settings/wizard
60+usr/share/upstart/sessions/ubuntu-system-settings-wizard*.conf
61+usr/lib/*/ubuntu-system-settings/private/Ubuntu/SystemSettings/Wizard
62+var/lib/polkit-1/localauthority/10-vendor.d/50-com.ubuntu.system-settings.wizard.pkla
63
64=== added file 'debian/ubuntu-system-settings-wizard.lintian-overrides'
65--- debian/ubuntu-system-settings-wizard.lintian-overrides 1970-01-01 00:00:00 +0000
66+++ debian/ubuntu-system-settings-wizard.lintian-overrides 2014-12-02 18:43:43 +0000
67@@ -0,0 +1,1 @@
68+ubuntu-system-settings-wizard: binary-without-manpage usr/bin/system-settings-wizard
69
70=== modified file 'tests/CMakeLists.txt'
71--- tests/CMakeLists.txt 2014-10-01 13:20:32 +0000
72+++ tests/CMakeLists.txt 2014-12-02 18:43:43 +0000
73@@ -14,3 +14,4 @@
74 add_subdirectory(plugins)
75 add_subdirectory(utils)
76 add_subdirectory(uqmlscene)
77+add_subdirectory(wizard)
78
79=== added directory 'tests/wizard'
80=== added file 'tests/wizard/CMakeLists.txt'
81--- tests/wizard/CMakeLists.txt 1970-01-01 00:00:00 +0000
82+++ tests/wizard/CMakeLists.txt 2014-12-02 18:43:43 +0000
83@@ -0,0 +1,5 @@
84+add_executable(tst-pagelist tst_pagelist.cpp ${CMAKE_SOURCE_DIR}/wizard/PageList.cpp)
85+set_target_properties(tst-pagelist PROPERTIES
86+ INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR};${CMAKE_SOURCE_DIR}/wizard")
87+qt5_use_modules(tst-pagelist Core Test)
88+add_test(tst-pagelist tst-pagelist)
89
90=== added file 'tests/wizard/tst_pagelist.cpp'
91--- tests/wizard/tst_pagelist.cpp 1970-01-01 00:00:00 +0000
92+++ tests/wizard/tst_pagelist.cpp 2014-12-02 18:43:43 +0000
93@@ -0,0 +1,156 @@
94+/*
95+ * This file is part of system-settings
96+ *
97+ * Copyright (C) 2014 Canonical Ltd.
98+ *
99+ * This program is free software: you can redistribute it and/or modify it
100+ * under the terms of the GNU General Public License version 3, as published
101+ * by the Free Software Foundation.
102+ *
103+ * This program is distributed in the hope that it will be useful, but
104+ * WITHOUT ANY WARRANTY; without even the implied warranties of
105+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
106+ * PURPOSE. See the GNU General Public License for more details.
107+ *
108+ * You should have received a copy of the GNU General Public License along
109+ * with this program. If not, see <http://www.gnu.org/licenses/>.
110+ */
111+
112+#include "PageList.h"
113+
114+#include <QDebug>
115+#include <QObject>
116+#include <QTemporaryDir>
117+#include <QTest>
118+
119+#define PAGES_PATH "ubuntu/settings/wizard/qml/Pages"
120+
121+class PageListTest: public QObject
122+{
123+ Q_OBJECT
124+
125+public:
126+ PageListTest() {};
127+
128+private Q_SLOTS:
129+ void testCollect();
130+ void testIterate();
131+ void testIgnoreNonNumbered();
132+ void testIgnoreNonQml();
133+ void testIgnoreDuplicates();
134+ void testDisabled();
135+
136+private:
137+ void fillRoot(const QTemporaryDir &root);
138+ void makeFile(const QTemporaryDir &root, const QString &dir, const QString &filename);
139+};
140+
141+void PageListTest::fillRoot(const QTemporaryDir &root)
142+{
143+ QVERIFY(root.isValid());
144+ QDir rootDir = root.path();
145+ QVERIFY(rootDir.mkpath(QString("a/") + PAGES_PATH));
146+ QVERIFY(rootDir.mkpath(QString("b/") + PAGES_PATH));
147+ QVERIFY(rootDir.mkpath(QString("c/") + PAGES_PATH));
148+ qputenv("XDG_DATA_DIRS", QString(rootDir.path() + "/a:" +
149+ rootDir.path() + "/b:" +
150+ rootDir.path() + "/c").toLatin1());
151+}
152+
153+void PageListTest::makeFile(const QTemporaryDir &root, const QString &dir, const QString &filename)
154+{
155+ QFile file(root.path() + "/" + dir + "/" + PAGES_PATH + "/" + filename);
156+ QVERIFY(file.open(QIODevice::WriteOnly));
157+ file.close();
158+ QVERIFY(file.exists());
159+}
160+
161+void PageListTest::testCollect()
162+{
163+ QTemporaryDir root;
164+ fillRoot(root);
165+ makeFile(root, "a", "3.qml");
166+ makeFile(root, "b", "1.qml");
167+ makeFile(root, "c", "2.qml");
168+
169+ PageList pageList;
170+ QCOMPARE(pageList.entries(), QStringList() << "1.qml" << "2.qml" << "3.qml");
171+ QCOMPARE(pageList.paths(), QStringList() << root.path() + "/b/" + PAGES_PATH + "/1.qml"
172+ << root.path() + "/c/" + PAGES_PATH + "/2.qml"
173+ << root.path() + "/a/" + PAGES_PATH + "/3.qml");
174+}
175+
176+void PageListTest::testIterate()
177+{
178+ QTemporaryDir root;
179+ fillRoot(root);
180+ makeFile(root, "a", "1.qml");
181+ makeFile(root, "a", "2.qml");
182+ makeFile(root, "a", "3.qml");
183+
184+ PageList pageList;
185+ QCOMPARE(pageList.index(), -1);
186+ QCOMPARE(pageList.next(), root.path() + "/a/" + PAGES_PATH + "/1.qml");
187+ QCOMPARE(pageList.prev(), QString());
188+ QCOMPARE(pageList.next(), root.path() + "/a/" + PAGES_PATH + "/2.qml");
189+ QCOMPARE(pageList.prev(), root.path() + "/a/" + PAGES_PATH + "/1.qml");
190+ QCOMPARE(pageList.index(), 0);
191+ QCOMPARE(pageList.next(), root.path() + "/a/" + PAGES_PATH + "/2.qml");
192+ QCOMPARE(pageList.next(), root.path() + "/a/" + PAGES_PATH + "/3.qml");
193+ QCOMPARE(pageList.index(), 2);
194+ QCOMPARE(pageList.next(), QString());
195+ QCOMPARE(pageList.index(), 2);
196+}
197+
198+void PageListTest::testIgnoreNonNumbered()
199+{
200+ QTemporaryDir root;
201+ fillRoot(root);
202+ makeFile(root, "a", "1.qml");
203+ makeFile(root, "a", "nope.qml");
204+
205+ PageList pageList;
206+ QCOMPARE(pageList.entries(), QStringList() << "1.qml");
207+}
208+
209+void PageListTest::testIgnoreNonQml()
210+{
211+ QTemporaryDir root;
212+ fillRoot(root);
213+ makeFile(root, "a", "1.qml");
214+ makeFile(root, "a", "2");
215+ makeFile(root, "a", "2.txt");
216+
217+ PageList pageList;
218+ QCOMPARE(pageList.entries(), QStringList() << "1.qml");
219+}
220+
221+void PageListTest::testIgnoreDuplicates()
222+{
223+ QTemporaryDir root;
224+ fillRoot(root);
225+ makeFile(root, "a", "1.qml");
226+ makeFile(root, "b", "1.qml");
227+
228+ PageList pageList;
229+ QCOMPARE(pageList.paths(), QStringList() << root.path() + "/a/" + PAGES_PATH + "/1.qml");
230+}
231+
232+void PageListTest::testDisabled()
233+{
234+ QTemporaryDir root;
235+ fillRoot(root);
236+ makeFile(root, "a", "1.qml.disabled"); // before the fact
237+ makeFile(root, "b", "1.qml");
238+ makeFile(root, "b", "2.qml");
239+ makeFile(root, "b", "2.qml.disabled"); // same dir
240+ makeFile(root, "b", "3.qml");
241+ makeFile(root, "b", "4.qml"); // only survivor
242+ makeFile(root, "c", "3.qml.disabled"); // after the fact
243+
244+ PageList pageList;
245+ QCOMPARE(pageList.entries(), QStringList() << "4.qml");
246+}
247+
248+QTEST_MAIN(PageListTest)
249+#include "tst_pagelist.moc"
250
251=== added directory 'wizard'
252=== added file 'wizard/50-com.ubuntu.system-settings.wizard.pkla'
253--- wizard/50-com.ubuntu.system-settings.wizard.pkla 1970-01-01 00:00:00 +0000
254+++ wizard/50-com.ubuntu.system-settings.wizard.pkla 2014-12-02 18:43:43 +0000
255@@ -0,0 +1,6 @@
256+[Allow welcome wizard to set AccountsService fields]
257+Identity=unix-user:lightdm
258+Action=org.freedesktop.accounts.user-administration
259+ResultActive=yes
260+ResultInactive=no
261+ResultAny=no
262
263=== added file 'wizard/CMakeLists.txt'
264--- wizard/CMakeLists.txt 1970-01-01 00:00:00 +0000
265+++ wizard/CMakeLists.txt 2014-12-02 18:43:43 +0000
266@@ -0,0 +1,65 @@
267+# This file uses a lot of namespacing like "ubuntu-system-settings" instead of
268+# "unity8". This is because we have imported it from ubuntu-system-settings
269+# and haven't fully integrated it yet.
270+
271+include_directories(
272+ ${CMAKE_CURRENT_BINARY_DIR}
273+ ${Qt5Gui_PRIVATE_INCLUDE_DIRS}
274+)
275+
276+set(PLUGIN_MANIFEST_DIR_BASE share/ubuntu/settings/system)
277+set(PLUGIN_MODULE_DIR_BASE ubuntu-system-settings)
278+set(PLUGIN_PRIVATE_MODULE_DIR_BASE "${PLUGIN_MODULE_DIR_BASE}/private")
279+set(PLUGIN_QML_DIR_BASE share/ubuntu/settings/system/qml-plugins)
280+
281+set(PLUGIN_MANIFEST_DIR "${CMAKE_INSTALL_PREFIX}/${PLUGIN_MANIFEST_DIR_BASE}")
282+set(PLUGIN_MODULE_DIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/${PLUGIN_MODULE_DIR_BASE}")
283+set(PLUGIN_PRIVATE_MODULE_DIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/${PLUGIN_PRIVATE_MODULE_DIR_BASE}")
284+set(PLUGIN_QML_DIR "${CMAKE_INSTALL_PREFIX}/${PLUGIN_QML_DIR_BASE}")
285+
286+add_definitions(-DI18N_DOMAIN="unity8")
287+add_definitions(-DPLUGIN_MANIFEST_DIR="${PLUGIN_MANIFEST_DIR}")
288+add_definitions(-DPLUGIN_MODULE_DIR="${PLUGIN_MODULE_DIR}")
289+add_definitions(-DPLUGIN_PRIVATE_MODULE_DIR="${PLUGIN_PRIVATE_MODULE_DIR}")
290+add_definitions(-DPLUGIN_QML_DIR="${PLUGIN_QML_DIR}")
291+
292+execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE} --variable=plugindir unity-shell-api OUTPUT_VARIABLE SHELL_PLUGINDIR OUTPUT_STRIP_TRAILING_WHITESPACE)
293+if(SHELL_PLUGINDIR STREQUAL "")
294+ message(FATAL_ERROR "Could not determine plugin import dir.")
295+endif()
296+
297+add_definitions(-DSHELL_PLUGINDIR="${SHELL_PLUGINDIR}")
298+
299+set(WIZARD_ROOT "${CMAKE_INSTALL_PREFIX}/share")
300+add_definitions(-DWIZARD_ROOT="${WIZARD_ROOT}")
301+
302+file(GLOB_RECURSE QML_FILES
303+ qml/*
304+)
305+
306+set(WIZARD_SOURCES
307+ main.cpp
308+ PageList.cpp
309+)
310+
311+add_executable(system-settings-wizard
312+ ${WIZARD_SOURCES}
313+ ${system-settings-wizard-resources}
314+ ${QML_FILES} # This is to make qml and image files appear in the IDE's project tree
315+)
316+
317+qt5_use_modules(system-settings-wizard Core Gui Quick Qml)
318+
319+add_subdirectory(Unity)
320+add_subdirectory(Utils)
321+
322+install(TARGETS system-settings-wizard RUNTIME DESTINATION bin)
323+install(FILES ubuntu-system-settings-wizard.conf
324+ ubuntu-system-settings-wizard-cleanup.conf
325+ ubuntu-system-settings-wizard-set-lang.conf
326+ DESTINATION share/upstart/sessions)
327+
328+set(POLKIT_LIB_DIR "${CMAKE_INSTALL_LOCALSTATEDIR}/lib/polkit-1")
329+install(FILES 50-com.ubuntu.system-settings.wizard.pkla DESTINATION ${POLKIT_LIB_DIR}/localauthority/10-vendor.d)
330+
331+install(DIRECTORY qml DESTINATION ${WIZARD_ROOT}/ubuntu/settings/wizard)
332
333=== added file 'wizard/PageList.cpp'
334--- wizard/PageList.cpp 1970-01-01 00:00:00 +0000
335+++ wizard/PageList.cpp 2014-12-02 18:43:43 +0000
336@@ -0,0 +1,111 @@
337+/*
338+ * This file is part of system-settings
339+ *
340+ * Copyright (C) 2014 Canonical Ltd.
341+ *
342+ * This program is free software: you can redistribute it and/or modify it
343+ * under the terms of the GNU General Public License version 3, as published
344+ * by the Free Software Foundation.
345+ *
346+ * This program is distributed in the hope that it will be useful, but
347+ * WITHOUT ANY WARRANTY; without even the implied warranties of
348+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
349+ * PURPOSE. See the GNU General Public License for more details.
350+ *
351+ * You should have received a copy of the GNU General Public License along
352+ * with this program. If not, see <http://www.gnu.org/licenses/>.
353+ */
354+
355+/**
356+ * This class lets the list of wizard pages be dynamic.
357+ * - To add new ones, drop them into
358+ * $XDG_DATA_DIRS/ubuntu/settings/wizard/qml/Pages with a numbered prefix,
359+ * like "21-custom-page.qml". The number determines the order in the page
360+ * sequence that your page will appear.
361+ * - To disable an existing page, add a file like "21-custom-page.qml.disabled"
362+ * - To go to the next page, use pageStack.next()
363+ * - To go back to the previous page, use pageStack.prev()
364+ * - To load a page outside of the normal flow (so that it doesn't affect the
365+ * back button), use pageStack.push(Qt.resolvedUrl("custom-page.qml")) in
366+ * your page.
367+ * - See default pages for plenty of examples.
368+ */
369+
370+#include "PageList.h"
371+#include <QDir>
372+#include <QStandardPaths>
373+
374+#include <QDebug>
375+PageList::PageList(QObject *parent)
376+ : QObject(parent),
377+ m_index(-1),
378+ m_pages()
379+{
380+ QString qmlSuffix = ".qml";
381+ QString disabledSuffix = ".disabled";
382+ QSet<QString> disabledPages;
383+ QStringList dataDirs = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation);
384+
385+ QString rootDir = qgetenv("UBUNTU_SYSTEM_SETTINGS_WIZARD_ROOT"); // for testing
386+ if (!rootDir.isEmpty())
387+ dataDirs = QStringList() << rootDir;
388+
389+ Q_FOREACH(const QString &dataDir, dataDirs) {
390+ QDir dir(dataDir + "/ubuntu/settings/wizard/qml/Pages");
391+ QStringList entries = dir.entryList(QStringList("[0-9]*"), QDir::Files | QDir::Readable);
392+ Q_FOREACH(const QString &entry, entries) {
393+ if (!m_pages.contains(entry) && entry.endsWith(qmlSuffix))
394+ m_pages.insert(entry, dir.absoluteFilePath(entry));
395+ else if (entry.endsWith(qmlSuffix + disabledSuffix))
396+ disabledPages.insert(entry.left(entry.size() - disabledSuffix.size()));
397+ }
398+ }
399+
400+ // Now remove any explicitly disabled entries
401+ Q_FOREACH(const QString &page, disabledPages) {
402+ m_pages.remove(page);
403+ }
404+}
405+
406+QStringList PageList::entries() const
407+{
408+ return m_pages.keys();
409+}
410+
411+QStringList PageList::paths() const
412+{
413+ return m_pages.values();
414+}
415+
416+int PageList::index() const
417+{
418+ return m_index;
419+}
420+
421+int PageList::numPages() const
422+{
423+ return m_pages.size();
424+}
425+
426+QString PageList::prev()
427+{
428+ if (m_index > 0)
429+ return m_pages.values()[setIndex(m_index - 1)];
430+ else
431+ return QString();
432+}
433+
434+QString PageList::next()
435+{
436+ if (m_index < m_pages.count() - 1)
437+ return m_pages.values()[setIndex(m_index + 1)];
438+ else
439+ return QString();
440+}
441+
442+int PageList::setIndex(int index)
443+{
444+ m_index = index;
445+ Q_EMIT indexChanged();
446+ return m_index;
447+}
448
449=== added file 'wizard/PageList.h'
450--- wizard/PageList.h 1970-01-01 00:00:00 +0000
451+++ wizard/PageList.h 2014-12-02 18:43:43 +0000
452@@ -0,0 +1,55 @@
453+/*
454+ * This file is part of system-settings
455+ *
456+ * Copyright (C) 2014 Canonical Ltd.
457+ *
458+ * This program is free software: you can redistribute it and/or modify it
459+ * under the terms of the GNU General Public License version 3, as published
460+ * by the Free Software Foundation.
461+ *
462+ * This program is distributed in the hope that it will be useful, but
463+ * WITHOUT ANY WARRANTY; without even the implied warranties of
464+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
465+ * PURPOSE. See the GNU General Public License for more details.
466+ *
467+ * You should have received a copy of the GNU General Public License along
468+ * with this program. If not, see <http://www.gnu.org/licenses/>.
469+ */
470+
471+#ifndef PAGELIST_H
472+#define PAGEList_H
473+
474+#include <QMap>
475+#include <QObject>
476+#include <QString>
477+
478+class PageList : public QObject
479+{
480+ Q_OBJECT
481+ Q_PROPERTY(int index READ index NOTIFY indexChanged)
482+ Q_PROPERTY(int numPages READ numPages NOTIFY numPagesChanged)
483+
484+public:
485+ explicit PageList(QObject *parent = 0);
486+
487+ QStringList entries() const;
488+ QStringList paths() const;
489+ int index() const;
490+ int numPages() const;
491+
492+public Q_SLOTS:
493+ QString prev();
494+ QString next();
495+
496+Q_SIGNALS:
497+ void indexChanged();
498+ void numPagesChanged(); // never emitted, just here to quiet Qml warnings
499+
500+private:
501+ int setIndex(int index);
502+
503+ int m_index;
504+ QMap<QString, QString> m_pages;
505+};
506+
507+#endif // PAGELIST_H
508
509=== added directory 'wizard/Unity'
510=== added directory 'wizard/Unity/Application'
511=== added file 'wizard/Unity/Application/CMakeLists.txt'
512--- wizard/Unity/Application/CMakeLists.txt 1970-01-01 00:00:00 +0000
513+++ wizard/Unity/Application/CMakeLists.txt 2014-12-02 18:43:43 +0000
514@@ -0,0 +1,3 @@
515+# This is just a small fake Unity.Application for non-Mir environments
516+set(PLUG_DIR ${PLUGIN_PRIVATE_MODULE_DIR}/Ubuntu/SystemSettings/Wizard/NonMir/Unity/Application)
517+install(FILES qmldir OSKController.qml DESTINATION ${PLUG_DIR})
518
519=== added file 'wizard/Unity/Application/OSKController.qml'
520--- wizard/Unity/Application/OSKController.qml 1970-01-01 00:00:00 +0000
521+++ wizard/Unity/Application/OSKController.qml 2014-12-02 18:43:43 +0000
522@@ -0,0 +1,20 @@
523+/*
524+ * Copyright (C) 2013 Canonical, Ltd.
525+ *
526+ * This program is free software; you can redistribute it and/or modify
527+ * it under the terms of the GNU General Public License as published by
528+ * the Free Software Foundation; version 3.
529+ *
530+ * This program is distributed in the hope that it will be useful,
531+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
532+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
533+ * GNU General Public License for more details.
534+ *
535+ * You should have received a copy of the GNU General Public License
536+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
537+ */
538+
539+import QtQuick 2.0;
540+
541+Item {
542+}
543
544=== added file 'wizard/Unity/Application/qmldir'
545--- wizard/Unity/Application/qmldir 1970-01-01 00:00:00 +0000
546+++ wizard/Unity/Application/qmldir 2014-12-02 18:43:43 +0000
547@@ -0,0 +1,2 @@
548+module Unity.Application
549+OSKController 0.1 OSKController.qml
550
551=== added file 'wizard/Unity/CMakeLists.txt'
552--- wizard/Unity/CMakeLists.txt 1970-01-01 00:00:00 +0000
553+++ wizard/Unity/CMakeLists.txt 2014-12-02 18:43:43 +0000
554@@ -0,0 +1,1 @@
555+add_subdirectory(Application)
556
557=== added directory 'wizard/Utils'
558=== added file 'wizard/Utils/CMakeLists.txt'
559--- wizard/Utils/CMakeLists.txt 1970-01-01 00:00:00 +0000
560+++ wizard/Utils/CMakeLists.txt 2014-12-02 18:43:43 +0000
561@@ -0,0 +1,27 @@
562+include_directories(
563+ ${CMAKE_CURRENT_SOURCE_DIR}
564+ ${CMAKE_CURRENT_BINARY_DIR}
565+ ${Qt5Gui_PRIVATE_INCLUDE_DIRS}
566+)
567+
568+set(QMLPLUGIN_SRC
569+ qsortfilterproxymodelqml.cpp
570+ plugin.cpp
571+ system.cpp
572+ )
573+
574+add_library(WizardUtils-qml SHARED
575+ ${QMLPLUGIN_SRC}
576+ )
577+
578+# Because this is an internal support library, we want
579+# to expose all symbols in it. Consider changing this
580+# either to a static library or just using the
581+# files directly in targets.
582+set_target_properties(WizardUtils-qml PROPERTIES COMPILE_FLAGS -fvisibility=default)
583+
584+qt5_use_modules(WizardUtils-qml DBus Qml Quick)
585+
586+set(PLUG_DIR ${PLUGIN_PRIVATE_MODULE_DIR}/Ubuntu/SystemSettings/Wizard/Utils)
587+install(FILES qmldir DESTINATION ${PLUG_DIR})
588+install(TARGETS WizardUtils-qml DESTINATION ${PLUG_DIR})
589
590=== added file 'wizard/Utils/plugin.cpp'
591--- wizard/Utils/plugin.cpp 1970-01-01 00:00:00 +0000
592+++ wizard/Utils/plugin.cpp 2014-12-02 18:43:43 +0000
593@@ -0,0 +1,41 @@
594+/*
595+ * Copyright (C) 2014 Canonical, Ltd.
596+ *
597+ * This program is free software; you can redistribute it and/or modify
598+ * it under the terms of the GNU General Public License as published by
599+ * the Free Software Foundation; version 3.
600+ *
601+ * This program is distributed in the hope that it will be useful,
602+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
603+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
604+ * GNU General Public License for more details.
605+ *
606+ * You should have received a copy of the GNU General Public License
607+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
608+ */
609+
610+// Qt
611+#include <QtQml/qqml.h>
612+#include <QQmlContext>
613+#include <QDebug>
614+// self
615+#include "plugin.h"
616+
617+// local
618+#include "qsortfilterproxymodelqml.h"
619+#include "system.h"
620+
621+static QObject *system_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
622+{
623+ Q_UNUSED(engine)
624+ Q_UNUSED(scriptEngine)
625+ return new System();
626+}
627+
628+void UtilsPlugin::registerTypes(const char *uri)
629+{
630+ Q_ASSERT(uri == QLatin1String("Ubuntu.SystemSettings.Wizard.Utils"));
631+ qmlRegisterType<QAbstractItemModel>();
632+ qmlRegisterType<QSortFilterProxyModelQML>(uri, 0, 1, "SortFilterProxyModel");
633+ qmlRegisterSingletonType<System>(uri, 0, 1, "System", system_provider);
634+}
635
636=== added file 'wizard/Utils/plugin.h'
637--- wizard/Utils/plugin.h 1970-01-01 00:00:00 +0000
638+++ wizard/Utils/plugin.h 2014-12-02 18:43:43 +0000
639@@ -0,0 +1,33 @@
640+/*
641+ * Copyright (C) 2014 Canonical, Ltd.
642+ *
643+ * This program is free software; you can redistribute it and/or modify
644+ * it under the terms of the GNU General Public License as published by
645+ * the Free Software Foundation; version 3.
646+ *
647+ * This program is distributed in the hope that it will be useful,
648+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
649+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
650+ * GNU General Public License for more details.
651+ *
652+ * You should have received a copy of the GNU General Public License
653+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
654+ *
655+ */
656+
657+#ifndef UTILS_PLUGIN_H
658+#define UTILS_PLUGIN_H
659+
660+#include <QtQml/QQmlEngine>
661+#include <QtQml/QQmlExtensionPlugin>
662+
663+class UtilsPlugin : public QQmlExtensionPlugin
664+{
665+ Q_OBJECT
666+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
667+
668+public:
669+ void registerTypes(const char *uri);
670+};
671+
672+#endif
673
674=== added file 'wizard/Utils/qmldir'
675--- wizard/Utils/qmldir 1970-01-01 00:00:00 +0000
676+++ wizard/Utils/qmldir 2014-12-02 18:43:43 +0000
677@@ -0,0 +1,2 @@
678+module Ubuntu.SystemSettings.Wizard.Utils
679+plugin WizardUtils-qml
680
681=== added file 'wizard/Utils/qsortfilterproxymodelqml.cpp'
682--- wizard/Utils/qsortfilterproxymodelqml.cpp 1970-01-01 00:00:00 +0000
683+++ wizard/Utils/qsortfilterproxymodelqml.cpp 2014-12-02 18:43:43 +0000
684@@ -0,0 +1,167 @@
685+/*
686+ * Copyright (C) 2012 Canonical, Ltd.
687+ *
688+ * This program is free software; you can redistribute it and/or modify
689+ * it under the terms of the GNU General Public License as published by
690+ * the Free Software Foundation; version 3.
691+ *
692+ * This program is distributed in the hope that it will be useful,
693+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
694+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
695+ * GNU General Public License for more details.
696+ *
697+ * You should have received a copy of the GNU General Public License
698+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
699+ */
700+
701+// self
702+#include "qsortfilterproxymodelqml.h"
703+
704+// Qt
705+#include <QDebug>
706+
707+QSortFilterProxyModelQML::QSortFilterProxyModelQML(QObject *parent)
708+ : QSortFilterProxyModel(parent)
709+ , m_invertMatch(false)
710+{
711+ connect(this, SIGNAL(modelReset()), SIGNAL(countChanged()));
712+ connect(this, SIGNAL(rowsInserted(QModelIndex,int,int)), SIGNAL(countChanged()));
713+ connect(this, SIGNAL(rowsRemoved(QModelIndex,int,int)), SIGNAL(countChanged()));
714+}
715+
716+/*
717+ * Enter row index of filtered/sorted model, returns row index of source model
718+ */
719+int QSortFilterProxyModelQML::mapRowToSource(int row)
720+{
721+ if (sourceModel() == NULL)
722+ return -1;
723+
724+ return QSortFilterProxyModel::mapToSource(index(row, 0)).row();
725+}
726+
727+QHash<int, QByteArray> QSortFilterProxyModelQML::roleNames() const
728+{
729+ return sourceModel() ? sourceModel()->roleNames() : QHash<int, QByteArray>();
730+}
731+
732+void
733+QSortFilterProxyModelQML::setModel(QAbstractItemModel *itemModel)
734+{
735+ if (itemModel == NULL) {
736+ return;
737+ }
738+
739+ if (itemModel != sourceModel()) {
740+ if (sourceModel() != NULL) {
741+ sourceModel()->disconnect(this);
742+ }
743+
744+ setSourceModel(itemModel);
745+
746+ connect(itemModel, SIGNAL(modelReset()), SIGNAL(totalCountChanged()));
747+ connect(itemModel, SIGNAL(rowsInserted(QModelIndex,int,int)), SIGNAL(totalCountChanged()));
748+ connect(itemModel, SIGNAL(rowsRemoved(QModelIndex,int,int)), SIGNAL(totalCountChanged()));
749+
750+ Q_EMIT totalCountChanged();
751+ Q_EMIT modelChanged();
752+ }
753+}
754+
755+QVariantMap
756+QSortFilterProxyModelQML::get(int row)
757+{
758+ QVariantMap res;
759+ const QHash<int, QByteArray> roles = roleNames();
760+ auto it = roles.begin();
761+ for ( ; it != roles.end(); ++it) {
762+ res[*it] = data(row, it.key());
763+ }
764+ return res;
765+}
766+
767+QVariant
768+QSortFilterProxyModelQML::data(int row, int role)
769+{
770+ if (sourceModel() == NULL) {
771+ return QVariant();
772+ }
773+
774+ return index(row, 0).data(role);
775+}
776+
777+int
778+QSortFilterProxyModelQML::totalCount() const
779+{
780+ if (sourceModel() != NULL) {
781+ return sourceModel()->rowCount();
782+ } else {
783+ return 0;
784+ }
785+}
786+
787+int
788+QSortFilterProxyModelQML::count()
789+{
790+ return rowCount();
791+}
792+
793+bool
794+QSortFilterProxyModelQML::invertMatch() const
795+{
796+ return m_invertMatch;
797+}
798+
799+void
800+QSortFilterProxyModelQML::setInvertMatch(bool invertMatch)
801+{
802+ if (invertMatch != m_invertMatch) {
803+ m_invertMatch = invertMatch;
804+ Q_EMIT invertMatchChanged(invertMatch);
805+ invalidateFilter();
806+ }
807+}
808+
809+bool
810+QSortFilterProxyModelQML::filterAcceptsRow(int sourceRow,
811+ const QModelIndex &sourceParent) const
812+{
813+ // If there's no regexp set, always accept all rows indepenently of the invertMatch setting
814+ if (filterRegExp().isEmpty()) {
815+ return true;
816+ }
817+
818+ bool result = QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent);
819+ return (m_invertMatch) ? !result : result;
820+}
821+
822+int
823+QSortFilterProxyModelQML::findFirst(int role, const QVariant& value) const
824+{
825+ QModelIndexList matches = match(index(0, 0), role, value, 1, Qt::MatchExactly);
826+ if (!matches.isEmpty()) {
827+ return matches.first().row();
828+ } else {
829+ return -1;
830+ }
831+}
832+
833+int
834+QSortFilterProxyModelQML::mapFromSource(int row)
835+{
836+ if (sourceModel() != NULL) {
837+ return QSortFilterProxyModel::mapFromSource(sourceModel()->index(row, 0)).row();
838+ } else {
839+ return -1;
840+ }
841+}
842+
843+int
844+QSortFilterProxyModelQML::mapToSource(int row)
845+{
846+ if (sourceModel() != NULL) {
847+ return QSortFilterProxyModel::mapToSource(index(row, 0)).row();
848+ } else {
849+ return -1;
850+ }
851+}
852
853=== added file 'wizard/Utils/qsortfilterproxymodelqml.h'
854--- wizard/Utils/qsortfilterproxymodelqml.h 1970-01-01 00:00:00 +0000
855+++ wizard/Utils/qsortfilterproxymodelqml.h 2014-12-02 18:43:43 +0000
856@@ -0,0 +1,63 @@
857+/*
858+ * Copyright (C) 2012 Canonical, Ltd.
859+ *
860+ * This program is free software; you can redistribute it and/or modify
861+ * it under the terms of the GNU General Public License as published by
862+ * the Free Software Foundation; version 3.
863+ *
864+ * This program is distributed in the hope that it will be useful,
865+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
866+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
867+ * GNU General Public License for more details.
868+ *
869+ * You should have received a copy of the GNU General Public License
870+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
871+ */
872+
873+#ifndef QSORTFILTERPROXYMODELQML_H
874+#define QSORTFILTERPROXYMODELQML_H
875+
876+#include <QSortFilterProxyModel>
877+
878+class QSortFilterProxyModelQML : public QSortFilterProxyModel
879+{
880+ Q_OBJECT
881+
882+ Q_PROPERTY(QAbstractItemModel* model READ sourceModel WRITE setModel NOTIFY modelChanged)
883+ Q_PROPERTY(int totalCount READ totalCount NOTIFY totalCountChanged)
884+ Q_PROPERTY(int count READ count NOTIFY countChanged)
885+ Q_PROPERTY(bool invertMatch READ invertMatch WRITE setInvertMatch NOTIFY invertMatchChanged)
886+
887+public:
888+ explicit QSortFilterProxyModelQML(QObject *parent = 0);
889+
890+ Q_INVOKABLE QVariantMap get(int row); // Use with caution, it can be slow to query all the roles
891+ Q_INVOKABLE QVariant data(int row, int role);
892+ Q_INVOKABLE int count();
893+ Q_INVOKABLE int findFirst(int role, const QVariant& value) const;
894+ Q_INVOKABLE int mapRowToSource(int row);
895+ virtual bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;
896+
897+ /* getters */
898+ int totalCount() const;
899+ bool invertMatch() const;
900+ QHash<int, QByteArray> roleNames() const;
901+
902+ /* setters */
903+ void setModel(QAbstractItemModel *model);
904+ void setInvertMatch(bool invertMatch);
905+
906+ Q_INVOKABLE int mapFromSource(int row);
907+ Q_INVOKABLE int mapToSource(int row);
908+
909+Q_SIGNALS:
910+ void totalCountChanged();
911+ void countChanged();
912+ void invertMatchChanged(bool);
913+ void modelChanged();
914+
915+private:
916+ bool m_invertMatch;
917+};
918+
919+#endif // QSORTFILTERPROXYMODELQML_H
920
921=== added file 'wizard/Utils/system.cpp'
922--- wizard/Utils/system.cpp 1970-01-01 00:00:00 +0000
923+++ wizard/Utils/system.cpp 2014-12-02 18:43:43 +0000
924@@ -0,0 +1,118 @@
925+/*
926+ * This file is part of system-settings
927+ *
928+ * Copyright (C) 2014 Canonical Ltd.
929+ *
930+ * This program is free software: you can redistribute it and/or modify it
931+ * under the terms of the GNU General Public License version 3, as published
932+ * by the Free Software Foundation.
933+ *
934+ * This program is distributed in the hope that it will be useful, but
935+ * WITHOUT ANY WARRANTY; without even the implied warranties of
936+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
937+ * PURPOSE. See the GNU General Public License for more details.
938+ *
939+ * You should have received a copy of the GNU General Public License along
940+ * with this program. If not, see <http://www.gnu.org/licenses/>.
941+ */
942+
943+#include "system.h"
944+#include <QDBusInterface>
945+#include <QDBusPendingCall>
946+#include <QDBusPendingReply>
947+#include <QFile>
948+#include <QProcess>
949+#include <unistd.h>
950+
951+#define HERE_IFACE "com.ubuntu.location.providers.here.AccountsService"
952+#define ENABLED_PROP "LicenseAccepted"
953+#define PATH_PROP "LicenseBasePath"
954+
955+System::System()
956+ : QObject(),
957+ m_accounts(nullptr),
958+ m_hereEnabled(false),
959+ m_hereLicensePath(" ") // use a single space to indicate it is unasssigned
960+{
961+ m_accounts = new QDBusInterface("org.freedesktop.Accounts",
962+ "/org/freedesktop/Accounts/User" + QString::number(geteuid()),
963+ "org.freedesktop.DBus.Properties",
964+ QDBusConnection::systemBus(),
965+ this);
966+
967+ m_accounts->connection().connect(m_accounts->service(),
968+ m_accounts->path(),
969+ m_accounts->interface(),
970+ "PropertiesChanged",
971+ this,
972+ SLOT(propertiesChanged(QString, QVariantMap, QStringList)));
973+
974+ QDBusPendingCall call = m_accounts->asyncCall("Get", HERE_IFACE, PATH_PROP);
975+ QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this);
976+ QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher *)),
977+ this, SLOT(getHereLicensePathFinished(QDBusPendingCallWatcher *)));
978+}
979+
980+void System::propertiesChanged(const QString &interface, const QVariantMap &changed, const QStringList &invalid)
981+{
982+ if (interface == HERE_IFACE) {
983+ if (changed.contains(ENABLED_PROP)) {
984+ m_hereEnabled = changed[ENABLED_PROP].toBool();
985+ Q_EMIT hereEnabledChanged();
986+ } else if (invalid.contains(ENABLED_PROP)) {
987+ QDBusPendingCall call = m_accounts->asyncCall("Get", HERE_IFACE, ENABLED_PROP);
988+ QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this);
989+ QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher *)),
990+ this, SLOT(getHereEnabledFinished(QDBusPendingCallWatcher *)));
991+ }
992+ }
993+}
994+
995+void System::getHereEnabledFinished(QDBusPendingCallWatcher *watcher)
996+{
997+ QDBusPendingReply<QVariant> reply = *watcher;
998+ if (!reply.isError()) {
999+ QVariant value = reply.argumentAt<0>();
1000+ m_hereEnabled = value.toBool();
1001+ Q_EMIT hereEnabledChanged();
1002+ }
1003+ watcher->deleteLater();
1004+}
1005+
1006+void System::getHereLicensePathFinished(QDBusPendingCallWatcher *watcher)
1007+{
1008+ QDBusPendingReply<QVariant> reply = *watcher;
1009+
1010+ m_hereLicensePath = "";
1011+
1012+ if (!reply.isError()) {
1013+ QVariant value = reply.argumentAt<0>();
1014+ if (QFile::exists(value.toString())) {
1015+ m_hereLicensePath = value.toString();
1016+ }
1017+ }
1018+
1019+ Q_EMIT hereLicensePathChanged();
1020+
1021+ watcher->deleteLater();
1022+}
1023+
1024+bool System::hereEnabled() const
1025+{
1026+ return m_hereEnabled;
1027+}
1028+
1029+void System::setHereEnabled(bool enabled)
1030+{
1031+ m_accounts->asyncCall("Set", HERE_IFACE, ENABLED_PROP, QVariant::fromValue(QDBusVariant(enabled)));
1032+}
1033+
1034+QString System::hereLicensePath() const
1035+{
1036+ return m_hereLicensePath;
1037+}
1038+
1039+void System::updateSessionLanguage()
1040+{
1041+ QProcess::startDetached("sh -c \"initctl start ubuntu-system-settings-wizard-set-lang; initctl emit --no-wait indicator-services-start; initctl start --no-wait maliit-server\"");
1042+}
1043
1044=== added file 'wizard/Utils/system.h'
1045--- wizard/Utils/system.h 1970-01-01 00:00:00 +0000
1046+++ wizard/Utils/system.h 2014-12-02 18:43:43 +0000
1047@@ -0,0 +1,57 @@
1048+/*
1049+ * This file is part of system-settings
1050+ *
1051+ * Copyright (C) 2014 Canonical Ltd.
1052+ *
1053+ * This program is free software: you can redistribute it and/or modify it
1054+ * under the terms of the GNU General Public License version 3, as published
1055+ * by the Free Software Foundation.
1056+ *
1057+ * This program is distributed in the hope that it will be useful, but
1058+ * WITHOUT ANY WARRANTY; without even the implied warranties of
1059+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
1060+ * PURPOSE. See the GNU General Public License for more details.
1061+ *
1062+ * You should have received a copy of the GNU General Public License along
1063+ * with this program. If not, see <http://www.gnu.org/licenses/>.
1064+ */
1065+
1066+#include <QObject>
1067+#include <QString>
1068+
1069+class QDBusInterface;
1070+class QDBusPendingCallWatcher;
1071+
1072+class System : public QObject
1073+{
1074+ Q_OBJECT
1075+ Q_PROPERTY(bool hereEnabled READ hereEnabled WRITE setHereEnabled NOTIFY hereEnabledChanged)
1076+ Q_PROPERTY(QString hereLicensePath READ hereLicensePath NOTIFY hereLicensePathChanged)
1077+
1078+public:
1079+ System();
1080+
1081+ bool hereEnabled() const;
1082+ void setHereEnabled(bool enabled);
1083+
1084+ QString hereLicensePath() const;
1085+
1086+public Q_SLOTS:
1087+ void updateSessionLanguage();
1088+
1089+Q_SIGNALS:
1090+ void hereEnabledChanged();
1091+ void hereLicensePathChanged();
1092+
1093+private Q_SLOTS:
1094+ void propertiesChanged(const QString &interface, const QVariantMap &changed, const QStringList &invalid);
1095+ void getHereEnabledFinished(QDBusPendingCallWatcher *watcher);
1096+ void getHereLicensePathFinished(QDBusPendingCallWatcher *watcher);
1097+
1098+private:
1099+ Q_DISABLE_COPY(System)
1100+
1101+ QDBusInterface *m_accounts;
1102+ bool m_hereEnabled;
1103+ QString m_hereLicensePath;
1104+};
1105
1106=== added file 'wizard/main.cpp'
1107--- wizard/main.cpp 1970-01-01 00:00:00 +0000
1108+++ wizard/main.cpp 2014-12-02 18:43:43 +0000
1109@@ -0,0 +1,93 @@
1110+/*
1111+ * This file is part of system-settings
1112+ *
1113+ * Copyright (C) 2014 Canonical Ltd.
1114+ *
1115+ * This program is free software: you can redistribute it and/or modify it
1116+ * under the terms of the GNU General Public License version 3, as published
1117+ * by the Free Software Foundation.
1118+ *
1119+ * This program is distributed in the hope that it will be useful, but
1120+ * WITHOUT ANY WARRANTY; without even the implied warranties of
1121+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
1122+ * PURPOSE. See the GNU General Public License for more details.
1123+ *
1124+ * You should have received a copy of the GNU General Public License along
1125+ * with this program. If not, see <http://www.gnu.org/licenses/>.
1126+ */
1127+
1128+#include <csignal>
1129+#include <libintl.h>
1130+#include <qpa/qplatformnativeinterface.h>
1131+#include <QDebug>
1132+#include <QGuiApplication>
1133+#include <QLibrary>
1134+#include <QObject>
1135+#include <QProcess>
1136+#include <QQmlContext>
1137+#include <QQmlEngine>
1138+#include <QQuickItem>
1139+#include <QQuickView>
1140+#include <QTimer>
1141+
1142+#include "PageList.h"
1143+
1144+void handleQuit()
1145+{
1146+ QProcess::startDetached("initctl start ubuntu-system-settings-wizard-cleanup");
1147+}
1148+
1149+int main(int argc, const char *argv[])
1150+{
1151+ bool isMirServer = false;
1152+ if (qgetenv("QT_QPA_PLATFORM") == "ubuntumirclient") {
1153+ setenv("QT_QPA_PLATFORM", "mirserver", 1 /* overwrite */);
1154+ isMirServer = true;
1155+ }
1156+
1157+ QGuiApplication::setApplicationName("System Settings Wizard");
1158+ QGuiApplication *application = new QGuiApplication(argc, (char**)argv);
1159+
1160+ bindtextdomain(I18N_DOMAIN, NULL);
1161+ textdomain(I18N_DOMAIN);
1162+
1163+ QQuickView* view = new QQuickView();
1164+ view->setResizeMode(QQuickView::SizeRootObjectToView);
1165+ view->setTitle("Welcome Wizard");
1166+
1167+ QString rootDir = qgetenv("UBUNTU_SYSTEM_SETTINGS_WIZARD_ROOT"); // for testing
1168+ if (rootDir.isEmpty())
1169+ rootDir = WIZARD_ROOT;
1170+
1171+ QString modulesDir = qgetenv("UBUNTU_SYSTEM_SETTINGS_WIZARD_MODULES"); // for testing
1172+ if (modulesDir.isEmpty())
1173+ modulesDir = PLUGIN_PRIVATE_MODULE_DIR;
1174+
1175+ if (!isMirServer) {
1176+ view->engine()->addImportPath(modulesDir + "/Ubuntu/SystemSettings/Wizard/NonMir");
1177+ }
1178+ view->engine()->addImportPath(modulesDir);
1179+ view->engine()->addImportPath(PLUGIN_QML_DIR);
1180+ view->engine()->addImportPath(SHELL_PLUGINDIR);
1181+
1182+ PageList pageList;
1183+ view->rootContext()->setContextProperty("pageList", &pageList);
1184+ view->setSource(QUrl(rootDir + "/ubuntu/settings/wizard/qml/main.qml"));
1185+ view->setColor("transparent");
1186+
1187+ QObject::connect(view->engine(), &QQmlEngine::quit, handleQuit);
1188+
1189+ if (isMirServer) {
1190+ view->showFullScreen();
1191+ } else {
1192+ view->show();
1193+ }
1194+
1195+ int result = application->exec();
1196+
1197+ delete view;
1198+ delete application;
1199+ return result;
1200+}
1201+
1202+#include "main.moc"
1203
1204=== added directory 'wizard/qml'
1205=== added directory 'wizard/qml/Components'
1206=== added file 'wizard/qml/Components/CheckableSetting.qml'
1207--- wizard/qml/Components/CheckableSetting.qml 1970-01-01 00:00:00 +0000
1208+++ wizard/qml/Components/CheckableSetting.qml 2014-12-02 18:43:43 +0000
1209@@ -0,0 +1,85 @@
1210+/*
1211+ * Copyright (C) 2014 Canonical, Ltd.
1212+ *
1213+ * This program is free software; you can redistribute it and/or modify
1214+ * it under the terms of the GNU General Public License as published by
1215+ * the Free Software Foundation; version 3.
1216+ *
1217+ * This program is distributed in the hope that it will be useful,
1218+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1219+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1220+ * GNU General Public License for more details.
1221+ *
1222+ * You should have received a copy of the GNU General Public License
1223+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1224+ */
1225+
1226+import QtQuick 2.3
1227+import QMenuModel 0.1
1228+import Ubuntu.Components 1.1
1229+import Ubuntu.Components.ListItems 1.0 as ListItem
1230+
1231+ListItem.Empty {
1232+ id: listItem
1233+
1234+ property alias text: label.text
1235+ property bool checked: false
1236+ property real leftMargin
1237+ property real rightMargin
1238+
1239+ readonly property real labelOffset: label.x
1240+
1241+ signal linkActivated(string link)
1242+
1243+ implicitHeight: Math.max(label.height, checkBox.height)
1244+
1245+ Item {
1246+ anchors.fill: parent
1247+
1248+ CheckBox {
1249+ id: checkBox
1250+
1251+ anchors {
1252+ left: parent.left
1253+ top: parent.top
1254+ leftMargin: listItem.leftMargin
1255+ }
1256+
1257+ Component.onCompleted: {
1258+ checked = listItem.checked;
1259+ }
1260+
1261+ onClicked: {
1262+ listItem.checked = checked
1263+ listItem.triggered(listItem.checked)
1264+ }
1265+
1266+ Connections {
1267+ target: listItem
1268+ onCheckedChanged: checkBox.checked = listItem.checked
1269+ }
1270+
1271+ Connections {
1272+ target: listItem.__mouseArea
1273+ onClicked: {
1274+ listItem.checked = !listItem.checked
1275+ listItem.triggered(listItem.checked)
1276+ }
1277+ }
1278+ }
1279+
1280+ Label {
1281+ id: label
1282+ anchors {
1283+ left: checkBox.right
1284+ right: parent.right
1285+ verticalCenter: parent.verticalCenter
1286+ leftMargin: units.gu(2)
1287+ rightMargin: listItem.rightMargin
1288+ }
1289+ wrapMode: Text.Wrap
1290+ linkColor: Theme.palette.normal.foregroundText
1291+ onLinkActivated: listItem.linkActivated(link)
1292+ }
1293+ }
1294+}
1295
1296=== added file 'wizard/qml/Components/InputMethod.qml'
1297--- wizard/qml/Components/InputMethod.qml 1970-01-01 00:00:00 +0000
1298+++ wizard/qml/Components/InputMethod.qml 2014-12-02 18:43:43 +0000
1299@@ -0,0 +1,113 @@
1300+/*
1301+ * Copyright (C) 2014 Canonical, Ltd.
1302+ *
1303+ * This program is free software; you can redistribute it and/or modify
1304+ * it under the terms of the GNU General Public License as published by
1305+ * the Free Software Foundation; version 3.
1306+ *
1307+ * This program is distributed in the hope that it will be useful,
1308+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1309+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1310+ * GNU General Public License for more details.
1311+ *
1312+ * You should have received a copy of the GNU General Public License
1313+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1314+ */
1315+
1316+import QtQuick 2.0
1317+import Unity.Application 0.1
1318+import Ubuntu.Components 0.1
1319+
1320+// TODO: try to share this code with that from the unity8 shell
1321+
1322+Item {
1323+ id: root
1324+
1325+ Connections {
1326+ target: SurfaceManager
1327+ onSurfaceCreated: {
1328+ if (surface.type == MirSurfaceItem.InputMethod) {
1329+ root.surface = surface;
1330+ }
1331+ }
1332+
1333+ onSurfaceDestroyed: {
1334+ if (root.surface == surface) {
1335+ root.surface = null;
1336+ surface.parent = null;
1337+ }
1338+ if (!surface.parent) {
1339+ // there's no one displaying it. delete it right away
1340+ surface.release();
1341+ }
1342+ }
1343+ }
1344+
1345+ property var surface: null
1346+
1347+ property int transitionDuration: UbuntuAnimation.FastDuration
1348+
1349+ state: {
1350+ if (surface && surface.state != MirSurfaceItem.Minimized) {
1351+ return "shown";
1352+ } else {
1353+ return "hidden";
1354+ }
1355+ }
1356+
1357+ states: [
1358+ State {
1359+ name: "shown"
1360+ PropertyChanges {
1361+ target: root
1362+ visible: true
1363+ y: 0
1364+ }
1365+ },
1366+ State {
1367+ name: "hidden"
1368+ PropertyChanges {
1369+ target: root
1370+ visible: false
1371+ // half-way down because the vkb occupies only the lower half of the surface
1372+ // TODO: consider keyboard rotation
1373+ y: root.parent.height / 2.0
1374+ }
1375+ }
1376+ ]
1377+
1378+ transitions: [
1379+ Transition {
1380+ from: "*"; to: "*"
1381+ PropertyAction { property: "visible"; value: true }
1382+ UbuntuNumberAnimation { property: "y"; duration: transitionDuration }
1383+ }
1384+ ]
1385+
1386+ Connections {
1387+ target: surface
1388+ ignoreUnknownSignals: true // don't wanna spam the log when surface is null
1389+ onStateChanged: {
1390+ if (state == MirSurfaceItem.Minimized) {
1391+ root.hide();
1392+ } else if (state == MirSurfaceItem.Maximized) {
1393+ root.show();
1394+ }
1395+ }
1396+ }
1397+
1398+ onSurfaceChanged: {
1399+ if (surface) {
1400+ surface.parent = root;
1401+ surface.anchors.fill = root;
1402+ }
1403+ }
1404+
1405+ Component.onDestruction: {
1406+ if (surface) {
1407+ surface.parent = null;
1408+ surface.release();
1409+ surface = null;
1410+ }
1411+ }
1412+}
1413
1414=== added file 'wizard/qml/Components/Page.qml'
1415--- wizard/qml/Components/Page.qml 1970-01-01 00:00:00 +0000
1416+++ wizard/qml/Components/Page.qml 2014-12-02 18:43:43 +0000
1417@@ -0,0 +1,107 @@
1418+/*
1419+ * Copyright (C) 2013 Canonical, Ltd.
1420+ *
1421+ * This program is free software; you can redistribute it and/or modify
1422+ * it under the terms of the GNU General Public License as published by
1423+ * the Free Software Foundation; version 3.
1424+ *
1425+ * This program is distributed in the hope that it will be useful,
1426+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1427+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1428+ * GNU General Public License for more details.
1429+ *
1430+ * You should have received a copy of the GNU General Public License
1431+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1432+ */
1433+
1434+import QtQuick 2.3
1435+import Ubuntu.Components 1.1
1436+import "." as LocalComponents
1437+
1438+Item {
1439+ readonly property real buttonMargin: units.gu(2)
1440+ readonly property real buttonWidth: (width - buttonMargin * 2) / 2 -
1441+ buttonMargin / 2
1442+ readonly property real topMargin: units.gu(8)
1443+ readonly property real leftMargin: units.gu(2)
1444+ readonly property real rightMargin: units.gu(2)
1445+
1446+ // If you want to skip a page, mark skipValid false while you figure out
1447+ // whether to skip, then set it to true once you've determined the value
1448+ // of the skip property.
1449+ property bool skipValid: true
1450+ property bool skip: false
1451+
1452+ property bool hasBackButton: true
1453+ property bool customBack: false
1454+ property alias forwardButtonSourceComponent: forwardButton.sourceComponent
1455+ property alias content: contentHolder
1456+
1457+ property string title: ""
1458+
1459+ signal backClicked()
1460+
1461+ visible: false
1462+ anchors.fill: parent
1463+
1464+ // We want larger than even fontSize: "x-large", so we use a Text instead
1465+ // of a Label.
1466+ Text {
1467+ id: titleLabel
1468+ anchors {
1469+ top: parent.top
1470+ left: parent.left
1471+ right: parent.right
1472+ topMargin: topMargin
1473+ leftMargin: leftMargin
1474+ rightMargin: rightMargin
1475+ }
1476+ wrapMode: Text.Wrap
1477+ text: title
1478+ color: Theme.palette.normal.baseText
1479+ font.pixelSize: units.gu(4)
1480+ }
1481+
1482+ Item {
1483+ id: contentHolder
1484+ anchors {
1485+ top: titleLabel.bottom
1486+ left: parent.left
1487+ right: parent.right
1488+ bottom: backButton.top
1489+ topMargin: units.gu(4)
1490+ leftMargin: leftMargin
1491+ rightMargin: rightMargin
1492+ bottomMargin: buttonMargin
1493+ }
1494+ }
1495+
1496+ LocalComponents.StackButton {
1497+ id: backButton
1498+ width: buttonWidth
1499+ anchors {
1500+ left: parent.left
1501+ bottom: parent.bottom
1502+ leftMargin: buttonMargin
1503+ bottomMargin: buttonMargin
1504+ }
1505+ z: 1
1506+ text: i18n.tr("Back")
1507+ visible: pageStack.depth > 1 && hasBackButton
1508+ backArrow: true
1509+
1510+ onClicked: customBack ? backClicked() : pageStack.prev()
1511+ }
1512+
1513+ Loader {
1514+ id: forwardButton
1515+ width: buttonWidth
1516+ anchors {
1517+ right: parent.right
1518+ bottom: parent.bottom
1519+ rightMargin: buttonMargin
1520+ bottomMargin: buttonMargin
1521+ }
1522+ z: 1
1523+ }
1524+}
1525
1526=== added file 'wizard/qml/Components/StackButton.qml'
1527--- wizard/qml/Components/StackButton.qml 1970-01-01 00:00:00 +0000
1528+++ wizard/qml/Components/StackButton.qml 2014-12-02 18:43:43 +0000
1529@@ -0,0 +1,47 @@
1530+/*
1531+ * Copyright (C) 2014 Canonical, Ltd.
1532+ *
1533+ * This program is free software; you can redistribute it and/or modify
1534+ * it under the terms of the GNU General Public License as published by
1535+ * the Free Software Foundation; version 3.
1536+ *
1537+ * This program is distributed in the hope that it will be useful,
1538+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1539+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1540+ * GNU General Public License for more details.
1541+ *
1542+ * You should have received a copy of the GNU General Public License
1543+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1544+ */
1545+
1546+import QtQuick 2.3
1547+import Ubuntu.Components 1.1
1548+
1549+AbstractButton {
1550+ id: stackButton
1551+
1552+ property string text
1553+
1554+ property bool backArrow: false
1555+
1556+ width: label.width
1557+ height: label.height + units.gu(4)
1558+
1559+ Label {
1560+ id: label
1561+ anchors.verticalCenter: parent.verticalCenter
1562+ anchors.left: parent.left
1563+ anchors.right: parent.right
1564+ color: enabled ? Theme.palette.selected.backgroundText : Qt.darker(Theme.palette.selected.backgroundText, 1.5)
1565+ text: {
1566+ if (backArrow) {
1567+ // Translators: This is the arrow for "Back" buttons
1568+ return i18n.tr("〈 %1".arg(stackButton.text))
1569+ } else {
1570+ // Translators: This is the arrow for "Forward" buttons
1571+ return i18n.tr("%1 〉".arg(stackButton.text))
1572+ }
1573+ }
1574+ horizontalAlignment: backArrow ? Text.AlignLeft : Text.AlignRight
1575+ }
1576+}
1577
1578=== added directory 'wizard/qml/Pages'
1579=== added file 'wizard/qml/Pages/10-welcome.qml'
1580--- wizard/qml/Pages/10-welcome.qml 1970-01-01 00:00:00 +0000
1581+++ wizard/qml/Pages/10-welcome.qml 2014-12-02 18:43:43 +0000
1582@@ -0,0 +1,93 @@
1583+/*
1584+ * Copyright (C) 2013 Canonical, Ltd.
1585+ *
1586+ * This program is free software; you can redistribute it and/or modify
1587+ * it under the terms of the GNU General Public License as published by
1588+ * the Free Software Foundation; version 3.
1589+ *
1590+ * This program is distributed in the hope that it will be useful,
1591+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1592+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1593+ * GNU General Public License for more details.
1594+ *
1595+ * You should have received a copy of the GNU General Public License
1596+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1597+ */
1598+
1599+import QtQuick 2.3
1600+import Ubuntu.Components 1.1
1601+import Ubuntu.Components.ListItems 0.1
1602+import Ubuntu.SystemSettings.LanguagePlugin 1.0
1603+import Ubuntu.SystemSettings.Wizard.Utils 0.1
1604+import "../Components" as LocalComponents
1605+
1606+LocalComponents.Page {
1607+ title: i18n.tr("Hi!")
1608+ forwardButtonSourceComponent: forwardButton
1609+
1610+ UbuntuLanguagePlugin {
1611+ id: plugin
1612+ }
1613+
1614+ Column {
1615+ id: column
1616+ anchors.fill: content
1617+ spacing: units.gu(1)
1618+
1619+ Label {
1620+ id: label1
1621+ anchors.left: parent.left
1622+ anchors.right: parent.right
1623+ wrapMode: Text.Wrap
1624+ text: i18n.tr("Welcome to your Ubuntu phone.")
1625+ }
1626+
1627+ Label {
1628+ id: label2
1629+ anchors.left: parent.left
1630+ anchors.right: parent.right
1631+ wrapMode: Text.Wrap
1632+ text: i18n.tr("Let’s get started.")
1633+ }
1634+
1635+ Item { // spacer
1636+ height: units.gu(2)
1637+ width: units.gu(1) // needed else it will be ignored
1638+ }
1639+
1640+ ComboButton {
1641+ id: combo
1642+ anchors.left: parent.left
1643+ anchors.right: parent.right
1644+ text: listview.currentItem.text
1645+ onClicked: expanded = !expanded
1646+ expandedHeight: column.height - combo.y
1647+ UbuntuListView {
1648+ id: listview
1649+ model: plugin.languageNames
1650+ currentIndex: plugin.currentLanguage
1651+ delegate: Standard {
1652+ text: modelData
1653+ onClicked: {
1654+ listview.currentIndex = index
1655+ combo.expanded = false
1656+ i18n.language = plugin.languageCodes[index]
1657+ i18n.domain = i18n.domain
1658+ }
1659+ }
1660+ }
1661+ }
1662+ }
1663+
1664+ Component {
1665+ id: forwardButton
1666+ LocalComponents.StackButton {
1667+ text: i18n.tr("Continue")
1668+ onClicked: {
1669+ plugin.currentLanguage = listview.currentIndex
1670+ System.updateSessionLanguage()
1671+ pageStack.next()
1672+ }
1673+ }
1674+ }
1675+}
1676
1677=== added file 'wizard/qml/Pages/20-sim.qml'
1678--- wizard/qml/Pages/20-sim.qml 1970-01-01 00:00:00 +0000
1679+++ wizard/qml/Pages/20-sim.qml 2014-12-02 18:43:43 +0000
1680@@ -0,0 +1,71 @@
1681+/*
1682+ * Copyright (C) 2013 Canonical, Ltd.
1683+ *
1684+ * This program is free software; you can redistribute it and/or modify
1685+ * it under the terms of the GNU General Public License as published by
1686+ * the Free Software Foundation; version 3.
1687+ *
1688+ * This program is distributed in the hope that it will be useful,
1689+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1690+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1691+ * GNU General Public License for more details.
1692+ *
1693+ * You should have received a copy of the GNU General Public License
1694+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1695+ */
1696+
1697+import QtQuick 2.0
1698+import MeeGo.QOfono 0.2
1699+import Ubuntu.Components 0.1
1700+import "../Components" as LocalComponents
1701+
1702+LocalComponents.Page {
1703+ title: i18n.tr("Add a SIM card and restart your device")
1704+ forwardButtonSourceComponent: forwardButton
1705+
1706+ // No need for skipValid, since OfonoManager does everything synchronously
1707+ skip: !manager.available || manager.modems.length === 0 || simManager0.present || simManager1.present
1708+
1709+ OfonoManager {
1710+ id: manager
1711+ }
1712+
1713+ // Ideally we would query the system more cleverly than hardcoding two
1714+ // modems. But we don't yet have a more clever way. :(
1715+ OfonoSimManager {
1716+ id: simManager0
1717+ modemPath: manager.modems.length >= 1 ? manager.modems[0] : ""
1718+ }
1719+
1720+ OfonoSimManager {
1721+ id: simManager1
1722+ modemPath: manager.modems.length >= 2 ? manager.modems[1] : ""
1723+ }
1724+
1725+ Column {
1726+ anchors.fill: content
1727+ spacing: units.gu(4)
1728+
1729+ Label {
1730+ anchors.left: parent.left
1731+ anchors.right: parent.right
1732+ wrapMode: Text.Wrap
1733+ text: i18n.tr("Without it, you won’t be able to make calls or use text messaging.")
1734+ }
1735+
1736+ Image {
1737+ id: image
1738+ source: "data/meet_ubuntu_simcard@30.png"
1739+ height: units.gu(6.5)
1740+ width: units.gu(9)
1741+ }
1742+ }
1743+
1744+ Component {
1745+ id: forwardButton
1746+ LocalComponents.StackButton {
1747+ text: i18n.tr("Skip")
1748+ onClicked: pageStack.next()
1749+ }
1750+ }
1751+}
1752
1753=== added file 'wizard/qml/Pages/30-passwd-type.qml'
1754--- wizard/qml/Pages/30-passwd-type.qml 1970-01-01 00:00:00 +0000
1755+++ wizard/qml/Pages/30-passwd-type.qml 2014-12-02 18:43:43 +0000
1756@@ -0,0 +1,119 @@
1757+/*
1758+ * Copyright (C) 2014 Canonical, Ltd.
1759+ *
1760+ * This program is free software; you can redistribute it and/or modify
1761+ * it under the terms of the GNU General Public License as published by
1762+ * the Free Software Foundation; version 3.
1763+ *
1764+ * This program is distributed in the hope that it will be useful,
1765+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1766+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1767+ * GNU General Public License for more details.
1768+ *
1769+ * You should have received a copy of the GNU General Public License
1770+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1771+ */
1772+
1773+import QtQuick 2.3
1774+import Ubuntu.Components 1.1
1775+import Ubuntu.Components.ListItems 1.0
1776+import Ubuntu.SystemSettings.SecurityPrivacy 1.0
1777+import "../Components" as LocalComponents
1778+
1779+/**
1780+ * One quirk with this page: we don't actually set the password. We avoid
1781+ * doing it here because the user can come back to this page and change their
1782+ * answer. We don't run as root, so if we did set the password immediately,
1783+ * we'd need to prompt for their previous password when they came back and
1784+ * changed their answer. Which is silly UX. So instead, we just keep track
1785+ * of their choice and set the password at the end (see main.qml).
1786+ * Setting the password shouldn't fail, since Ubuntu Touch has loose password
1787+ * requirements, but we'll check what we can here. Ideally we'd be able to ask
1788+ * the system if a password is legal without actually setting that password.
1789+ */
1790+
1791+LocalComponents.Page {
1792+ id: passwdPage
1793+ title: i18n.tr("Lock security")
1794+ forwardButtonSourceComponent: forwardButton
1795+
1796+ function indexToMethod(index) {
1797+ if (index === 0)
1798+ return UbuntuSecurityPrivacyPanel.Swipe
1799+ else if (index === 1)
1800+ return UbuntuSecurityPrivacyPanel.Passcode
1801+ else
1802+ return UbuntuSecurityPrivacyPanel.Passphrase
1803+ }
1804+
1805+ function methodToIndex(method) {
1806+ if (method === UbuntuSecurityPrivacyPanel.Swipe)
1807+ return 0
1808+ else if (method === UbuntuSecurityPrivacyPanel.Passcode)
1809+ return 1
1810+ else
1811+ return 2
1812+ }
1813+
1814+ Connections {
1815+ target: root
1816+ onPasswordMethodChanged: selector.selectedIndex = methodToIndex(root.passwordMethod)
1817+ }
1818+
1819+ Column {
1820+ id: column
1821+ anchors.fill: content
1822+ spacing: units.gu(4)
1823+
1824+ Label {
1825+ anchors.left: parent.left
1826+ anchors.right: parent.right
1827+ wrapMode: Text.Wrap
1828+ text: i18n.tr("Please select how you’d like to unlock your phone.")
1829+ }
1830+
1831+ ItemSelector {
1832+ id: selector
1833+ expanded: true
1834+ anchors.left: parent.left
1835+ anchors.right: parent.right
1836+
1837+ model: ["", "", ""] // otherwise the delegate will show the text itself and we only want subText
1838+
1839+ selectedIndex: methodToIndex(root.passwordMethod)
1840+
1841+ delegate: OptionSelectorDelegate {
1842+ // use subText because we want the text to be small, and we have no other way to control it
1843+ subText: {
1844+ var method = indexToMethod(index)
1845+ var name = ""
1846+ var desc = ""
1847+ if (method === UbuntuSecurityPrivacyPanel.Swipe) {
1848+ name = i18n.tr("Swipe")
1849+ desc = i18n.tr("No security")
1850+ } else if (method === UbuntuSecurityPrivacyPanel.Passcode) {
1851+ name = i18n.tr("Passcode")
1852+ desc = i18n.tr("4 digits only")
1853+ } else {
1854+ name = i18n.tr("Passphrase")
1855+ desc = i18n.tr("Numbers and letters")
1856+ }
1857+ return "<b>%1</b> (%2)".arg(name).arg(desc)
1858+ }
1859+ }
1860+
1861+ style: Item {}
1862+ }
1863+ }
1864+
1865+ Component {
1866+ id: forwardButton
1867+ LocalComponents.StackButton {
1868+ text: i18n.tr("Continue")
1869+ onClicked: {
1870+ root.passwordMethod = indexToMethod(selector.selectedIndex)
1871+ pageStack.load(Qt.resolvedUrl("passwd-set.qml"))
1872+ }
1873+ }
1874+ }
1875+}
1876
1877=== added file 'wizard/qml/Pages/40-wifi.qml'
1878--- wizard/qml/Pages/40-wifi.qml 1970-01-01 00:00:00 +0000
1879+++ wizard/qml/Pages/40-wifi.qml 2014-12-02 18:43:43 +0000
1880@@ -0,0 +1,200 @@
1881+/*
1882+ * Copyright (C) 2013 Canonical, Ltd.
1883+ *
1884+ * This program is free software; you can redistribute it and/or modify
1885+ * it under the terms of the GNU General Public License as published by
1886+ * the Free Software Foundation; version 3.
1887+ *
1888+ * This program is distributed in the hope that it will be useful,
1889+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1890+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1891+ * GNU General Public License for more details.
1892+ *
1893+ * You should have received a copy of the GNU General Public License
1894+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1895+ */
1896+
1897+import QtQuick 2.0
1898+import QMenuModel 0.1 as QMenuModel
1899+import Ubuntu.Components 0.1
1900+import Ubuntu.Components.ListItems 0.1 as ListItem
1901+import Ubuntu.SystemSettings.Wizard.Utils 0.1
1902+import Ubuntu.Settings.Menus 0.1 as Menus
1903+import "../Components" as LocalComponents
1904+
1905+LocalComponents.Page {
1906+ id: wifiPage
1907+ title: i18n.tr("Connect to Wi‑Fi")
1908+ forwardButtonSourceComponent: forwardButton
1909+
1910+ readonly property bool connected: mainMenu.connectedAPs === 1
1911+
1912+ function getExtendedProperty(object, propertyName, defaultValue) {
1913+ if (object && object.hasOwnProperty(propertyName)) {
1914+ return object[propertyName];
1915+ }
1916+ return defaultValue;
1917+ }
1918+
1919+ QMenuModel.UnityMenuModel {
1920+ id: menuModel
1921+ busName: "com.canonical.indicator.network"
1922+ actions: { "indicator": "/com/canonical/indicator/network" }
1923+ menuObjectPath: "/com/canonical/indicator/network/phone_wifi_settings"
1924+ }
1925+
1926+ Component {
1927+ id: accessPointComponent
1928+ ListItem.Standard {
1929+ id: accessPoint
1930+ objectName: "accessPoint"
1931+
1932+ property QtObject menuData: null
1933+ property var unityMenuModel: menuModel
1934+ property var extendedData: menuData && menuData.ext || undefined
1935+ property var strengthAction: QMenuModel.UnityMenuAction {
1936+ model: unityMenuModel
1937+ index: menuIndex
1938+ name: getExtendedProperty(extendedData, "xCanonicalWifiApStrengthAction", "")
1939+ }
1940+ property bool checked: menuData && menuData.isToggled || false
1941+ property bool secure: getExtendedProperty(extendedData, "xCanonicalWifiApIsSecure", false)
1942+ property bool adHoc: getExtendedProperty(extendedData, "xCanonicalWifiApIsAdhoc", false)
1943+ property int signalStrength: strengthAction.valid ? strengthAction.state : 0
1944+ property int menuIndex: -1
1945+
1946+ function loadAttributes() {
1947+ if (!unityMenuModel || menuIndex == -1) return;
1948+ unityMenuModel.loadExtendedAttributes(menuIndex, {'x-canonical-wifi-ap-is-adhoc': 'bool',
1949+ 'x-canonical-wifi-ap-is-secure': 'bool',
1950+ 'x-canonical-wifi-ap-strength-action': 'string'});
1951+ }
1952+
1953+ signal activate()
1954+
1955+ text: menuData && menuData.label || ""
1956+ enabled: menuData && menuData.sensitive || false
1957+ iconName: {
1958+ var imageName = "nm-signal-100";
1959+
1960+ if (adHoc) {
1961+ imageName = "nm-adhoc";
1962+ } else if (signalStrength == 0) {
1963+ imageName = "nm-signal-00";
1964+ } else if (signalStrength <= 25) {
1965+ imageName = "nm-signal-25";
1966+ } else if (signalStrength <= 50) {
1967+ imageName = "nm-signal-50";
1968+ } else if (signalStrength <= 75) {
1969+ imageName = "nm-signal-75";
1970+ }
1971+
1972+ if (secure) {
1973+ imageName += "-secure";
1974+ }
1975+ return imageName;
1976+ }
1977+ iconFrame: false
1978+ control: CheckBox {
1979+ id: checkBoxActive
1980+
1981+ onClicked: {
1982+ accessPoint.activate();
1983+ }
1984+ }
1985+ style: Rectangle {
1986+ color: "#4c000000"
1987+ }
1988+
1989+ Component.onCompleted: {
1990+ loadAttributes();
1991+ }
1992+ onUnityMenuModelChanged: {
1993+ loadAttributes();
1994+ }
1995+ onMenuIndexChanged: {
1996+ loadAttributes();
1997+ }
1998+ onCheckedChanged: {
1999+ // Can't rely on binding. Checked is assigned on click.
2000+ checkBoxActive.checked = checked;
2001+ if (checked) {
2002+ mainMenu.connectedAPs++
2003+ } else {
2004+ mainMenu.connectedAPs--
2005+ }
2006+ }
2007+ onActivate: unityMenuModel.activate(menuIndex);
2008+ }
2009+ }
2010+
2011+ Column {
2012+ id: column
2013+ spacing: units.gu(2)
2014+ anchors.top: content.top
2015+ anchors.bottom: content.bottom
2016+ anchors.left: wifiPage.left
2017+ anchors.right: wifiPage.right
2018+
2019+ Label {
2020+ id: label
2021+ anchors.left: parent.left
2022+ anchors.leftMargin: leftMargin
2023+ anchors.right: parent.right
2024+ anchors.rightMargin: rightMargin
2025+ fontSize: "small"
2026+ text: mainMenu.count > 0 ? i18n.tr("Available networks…")
2027+ : i18n.tr("No available networks.")
2028+ }
2029+
2030+ Flickable {
2031+ anchors.left: parent.left
2032+ anchors.right: parent.right
2033+ height: column.height - label.height - column.spacing
2034+ contentHeight: contentItem.childrenRect.height
2035+ clip: true
2036+ flickDeceleration: 1500 * units.gridUnit / 8
2037+ maximumFlickVelocity: 2500 * units.gridUnit / 8
2038+ boundsBehavior: (contentHeight > height) ? Flickable.DragAndOvershootBounds : Flickable.StopAtBounds
2039+
2040+ Column {
2041+ anchors.left: parent.left
2042+ anchors.right: parent.right
2043+
2044+ Repeater {
2045+ id: mainMenu
2046+
2047+ // FIXME Check connection better https://bugs.launchpad.net/indicator-network/+bug/1349371
2048+ property int connectedAPs: 0
2049+
2050+ model: menuModel
2051+
2052+ delegate: Loader {
2053+ id: loader
2054+
2055+ readonly property bool isAccessPoint: model.type === "unity.widgets.systemsettings.tablet.accesspoint"
2056+
2057+ anchors.left: parent.left
2058+ anchors.right: parent.right
2059+ height: isAccessPoint ? units.gu(6) : 0
2060+ asynchronous: true
2061+ sourceComponent: isAccessPoint ? accessPointComponent : null
2062+
2063+ onLoaded: {
2064+ item.menuData = Qt.binding(function() { return model; });
2065+ item.menuIndex = Qt.binding(function() { return index; });
2066+ }
2067+ }
2068+ }
2069+ }
2070+ }
2071+ }
2072+
2073+ Component {
2074+ id: forwardButton
2075+ LocalComponents.StackButton {
2076+ text: (connected || mainMenu.count === 0) ? i18n.tr("Continue") : i18n.tr("Skip")
2077+ onClicked: pageStack.next()
2078+ }
2079+ }
2080+}
2081
2082=== added file 'wizard/qml/Pages/50-location.qml'
2083--- wizard/qml/Pages/50-location.qml 1970-01-01 00:00:00 +0000
2084+++ wizard/qml/Pages/50-location.qml 2014-12-02 18:43:43 +0000
2085@@ -0,0 +1,149 @@
2086+/*
2087+ * Copyright (C) 2013,2014 Canonical, Ltd.
2088+ *
2089+ * This program is free software; you can redistribute it and/or modify
2090+ * it under the terms of the GNU General Public License as published by
2091+ * the Free Software Foundation; version 3.
2092+ *
2093+ * This program is distributed in the hope that it will be useful,
2094+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2095+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2096+ * GNU General Public License for more details.
2097+ *
2098+ * You should have received a copy of the GNU General Public License
2099+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2100+ */
2101+
2102+import QtQuick 2.3
2103+import QMenuModel 0.1 as QMenuModel
2104+import Qt.labs.folderlistmodel 2.1
2105+import Ubuntu.Components 1.1
2106+import Ubuntu.SystemSettings.Wizard.Utils 0.1
2107+import "../Components" as LocalComponents
2108+
2109+LocalComponents.Page {
2110+ title: i18n.tr("Location")
2111+ forwardButtonSourceComponent: forwardButton
2112+
2113+ property bool pathSet: System.hereLicensePath !== " " // single space means it's unassigned
2114+ property bool countSet: false
2115+ skipValid: pathSet && (System.hereLicensePath === "" || countSet)
2116+ skip: skipValid && (System.hereLicensePath === "" || termsModel.count === 0)
2117+
2118+ Connections {
2119+ target: termsModel
2120+ onCountChanged: if (pathSet) countSet = true
2121+ }
2122+
2123+ FolderListModel {
2124+ id: termsModel
2125+ folder: System.hereLicensePath
2126+ nameFilters: ["*.html"]
2127+ showDirs: false
2128+ showOnlyReadable: true
2129+ }
2130+
2131+ QMenuModel.QDBusActionGroup {
2132+ id: locationActionGroup
2133+ busType: QMenuModel.DBus.SessionBus
2134+ busName: "com.canonical.indicator.location"
2135+ objectPath: "/com/canonical/indicator/location"
2136+ property variant location: action("location-detection-enabled")
2137+ property variant gps: action("gps-detection-enabled")
2138+ Component.onCompleted: start()
2139+ }
2140+
2141+ Column {
2142+ id: column
2143+ anchors.fill: content
2144+ spacing: units.gu(3)
2145+
2146+ Label {
2147+ anchors.left: parent.left
2148+ anchors.right: parent.right
2149+ wrapMode: Text.Wrap
2150+ text: i18n.tr("Let the phone detect your location:")
2151+ }
2152+
2153+ LocalComponents.CheckableSetting {
2154+ id: gpsCheck
2155+ showDivider: false
2156+ text: i18n.tr("Using GPS only (less accurate)")
2157+ onTriggered: {
2158+ gpsCheck.checked = true;
2159+ hereCheck.checked = false;
2160+ nopeCheck.checked = false;
2161+ }
2162+ }
2163+
2164+ Column {
2165+ anchors.left: parent.left
2166+ anchors.right: parent.right
2167+ height: childrenRect.height
2168+
2169+ LocalComponents.CheckableSetting {
2170+ id: hereCheck
2171+ showDivider: false
2172+ text: i18n.tr("Using GPS, anonymized Wi-Fi and cellular network info (recommended)")
2173+ checked: true
2174+ onTriggered: {
2175+ gpsCheck.checked = false;
2176+ hereCheck.checked = true;
2177+ nopeCheck.checked = false;
2178+ }
2179+ }
2180+
2181+ Label {
2182+ anchors.left: parent.left
2183+ anchors.leftMargin: hereCheck.labelOffset
2184+ anchors.right: parent.right
2185+ wrapMode: Text.Wrap
2186+ linkColor: Theme.palette.normal.foregroundText
2187+ // TRANSLATORS: HERE is a trademark for Nokia's location service, you probably shouldn't translate it
2188+ text: i18n.tr("By selecting this option you agree to the Nokia HERE <a href='#'>terms and conditions</a>.")
2189+ onLinkActivated: pageStack.load(Qt.resolvedUrl("here-terms.qml"))
2190+ }
2191+ }
2192+
2193+ LocalComponents.CheckableSetting {
2194+ id: nopeCheck
2195+ showDivider: false
2196+ text: i18n.tr("Not at all")
2197+ onTriggered: {
2198+ gpsCheck.checked = false;
2199+ hereCheck.checked = false;
2200+ nopeCheck.checked = true;
2201+ }
2202+ }
2203+
2204+ Label {
2205+ anchors.left: parent.left
2206+ anchors.right: parent.right
2207+ wrapMode: Text.Wrap
2208+ text: i18n.tr("You can change your mind later in <b>System Settings</b>.")
2209+ }
2210+ }
2211+
2212+ Component {
2213+ id: forwardButton
2214+ LocalComponents.StackButton {
2215+ text: i18n.tr("Continue")
2216+ onClicked: {
2217+ var locationOn = gpsCheck.checked || hereCheck.checked;
2218+ var gpsOn = gpsCheck.checked || hereCheck.checked;
2219+ var hereOn = hereCheck.checked;
2220+
2221+ // location service doesn't currently listen to updateState
2222+ // requests, so we activate the actions if needed.
2223+ if (locationActionGroup.location.state != locationOn) {
2224+ locationActionGroup.location.activate();
2225+ }
2226+ if (locationActionGroup.gps.state != gpsOn) {
2227+ locationActionGroup.gps.activate();
2228+ }
2229+ System.hereEnabled = hereOn;
2230+ pageStack.next()
2231+ }
2232+ }
2233+ }
2234+}
2235
2236=== added file 'wizard/qml/Pages/60-reporting.qml'
2237--- wizard/qml/Pages/60-reporting.qml 1970-01-01 00:00:00 +0000
2238+++ wizard/qml/Pages/60-reporting.qml 2014-12-02 18:43:43 +0000
2239@@ -0,0 +1,52 @@
2240+/*
2241+ * Copyright (C) 2013,2014 Canonical, Ltd.
2242+ *
2243+ * This program is free software; you can redistribute it and/or modify
2244+ * it under the terms of the GNU General Public License as published by
2245+ * the Free Software Foundation; version 3.
2246+ *
2247+ * This program is distributed in the hope that it will be useful,
2248+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2249+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2250+ * GNU General Public License for more details.
2251+ *
2252+ * You should have received a copy of the GNU General Public License
2253+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2254+ */
2255+
2256+import QtQuick 2.0
2257+import Ubuntu.Components 0.1
2258+import "../Components" as LocalComponents
2259+
2260+LocalComponents.Page {
2261+ title: i18n.tr("Improving your experience")
2262+ forwardButtonSourceComponent: forwardButton
2263+
2264+ Column {
2265+ id: column
2266+ anchors.fill: content
2267+ spacing: units.gu(2)
2268+
2269+ Label {
2270+ anchors.left: parent.left
2271+ anchors.right: parent.right
2272+ wrapMode: Text.Wrap
2273+ text: i18n.tr("Your phone is set up to automatically report errors to Canonical and its partners, the makers of the operating system.")
2274+ }
2275+
2276+ Label {
2277+ anchors.left: parent.left
2278+ anchors.right: parent.right
2279+ wrapMode: Text.Wrap
2280+ text: i18n.tr("This can be disabled in <b>System Settings</b> under <b>Security &amp; Privacy</b>")
2281+ }
2282+ }
2283+
2284+ Component {
2285+ id: forwardButton
2286+ LocalComponents.StackButton {
2287+ text: i18n.tr("Continue")
2288+ onClicked: pageStack.next()
2289+ }
2290+ }
2291+}
2292
2293=== added file 'wizard/qml/Pages/80-finished.qml'
2294--- wizard/qml/Pages/80-finished.qml 1970-01-01 00:00:00 +0000
2295+++ wizard/qml/Pages/80-finished.qml 2014-12-02 18:43:43 +0000
2296@@ -0,0 +1,55 @@
2297+/*
2298+ * Copyright (C) 2013,2014 Canonical, Ltd.
2299+ *
2300+ * This program is free software; you can redistribute it and/or modify
2301+ * it under the terms of the GNU General Public License as published by
2302+ * the Free Software Foundation; version 3.
2303+ *
2304+ * This program is distributed in the hope that it will be useful,
2305+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2306+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2307+ * GNU General Public License for more details.
2308+ *
2309+ * You should have received a copy of the GNU General Public License
2310+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2311+ */
2312+
2313+import QtQuick 2.0
2314+import Ubuntu.Components 0.1
2315+import "../Components" as LocalComponents
2316+
2317+LocalComponents.Page {
2318+ title: i18n.tr("All done")
2319+ forwardButtonSourceComponent: forwardButton
2320+ hasBackButton: false
2321+
2322+ Column {
2323+ id: column
2324+ anchors.fill: content
2325+ spacing: units.gu(1)
2326+
2327+ Label {
2328+ anchors.left: parent.left
2329+ anchors.right: parent.right
2330+ wrapMode: Text.Wrap
2331+ fontSize: "large"
2332+ font.bold: true
2333+ text: i18n.tr("Nice work!")
2334+ }
2335+
2336+ Label {
2337+ anchors.left: parent.left
2338+ anchors.right: parent.right
2339+ wrapMode: Text.Wrap
2340+ text: i18n.tr("Your phone is now ready to use.")
2341+ }
2342+ }
2343+
2344+ Component {
2345+ id: forwardButton
2346+ LocalComponents.StackButton {
2347+ text: i18n.tr("Finish")
2348+ onClicked: root.quitWizard()
2349+ }
2350+ }
2351+}
2352
2353=== added directory 'wizard/qml/Pages/data'
2354=== added file 'wizard/qml/Pages/data/meet_ubuntu_simcard@30.png'
2355Binary files wizard/qml/Pages/data/meet_ubuntu_simcard@30.png 1970-01-01 00:00:00 +0000 and wizard/qml/Pages/data/meet_ubuntu_simcard@30.png 2014-12-02 18:43:43 +0000 differ
2356=== added file 'wizard/qml/Pages/here-terms.qml'
2357--- wizard/qml/Pages/here-terms.qml 1970-01-01 00:00:00 +0000
2358+++ wizard/qml/Pages/here-terms.qml 2014-12-02 18:43:43 +0000
2359@@ -0,0 +1,117 @@
2360+/*
2361+ * Copyright (C) 2014 Canonical, Ltd.
2362+ *
2363+ * This program is free software; you can redistribute it and/or modify
2364+ * it under the terms of the GNU General Public License as published by
2365+ * the Free Software Foundation; version 3.
2366+ *
2367+ * This program is distributed in the hope that it will be useful,
2368+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2369+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2370+ * GNU General Public License for more details.
2371+ *
2372+ * You should have received a copy of the GNU General Public License
2373+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2374+ */
2375+
2376+import QtQuick 2.3
2377+import Qt.labs.folderlistmodel 2.1
2378+import Ubuntu.Components 1.1
2379+import Ubuntu.SystemSettings.Wizard.Utils 0.1
2380+import Ubuntu.Web 0.2
2381+import "../Components" as LocalComponents
2382+
2383+LocalComponents.Page {
2384+ title: i18n.tr("Terms & Conditions")
2385+ customBack: true
2386+
2387+ FolderListModel {
2388+ id: termsModel
2389+ folder: System.hereLicensePath
2390+ nameFilters: ["*.html"]
2391+ showDirs: false
2392+ showOnlyReadable: true
2393+ onCountChanged: loadFileContent()
2394+ }
2395+
2396+ function makeFileName(lang, country) {
2397+ return lang + "_" + country + ".html"
2398+ }
2399+
2400+ function defaultCountryForLanguage(lang) {
2401+ if (lang === "da") return "DK"
2402+ if (lang === "en") return "US"
2403+ if (lang === "ko") return "KR"
2404+ if (lang === "zh") return "CN"
2405+ return lang.toUpperCase()
2406+ }
2407+
2408+ function determineFileName() {
2409+ var codes = i18n.language.split(".")[0].split("_")
2410+ var defaultCountry = defaultCountryForLanguage(codes[0])
2411+ if (codes.count === 1)
2412+ codes = [codes[0], defaultCountry]
2413+ var perfectMatch = makeFileName(codes[0], codes[1])
2414+ var nearMatch = makeFileName(codes[0], defaultCountry)
2415+ var nearMatchExists = false
2416+
2417+ for (var i = 0; i < termsModel.count; i++) {
2418+ var fileName = termsModel.get(i, "fileName")
2419+ if (fileName == perfectMatch) {
2420+ return perfectMatch
2421+ } else if (fileName == nearMatch) {
2422+ nearMatchExists = true
2423+ }
2424+ }
2425+
2426+ if (nearMatchExists) {
2427+ return nearMatch
2428+ } else {
2429+ return makeFileName("en", "US")
2430+ }
2431+ }
2432+
2433+ function loadFileContent() {
2434+ var xhr = new XMLHttpRequest
2435+ xhr.open("GET", System.hereLicensePath + "/" + determineFileName())
2436+ xhr.onreadystatechange = function() {
2437+ if (xhr.readyState == XMLHttpRequest.DONE) {
2438+ termsLabel.text = xhr.responseText
2439+ }
2440+ }
2441+ xhr.send()
2442+ }
2443+
2444+ onBackClicked: {
2445+ if (webview.visible) {
2446+ termsLabel.visible = true
2447+ } else {
2448+ pageStack.prev()
2449+ }
2450+ }
2451+
2452+ Column {
2453+ id: column
2454+ anchors.fill: content
2455+
2456+ Label {
2457+ id: termsLabel
2458+ anchors.left: parent.left
2459+ anchors.right: parent.right
2460+ wrapMode: Text.Wrap
2461+ linkColor: Theme.palette.normal.foregroundText
2462+ onLinkActivated: {
2463+ webview.url = link
2464+ termsLabel.visible = false
2465+ }
2466+ }
2467+
2468+ WebView {
2469+ id: webview
2470+ anchors.left: parent.left
2471+ anchors.right: parent.right
2472+ height: parent.height
2473+ visible: !termsLabel.visible
2474+ }
2475+ }
2476+}
2477
2478=== added file 'wizard/qml/Pages/passwd-confirm.qml'
2479--- wizard/qml/Pages/passwd-confirm.qml 1970-01-01 00:00:00 +0000
2480+++ wizard/qml/Pages/passwd-confirm.qml 2014-12-02 18:43:43 +0000
2481@@ -0,0 +1,85 @@
2482+/*
2483+ * Copyright (C) 2014 Canonical, Ltd.
2484+ *
2485+ * This program is free software; you can redistribute it and/or modify
2486+ * it under the terms of the GNU General Public License as published by
2487+ * the Free Software Foundation; version 3.
2488+ *
2489+ * This program is distributed in the hope that it will be useful,
2490+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2491+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2492+ * GNU General Public License for more details.
2493+ *
2494+ * You should have received a copy of the GNU General Public License
2495+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2496+ */
2497+
2498+import QtQuick 2.3
2499+import Ubuntu.Components 1.1
2500+import Ubuntu.SystemSettings.SecurityPrivacy 1.0
2501+import "../Components" as LocalComponents
2502+import "file:///usr/share/unity8/Components" as UnityComponents
2503+
2504+/**
2505+ * See the main passwd-type page for an explanation of why we don't actually
2506+ * directly set the password here.
2507+ */
2508+
2509+LocalComponents.Page {
2510+ id: passwdSetPage
2511+ forwardButtonSourceComponent: forwardButton
2512+
2513+ skip: root.passwordMethod === UbuntuSecurityPrivacyPanel.Swipe
2514+
2515+ // If we are entering this page, clear any saved password and get focus
2516+ onEnabledChanged: if (enabled) lockscreen.clear(false)
2517+
2518+ UnityComponents.Lockscreen {
2519+ id: lockscreen
2520+ anchors {
2521+ fill: parent
2522+ topMargin: topMargin
2523+ leftMargin: leftMargin
2524+ rightMargin: rightMargin
2525+ bottomMargin: buttonMargin
2526+ }
2527+
2528+ infoText: root.passwordMethod === UbuntuSecurityPrivacyPanel.Passphrase ?
2529+ i18n.tr("Confirm passphrase") :
2530+ i18n.tr("Confirm passcode")
2531+
2532+ errorText: root.passwordMethod === UbuntuSecurityPrivacyPanel.Passphrase ?
2533+ i18n.tr("Sorry, incorrect passphrase.") + "\n" + i18n.tr("Please try again.") :
2534+ i18n.tr("Sorry, incorrect passcode.") + "\n" + i18n.tr("Please try again.")
2535+
2536+ showEmergencyCallButton: false
2537+ showCancelButton: false
2538+ alphaNumeric: root.passwordMethod === UbuntuSecurityPrivacyPanel.Passphrase
2539+ minPinLength: 4
2540+ maxPinLength: 4
2541+
2542+ onEntered: {
2543+ if (passphrase === root.password) {
2544+ confirmTimer.start()
2545+ } else {
2546+ clear(true)
2547+ }
2548+ }
2549+
2550+ Timer {
2551+ id: confirmTimer
2552+ interval: UbuntuAnimation.SnapDuration
2553+ onTriggered: pageStack.next()
2554+ }
2555+ }
2556+
2557+ Component {
2558+ id: forwardButton
2559+ LocalComponents.StackButton {
2560+ visible: root.passwordMethod === UbuntuSecurityPrivacyPanel.Passphrase
2561+ enabled: root.password === lockscreen.passphrase
2562+ text: i18n.tr("Continue")
2563+ onClicked: pageStack.next()
2564+ }
2565+ }
2566+}
2567
2568=== added file 'wizard/qml/Pages/passwd-set.qml'
2569--- wizard/qml/Pages/passwd-set.qml 1970-01-01 00:00:00 +0000
2570+++ wizard/qml/Pages/passwd-set.qml 2014-12-02 18:43:43 +0000
2571@@ -0,0 +1,93 @@
2572+/*
2573+ * Copyright (C) 2014 Canonical, Ltd.
2574+ *
2575+ * This program is free software; you can redistribute it and/or modify
2576+ * it under the terms of the GNU General Public License as published by
2577+ * the Free Software Foundation; version 3.
2578+ *
2579+ * This program is distributed in the hope that it will be useful,
2580+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2581+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2582+ * GNU General Public License for more details.
2583+ *
2584+ * You should have received a copy of the GNU General Public License
2585+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2586+ */
2587+
2588+import QtQuick 2.3
2589+import Ubuntu.Components 1.1
2590+import Ubuntu.SystemSettings.SecurityPrivacy 1.0
2591+import "../Components" as LocalComponents
2592+import "file:///usr/share/unity8/Components" as UnityComponents
2593+
2594+/**
2595+ * See the main passwd-type page for an explanation of why we don't actually
2596+ * directly set the password here.
2597+ */
2598+
2599+LocalComponents.Page {
2600+ id: passwdSetPage
2601+ forwardButtonSourceComponent: forwardButton
2602+
2603+ skip: root.passwordMethod === UbuntuSecurityPrivacyPanel.Swipe
2604+
2605+ // If we are entering this page, clear any saved password and get focus
2606+ onEnabledChanged: if (enabled) lockscreen.clear(false)
2607+
2608+ function confirm() {
2609+ root.password = lockscreen.passphrase;
2610+ confirmTimer.start()
2611+ }
2612+
2613+ Timer {
2614+ id: confirmTimer
2615+ interval: UbuntuAnimation.SnapDuration
2616+ onTriggered: pageStack.load(Qt.resolvedUrl("passwd-confirm.qml"));
2617+ }
2618+
2619+ UnityComponents.Lockscreen {
2620+ id: lockscreen
2621+ anchors {
2622+ fill: parent
2623+ topMargin: topMargin
2624+ leftMargin: leftMargin
2625+ rightMargin: rightMargin
2626+ bottomMargin: buttonMargin
2627+ }
2628+
2629+ infoText: root.passwordMethod === UbuntuSecurityPrivacyPanel.Passphrase ?
2630+ i18n.tr("Enter passphrase") :
2631+ i18n.tr("Choose your passcode")
2632+
2633+ // Note that the number four comes from PAM settings,
2634+ // which we don't have a good way to interrogate. We
2635+ // only do this matching instead of PAM because we want
2636+ // to set the password via PAM in a different place
2637+ // than this page. See comments at top of passwd-type file.
2638+ errorText: i18n.tr("Passphrase must be 4 characters long")
2639+
2640+ showEmergencyCallButton: false
2641+ showCancelButton: false
2642+ alphaNumeric: root.passwordMethod === UbuntuSecurityPrivacyPanel.Passphrase
2643+ minPinLength: 4
2644+ maxPinLength: 4
2645+
2646+ onEntered: {
2647+ if (passphrase.length >= 4) {
2648+ passwdSetPage.confirm();
2649+ } else {
2650+ lockscreen.clear(true)
2651+ }
2652+ }
2653+ }
2654+
2655+ Component {
2656+ id: forwardButton
2657+ LocalComponents.StackButton {
2658+ visible: root.passwordMethod === UbuntuSecurityPrivacyPanel.Passphrase
2659+ enabled: lockscreen.passphrase.length >= 4
2660+ text: i18n.tr("Continue")
2661+ onClicked: passwdSetPage.confirm()
2662+ }
2663+ }
2664+}
2665
2666=== added file 'wizard/qml/main.qml'
2667--- wizard/qml/main.qml 1970-01-01 00:00:00 +0000
2668+++ wizard/qml/main.qml 2014-12-02 18:43:43 +0000
2669@@ -0,0 +1,246 @@
2670+/*
2671+ * Copyright (C) 2013 Canonical, Ltd.
2672+ *
2673+ * This program is free software; you can redistribute it and/or modify
2674+ * it under the terms of the GNU General Public License as published by
2675+ * the Free Software Foundation; version 3.
2676+ *
2677+ * This program is distributed in the hope that it will be useful,
2678+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2679+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2680+ * GNU General Public License for more details.
2681+ *
2682+ * You should have received a copy of the GNU General Public License
2683+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2684+ */
2685+
2686+import QtQuick 2.3
2687+import GSettings 1.0
2688+import Ubuntu.Components 1.1
2689+import Ubuntu.SystemSettings.SecurityPrivacy 1.0
2690+import Unity.Application 0.1
2691+import Unity.Notifications 1.0 as NotificationBackend
2692+import Unity.Session 0.1
2693+import "Components"
2694+import "file:///usr/share/unity8/Notifications" as Notifications // FIXME This should become a module or go away
2695+import "file:///usr/share/unity8/Components" as UnityComponents
2696+
2697+Item {
2698+ id: root
2699+ width: units.gu(40)
2700+ height: units.gu(71)
2701+ focus: true
2702+
2703+ // These should be set by a security page and we apply the settings when
2704+ // the user exits the wizard.
2705+ property int passwordMethod: UbuntuSecurityPrivacyPanel.Passcode
2706+ property string password: ""
2707+
2708+ Component.onCompleted: {
2709+ Theme.name = "Ubuntu.Components.Themes.SuruGradient"
2710+ // A visible selected background looks bad in ListItem widgets with our theme
2711+ Theme.palette.selected.background = "#00000000"
2712+ i18n.domain = "unity8"
2713+ }
2714+
2715+ UbuntuSecurityPrivacyPanel {
2716+ id: securityPrivacy
2717+ }
2718+
2719+ function quitWizard() {
2720+ // Immediately go to black to give quick feedback
2721+ blackCover.visible = true
2722+
2723+ var errorMsg = securityPrivacy.setSecurity("", password, passwordMethod)
2724+ if (errorMsg !== "") {
2725+ // Ignore (but log) any errors, since we're past where the user set
2726+ // the method. Worst case, we just leave the user with a swipe
2727+ // security method and they fix it in the system settings.
2728+ console.log("Error setting security method:", errorMsg)
2729+ }
2730+
2731+ Qt.quit()
2732+ }
2733+
2734+ // This is just a little screen to immediately go to black once the wizard
2735+ // is done, to give quick feedback to the user.
2736+ Rectangle {
2737+ id: blackCover
2738+ color: "#000000"
2739+ anchors.fill: parent
2740+ z: 1
2741+ visible: false
2742+ }
2743+
2744+ MainView {
2745+ anchors.fill: parent
2746+ headerColor: "#57365E"
2747+ backgroundColor: "#A55263"
2748+ footerColor: "#D75669"
2749+ anchorToKeyboard: true
2750+ useDeprecatedToolbar: false
2751+
2752+ GSettings {
2753+ id: background
2754+ schema.id: "org.gnome.desktop.background"
2755+ }
2756+
2757+ Image {
2758+ id: image
2759+ // Use x/y/height/width instead of anchors so that we don't adjust
2760+ // the image when the OSK appears.
2761+ x: 0
2762+ y: 0
2763+ height: root.height
2764+ width: root.width
2765+ source: background.pictureUri
2766+ fillMode: Image.PreserveAspectCrop
2767+ visible: status === Image.Ready
2768+ }
2769+
2770+ PageStack {
2771+ id: pageStack
2772+
2773+ function next() {
2774+ // If we've opened any extra (non-main) pages, pop them before
2775+ // continuing so back button returns to the previous main page.
2776+ while (pageList.index < pageStack.depth - 1)
2777+ pop()
2778+ load(pageList.next())
2779+ }
2780+
2781+ function prev() {
2782+ if (pageList.index >= pageStack.depth - 1)
2783+ pageList.prev() // update pageList.index, but not for extra pages
2784+ pop()
2785+ if (!currentPage || currentPage.opacity === 0) { // undo skipped pages
2786+ prev()
2787+ } else {
2788+ currentPage.enabled = true
2789+ }
2790+ }
2791+
2792+ function load(path) {
2793+ if (currentPage) {
2794+ currentPage.enabled = false
2795+ }
2796+
2797+ // First load it invisible, check that we should actually use
2798+ // this page, and either skip it or continue.
2799+ push(path, {"opacity": 0, "enabled": false})
2800+
2801+ // Check for immediate skip or not. We may have to wait for
2802+ // skipValid to be assigned (see Connections object below)
2803+ _checkSkip()
2804+ }
2805+
2806+ function _checkSkip() {
2807+ if (!currentPage) { // may have had a parse error
2808+ next()
2809+ } else if (currentPage.skipValid) {
2810+ if (currentPage.skip) {
2811+ next()
2812+ } else {
2813+ currentPage.opacity = 1
2814+ currentPage.enabled = true
2815+ }
2816+ }
2817+ }
2818+
2819+ Connections {
2820+ target: pageStack.currentPage
2821+ onSkipValidChanged: pageStack._checkSkip()
2822+ }
2823+
2824+ Component.onCompleted: next()
2825+ }
2826+ }
2827+
2828+ Rectangle {
2829+ id: modalNotificationBackground
2830+ visible: notifications.useModal && (notifications.state == "narrow")
2831+ anchors.fill: parent
2832+ color: "#80000000"
2833+
2834+ MouseArea {
2835+ anchors.fill: parent
2836+ }
2837+ }
2838+
2839+ InputMethod {
2840+ anchors.fill: parent
2841+ }
2842+
2843+ Notifications.Notifications {
2844+ id: notifications
2845+ model: NotificationBackend.Model
2846+ margin: units.gu(1)
2847+ anchors {
2848+ top: parent.top
2849+ right: parent.right
2850+ bottom: parent.bottom
2851+ }
2852+ states: [
2853+ State {
2854+ name: "narrow"
2855+ when: parent.width <= units.gu(60)
2856+ AnchorChanges { target: notifications; anchors.left: parent.left }
2857+ },
2858+ State {
2859+ name: "wide"
2860+ when: parent.width > units.gu(60)
2861+ AnchorChanges { target: notifications; anchors.left: undefined }
2862+ PropertyChanges { target: notifications; width: units.gu(38) }
2863+ }
2864+ ]
2865+ }
2866+
2867+ UnityComponents.Dialogs {
2868+ id: dialogs
2869+ anchors.fill: parent
2870+ z: 10
2871+ onPowerOffClicked: {
2872+ shutdownFadeOutRectangle.enabled = true;
2873+ shutdownFadeOutRectangle.visible = true;
2874+ shutdownFadeOut.start();
2875+ }
2876+ }
2877+
2878+ Rectangle {
2879+ id: shutdownFadeOutRectangle
2880+ z: dialogs.z + 10
2881+ enabled: false
2882+ visible: false
2883+ color: "black"
2884+ anchors.fill: parent
2885+ opacity: 0.0
2886+ NumberAnimation on opacity {
2887+ id: shutdownFadeOut
2888+ from: 0.0
2889+ to: 1.0
2890+ onStopped: {
2891+ if (shutdownFadeOutRectangle.enabled && shutdownFadeOutRectangle.visible) {
2892+ DBusUnitySessionService.Shutdown();
2893+ }
2894+ }
2895+ }
2896+ }
2897+
2898+ Keys.onPressed: {
2899+ if (event.key == Qt.Key_PowerOff || event.key == Qt.Key_PowerDown) {
2900+ dialogs.onPowerKeyPressed();
2901+ event.accepted = true;
2902+ } else {
2903+ event.accepted = false;
2904+ }
2905+ }
2906+
2907+ Keys.onReleased: {
2908+ if (event.key == Qt.Key_PowerOff || event.key == Qt.Key_PowerDown) {
2909+ dialogs.onPowerKeyReleased();
2910+ event.accepted = true;
2911+ } else {
2912+ event.accepted = false;
2913+ }
2914+ }
2915+}
2916
2917=== added file 'wizard/test.sh'
2918--- wizard/test.sh 1970-01-01 00:00:00 +0000
2919+++ wizard/test.sh 2014-12-02 18:43:43 +0000
2920@@ -0,0 +1,18 @@
2921+#!/bin/sh
2922+
2923+TOPDIR=$(readlink -e "$(dirname ${0})/..")
2924+
2925+LOCAL_PRIVATE_DIR=$(ls -d ${TOPDIR}/debian/tmp/usr/lib/*/ubuntu-system-settings/private)
2926+if [ -n ${LOCAL_PRIVATE_DIR} ]; then
2927+ echo "Testing against locally built version"
2928+ export UBUNTU_SYSTEM_SETTINGS_WIZARD_ROOT="${TOPDIR}/debian/tmp/usr/share"
2929+ export UBUNTU_SYSTEM_SETTINGS_WIZARD_MODULES="${LOCAL_PRIVATE_DIR}"
2930+ export QML2_IMPORT_PATH=${LOCAL_PRIVATE_DIR}:${QML2_IMPORT_PATH}
2931+ export PATH=${TOPDIR}/debian/tmp/usr/bin:${PATH}
2932+else
2933+ echo "Testing against system version"
2934+fi
2935+
2936+export QML2_IMPORT_PATH=${TOPDIR}/tests/mocks:${QML2_IMPORT_PATH}
2937+
2938+exec system-settings-wizard
2939
2940=== added file 'wizard/ubuntu-system-settings-wizard-cleanup.conf'
2941--- wizard/ubuntu-system-settings-wizard-cleanup.conf 1970-01-01 00:00:00 +0000
2942+++ wizard/ubuntu-system-settings-wizard-cleanup.conf 2014-12-02 18:43:43 +0000
2943@@ -0,0 +1,20 @@
2944+description "Welcome to Ubuntu Cleanup"
2945+author "Michael Terry <michael.terry@canonical.com>"
2946+
2947+# These are all tasks that need to be completed only if the wizard was
2948+# intentionally stopped (i.e. the user clicked 'Finish' at the end)
2949+
2950+task
2951+
2952+# If you change this, also change it in the main upstart job
2953+env RUN_FILE=".config/ubuntu-system-settings/wizard-has-run"
2954+
2955+script
2956+ # Don't run again in the future. We do this here, rather than in the main
2957+ # job because we only want to run this code if user actually clicked on the
2958+ # "Finish" button.
2959+ mkdir -p $(dirname "$HOME/$RUN_FILE")
2960+ touch "$HOME/$RUN_FILE" || true
2961+
2962+ stop ubuntu-system-settings-wizard
2963+end script
2964
2965=== added file 'wizard/ubuntu-system-settings-wizard-set-lang.conf'
2966--- wizard/ubuntu-system-settings-wizard-set-lang.conf 1970-01-01 00:00:00 +0000
2967+++ wizard/ubuntu-system-settings-wizard-set-lang.conf 2014-12-02 18:43:43 +0000
2968@@ -0,0 +1,30 @@
2969+description "Welcome to Ubuntu Cleanup"
2970+author "Michael Terry <michael.terry@canonical.com>"
2971+
2972+# This job updates the system idea of what language is configured. It adjusts
2973+# the upstart env and the DBus activation env. It also stops indicators and
2974+# the OSK so that they can be restarted with the new env.
2975+
2976+task
2977+
2978+script
2979+ setenv() {
2980+ initctl set-env --global $1=$2
2981+ gdbus call --session --dest org.freedesktop.DBus --object-path /org/freedesktop/DBus --method org.freedesktop.DBus.UpdateActivationEnvironment "@a{ss} {'$1': '$2'}"
2982+ }
2983+
2984+ UID=$(id -u)
2985+
2986+ # Change upstart's ideas about locales
2987+ LANGUAGE=$(gdbus call --system --dest org.freedesktop.Accounts --object-path /org/freedesktop/Accounts/User$UID --method org.freedesktop.DBus.Properties.Get org.freedesktop.Accounts.User Language | cut -d\' -f2)
2988+ setenv LANGUAGE $LANGUAGE
2989+ echo "Set language for $USER_PATH as $LANGUAGE"
2990+ LOCALE=$(gdbus call --system --dest org.freedesktop.Accounts --object-path /org/freedesktop/Accounts/User$UID --method org.freedesktop.DBus.Properties.Get org.freedesktop.Accounts.User FormatsLocale | cut -d\' -f2)
2991+ setenv LC_ALL $LOCALE
2992+ setenv LANG $LOCALE
2993+ echo "Set locale as $LOCALE"
2994+
2995+ # Stop any indicators and OSK so they will be restarted with new environment
2996+ initctl emit indicator-services-end
2997+ stop maliit-server || true
2998+end script
2999
3000=== added file 'wizard/ubuntu-system-settings-wizard.conf'
3001--- wizard/ubuntu-system-settings-wizard.conf 1970-01-01 00:00:00 +0000
3002+++ wizard/ubuntu-system-settings-wizard.conf 2014-12-02 18:43:43 +0000
3003@@ -0,0 +1,75 @@
3004+description "Welcome to Ubuntu"
3005+author "Michael Terry <michael.terry@canonical.com>"
3006+
3007+start on starting unity8
3008+task
3009+
3010+expect stop
3011+
3012+# If you change this, also change it in the cleanup upstart job
3013+env RUN_FILE=".config/ubuntu-system-settings/wizard-has-run"
3014+
3015+pre-start script
3016+ if [ -e "$HOME/$RUN_FILE" ]; then
3017+ initctl set-env WIZARD_SKIPPED=true
3018+ stop
3019+ else
3020+ # Stop unity8, we'll start it again in post-stop (this avoids a race
3021+ # between post-stop and unity8 unpausing)
3022+ stop --no-wait $JOB
3023+
3024+ # Tell unity-mir to raise SIGSTOP after we start
3025+ initctl set-env UNITY_MIR_EMITS_SIGSTOP=1
3026+
3027+ if [ -n "$MIR_SOCKET" ]; then
3028+ initctl set-env --global WIZARD_ORIG_MIR_SOCKET=$MIR_SOCKET
3029+
3030+ # Point wizard at unity-system-compositor
3031+ MIR_SERVER_FILE=$XDG_RUNTIME_DIR/wizard_socket
3032+ initctl set-env MIR_SERVER_FILE=$MIR_SERVER_FILE
3033+ initctl set-env MIR_SERVER_HOST_SOCKET=$MIR_SOCKET
3034+
3035+ # Remove the socket if still there
3036+ if [ -S "$MIR_SERVER_FILE" ]; then
3037+ rm "$MIR_SERVER_FILE"
3038+ fi
3039+
3040+ # Point future jobs in this session to our Mir socket instead of
3041+ # unity-system-compositor's socket.
3042+ initctl set-env --global MIR_SOCKET=$MIR_SERVER_FILE
3043+ gdbus call --session --dest org.freedesktop.DBus --object-path /org/freedesktop/DBus --method org.freedesktop.DBus.UpdateActivationEnvironment "@a{ss} {'MIR_SOCKET': '$MIR_SERVER_FILE'}"
3044+ fi
3045+ fi
3046+end script
3047+
3048+exec system-settings-wizard
3049+
3050+post-stop script
3051+ if [ -n "$WIZARD_SKIPPED" ]; then
3052+ exit
3053+ fi
3054+
3055+ setenv() {
3056+ initctl set-env --global $1=$2
3057+ gdbus call --session --dest org.freedesktop.DBus --object-path /org/freedesktop/DBus --method org.freedesktop.DBus.UpdateActivationEnvironment "@a{ss} {'$1': '$2'}"
3058+ }
3059+
3060+ echo "Ending wizard"
3061+
3062+ if [ -S "$MIR_SERVER_FILE" ]; then
3063+ rm -f "$MIR_SERVER_FILE"
3064+ fi
3065+
3066+ # Undo changes to global variables
3067+ if [ -n "$WIZARD_ORIG_MIR_SOCKET" ]; then
3068+ echo "Resetting MIR_SOCKET to $WIZARD_ORIG_MIR_SOCKET"
3069+ setenv MIR_SOCKET $WIZARD_ORIG_MIR_SOCKET
3070+ fi
3071+
3072+ # Stop any indicators and OSK so they will be restarted with new environment
3073+ initctl emit indicator-services-end
3074+ stop maliit-server || true
3075+
3076+ # And finally, resume unity8
3077+ start --no-wait $JOB || true
3078+end script

Subscribers

People subscribed via source and target branches