on xenial help sign in
Convert the welcome wizard from a separate executable into a qml plugin (with a small C++ plugin for support).

- This changes the path for adding customized wizard pages (drops system-settings namespacing). I checked with cwayne, that support isn't being used yet. So that's safe to adjust while we're here. - I did not change the path for the 'has the wizard run yet' marker, since that is being used in the wild. But I added a comment as to why we're using the phrase "ubuntu-system-settings" in that filename. - I fleshed out unity8's support for changing the language on the fly, since that's now done in-process. I believe I caught all cases (anything that used a qml binding to i18n worked automatically, just had to catch the cases that were pulling from outside sources like infographics). - If an incoming call happens during the wizard, we just bail out of it and the edge demo. I'm not sure what the ideal behavior is, but this is at least reasonable. There's nothing in the wizard that *needs* to be done. - Making the wizard a plugin lets us drop the gap between the end of the wizard and the start of the shell. Yay! Approved by: Andrea Cimitan

commit39eae8ac17128e0b5d31c959fde017f78014401d authorMichael Terry <michael.terry@canonical.com> dateThu 4 Dec 2014, 20:54 (12 years ago) parent67a2df5d6088f3
88 files changed+1034−609
CMakeLists.txt+5−1 build.sh+1 debian/control+2−12 debian/rules+1−1 debian/ubuntu-system-settings-wizard.install−5 debian/ubuntu-system-settings-wizard.lintian-overrides−1 debian/unity8-common.install+1 debian/unity8-private.install+1 debian/unity8.install+1 include/paths.h.in+2 plugins/AccountsService/AccountsService.cpp+61−2 plugins/AccountsService/AccountsService.h+20 plugins/CMakeLists.txt+1 plugins/Unity/Launcher/desktopfilehandler.cpp+1−1 plugins/Unity/Launcher/launcheritem.cpp+11−4 plugins/Unity/Launcher/launchermodel.cpp+1 plugins/Unity/Launcher/launchermodel.h+1−1 wizard/50-com.ubuntu.system-settings.wizard.pkla → plugins/Wizard/50-com.canonical.unity.wizard.pkla plugins/Wizard/CMakeLists.txt+11 wizard/PageList.cpp → plugins/Wizard/PageList.cpp+10−9 wizard/PageList.h → plugins/Wizard/PageList.h+3−5 plugins/Wizard/System.cpp+99 plugins/Wizard/System.h+50 wizard/Unity/Application/CMakeLists.txt → plugins/Wizard/Unity/Application/CMakeLists.txt wizard/Unity/Application/OSKController.qml → plugins/Wizard/Unity/Application/OSKController.qml wizard/Unity/Application/qmldir → plugins/Wizard/Unity/Application/qmldir wizard/Unity/CMakeLists.txt → plugins/Wizard/Unity/CMakeLists.txt wizard/Utils/CMakeLists.txt → plugins/Wizard/Utils/CMakeLists.txt wizard/Utils/plugin.cpp → plugins/Wizard/Utils/plugin.cpp wizard/Utils/plugin.h → plugins/Wizard/Utils/plugin.h wizard/Utils/qmldir → plugins/Wizard/Utils/qmldir wizard/Utils/qsortfilterproxymodelqml.cpp → plugins/Wizard/Utils/qsortfilterproxymodelqml.cpp wizard/Utils/qsortfilterproxymodelqml.h → plugins/Wizard/Utils/qsortfilterproxymodelqml.h plugins/Wizard/Wizard.qmltypes+36 wizard/main.cpp → plugins/Wizard/main.cpp plugins/Wizard/plugin.cpp+42 plugins/Wizard/plugin.h+32 plugins/Wizard/qmldir+3 wizard/test.sh → plugins/Wizard/test.sh wizard/ubuntu-system-settings-wizard-cleanup.conf → plugins/Wizard/ubuntu-system-settings-wizard-cleanup.conf wizard/ubuntu-system-settings-wizard-set-lang.conf → plugins/Wizard/ubuntu-system-settings-wizard-set-lang.conf wizard/ubuntu-system-settings-wizard.conf → plugins/Wizard/ubuntu-system-settings-wizard.conf qml/CMakeLists.txt+1 qml/Components/Dialogs.qml+17−21 qml/Components/EdgeDemo.qml+19−6 qml/Greeter/Clock.qml+10 qml/Greeter/GreeterContent.qml+5 qml/Launcher/Launcher.qml+5 qml/Shell.qml+26−15 wizard/qml/Components/CheckableSetting.qml → qml/Wizard/CheckableSetting.qml−1 wizard/qml/Components/InputMethod.qml → qml/Wizard/Components/InputMethod.qml wizard/qml/Components/Page.qml → qml/Wizard/Page.qml+1−2 qml/Wizard/Pages.qml+129 wizard/qml/Pages/10-welcome.qml → qml/Wizard/Pages/10-welcome.qml+7−5 wizard/qml/Pages/20-sim.qml → qml/Wizard/Pages/20-sim.qml+1−1 wizard/qml/Pages/30-passwd-type.qml → qml/Wizard/Pages/30-passwd-type.qml+13−1 wizard/qml/Pages/40-wifi.qml → qml/Wizard/Pages/40-wifi.qml+1−2 wizard/qml/Pages/50-location.qml → qml/Wizard/Pages/50-location.qml+7−7 wizard/qml/Pages/60-reporting.qml → qml/Wizard/Pages/60-reporting.qml+1−1 wizard/qml/Pages/80-finished.qml → qml/Wizard/Pages/80-finished.qml+1−1 wizard/qml/Pages/data/meet_ubuntu_simcard@30.png → qml/Wizard/Pages/data/meet_ubuntu_simcard@30.png wizard/qml/Pages/here-terms.qml → qml/Wizard/Pages/here-terms.qml+4−4 wizard/qml/Pages/passwd-confirm.qml → qml/Wizard/Pages/passwd-confirm.qml+2−2 wizard/qml/Pages/passwd-set.qml → qml/Wizard/Pages/passwd-set.qml+2−2 wizard/qml/Components/StackButton.qml → qml/Wizard/StackButton.qml qml/Wizard/Wizard.qml+55 tests/CMakeLists.txt−1 tests/mocks/AccountsService/AccountsService.cpp+31−1 tests/mocks/AccountsService/AccountsService.h+20 tests/mocks/CMakeLists.txt+1 tests/mocks/QMenuModel/CMakeLists.txt+1 tests/mocks/QMenuModel/dbus-enums.h+52 tests/mocks/QMenuModel/plugin.cpp+3 tests/mocks/Wizard/CMakeLists.txt+12 tests/mocks/Wizard/MockSystem.cpp+38 tests/mocks/Wizard/MockSystem.h+46 tests/mocks/Wizard/Wizard.qmltypes+36 tests/mocks/Wizard/mockplugin.cpp+42 tests/mocks/Wizard/mockplugin.h+32 tests/mocks/Wizard/qmldir+3 tests/plugins/CMakeLists.txt+1 tests/plugins/Wizard/CMakeLists.txt+12 tests/wizard/tst_pagelist.cpp → tests/plugins/Wizard/tst_pagelist.cpp+1−3 tests/wizard/CMakeLists.txt−5 wizard/CMakeLists.txt−65 wizard/Utils/system.cpp−118 wizard/Utils/system.h−57 wizard/qml/main.qml−246
CMakeLists.txt+5−1
@@ -61,6 +61,11 @@ include(GNUInstallDirs)
6161set(SHELL_APP_DIR ${CMAKE_INSTALL_DATADIR}/unity8)
6262set(SHELL_PRIVATE_LIBDIR ${CMAKE_INSTALL_LIBDIR}/unity8)
6363
64+execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE} --variable=plugin_private_module_dir SystemSettings OUTPUT_VARIABLE USS_PRIVATE_PLUGINDIR OUTPUT_STRIP_TRAILING_WHITESPACE)
65+if(USS_PRIVATE_PLUGINDIR STREQUAL "")
66+ message(FATAL_ERROR "Could not determine USS private plugin installation dir.")
67+endif()
68+
6469execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE} --variable=plugindir_suffix unity-shell-api OUTPUT_VARIABLE SHELL_INSTALL_QML OUTPUT_STRIP_TRAILING_WHITESPACE)
6570if(SHELL_INSTALL_QML STREQUAL "")
6671 message(FATAL_ERROR "Could not determine plugin installation dir.")
@@ -117,7 +122,6 @@ add_subdirectory(tools)
117122add_subdirectory(qml)
118123add_subdirectory(tests)
119124add_subdirectory(plugins)
120−add_subdirectory(wizard)
121125
122126#
123127# Data files
build.sh+1
@@ -54,6 +54,7 @@ install_dependencies() {
5454 qtdeclarative5-unity-notifications-plugin \
5555 qml-module-ubuntu-connectivity \
5656 ubuntu-mobile-icons \
57+ ubuntu-system-settings \
5758 unity-plugin-scopes \
5859 xvfb \
5960 || exit 5
debian/control+2−12
@@ -88,6 +88,7 @@ Depends: gsettings-desktop-schemas,
8888 qtdeclarative5-gsettings1.0,
8989 qtdeclarative5-qtmir-plugin (>= 0.4.4),
9090 qtdeclarative5-ubuntu-telephony0.1,
91+ ubuntu-system-settings,
9192 unity-launcher-impl-4,
9293 unity8-common (= ${source:Version}),
9394 unity8-private (= ${binary:Version}),
@@ -102,6 +103,7 @@ Breaks: indicator-network (<< 0.5.1+14.10.20141014),
102103 unity8-greeter (<< 7.89),
103104Replaces: ubuntu-touch-session (<< 0.82~),
104105 unity8-greeter (<< 7.89),
106+Conflicts: ubuntu-system-settings-wizard,
105107Description: Unity 8 shell
106108 The Unity 8 shell is the primary user interface for Ubuntu devices.
107109
@@ -192,15 +194,3 @@ Multi-Arch: foreign
192194Depends: ${misc:Depends},
193195Description: Documentation for Unity8
194196 The Unity 8 shell is the primary user interface for Ubuntu devices. (documentation)
195−
196−Package: ubuntu-system-settings-wizard
197−Architecture: any
198−Depends: unity8 (= ${binary:Version}),
199− ${misc:Depends},
200− ${shlibs:Depends},
201−Recommends: qtdeclarative5-qtmir-plugin (>= 0.4),
202−Breaks: ubuntu-system-settings (<< 0.4),
203−Replaces: ubuntu-system-settings (<< 0.4),
204−Description: Welcome Wizard for Ubuntu Touch
205− This package contains the Welcome Wizard used on the Ubuntu Touch images,
206− it's designed for phones, tablets and convergent devices.
debian/rules+1−1
@@ -40,7 +40,7 @@ override_dh_install:
4040
4141# use private lib directories
4242override_dh_makeshlibs:
43− dh_makeshlibs -Nunity8-private -Nunity8-fake-env -Nubuntu-system-settings-wizard
43+ dh_makeshlibs -Nunity8-private -Nunity8-fake-env
4444
4545# libMockLightDM-qml.so links against liblightdm-qt5-2.so which doesn't exist
4646override_dh_shlibdeps:
debian/ubuntu-system-settings-wizard.installdeleted−5
@@ -1,5 +0,0 @@
1−usr/bin/system-settings-wizard
2−usr/share/ubuntu/settings/wizard
3−usr/share/upstart/sessions/ubuntu-system-settings-wizard*.conf
4−usr/lib/*/ubuntu-system-settings/private/Ubuntu/SystemSettings/Wizard
5−var/lib/polkit-1/localauthority/10-vendor.d/50-com.ubuntu.system-settings.wizard.pkla
debian/ubuntu-system-settings-wizard.lintian-overridesdeleted−1
@@ -1 +0,0 @@
1−ubuntu-system-settings-wizard: binary-without-manpage usr/bin/system-settings-wizard
debian/unity8-common.install+1
@@ -3,3 +3,4 @@ usr/share/unity8/Components
33usr/share/unity8/Dash
44usr/share/unity8/Notifications
55usr/share/unity8/graphics
6+var/lib/polkit-1/localauthority/10-vendor.d
debian/unity8-private.install+1
@@ -9,6 +9,7 @@ usr/lib/*/unity8/qml/ScreenGrabber
99usr/lib/*/unity8/qml/Ubuntu
1010usr/lib/*/unity8/qml/Unity
1111usr/lib/*/unity8/qml/Utils
12+usr/lib/*/unity8/qml/Wizard
1213usr/lib/*/unity8/libUbuntuGestures*
1314usr/share/accountsservice/interfaces
1415usr/share/dbus-1/interfaces
debian/unity8.install+1
@@ -10,4 +10,5 @@ usr/share/unity8/Launcher
1010usr/share/unity8/Panel
1111usr/share/unity8/Shell.qml
1212usr/share/unity8/Stages
13+usr/share/unity8/Wizard
1314usr/share/url-dispatcher/urls/unity8-dash.url-dispatcher
include/paths.h.in+2
@@ -71,9 +71,11 @@ inline QStringList fallbackImportPaths() {
7171 QStringList paths;
7272 if (isRunningInstalled()) {
7373 paths << QString("@CMAKE_INSTALL_PREFIX@/@SHELL_INSTALL_QML@");
74+ paths << QString("@USS_PRIVATE_PLUGINDIR@");
7475 paths << QString("@SHELL_PLUGINDIR@");
7576 paths << QString("@CMAKE_INSTALL_PREFIX@/@SHELL_INSTALL_QML@/mocks");
7677 } else {
78+ paths << QString("@USS_PRIVATE_PLUGINDIR@");
7779 paths << QString("@SHELL_PLUGINDIR@");
7880 paths << QString("@CMAKE_BINARY_DIR@/tests/mocks");
7981 }
plugins/AccountsService/AccountsService.cpp+61−2
@@ -19,23 +19,28 @@
1919#include "AccountsService.h"
2020#include "AccountsServiceDBusAdaptor.h"
2121
22+#include <QFile>
2223#include <QStringList>
2324
2425AccountsService::AccountsService(QObject* parent)
2526 : QObject(parent),
2627 m_service(new AccountsServiceDBusAdaptor(this)),
27− m_user(qgetenv("USER")),
28+ m_user(""),
2829 m_demoEdges(false),
2930 m_enableLauncherWhileLocked(false),
3031 m_enableIndicatorsWhileLocked(false),
3132 m_statsWelcomeScreen(false),
3233 m_passwordDisplayHint(Keyboard),
33− m_failedLogins(0)
34+ m_failedLogins(0),
35+ m_hereEnabled(false),
36+ m_hereLicensePath() // null means not set yet
3437{
3538 connect(m_service, SIGNAL(propertiesChanged(const QString &, const QString &, const QStringList &)),
3639 this, SLOT(propertiesChanged(const QString &, const QString &, const QStringList &)));
3740 connect(m_service, SIGNAL(maybeChanged(const QString &)),
3841 this, SLOT(maybeChanged(const QString &)));
42+
43+ setUser(qgetenv("USER"));
3944}
4045
4146QString AccountsService::user() const
@@ -45,6 +50,9 @@ QString AccountsService::user() const
4550
4651void AccountsService::setUser(const QString &user)
4752{
53+ if (user.isEmpty() || m_user == user)
54+ return;
55+
4856 m_user = user;
4957 Q_EMIT userChanged();
5058
@@ -55,6 +63,8 @@ void AccountsService::setUser(const QString &user)
5563 updateStatsWelcomeScreen();
5664 updatePasswordDisplayHint();
5765 updateFailedLogins();
66+ updateHereEnabled();
67+ updateHereLicensePath();
5868}
5969
6070bool AccountsService::demoEdges() const
@@ -93,6 +103,26 @@ AccountsService::PasswordDisplayHint AccountsService::passwordDisplayHint() cons
93103 return m_passwordDisplayHint;
94104}
95105
106+bool AccountsService::hereEnabled() const
107+{
108+ return m_hereEnabled;
109+}
110+
111+void AccountsService::setHereEnabled(bool enabled)
112+{
113+ m_service->setUserProperty(m_user, "com.ubuntu.location.providers.here.AccountsService", "LicenseAccepted", enabled);
114+}
115+
116+QString AccountsService::hereLicensePath() const
117+{
118+ return m_hereLicensePath;
119+}
120+
121+bool AccountsService::hereLicensePathValid() const
122+{
123+ return !m_hereLicensePath.isNull();
124+}
125+
96126void AccountsService::updateDemoEdges()
97127{
98128 auto demoEdges = m_service->getUserProperty(m_user, "com.canonical.unity.AccountsService", "demo-edges").toBool();
@@ -156,6 +186,28 @@ void AccountsService::updateFailedLogins()
156186 }
157187}
158188
189+void AccountsService::updateHereEnabled()
190+{
191+ bool hereEnabled = m_service->getUserProperty(m_user, "com.ubuntu.location.providers.here.AccountsService", "LicenseAccepted").toBool();
192+ if (m_hereEnabled != hereEnabled) {
193+ m_hereEnabled = hereEnabled;
194+ Q_EMIT hereEnabledChanged();
195+ }
196+}
197+
198+void AccountsService::updateHereLicensePath()
199+{
200+ QString hereLicensePath = m_service->getUserProperty(m_user, "com.ubuntu.location.providers.here.AccountsService", "LicenseBasePath").toString();
201+
202+ if (hereLicensePath.isEmpty() || !QFile::exists(hereLicensePath))
203+ hereLicensePath = "";
204+
205+ if (m_hereLicensePath.isNull() || m_hereLicensePath != hereLicensePath) {
206+ m_hereLicensePath = hereLicensePath;
207+ Q_EMIT hereLicensePathChanged();
208+ }
209+}
210+
159211uint AccountsService::failedLogins() const
160212{
161213 return m_failedLogins;
@@ -195,6 +247,13 @@ void AccountsService::propertiesChanged(const QString &user, const QString &inte
195247 if (changed.contains("EnableIndicatorsWhileLocked")) {
196248 updateEnableIndicatorsWhileLocked();
197249 }
250+ } else if (interface == "com.ubuntu.location.providers.here.AccountsService") {
251+ if (changed.contains("LicenseAccepted")) {
252+ updateHereEnabled();
253+ }
254+ if (changed.contains("LicenseBasePath")) {
255+ updateHereLicensePath();
256+ }
198257 }
199258}
200259
plugins/AccountsService/AccountsService.h+20
@@ -55,6 +55,16 @@ class AccountsService: public QObject
5555 READ failedLogins
5656 WRITE setFailedLogins
5757 NOTIFY failedLoginsChanged)
58+ Q_PROPERTY(bool hereEnabled
59+ READ hereEnabled
60+ WRITE setHereEnabled
61+ NOTIFY hereEnabledChanged)
62+ Q_PROPERTY(QString hereLicensePath
63+ READ hereLicensePath
64+ NOTIFY hereLicensePathChanged)
65+ Q_PROPERTY(bool hereLicensePathValid // qml sees a null string as "", so we use proxy setting for that
66+ READ hereLicensePathValid
67+ NOTIFY hereLicensePathChanged)
5868
5969public:
6070 enum PasswordDisplayHint {
@@ -75,6 +85,10 @@ public:
7585 PasswordDisplayHint passwordDisplayHint() const;
7686 uint failedLogins() const;
7787 void setFailedLogins(uint failedLogins);
88+ bool hereEnabled() const;
89+ void setHereEnabled(bool enabled);
90+ QString hereLicensePath() const;
91+ bool hereLicensePathValid() const;
7892
7993Q_SIGNALS:
8094 void userChanged();
@@ -85,6 +99,8 @@ Q_SIGNALS:
8599 void statsWelcomeScreenChanged();
86100 void passwordDisplayHintChanged();
87101 void failedLoginsChanged();
102+ void hereEnabledChanged();
103+ void hereLicensePathChanged();
88104
89105private Q_SLOTS:
90106 void propertiesChanged(const QString &user, const QString &interface, const QStringList &changed);
@@ -98,6 +114,8 @@ private:
98114 void updateStatsWelcomeScreen();
99115 void updatePasswordDisplayHint();
100116 void updateFailedLogins();
117+ void updateHereEnabled();
118+ void updateHereLicensePath();
101119
102120 AccountsServiceDBusAdaptor *m_service;
103121 QString m_user;
@@ -108,6 +126,8 @@ private:
108126 bool m_statsWelcomeScreen;
109127 PasswordDisplayHint m_passwordDisplayHint;
110128 uint m_failedLogins;
129+ bool m_hereEnabled;
130+ QString m_hereLicensePath;
111131};
112132
113133#endif
plugins/CMakeLists.txt+1
@@ -21,3 +21,4 @@ add_subdirectory(ScreenGrabber)
2121add_subdirectory(Ubuntu)
2222add_subdirectory(Unity)
2323add_subdirectory(Utils)
24+add_subdirectory(Wizard)
plugins/Unity/Launcher/desktopfilehandler.cpp+1−1
@@ -110,7 +110,7 @@ QString DesktopFileHandler::displayName() const
110110 settings.beginGroup("Desktop Entry");
111111
112112 // First try to find Name[xx_YY] and Name[xx] in .desktop file
113− QString locale = QLocale::system().name();
113+ QString locale = QLocale().name();
114114 QString shortLocale = locale.split('_').first();
115115
116116 if (locale != shortLocale && settings.contains(QString("Name[%1]").arg(locale))) {
plugins/Unity/Launcher/launcheritem.cpp+11−4
@@ -60,6 +60,10 @@ void LauncherItem::setName(const QString &name)
6060{
6161 if (m_name != name) {
6262 m_name = name;
63+ QuickListEntry entry;
64+ entry.setActionId("launch_item");
65+ entry.setText(m_name);
66+ m_quickList->updateAction(entry);
6367 Q_EMIT nameChanged(name);
6468 }
6569}
@@ -86,12 +90,15 @@ void LauncherItem::setPinned(bool pinned)
8690{
8791 if (m_pinned != pinned) {
8892 m_pinned = pinned;
89− QuickListEntry entry;
90− entry.setActionId("pin_item");
91− entry.setText(pinned ? gettext("Unpin shortcut") : gettext("Pin shortcut"));
92− m_quickList->updateAction(entry);
9393 Q_EMIT pinnedChanged(pinned);
9494 }
95+
96+ // Even if pinned status didn't change, we want to update text in case
97+ // the locale has changed since we last set pinned status.
98+ QuickListEntry entry;
99+ entry.setActionId("pin_item");
100+ entry.setText(pinned ? gettext("Unpin shortcut") : gettext("Pin shortcut"));
101+ m_quickList->updateAction(entry);
95102}
96103
97104bool LauncherItem::running() const
plugins/Unity/Launcher/launchermodel.cpp+1
@@ -370,6 +370,7 @@ void LauncherModel::refresh()
370370 int idx = m_list.indexOf(item);
371371 item->setName(desktopFile.displayName());
372372 item->setIcon(desktopFile.icon());
373+ item->setPinned(item->pinned()); // update pinned text if needed
373374 Q_EMIT dataChanged(index(idx), index(idx), QVector<int>() << RoleName << RoleIcon);
374375 }
375376 }
plugins/Unity/Launcher/launchermodel.h+1−1
@@ -58,6 +58,7 @@ public:
5858
5959public Q_SLOTS:
6060 void requestRemove(const QString &appId);
61+ Q_INVOKABLE void refresh();
6162
6263private:
6364 void storeAppList();
@@ -68,7 +69,6 @@ private Q_SLOTS:
6869 void countChanged(const QString &appId, int count);
6970 void countVisibleChanged(const QString &appId, int count);
7071 void progressChanged(const QString &appId, int progress);
71− void refresh();
7272
7373 void applicationAdded(const QModelIndex &parent, int row);
7474 void applicationRemoved(const QModelIndex &parent, int row);
wizard/50-com.ubuntu.system-settings.wizard.pkla → plugins/Wizard/50-com.canonical.unity.wizard.pklarenamed

The content is the same.

plugins/Wizard/CMakeLists.txtnew file+11
@@ -0,0 +1,11 @@
1+add_library(Wizard-qml MODULE
2+ plugin.cpp
3+ PageList.cpp
4+ System.cpp
5+)
6+
7+qt5_use_modules(Wizard-qml DBus Qml)
8+add_unity8_plugin(Wizard 0.1 Wizard TARGETS Wizard-qml)
9+
10+set(POLKIT_LIB_DIR "${CMAKE_INSTALL_LOCALSTATEDIR}/lib/polkit-1")
11+install(FILES 50-com.canonical.unity.wizard.pkla DESTINATION ${POLKIT_LIB_DIR}/localauthority/10-vendor.d)
wizard/PageList.cpp → plugins/Wizard/PageList.cpprenamed+10−9
@@ -1,6 +1,4 @@
11/*
2− * This file is part of system-settings
3− *
42 * Copyright (C) 2014 Canonical Ltd.
53 *
64 * This program is free software: you can redistribute it and/or modify it
@@ -19,7 +17,7 @@
1917/**
2018 * This class lets the list of wizard pages be dynamic.
2119 * - To add new ones, drop them into
22− * $XDG_DATA_DIRS/ubuntu/settings/wizard/qml/Pages with a numbered prefix,
20+ * $XDG_DATA_DIRS/Wizard/Pages with a numbered prefix,
2321 * like "21-custom-page.qml". The number determines the order in the page
2422 * sequence that your page will appear.
2523 * - To disable an existing page, add a file like "21-custom-page.qml.disabled"
@@ -32,10 +30,11 @@
3230 */
3331
3432#include "PageList.h"
33+#include <paths.h>
3534#include <QDir>
35+#include <QSet>
3636#include <QStandardPaths>
3737
38−#include <QDebug>
3938PageList::PageList(QObject *parent)
4039 : QObject(parent),
4140 m_index(-1),
@@ -44,14 +43,16 @@ PageList::PageList(QObject *parent)
4443 QString qmlSuffix = ".qml";
4544 QString disabledSuffix = ".disabled";
4645 QSet<QString> disabledPages;
47− QStringList dataDirs = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation);
46+ QStringList dataDirs;
4847
49− QString rootDir = qgetenv("UBUNTU_SYSTEM_SETTINGS_WIZARD_ROOT"); // for testing
50− if (!rootDir.isEmpty())
51− dataDirs = QStringList() << rootDir;
48+ if (!isRunningInstalled() && getenv("UNITY_TEST_ENV") == nullptr) {
49+ dataDirs = QStringList() << qmlDirectory();
50+ } else {
51+ dataDirs = shellDataDirs();
52+ }
5253
5354 Q_FOREACH(const QString &dataDir, dataDirs) {
54− QDir dir(dataDir + "/ubuntu/settings/wizard/qml/Pages");
55+ QDir dir(dataDir + "/Wizard/Pages");
5556 QStringList entries = dir.entryList(QStringList("[0-9]*"), QDir::Files | QDir::Readable);
5657 Q_FOREACH(const QString &entry, entries) {
5758 if (!m_pages.contains(entry) && entry.endsWith(qmlSuffix))
wizard/PageList.h → plugins/Wizard/PageList.hrenamed+3−5
@@ -1,6 +1,4 @@
11/*
2− * This file is part of system-settings
3− *
42 * Copyright (C) 2014 Canonical Ltd.
53 *
64 * This program is free software: you can redistribute it and/or modify it
@@ -16,8 +14,8 @@
1614 * with this program. If not, see <http://www.gnu.org/licenses/>.
1715 */
1816
19−#ifndef PAGELIST_H
20−#define PAGEList_H
17+#ifndef WIZARD_PAGELIST_H
18+#define WIZARD_PAGELIST_H
2119
2220#include <QMap>
2321#include <QObject>
@@ -52,4 +50,4 @@ private:
5250 QMap<QString, QString> m_pages;
5351};
5452
55−#endif // PAGELIST_H
53+#endif // WIZARD_PAGELIST_H
plugins/Wizard/System.cppnew file+99
@@ -0,0 +1,99 @@
1+/*
2+ * Copyright (C) 2014 Canonical Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it
5+ * under the terms of the GNU General Public License version 3, as published
6+ * by the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful, but
9+ * WITHOUT ANY WARRANTY; without even the implied warranties of
10+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11+ * PURPOSE. See the GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License along
14+ * with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include "System.h"
18+
19+#include <QDBusInterface>
20+#include <QDBusMetaType>
21+#include <QDir>
22+#include <QFile>
23+#include <QLocale>
24+#include <QMap>
25+#include <QProcess>
26+
27+System::System()
28+ : QObject(),
29+ m_fsWatcher()
30+{
31+ // Register the argument needed for UpdateActivationEnvironment below
32+ qDBusRegisterMetaType<QMap<QString,QString>>();
33+
34+ m_fsWatcher.addPath(wizardEnabledPath());
35+ connect(&m_fsWatcher, SIGNAL(fileChanged(const QString &)),
36+ this, SIGNAL(wizardEnabledChanged()));
37+}
38+
39+QString System::wizardEnabledPath()
40+{
41+ // Uses ubuntu-system-settings namespace for historic compatibility reasons
42+ return QDir::home().filePath(".config/ubuntu-system-settings/wizard-has-run");
43+}
44+
45+bool System::wizardEnabled() const
46+{
47+ return !QFile::exists(wizardEnabledPath());
48+}
49+
50+void System::setWizardEnabled(bool enabled)
51+{
52+ if (wizardEnabled() == enabled)
53+ return;
54+
55+ if (enabled) {
56+ QFile::remove(wizardEnabledPath());
57+ } else {
58+ QDir(wizardEnabledPath()).mkpath("..");
59+ QFile(wizardEnabledPath()).open(QIODevice::WriteOnly);
60+ m_fsWatcher.addPath(wizardEnabledPath());
61+ wizardEnabledChanged();
62+ }
63+}
64+
65+void System::setSessionVariable(const QString &variable, const QString &value)
66+{
67+ // We need to update both upstart's and DBus's environment
68+ QProcess::execute(QString("initctl set-env --global %1=%2").arg(variable, value));
69+
70+ QDBusInterface iface("org.freedesktop.DBus",
71+ "/org/freedesktop/DBus",
72+ "org.freedesktop.DBus",
73+ QDBusConnection::sessionBus());
74+
75+ QMap<QString,QString> valueMap;
76+ valueMap.insert(variable, value);
77+ iface.call("UpdateActivationEnvironment", QVariant::fromValue(valueMap));
78+}
79+
80+void System::updateSessionLanguage(const QString &locale)
81+{
82+ QString language = locale.split(".")[0];
83+
84+ setSessionVariable("LANGUAGE", language);
85+ setSessionVariable("LANG", locale);
86+ setSessionVariable("LC_ALL", locale);
87+
88+ // QLocale caches the default locale on startup, and Qt uses that cached
89+ // copy when formatting dates. So manually update it here.
90+ QLocale::setDefault(QLocale(locale));
91+
92+ // Restart bits of the session to pick up new language.
93+ QProcess::startDetached("sh -c \"initctl emit indicator-services-end; \
94+ initctl stop scope-registry; \
95+ initctl stop smart-scopes-proxy; \
96+ initctl emit --no-wait indicator-services-start; \
97+ initctl restart --no-wait maliit-server; \
98+ initctl restart --no-wait unity8-dash\"");
99+}
plugins/Wizard/System.hnew file+50
@@ -0,0 +1,50 @@
1+/*
2+ * Copyright (C) 2014 Canonical Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it
5+ * under the terms of the GNU General Public License version 3, as published
6+ * by the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful, but
9+ * WITHOUT ANY WARRANTY; without even the implied warranties of
10+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11+ * PURPOSE. See the GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License along
14+ * with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#ifndef WIZARD_SYSTEM_H
18+#define WIZARD_SYSTEM_H
19+
20+#include <QFileSystemWatcher>
21+#include <QObject>
22+#include <QString>
23+
24+class System : public QObject
25+{
26+ Q_OBJECT
27+ Q_PROPERTY(bool wizardEnabled READ wizardEnabled WRITE setWizardEnabled NOTIFY wizardEnabledChanged)
28+
29+public:
30+ System();
31+
32+ bool wizardEnabled() const;
33+ void setWizardEnabled(bool enabled);
34+
35+public Q_SLOTS:
36+ void updateSessionLanguage(const QString &locale);
37+
38+Q_SIGNALS:
39+ void wizardEnabledChanged();
40+
41+private:
42+ Q_DISABLE_COPY(System)
43+
44+ static QString wizardEnabledPath();
45+ static void setSessionVariable(const QString &variable, const QString &value);
46+
47+ QFileSystemWatcher m_fsWatcher;
48+};
49+
50+#endif
wizard/Unity/Application/CMakeLists.txt → plugins/Wizard/Unity/Application/CMakeLists.txtrenamed

The content is the same.

wizard/Unity/Application/OSKController.qml → plugins/Wizard/Unity/Application/OSKController.qmlrenamed

The content is the same.

wizard/Unity/Application/qmldir → plugins/Wizard/Unity/Application/qmldirrenamed

The content is the same.

wizard/Unity/CMakeLists.txt → plugins/Wizard/Unity/CMakeLists.txtrenamed

The content is the same.

wizard/Utils/CMakeLists.txt → plugins/Wizard/Utils/CMakeLists.txtrenamed

The content is the same.

wizard/Utils/plugin.cpp → plugins/Wizard/Utils/plugin.cpprenamed

The content is the same.

wizard/Utils/plugin.h → plugins/Wizard/Utils/plugin.hrenamed

The content is the same.

wizard/Utils/qmldir → plugins/Wizard/Utils/qmldirrenamed

The content is the same.

wizard/Utils/qsortfilterproxymodelqml.cpp → plugins/Wizard/Utils/qsortfilterproxymodelqml.cpprenamed

The content is the same.

wizard/Utils/qsortfilterproxymodelqml.h → plugins/Wizard/Utils/qsortfilterproxymodelqml.hrenamed

The content is the same.

plugins/Wizard/Wizard.qmltypesnew file+36
@@ -0,0 +1,36 @@
1+import QtQuick.tooling 1.1
2+
3+// This file describes the plugin-supplied types contained in the library.
4+// It is used for QML tooling purposes only.
5+//
6+// This file was auto-generated by:
7+// 'qmlplugindump -notrelocatable Wizard 0.1 plugins'
8+
9+Module {
10+ Component {
11+ name: "PageList"
12+ prototype: "QObject"
13+ exports: ["Wizard/PageList 0.1"]
14+ isCreatable: false
15+ isSingleton: true
16+ exportMetaObjectRevisions: [0]
17+ Property { name: "index"; type: "int"; isReadonly: true }
18+ Property { name: "numPages"; type: "int"; isReadonly: true }
19+ Method { name: "prev"; type: "string" }
20+ Method { name: "next"; type: "string" }
21+ }
22+ Component {
23+ name: "System"
24+ prototype: "QObject"
25+ exports: ["Wizard/System 0.1"]
26+ isCreatable: false
27+ isSingleton: true
28+ exportMetaObjectRevisions: [0]
29+ Property { name: "wizardEnabled"; type: "bool" }
30+ Method {
31+ name: "updateSessionLanguage"
32+ Parameter { name: "locale"; type: "string" }
33+ }
34+ }
35+}
36+
wizard/main.cpp → plugins/Wizard/main.cpprenamed

The content is the same.

plugins/Wizard/plugin.cppnew file+42
@@ -0,0 +1,42 @@
1+/*
2+ * Copyright (C) 2014 Canonical Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it
5+ * under the terms of the GNU General Public License version 3, as published
6+ * by the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful, but
9+ * WITHOUT ANY WARRANTY; without even the implied warranties of
10+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11+ * PURPOSE. See the GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License along
14+ * with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include "plugin.h"
18+#include "PageList.h"
19+#include "System.h"
20+
21+#include <QtQml/qqml.h>
22+
23+static QObject *pagelist_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
24+{
25+ Q_UNUSED(engine)
26+ Q_UNUSED(scriptEngine)
27+ return new PageList();
28+}
29+
30+static QObject *system_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
31+{
32+ Q_UNUSED(engine)
33+ Q_UNUSED(scriptEngine)
34+ return new System();
35+}
36+
37+void WizardPlugin::registerTypes(const char *uri)
38+{
39+ Q_ASSERT(uri == QLatin1String("Wizard"));
40+ qmlRegisterSingletonType<PageList>(uri, 0, 1, "PageList", pagelist_provider);
41+ qmlRegisterSingletonType<System>(uri, 0, 1, "System", system_provider);
42+}
plugins/Wizard/plugin.hnew file+32
@@ -0,0 +1,32 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#ifndef WIZARD_PLUGIN_H
18+#define WIZARD_PLUGIN_H
19+
20+#include <QtQml/QQmlEngine>
21+#include <QtQml/QQmlExtensionPlugin>
22+
23+class WizardPlugin : public QQmlExtensionPlugin
24+{
25+ Q_OBJECT
26+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
27+
28+public:
29+ void registerTypes(const char *uri);
30+};
31+
32+#endif
plugins/Wizard/qmldirnew file+3
@@ -0,0 +1,3 @@
1+module Wizard
2+plugin Wizard-qml
3+typeinfo Wizard.qmltypes
wizard/test.sh → plugins/Wizard/test.shrenamed

The content is the same.

wizard/ubuntu-system-settings-wizard-cleanup.conf → plugins/Wizard/ubuntu-system-settings-wizard-cleanup.confrenamed

The content is the same.

wizard/ubuntu-system-settings-wizard-set-lang.conf → plugins/Wizard/ubuntu-system-settings-wizard-set-lang.confrenamed

The content is the same.

wizard/ubuntu-system-settings-wizard.conf → plugins/Wizard/ubuntu-system-settings-wizard.confrenamed

The content is the same.

qml/CMakeLists.txt+1
@@ -13,6 +13,7 @@ set(QML_DIRS
1313 Launcher
1414 Stages
1515 Notifications
16+ Wizard
1617 )
1718
1819install(DIRECTORY ${QML_DIRS}
qml/Components/Dialogs.qml+17−21
@@ -24,10 +24,6 @@ import Ubuntu.Components.Popups 0.1
2424Item {
2525 id: root
2626
27− // Explicitly use the right domain for this widget because it might be used
28− // in other applications like the welcome wizard.
29− readonly property string domain: "unity8"
30−
3127 function onPowerKeyPressed() {
3228 // FIXME: event.isAutoRepeat is always false on Nexus 4.
3329 // So we use powerKeyTimer.running to avoid the PowerOff key repeat
@@ -71,17 +67,17 @@ Item {
7167 id: logoutDialog
7268 Dialog {
7369 id: dialogueLogout
74− title: i18n.dtr(root.domain, "Log out")
75− text: i18n.dtr(root.domain, "Are you sure you want to log out?")
70+ title: i18n.tr("Log out")
71+ text: i18n.tr("Are you sure you want to log out?")
7672 Button {
77− text: i18n.dtr(root.domain, "No")
73+ text: i18n.tr("No")
7874 onClicked: {
7975 PopupUtils.close(dialogueLogout);
8076 d.dialogShown = false;
8177 }
8278 }
8379 Button {
84− text: i18n.dtr(root.domain, "Yes")
80+ text: i18n.tr("Yes")
8581 onClicked: {
8682 DBusUnitySessionService.Logout();
8783 PopupUtils.close(dialogueLogout);
@@ -95,17 +91,17 @@ Item {
9591 id: shutdownDialog
9692 Dialog {
9793 id: dialogueShutdown
98− title: i18n.dtr(root.domain, "Shut down")
99− text: i18n.dtr(root.domain, "Are you sure you want to shut down?")
94+ title: i18n.tr("Shut down")
95+ text: i18n.tr("Are you sure you want to shut down?")
10096 Button {
101− text: i18n.dtr(root.domain, "No")
97+ text: i18n.tr("No")
10298 onClicked: {
10399 PopupUtils.close(dialogueShutdown);
104100 d.dialogShown = false;
105101 }
106102 }
107103 Button {
108− text: i18n.dtr(root.domain, "Yes")
104+ text: i18n.tr("Yes")
109105 onClicked: {
110106 dBusUnitySessionServiceConnection.closeAllApps();
111107 DBusUnitySessionService.Shutdown();
@@ -120,17 +116,17 @@ Item {
120116 id: rebootDialog
121117 Dialog {
122118 id: dialogueReboot
123− title: i18n.dtr(root.domain, "Reboot")
124− text: i18n.dtr(root.domain, "Are you sure you want to reboot?")
119+ title: i18n.tr("Reboot")
120+ text: i18n.tr("Are you sure you want to reboot?")
125121 Button {
126− text: i18n.dtr(root.domain, "No")
122+ text: i18n.tr("No")
127123 onClicked: {
128124 PopupUtils.close(dialogueReboot)
129125 d.dialogShown = false;
130126 }
131127 }
132128 Button {
133− text: i18n.dtr(root.domain, "Yes")
129+ text: i18n.tr("Yes")
134130 onClicked: {
135131 dBusUnitySessionServiceConnection.closeAllApps();
136132 DBusUnitySessionService.Reboot();
@@ -145,10 +141,10 @@ Item {
145141 id: powerDialog
146142 Dialog {
147143 id: dialoguePower
148− title: i18n.dtr(root.domain, "Power")
149− text: i18n.dtr(root.domain, "Are you sure you would like\nto power off?")
144+ title: i18n.tr("Power")
145+ text: i18n.tr("Are you sure you would like\nto power off?")
150146 Button {
151− text: i18n.dtr(root.domain, "Power off")
147+ text: i18n.tr("Power off")
152148 onClicked: {
153149 dBusUnitySessionServiceConnection.closeAllApps();
154150 PopupUtils.close(dialoguePower);
@@ -158,7 +154,7 @@ Item {
158154 color: UbuntuColors.red
159155 }
160156 Button {
161− text: i18n.dtr(root.domain, "Restart")
157+ text: i18n.tr("Restart")
162158 onClicked: {
163159 dBusUnitySessionServiceConnection.closeAllApps();
164160 DBusUnitySessionService.Reboot();
@@ -168,7 +164,7 @@ Item {
168164 color: UbuntuColors.green
169165 }
170166 Button {
171− text: i18n.dtr(root.domain, "Cancel")
167+ text: i18n.tr("Cancel")
172168 onClicked: {
173169 PopupUtils.close(dialoguePower);
174170 d.dialogShown = false;
qml/Components/EdgeDemo.qml+19−6
@@ -17,6 +17,7 @@
1717import AccountsService 0.1
1818import LightDM 0.1 as LightDM
1919import QtQuick 2.0
20+import Ubuntu.Components 1.1
2021
2122Item {
2223 id: demo
@@ -61,11 +62,16 @@ Item {
6162 stagesEnabled = true
6263 panelEnabled = true
6364 panelContentEnabled = true
64− if (d.rightEdgeDemo) d.rightEdgeDemo.destroy()
65− if (d.topEdgeDemo) d.topEdgeDemo.destroy()
66− if (d.bottomEdgeDemo) d.bottomEdgeDemo.destroy()
67− if (d.leftEdgeDemo) d.leftEdgeDemo.destroy()
68− if (d.finalEdgeDemo) d.finalEdgeDemo.destroy()
65+
66+ // Use a tiny delay for these destroy() calls because if a lot is
67+ // happening at once (like creating and being destroyed in same event
68+ // loop, as might happen when answering a call while demo is open),
69+ // the destroy() call will be ignored.
70+ if (d.rightEdgeDemo) d.rightEdgeDemo.destroy(1);
71+ if (d.topEdgeDemo) d.topEdgeDemo.destroy(1);
72+ if (d.bottomEdgeDemo) d.bottomEdgeDemo.destroy(1);
73+ if (d.leftEdgeDemo) d.leftEdgeDemo.destroy(1);
74+ if (d.finalEdgeDemo) d.finalEdgeDemo.destroy(1);
6975 }
7076
7177 function startDemo() {
@@ -97,12 +103,19 @@ Item {
97103 property bool showEdgeDemo: AccountsService.demoEdges
98104 property bool showEdgeDemoInGreeter: AccountsService.demoEdges // TODO: AccountsService.demoEdges as lightdm user
99105
100− onShowEdgeDemoChanged: {
106+ function restartDemo() {
101107 stopDemo()
102108 if (d.showEdgeDemo) {
103109 startDemo()
104110 }
105111 }
112+
113+ onShowEdgeDemoChanged: restartDemo()
114+ }
115+
116+ Connections {
117+ target: i18n
118+ onLanguageChanged: d.restartDemo()
106119 }
107120
108121 function startRightEdgeDemo() {
qml/Greeter/Clock.qml+10
@@ -34,6 +34,16 @@ Item {
3434 }
3535 }
3636
37+ Connections {
38+ target: i18n
39+ onLanguageChanged: {
40+ if (visible) {
41+ timeLabel.text = Qt.formatTime(clock.currentDate); // kicks time
42+ clock.currentDate = new Date(); // kicks date
43+ }
44+ }
45+ }
46+
3747 Indicators.SharedUnityMenuModel {
3848 id: timeModel
3949 objectName: "timeModel"
qml/Greeter/GreeterContent.qml+5
@@ -133,6 +133,11 @@ Item {
133133 onSelected: infographics.selectedUser = greeterContentLoader.model.data(uid, LightDM.UserRoles.NameRole)
134134 }
135135
136+ Connections {
137+ target: i18n
138+ onLanguageChanged: greeterContentLoader.infographicModel.readyForDataChange()
139+ }
140+
136141 anchors {
137142 verticalCenter: parent.verticalCenter
138143 left: narrowMode ? root.left : loginLoader.right
qml/Launcher/Launcher.qml+5
@@ -118,6 +118,11 @@ Item {
118118 onHint: hint();
119119 }
120120
121+ Connections {
122+ target: i18n
123+ onLanguageChanged: LauncherModel.refresh()
124+ }
125+
121126 SequentialAnimation {
122127 id: fadeOutAnimation
123128 ScriptAction {
qml/Shell.qml+26−15
@@ -37,6 +37,7 @@ import "Components"
3737import "Notifications"
3838import "Stages"
3939import "Panel/Indicators"
40+import "Wizard"
4041import Unity.Notifications 1.0 as NotificationBackend
4142import Unity.Session 0.1
4243import Unity.DashCommunicator 0.1
@@ -236,6 +237,14 @@ Item {
236237 onApplicationAdded: {
237238 if (greeter.shown && appId != "unity8-dash") {
238239 greeter.startUnlock()
240+
241+ // If this happens on first boot, we may be in edge
242+ // tutorial or wizard while receiving a call. But a call
243+ // is more important than wizard so just bail out of those.
244+ if (edgeDemo.running) {
245+ edgeDemo.hideEdgeDemos();
246+ wizard.hide();
247+ }
239248 }
240249 if (greeter.narrowMode && greeter.hasLockedApp && appId === greeter.lockedApp) {
241250 lockscreen.hide() // show locked app
@@ -354,6 +363,15 @@ Item {
354363 minPinLength: 4
355364 maxPinLength: 4
356365
366+ property string promptText
367+ infoText: promptText !== "" ? i18n.tr("Enter %1").arg(promptText) :
368+ alphaNumeric ? i18n.tr("Enter passphrase") :
369+ i18n.tr("Enter passcode")
370+ errorText: promptText !== "" ? i18n.tr("Sorry, incorrect %1").arg(promptText) :
371+ alphaNumeric ? i18n.tr("Sorry, incorrect passphrase") + "\n" +
372+ i18n.tr("Please re-enter") :
373+ i18n.tr("Sorry, incorrect passcode")
374+
357375 // FIXME: We *should* show emergency dialer if there is a SIM present,
358376 // regardless of whether the side stage is enabled. But right now,
359377 // the assumption is that narrow screens are phones which have SIMs
@@ -407,20 +425,7 @@ Item {
407425 return; // could happen if hideGreeter() comes in before we prompt
408426 }
409427 if (greeter.narrowMode) {
410− if (isDefaultPrompt) {
411− if (lockscreen.alphaNumeric) {
412− lockscreen.infoText = i18n.tr("Enter passphrase")
413− lockscreen.errorText = i18n.tr("Sorry, incorrect passphrase") + "\n" +
414− i18n.tr("Please re-enter")
415− } else {
416− lockscreen.infoText = i18n.tr("Enter passcode")
417− lockscreen.errorText = i18n.tr("Sorry, incorrect passcode")
418− }
419− } else {
420− lockscreen.infoText = i18n.tr("Enter %1").arg(text.toLowerCase())
421− lockscreen.errorText = i18n.tr("Sorry, incorrect %1").arg(text.toLowerCase())
422− }
423−
428+ lockscreen.promptText = isDefaultPrompt ? "" : text.toLowerCase();
424429 lockscreen.maybeShow();
425430 }
426431 }
@@ -748,6 +753,12 @@ Item {
748753 }
749754 }
750755
756+ Wizard {
757+ id: wizard
758+ anchors.fill: parent
759+ background: shell.background
760+ }
761+
751762 Rectangle {
752763 id: modalNotificationBackground
753764
@@ -809,7 +820,7 @@ Item {
809820 id: edgeDemo
810821 objectName: "edgeDemo"
811822 z: dialogs.z + 10
812− paused: Powerd.status === Powerd.Off // Saves power
823+ paused: Powerd.status === Powerd.Off || wizard.active // Saves power
813824 greeter: greeter
814825 launcher: launcher
815826 panel: panel
wizard/qml/Components/CheckableSetting.qml → qml/Wizard/CheckableSetting.qmlrenamed−1
@@ -15,7 +15,6 @@
1515 */
1616
1717import QtQuick 2.3
18−import QMenuModel 0.1
1918import Ubuntu.Components 1.1
2019import Ubuntu.Components.ListItems 1.0 as ListItem
2120
wizard/qml/Components/InputMethod.qml → qml/Wizard/Components/InputMethod.qmlrenamed

The content is the same.

wizard/qml/Components/Page.qml → qml/Wizard/Page.qmlrenamed+1−2
@@ -16,7 +16,6 @@
1616
1717import QtQuick 2.3
1818import Ubuntu.Components 1.1
19−import "." as LocalComponents
2019
2120Item {
2221 readonly property real buttonMargin: units.gu(2)
@@ -76,7 +75,7 @@ Item {
7675 }
7776 }
7877
79− LocalComponents.StackButton {
78+ StackButton {
8079 id: backButton
8180 width: buttonWidth
8281 anchors {
qml/Wizard/Pages.qmlnew file+129
@@ -0,0 +1,129 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.3
18+import Ubuntu.Components 1.1
19+import Ubuntu.SystemSettings.SecurityPrivacy 1.0
20+import Wizard 0.1
21+import "../Components"
22+
23+Item {
24+ id: root
25+ focus: true
26+
27+ // The background wallpaper to use
28+ property string background
29+
30+ signal quit()
31+
32+ // These should be set by a security page and we apply the settings when
33+ // the user exits the wizard.
34+ property int passwordMethod: UbuntuSecurityPrivacyPanel.Passcode
35+ property string password: ""
36+
37+ UbuntuSecurityPrivacyPanel {
38+ id: securityPrivacy
39+ }
40+
41+ function quitWizard() {
42+ var errorMsg = securityPrivacy.setSecurity("", password, passwordMethod)
43+ if (errorMsg !== "") {
44+ // Ignore (but log) any errors, since we're past where the user set
45+ // the method. Worst case, we just leave the user with a swipe
46+ // security method and they fix it in the system settings.
47+ console.log("Error setting security method:", errorMsg)
48+ }
49+
50+ quit();
51+ }
52+
53+ MouseArea { // eat anything that gets past widgets
54+ anchors.fill: parent
55+ }
56+
57+ Image {
58+ id: image
59+ // Use x/y/height/width instead of anchors so that we don't adjust
60+ // the image when the OSK appears.
61+ x: 0
62+ y: 0
63+ height: root.height
64+ width: root.width
65+ sourceSize.height: height
66+ sourceSize.width: width
67+ source: root.background
68+ fillMode: Image.PreserveAspectCrop
69+ visible: status === Image.Ready
70+ }
71+
72+ PageStack {
73+ id: pageStack
74+ anchors.fill: parent
75+
76+ function next() {
77+ // If we've opened any extra (non-main) pages, pop them before
78+ // continuing so back button returns to the previous main page.
79+ while (PageList.index < pageStack.depth - 1)
80+ pop()
81+ load(PageList.next())
82+ }
83+
84+ function prev() {
85+ if (PageList.index >= pageStack.depth - 1)
86+ PageList.prev() // update PageList.index, but not for extra pages
87+ pop()
88+ if (!currentPage || currentPage.opacity === 0) { // undo skipped pages
89+ prev()
90+ } else {
91+ currentPage.enabled = true
92+ }
93+ }
94+
95+ function load(path) {
96+ if (currentPage) {
97+ currentPage.enabled = false
98+ }
99+
100+ // First load it invisible, check that we should actually use
101+ // this page, and either skip it or continue.
102+ push(path, {"opacity": 0, "enabled": false})
103+
104+ // Check for immediate skip or not. We may have to wait for
105+ // skipValid to be assigned (see Connections object below)
106+ checkSkip()
107+ }
108+
109+ function checkSkip() {
110+ if (!currentPage) { // may have had a parse error
111+ next()
112+ } else if (currentPage.skipValid) {
113+ if (currentPage.skip) {
114+ next()
115+ } else {
116+ currentPage.opacity = 1
117+ currentPage.enabled = true
118+ }
119+ }
120+ }
121+
122+ Connections {
123+ target: pageStack.currentPage
124+ onSkipValidChanged: pageStack.checkSkip()
125+ }
126+
127+ Component.onCompleted: next()
128+ }
129+}
wizard/qml/Pages/10-welcome.qml → qml/Wizard/Pages/10-welcome.qmlrenamed+7−5
@@ -18,8 +18,8 @@ import QtQuick 2.3
1818import Ubuntu.Components 1.1
1919import Ubuntu.Components.ListItems 0.1
2020import Ubuntu.SystemSettings.LanguagePlugin 1.0
21−import Ubuntu.SystemSettings.Wizard.Utils 0.1
22−import "../Components" as LocalComponents
21+import Wizard 0.1
22+import ".." as LocalComponents
2323
2424LocalComponents.Page {
2525 title: i18n.tr("Hi!")
@@ -72,7 +72,6 @@ LocalComponents.Page {
7272 listview.currentIndex = index
7373 combo.expanded = false
7474 i18n.language = plugin.languageCodes[index]
75− i18n.domain = i18n.domain
7675 }
7776 }
7877 }
@@ -84,8 +83,11 @@ LocalComponents.Page {
8483 LocalComponents.StackButton {
8584 text: i18n.tr("Continue")
8685 onClicked: {
87− plugin.currentLanguage = listview.currentIndex
88− System.updateSessionLanguage()
86+ if (plugin.currentLanguage !== listview.currentIndex) {
87+ plugin.currentLanguage = listview.currentIndex;
88+ System.updateSessionLanguage(plugin.languageCodes[listview.currentIndex]);
89+ i18n.language = i18n.language; // re-notify of change after above call (for qlocale change)
90+ }
8991 pageStack.next()
9092 }
9193 }
wizard/qml/Pages/20-sim.qml → qml/Wizard/Pages/20-sim.qmlrenamed+1−1
@@ -17,7 +17,7 @@
1717import QtQuick 2.0
1818import MeeGo.QOfono 0.2
1919import Ubuntu.Components 0.1
20−import "../Components" as LocalComponents
20+import ".." as LocalComponents
2121
2222LocalComponents.Page {
2323 title: i18n.tr("Add a SIM card and restart your device")
wizard/qml/Pages/30-passwd-type.qml → qml/Wizard/Pages/30-passwd-type.qmlrenamed+13−1
@@ -18,7 +18,7 @@ import QtQuick 2.3
1818import Ubuntu.Components 1.1
1919import Ubuntu.Components.ListItems 1.0
2020import Ubuntu.SystemSettings.SecurityPrivacy 1.0
21−import "../Components" as LocalComponents
21+import ".." as LocalComponents
2222
2323/**
2424 * One quirk with this page: we don't actually set the password. We avoid
@@ -77,6 +77,7 @@ LocalComponents.Page {
7777 expanded: true
7878 anchors.left: parent.left
7979 anchors.right: parent.right
80+ property color originalBackground
8081
8182 model: ["", "", ""] // otherwise the delegate will show the text itself and we only want subText
8283
@@ -103,6 +104,17 @@ LocalComponents.Page {
103104 }
104105
105106 style: Item {}
107+
108+ Component.onCompleted: {
109+ // A visible selected background looks bad in ListItem widgets with our theme
110+ originalBackground = Theme.palette.selected.background
111+ Theme.palette.selected.background = "transparent"
112+ }
113+
114+ Component.onDestruction: {
115+ // Restore original theme background
116+ Theme.palette.selected.background = originalBackground
117+ }
106118 }
107119 }
108120
wizard/qml/Pages/40-wifi.qml → qml/Wizard/Pages/40-wifi.qmlrenamed+1−2
@@ -18,9 +18,8 @@ import QtQuick 2.0
1818import QMenuModel 0.1 as QMenuModel
1919import Ubuntu.Components 0.1
2020import Ubuntu.Components.ListItems 0.1 as ListItem
21−import Ubuntu.SystemSettings.Wizard.Utils 0.1
2221import Ubuntu.Settings.Menus 0.1 as Menus
23−import "../Components" as LocalComponents
22+import ".." as LocalComponents
2423
2524LocalComponents.Page {
2625 id: wifiPage
wizard/qml/Pages/50-location.qml → qml/Wizard/Pages/50-location.qmlrenamed+7−7
@@ -15,20 +15,20 @@
1515 */
1616
1717import QtQuick 2.3
18+import AccountsService 0.1
1819import QMenuModel 0.1 as QMenuModel
1920import Qt.labs.folderlistmodel 2.1
2021import Ubuntu.Components 1.1
21−import Ubuntu.SystemSettings.Wizard.Utils 0.1
22−import "../Components" as LocalComponents
22+import ".." as LocalComponents
2323
2424LocalComponents.Page {
2525 title: i18n.tr("Location")
2626 forwardButtonSourceComponent: forwardButton
2727
28− property bool pathSet: System.hereLicensePath !== " " // single space means it's unassigned
28+ property bool pathSet: AccountsService.hereLicensePathValid
2929 property bool countSet: false
30− skipValid: pathSet && (System.hereLicensePath === "" || countSet)
31− skip: skipValid && (System.hereLicensePath === "" || termsModel.count === 0)
30+ skipValid: pathSet && (AccountsService.hereLicensePath === "" || countSet)
31+ skip: skipValid && (AccountsService.hereLicensePath === "" || termsModel.count === 0)
3232
3333 Connections {
3434 target: termsModel
@@ -37,7 +37,7 @@ LocalComponents.Page {
3737
3838 FolderListModel {
3939 id: termsModel
40− folder: System.hereLicensePath
40+ folder: AccountsService.hereLicensePath
4141 nameFilters: ["*.html"]
4242 showDirs: false
4343 showOnlyReadable: true
@@ -141,7 +141,7 @@ LocalComponents.Page {
141141 if (locationActionGroup.gps.state != gpsOn) {
142142 locationActionGroup.gps.activate();
143143 }
144− System.hereEnabled = hereOn;
144+ AccountsService.hereEnabled = hereOn;
145145 pageStack.next()
146146 }
147147 }
wizard/qml/Pages/60-reporting.qml → qml/Wizard/Pages/60-reporting.qmlrenamed+1−1
@@ -16,7 +16,7 @@
1616
1717import QtQuick 2.0
1818import Ubuntu.Components 0.1
19−import "../Components" as LocalComponents
19+import ".." as LocalComponents
2020
2121LocalComponents.Page {
2222 title: i18n.tr("Improving your experience")
wizard/qml/Pages/80-finished.qml → qml/Wizard/Pages/80-finished.qmlrenamed+1−1
@@ -16,7 +16,7 @@
1616
1717import QtQuick 2.0
1818import Ubuntu.Components 0.1
19−import "../Components" as LocalComponents
19+import ".." as LocalComponents
2020
2121LocalComponents.Page {
2222 title: i18n.tr("All done")
wizard/qml/Pages/data/meet_ubuntu_simcard@30.png → qml/Wizard/Pages/data/meet_ubuntu_simcard@30.pngrenamed

Binary file not shown.

wizard/qml/Pages/here-terms.qml → qml/Wizard/Pages/here-terms.qmlrenamed+4−4
@@ -15,11 +15,11 @@
1515 */
1616
1717import QtQuick 2.3
18+import AccountsService 0.1
1819import Qt.labs.folderlistmodel 2.1
1920import Ubuntu.Components 1.1
20−import Ubuntu.SystemSettings.Wizard.Utils 0.1
2121import Ubuntu.Web 0.2
22−import "../Components" as LocalComponents
22+import ".." as LocalComponents
2323
2424LocalComponents.Page {
2525 title: i18n.tr("Terms & Conditions")
@@ -27,7 +27,7 @@ LocalComponents.Page {
2727
2828 FolderListModel {
2929 id: termsModel
30− folder: System.hereLicensePath
30+ folder: AccountsService.hereLicensePath
3131 nameFilters: ["*.html"]
3232 showDirs: false
3333 showOnlyReadable: true
@@ -73,7 +73,7 @@ LocalComponents.Page {
7373
7474 function loadFileContent() {
7575 var xhr = new XMLHttpRequest
76− xhr.open("GET", System.hereLicensePath + "/" + determineFileName())
76+ xhr.open("GET", AccountsService.hereLicensePath + "/" + determineFileName())
7777 xhr.onreadystatechange = function() {
7878 if (xhr.readyState == XMLHttpRequest.DONE) {
7979 termsLabel.text = xhr.responseText
wizard/qml/Pages/passwd-confirm.qml → qml/Wizard/Pages/passwd-confirm.qmlrenamed+2−2
@@ -17,8 +17,8 @@
1717import QtQuick 2.3
1818import Ubuntu.Components 1.1
1919import Ubuntu.SystemSettings.SecurityPrivacy 1.0
20−import "../Components" as LocalComponents
21−import "file:///usr/share/unity8/Components" as UnityComponents
20+import ".." as LocalComponents
21+import "../../Components" as UnityComponents
2222
2323/**
2424 * See the main passwd-type page for an explanation of why we don't actually
wizard/qml/Pages/passwd-set.qml → qml/Wizard/Pages/passwd-set.qmlrenamed+2−2
@@ -17,8 +17,8 @@
1717import QtQuick 2.3
1818import Ubuntu.Components 1.1
1919import Ubuntu.SystemSettings.SecurityPrivacy 1.0
20−import "../Components" as LocalComponents
21−import "file:///usr/share/unity8/Components" as UnityComponents
20+import ".." as LocalComponents
21+import "../../Components" as UnityComponents
2222
2323/**
2424 * See the main passwd-type page for an explanation of why we don't actually
wizard/qml/Components/StackButton.qml → qml/Wizard/StackButton.qmlrenamed

The content is the same.

qml/Wizard/Wizard.qmlnew file+55
@@ -0,0 +1,55 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.3
18+import Ubuntu.Components 1.1
19+import Wizard 0.1
20+import "../Components"
21+
22+Showable {
23+ id: root
24+
25+ // The background wallpaper to use
26+ property string background
27+
28+ readonly property alias active: loader.active
29+
30+ hideAnimation: StandardAnimation { property: "opacity"; to: 0 }
31+
32+ onRequiredChanged: {
33+ if (!required) {
34+ System.wizardEnabled = false;
35+ }
36+ }
37+
38+ Loader {
39+ id: loader
40+ anchors.fill: parent
41+ active: System.wizardEnabled
42+ source: "Pages.qml"
43+
44+ Binding {
45+ target: loader.item
46+ property: "background"
47+ value: root.background
48+ }
49+
50+ Connections {
51+ target: loader.item
52+ onQuit: root.hide()
53+ }
54+ }
55+}
tests/CMakeLists.txt−1
@@ -14,4 +14,3 @@ add_subdirectory(whitespace)
1414add_subdirectory(plugins)
1515add_subdirectory(utils)
1616add_subdirectory(uqmlscene)
17−add_subdirectory(wizard)
tests/mocks/AccountsService/AccountsService.cpp+31−1
@@ -27,7 +27,9 @@ AccountsService::AccountsService(QObject* parent)
2727 m_backgroundFile(qmlDirectory() + "graphics/phone_background.jpg"),
2828 m_statsWelcomeScreen(true),
2929 m_failedLogins(0),
30− m_demoEdges(false)
30+ m_demoEdges(false),
31+ m_hereEnabled(false),
32+ m_hereLicensePath("")
3133{
3234}
3335
@@ -116,3 +118,31 @@ void AccountsService::setFailedLogins(uint failedLogins)
116118 m_failedLogins = failedLogins;
117119 failedLoginsChanged();
118120}
121+
122+bool AccountsService::hereEnabled() const
123+{
124+ return m_hereEnabled;
125+}
126+
127+void AccountsService::setHereEnabled(bool enabled)
128+{
129+ m_hereEnabled = enabled;
130+ hereEnabledChanged();
131+}
132+
133+QString AccountsService::hereLicensePath() const
134+{
135+ return m_hereLicensePath;
136+}
137+
138+void AccountsService::setHereLicensePath(const QString &path)
139+{
140+ // Path should always be valid (this code is all synchronous)
141+ m_hereLicensePath = path.isNull() ? "" : path;
142+ hereLicensePathChanged();
143+}
144+
145+bool AccountsService::hereLicensePathValid() const
146+{
147+ return !m_hereLicensePath.isNull();
148+}
tests/mocks/AccountsService/AccountsService.h+20
@@ -59,6 +59,17 @@ class AccountsService: public QObject
5959 READ failedLogins
6060 WRITE setFailedLogins
6161 NOTIFY failedLoginsChanged)
62+ Q_PROPERTY(bool hereEnabled
63+ READ hereEnabled
64+ WRITE setHereEnabled
65+ NOTIFY hereEnabledChanged)
66+ Q_PROPERTY(QString hereLicensePath
67+ READ hereLicensePath
68+ WRITE setHereLicensePath // only available in mock
69+ NOTIFY hereLicensePathChanged)
70+ Q_PROPERTY(bool hereLicensePathValid // qml sees a null string as "", so we use proxy setting for that
71+ READ hereLicensePathValid
72+ NOTIFY hereLicensePathChanged)
6273
6374public:
6475 enum PasswordDisplayHint {
@@ -83,6 +94,11 @@ public:
8394 PasswordDisplayHint passwordDisplayHint() const;
8495 uint failedLogins() const;
8596 void setFailedLogins(uint failedLogins);
97+ bool hereEnabled() const;
98+ void setHereEnabled(bool enabled);
99+ QString hereLicensePath() const;
100+ void setHereLicensePath(const QString &path);
101+ bool hereLicensePathValid() const;
86102
87103Q_SIGNALS:
88104 void userChanged();
@@ -93,6 +109,8 @@ Q_SIGNALS:
93109 void statsWelcomeScreenChanged();
94110 void passwordDisplayHintChanged();
95111 void failedLoginsChanged();
112+ void hereEnabledChanged();
113+ void hereLicensePathChanged();
96114
97115private:
98116 bool m_enableLauncherWhileLocked;
@@ -102,6 +120,8 @@ private:
102120 bool m_statsWelcomeScreen;
103121 uint m_failedLogins;
104122 bool m_demoEdges;
123+ bool m_hereEnabled;
124+ QString m_hereLicensePath;
105125};
106126
107127#endif
tests/mocks/CMakeLists.txt+1
@@ -37,6 +37,7 @@ add_subdirectory(QMenuModel)
3737add_subdirectory(Ubuntu)
3838add_subdirectory(Unity)
3939add_subdirectory(QtMultimedia)
40+add_subdirectory(Wizard)
4041
4142install(
4243 DIRECTORY data
tests/mocks/QMenuModel/CMakeLists.txt+1
@@ -5,6 +5,7 @@ include_directories(
55
66set(QMenuModelQml_SOURCES
77 actionstateparser.cpp
8+ dbus-enums.h
89 plugin.cpp
910 unitymenumodel.cpp
1011)
tests/mocks/QMenuModel/dbus-enums.hnew file+52
@@ -0,0 +1,52 @@
1+/*
2+ * Copyright 2012 Canonical Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU Lesser General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU Lesser General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors:
17+ * Olivier Tilloy <olivier.tilloy@canonical.com>
18+ */
19+
20+#ifndef __DBUS_ENUMS__
21+#define __DBUS_ENUMS__
22+
23+#include <QObject>
24+
25+// This class acts as a namespace only, with the addition that its enums
26+// are registered to be exposed on the QML side.
27+class DBusEnums : public QObject
28+{
29+ Q_OBJECT
30+
31+ Q_ENUMS(BusType)
32+ Q_ENUMS(ConnectionStatus)
33+
34+public:
35+ enum BusType {
36+ None = 0,
37+ SessionBus,
38+ SystemBus,
39+ LastBusType
40+ };
41+
42+ enum ConnectionStatus {
43+ Disconnected = 0,
44+ Connecting,
45+ Connected
46+ };
47+
48+private:
49+ DBusEnums() {}
50+};
51+
52+#endif // __DBUS_ENUMS__
tests/mocks/QMenuModel/plugin.cpp+3
@@ -19,12 +19,15 @@
1919#include "plugin.h"
2020#include "unitymenumodel.h"
2121#include "actionstateparser.h"
22+#include "dbus-enums.h"
2223
2324#include <QtQml/qqml.h>
2425
2526void QMenuModelPlugin::registerTypes(const char *uri)
2627{
2728 Q_ASSERT(uri == QLatin1String("QMenuModel"));
29+ qmlRegisterUncreatableType<DBusEnums>(uri, 0, 1, "DBus",
30+ "DBus is only a namespace");
2831 qmlRegisterType<UnityMenuModel>(uri, 0, 1, "UnityMenuModel");
2932 qmlRegisterType<ActionStateParser>(uri, 0, 1, "ActionStateParser");
3033}
tests/mocks/Wizard/CMakeLists.txtnew file+12
@@ -0,0 +1,12 @@
1+include_directories(
2+ ${CMAKE_SOURCE_DIR}/plugins/Wizard
3+)
4+
5+add_library(MockWizard-qml MODULE
6+ mockplugin.cpp
7+ MockSystem.cpp
8+ ${CMAKE_SOURCE_DIR}/plugins/Wizard/PageList.cpp
9+)
10+
11+qt5_use_modules(MockWizard-qml Qml)
12+add_unity8_mock(Wizard 0.1 Wizard TARGETS MockWizard-qml)
tests/mocks/Wizard/MockSystem.cppnew file+38
@@ -0,0 +1,38 @@
1+/*
2+ * Copyright (C) 2014 Canonical Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it
5+ * under the terms of the GNU General Public License version 3, as published
6+ * by the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful, but
9+ * WITHOUT ANY WARRANTY; without even the implied warranties of
10+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11+ * PURPOSE. See the GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License along
14+ * with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include "MockSystem.h"
18+
19+MockSystem::MockSystem()
20+ : QObject(),
21+ m_wizardEnabled(false)
22+{
23+}
24+
25+bool MockSystem::wizardEnabled() const
26+{
27+ return m_wizardEnabled;
28+}
29+
30+void MockSystem::setWizardEnabled(bool enabled)
31+{
32+ m_wizardEnabled = enabled;
33+ Q_EMIT wizardEnabledChanged();
34+}
35+
36+void MockSystem::updateSessionLanguage(const QString &)
37+{
38+}
tests/mocks/Wizard/MockSystem.hnew file+46
@@ -0,0 +1,46 @@
1+/*
2+ * Copyright (C) 2014 Canonical Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it
5+ * under the terms of the GNU General Public License version 3, as published
6+ * by the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful, but
9+ * WITHOUT ANY WARRANTY; without even the implied warranties of
10+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11+ * PURPOSE. See the GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License along
14+ * with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#ifndef WIZARD_MOCK_SYSTEM_H
18+#define WIZARD_MOCK_SYSTEM_H
19+
20+#include <QObject>
21+#include <QString>
22+
23+class MockSystem : public QObject
24+{
25+ Q_OBJECT
26+ Q_PROPERTY(bool wizardEnabled READ wizardEnabled WRITE setWizardEnabled NOTIFY wizardEnabledChanged)
27+
28+public:
29+ MockSystem();
30+
31+ bool wizardEnabled() const;
32+ void setWizardEnabled(bool enabled);
33+
34+public Q_SLOTS:
35+ void updateSessionLanguage(const QString &locale);
36+
37+Q_SIGNALS:
38+ void wizardEnabledChanged();
39+
40+private:
41+ Q_DISABLE_COPY(MockSystem)
42+
43+ bool m_wizardEnabled;
44+};
45+
46+#endif
tests/mocks/Wizard/Wizard.qmltypesnew file+36
@@ -0,0 +1,36 @@
1+import QtQuick.tooling 1.1
2+
3+// This file describes the plugin-supplied types contained in the library.
4+// It is used for QML tooling purposes only.
5+//
6+// This file was auto-generated by:
7+// 'qmlplugindump -notrelocatable Wizard 0.1 tests/mocks'
8+
9+Module {
10+ Component {
11+ name: "MockSystem"
12+ prototype: "QObject"
13+ exports: ["Wizard/System 0.1"]
14+ isCreatable: false
15+ isSingleton: true
16+ exportMetaObjectRevisions: [0]
17+ Property { name: "wizardEnabled"; type: "bool" }
18+ Method {
19+ name: "updateSessionLanguage"
20+ Parameter { name: "locale"; type: "string" }
21+ }
22+ }
23+ Component {
24+ name: "PageList"
25+ prototype: "QObject"
26+ exports: ["Wizard/PageList 0.1"]
27+ isCreatable: false
28+ isSingleton: true
29+ exportMetaObjectRevisions: [0]
30+ Property { name: "index"; type: "int"; isReadonly: true }
31+ Property { name: "numPages"; type: "int"; isReadonly: true }
32+ Method { name: "prev"; type: "string" }
33+ Method { name: "next"; type: "string" }
34+ }
35+}
36+
tests/mocks/Wizard/mockplugin.cppnew file+42
@@ -0,0 +1,42 @@
1+/*
2+ * Copyright (C) 2012,2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include "mockplugin.h"
18+#include "MockSystem.h"
19+#include "PageList.h"
20+
21+#include <QtQml/qqml.h>
22+
23+static QObject *pagelist_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
24+{
25+ Q_UNUSED(engine)
26+ Q_UNUSED(scriptEngine)
27+ return new PageList();
28+}
29+
30+static QObject *system_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
31+{
32+ Q_UNUSED(engine)
33+ Q_UNUSED(scriptEngine)
34+ return new MockSystem();
35+}
36+
37+void MockWizardPlugin::registerTypes(const char *uri)
38+{
39+ Q_ASSERT(uri == QLatin1String("Wizard"));
40+ qmlRegisterSingletonType<PageList>(uri, 0, 1, "PageList", pagelist_provider);
41+ qmlRegisterSingletonType<MockSystem>(uri, 0, 1, "System", system_provider);
42+}
tests/mocks/Wizard/mockplugin.hnew file+32
@@ -0,0 +1,32 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#ifndef MOCK_WIZARD_PLUGIN_H
18+#define MOCK_WIZARD_PLUGIN_H
19+
20+#include <QtQml/QQmlEngine>
21+#include <QtQml/QQmlExtensionPlugin>
22+
23+class MockWizardPlugin : public QQmlExtensionPlugin
24+{
25+ Q_OBJECT
26+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
27+
28+public:
29+ void registerTypes(const char *uri);
30+};
31+
32+#endif
tests/mocks/Wizard/qmldirnew file+3
@@ -0,0 +1,3 @@
1+module Wizard
2+plugin MockWizard-qml
3+typeinfo Wizard.qmltypes
tests/plugins/CMakeLists.txt+1
@@ -4,3 +4,4 @@ add_subdirectory(Dash)
44add_subdirectory(Ubuntu)
55add_subdirectory(Unity)
66add_subdirectory(Utils)
7+add_subdirectory(Wizard)
tests/plugins/Wizard/CMakeLists.txtnew file+12
@@ -0,0 +1,12 @@
1+include_directories(
2+ ${CMAKE_CURRENT_BINARY_DIR}
3+ ${CMAKE_SOURCE_DIR}/plugins/Wizard
4+)
5+
6+add_executable(tst-pagelist
7+ tst_pagelist.cpp
8+ ${CMAKE_SOURCE_DIR}/plugins/Wizard/PageList.cpp
9+)
10+qt5_use_modules(tst-pagelist Core Qml Test)
11+
12+add_test(NAME pagelisttest COMMAND env UNITY_TEST_ENV=1 ${CMAKE_CURRENT_BINARY_DIR}/tst-pagelist)
tests/wizard/tst_pagelist.cpp → tests/plugins/Wizard/tst_pagelist.cpprenamed+1−3
@@ -1,6 +1,4 @@
11/*
2− * This file is part of system-settings
3− *
42 * Copyright (C) 2014 Canonical Ltd.
53 *
64 * This program is free software: you can redistribute it and/or modify it
@@ -23,7 +21,7 @@
2321#include <QTemporaryDir>
2422#include <QTest>
2523
26−#define PAGES_PATH "ubuntu/settings/wizard/qml/Pages"
24+#define PAGES_PATH "Wizard/Pages"
2725
2826class PageListTest: public QObject
2927{
tests/wizard/CMakeLists.txtdeleted−5
@@ -1,5 +0,0 @@
1−add_executable(tst-pagelist tst_pagelist.cpp ${CMAKE_SOURCE_DIR}/wizard/PageList.cpp)
2−set_target_properties(tst-pagelist PROPERTIES
3− INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR};${CMAKE_SOURCE_DIR}/wizard")
4−qt5_use_modules(tst-pagelist Core Test)
5−add_test(tst-pagelist tst-pagelist)
wizard/CMakeLists.txtdeleted−65
@@ -1,65 +0,0 @@
1−# This file uses a lot of namespacing like "ubuntu-system-settings" instead of
2−# "unity8". This is because we have imported it from ubuntu-system-settings
3−# and haven't fully integrated it yet.
4−
5−include_directories(
6− ${CMAKE_CURRENT_BINARY_DIR}
7− ${Qt5Gui_PRIVATE_INCLUDE_DIRS}
8−)
9−
10−set(PLUGIN_MANIFEST_DIR_BASE share/ubuntu/settings/system)
11−set(PLUGIN_MODULE_DIR_BASE ubuntu-system-settings)
12−set(PLUGIN_PRIVATE_MODULE_DIR_BASE "${PLUGIN_MODULE_DIR_BASE}/private")
13−set(PLUGIN_QML_DIR_BASE share/ubuntu/settings/system/qml-plugins)
14−
15−set(PLUGIN_MANIFEST_DIR "${CMAKE_INSTALL_PREFIX}/${PLUGIN_MANIFEST_DIR_BASE}")
16−set(PLUGIN_MODULE_DIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/${PLUGIN_MODULE_DIR_BASE}")
17−set(PLUGIN_PRIVATE_MODULE_DIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/${PLUGIN_PRIVATE_MODULE_DIR_BASE}")
18−set(PLUGIN_QML_DIR "${CMAKE_INSTALL_PREFIX}/${PLUGIN_QML_DIR_BASE}")
19−
20−add_definitions(-DI18N_DOMAIN="unity8")
21−add_definitions(-DPLUGIN_MANIFEST_DIR="${PLUGIN_MANIFEST_DIR}")
22−add_definitions(-DPLUGIN_MODULE_DIR="${PLUGIN_MODULE_DIR}")
23−add_definitions(-DPLUGIN_PRIVATE_MODULE_DIR="${PLUGIN_PRIVATE_MODULE_DIR}")
24−add_definitions(-DPLUGIN_QML_DIR="${PLUGIN_QML_DIR}")
25−
26−execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE} --variable=plugindir unity-shell-api OUTPUT_VARIABLE SHELL_PLUGINDIR OUTPUT_STRIP_TRAILING_WHITESPACE)
27−if(SHELL_PLUGINDIR STREQUAL "")
28− message(FATAL_ERROR "Could not determine plugin import dir.")
29−endif()
30−
31−add_definitions(-DSHELL_PLUGINDIR="${SHELL_PLUGINDIR}")
32−
33−set(WIZARD_ROOT "${CMAKE_INSTALL_PREFIX}/share")
34−add_definitions(-DWIZARD_ROOT="${WIZARD_ROOT}")
35−
36−file(GLOB_RECURSE QML_FILES
37− qml/*
38−)
39−
40−set(WIZARD_SOURCES
41− main.cpp
42− PageList.cpp
43−)
44−
45−add_executable(system-settings-wizard
46− ${WIZARD_SOURCES}
47− ${system-settings-wizard-resources}
48− ${QML_FILES} # This is to make qml and image files appear in the IDE's project tree
49−)
50−
51−qt5_use_modules(system-settings-wizard Core Gui Quick Qml)
52−
53−add_subdirectory(Unity)
54−add_subdirectory(Utils)
55−
56−install(TARGETS system-settings-wizard RUNTIME DESTINATION bin)
57−install(FILES ubuntu-system-settings-wizard.conf
58− ubuntu-system-settings-wizard-cleanup.conf
59− ubuntu-system-settings-wizard-set-lang.conf
60− DESTINATION share/upstart/sessions)
61−
62−set(POLKIT_LIB_DIR "${CMAKE_INSTALL_LOCALSTATEDIR}/lib/polkit-1")
63−install(FILES 50-com.ubuntu.system-settings.wizard.pkla DESTINATION ${POLKIT_LIB_DIR}/localauthority/10-vendor.d)
64−
65−install(DIRECTORY qml DESTINATION ${WIZARD_ROOT}/ubuntu/settings/wizard)
wizard/Utils/system.cppdeleted−118
@@ -1,118 +0,0 @@
1−/*
2− * This file is part of system-settings
3− *
4− * Copyright (C) 2014 Canonical Ltd.
5− *
6− * This program is free software: you can redistribute it and/or modify it
7− * under the terms of the GNU General Public License version 3, as published
8− * by the Free Software Foundation.
9− *
10− * This program is distributed in the hope that it will be useful, but
11− * WITHOUT ANY WARRANTY; without even the implied warranties of
12− * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
13− * PURPOSE. See the GNU General Public License for more details.
14− *
15− * You should have received a copy of the GNU General Public License along
16− * with this program. If not, see <http://www.gnu.org/licenses/>.
17− */
18−
19−#include "system.h"
20−#include <QDBusInterface>
21−#include <QDBusPendingCall>
22−#include <QDBusPendingReply>
23−#include <QFile>
24−#include <QProcess>
25−#include <unistd.h>
26−
27−#define HERE_IFACE "com.ubuntu.location.providers.here.AccountsService"
28−#define ENABLED_PROP "LicenseAccepted"
29−#define PATH_PROP "LicenseBasePath"
30−
31−System::System()
32− : QObject(),
33− m_accounts(nullptr),
34− m_hereEnabled(false),
35− m_hereLicensePath(" ") // use a single space to indicate it is unasssigned
36−{
37− m_accounts = new QDBusInterface("org.freedesktop.Accounts",
38− "/org/freedesktop/Accounts/User" + QString::number(geteuid()),
39− "org.freedesktop.DBus.Properties",
40− QDBusConnection::systemBus(),
41− this);
42−
43− m_accounts->connection().connect(m_accounts->service(),
44− m_accounts->path(),
45− m_accounts->interface(),
46− "PropertiesChanged",
47− this,
48− SLOT(propertiesChanged(QString, QVariantMap, QStringList)));
49−
50− QDBusPendingCall call = m_accounts->asyncCall("Get", HERE_IFACE, PATH_PROP);
51− QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this);
52− QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher *)),
53− this, SLOT(getHereLicensePathFinished(QDBusPendingCallWatcher *)));
54−}
55−
56−void System::propertiesChanged(const QString &interface, const QVariantMap &changed, const QStringList &invalid)
57−{
58− if (interface == HERE_IFACE) {
59− if (changed.contains(ENABLED_PROP)) {
60− m_hereEnabled = changed[ENABLED_PROP].toBool();
61− Q_EMIT hereEnabledChanged();
62− } else if (invalid.contains(ENABLED_PROP)) {
63− QDBusPendingCall call = m_accounts->asyncCall("Get", HERE_IFACE, ENABLED_PROP);
64− QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this);
65− QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher *)),
66− this, SLOT(getHereEnabledFinished(QDBusPendingCallWatcher *)));
67− }
68− }
69−}
70−
71−void System::getHereEnabledFinished(QDBusPendingCallWatcher *watcher)
72−{
73− QDBusPendingReply<QVariant> reply = *watcher;
74− if (!reply.isError()) {
75− QVariant value = reply.argumentAt<0>();
76− m_hereEnabled = value.toBool();
77− Q_EMIT hereEnabledChanged();
78− }
79− watcher->deleteLater();
80−}
81−
82−void System::getHereLicensePathFinished(QDBusPendingCallWatcher *watcher)
83−{
84− QDBusPendingReply<QVariant> reply = *watcher;
85−
86− m_hereLicensePath = "";
87−
88− if (!reply.isError()) {
89− QVariant value = reply.argumentAt<0>();
90− if (QFile::exists(value.toString())) {
91− m_hereLicensePath = value.toString();
92− }
93− }
94−
95− Q_EMIT hereLicensePathChanged();
96−
97− watcher->deleteLater();
98−}
99−
100−bool System::hereEnabled() const
101−{
102− return m_hereEnabled;
103−}
104−
105−void System::setHereEnabled(bool enabled)
106−{
107− m_accounts->asyncCall("Set", HERE_IFACE, ENABLED_PROP, QVariant::fromValue(QDBusVariant(enabled)));
108−}
109−
110−QString System::hereLicensePath() const
111−{
112− return m_hereLicensePath;
113−}
114−
115−void System::updateSessionLanguage()
116−{
117− 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\"");
118−}
wizard/Utils/system.hdeleted−57
@@ -1,57 +0,0 @@
1−/*
2− * This file is part of system-settings
3− *
4− * Copyright (C) 2014 Canonical Ltd.
5− *
6− * This program is free software: you can redistribute it and/or modify it
7− * under the terms of the GNU General Public License version 3, as published
8− * by the Free Software Foundation.
9− *
10− * This program is distributed in the hope that it will be useful, but
11− * WITHOUT ANY WARRANTY; without even the implied warranties of
12− * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
13− * PURPOSE. See the GNU General Public License for more details.
14− *
15− * You should have received a copy of the GNU General Public License along
16− * with this program. If not, see <http://www.gnu.org/licenses/>.
17− */
18−
19−#include <QObject>
20−#include <QString>
21−
22−class QDBusInterface;
23−class QDBusPendingCallWatcher;
24−
25−class System : public QObject
26−{
27− Q_OBJECT
28− Q_PROPERTY(bool hereEnabled READ hereEnabled WRITE setHereEnabled NOTIFY hereEnabledChanged)
29− Q_PROPERTY(QString hereLicensePath READ hereLicensePath NOTIFY hereLicensePathChanged)
30−
31−public:
32− System();
33−
34− bool hereEnabled() const;
35− void setHereEnabled(bool enabled);
36−
37− QString hereLicensePath() const;
38−
39−public Q_SLOTS:
40− void updateSessionLanguage();
41−
42−Q_SIGNALS:
43− void hereEnabledChanged();
44− void hereLicensePathChanged();
45−
46−private Q_SLOTS:
47− void propertiesChanged(const QString &interface, const QVariantMap &changed, const QStringList &invalid);
48− void getHereEnabledFinished(QDBusPendingCallWatcher *watcher);
49− void getHereLicensePathFinished(QDBusPendingCallWatcher *watcher);
50−
51−private:
52− Q_DISABLE_COPY(System)
53−
54− QDBusInterface *m_accounts;
55− bool m_hereEnabled;
56− QString m_hereLicensePath;
57−};
wizard/qml/main.qmldeleted−246
@@ -1,246 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.3
18−import GSettings 1.0
19−import Ubuntu.Components 1.1
20−import Ubuntu.SystemSettings.SecurityPrivacy 1.0
21−import Unity.Application 0.1
22−import Unity.Notifications 1.0 as NotificationBackend
23−import Unity.Session 0.1
24−import "Components"
25−import "file:///usr/share/unity8/Notifications" as Notifications // FIXME This should become a module or go away
26−import "file:///usr/share/unity8/Components" as UnityComponents
27−
28−Item {
29− id: root
30− width: units.gu(40)
31− height: units.gu(71)
32− focus: true
33−
34− // These should be set by a security page and we apply the settings when
35− // the user exits the wizard.
36− property int passwordMethod: UbuntuSecurityPrivacyPanel.Passcode
37− property string password: ""
38−
39− Component.onCompleted: {
40− Theme.name = "Ubuntu.Components.Themes.SuruGradient"
41− // A visible selected background looks bad in ListItem widgets with our theme
42− Theme.palette.selected.background = "#00000000"
43− i18n.domain = "unity8"
44− }
45−
46− UbuntuSecurityPrivacyPanel {
47− id: securityPrivacy
48− }
49−
50− function quitWizard() {
51− // Immediately go to black to give quick feedback
52− blackCover.visible = true
53−
54− var errorMsg = securityPrivacy.setSecurity("", password, passwordMethod)
55− if (errorMsg !== "") {
56− // Ignore (but log) any errors, since we're past where the user set
57− // the method. Worst case, we just leave the user with a swipe
58− // security method and they fix it in the system settings.
59− console.log("Error setting security method:", errorMsg)
60− }
61−
62− Qt.quit()
63− }
64−
65− // This is just a little screen to immediately go to black once the wizard
66− // is done, to give quick feedback to the user.
67− Rectangle {
68− id: blackCover
69− color: "#000000"
70− anchors.fill: parent
71− z: 1
72− visible: false
73− }
74−
75− MainView {
76− anchors.fill: parent
77− headerColor: "#57365E"
78− backgroundColor: "#A55263"
79− footerColor: "#D75669"
80− anchorToKeyboard: true
81− useDeprecatedToolbar: false
82−
83− GSettings {
84− id: background
85− schema.id: "org.gnome.desktop.background"
86− }
87−
88− Image {
89− id: image
90− // Use x/y/height/width instead of anchors so that we don't adjust
91− // the image when the OSK appears.
92− x: 0
93− y: 0
94− height: root.height
95− width: root.width
96− source: background.pictureUri
97− fillMode: Image.PreserveAspectCrop
98− visible: status === Image.Ready
99− }
100−
101− PageStack {
102− id: pageStack
103−
104− function next() {
105− // If we've opened any extra (non-main) pages, pop them before
106− // continuing so back button returns to the previous main page.
107− while (pageList.index < pageStack.depth - 1)
108− pop()
109− load(pageList.next())
110− }
111−
112− function prev() {
113− if (pageList.index >= pageStack.depth - 1)
114− pageList.prev() // update pageList.index, but not for extra pages
115− pop()
116− if (!currentPage || currentPage.opacity === 0) { // undo skipped pages
117− prev()
118− } else {
119− currentPage.enabled = true
120− }
121− }
122−
123− function load(path) {
124− if (currentPage) {
125− currentPage.enabled = false
126− }
127−
128− // First load it invisible, check that we should actually use
129− // this page, and either skip it or continue.
130− push(path, {"opacity": 0, "enabled": false})
131−
132− // Check for immediate skip or not. We may have to wait for
133− // skipValid to be assigned (see Connections object below)
134− _checkSkip()
135− }
136−
137− function _checkSkip() {
138− if (!currentPage) { // may have had a parse error
139− next()
140− } else if (currentPage.skipValid) {
141− if (currentPage.skip) {
142− next()
143− } else {
144− currentPage.opacity = 1
145− currentPage.enabled = true
146− }
147− }
148− }
149−
150− Connections {
151− target: pageStack.currentPage
152− onSkipValidChanged: pageStack._checkSkip()
153− }
154−
155− Component.onCompleted: next()
156− }
157− }
158−
159− Rectangle {
160− id: modalNotificationBackground
161− visible: notifications.useModal && (notifications.state == "narrow")
162− anchors.fill: parent
163− color: "#80000000"
164−
165− MouseArea {
166− anchors.fill: parent
167− }
168− }
169−
170− InputMethod {
171− anchors.fill: parent
172− }
173−
174− Notifications.Notifications {
175− id: notifications
176− model: NotificationBackend.Model
177− margin: units.gu(1)
178− anchors {
179− top: parent.top
180− right: parent.right
181− bottom: parent.bottom
182− }
183− states: [
184− State {
185− name: "narrow"
186− when: parent.width <= units.gu(60)
187− AnchorChanges { target: notifications; anchors.left: parent.left }
188− },
189− State {
190− name: "wide"
191− when: parent.width > units.gu(60)
192− AnchorChanges { target: notifications; anchors.left: undefined }
193− PropertyChanges { target: notifications; width: units.gu(38) }
194− }
195− ]
196− }
197−
198− UnityComponents.Dialogs {
199− id: dialogs
200− anchors.fill: parent
201− z: 10
202− onPowerOffClicked: {
203− shutdownFadeOutRectangle.enabled = true;
204− shutdownFadeOutRectangle.visible = true;
205− shutdownFadeOut.start();
206− }
207− }
208−
209− Rectangle {
210− id: shutdownFadeOutRectangle
211− z: dialogs.z + 10
212− enabled: false
213− visible: false
214− color: "black"
215− anchors.fill: parent
216− opacity: 0.0
217− NumberAnimation on opacity {
218− id: shutdownFadeOut
219− from: 0.0
220− to: 1.0
221− onStopped: {
222− if (shutdownFadeOutRectangle.enabled && shutdownFadeOutRectangle.visible) {
223− DBusUnitySessionService.Shutdown();
224− }
225− }
226− }
227− }
228−
229− Keys.onPressed: {
230− if (event.key == Qt.Key_PowerOff || event.key == Qt.Key_PowerDown) {
231− dialogs.onPowerKeyPressed();
232− event.accepted = true;
233− } else {
234− event.accepted = false;
235− }
236− }
237−
238− Keys.onReleased: {
239− if (event.key == Qt.Key_PowerOff || event.key == Qt.Key_PowerDown) {
240− dialogs.onPowerKeyReleased();
241− event.accepted = true;
242− } else {
243− event.accepted = false;
244− }
245− }
246−}