on xenial help sign in
merged with trunk
3ecd374Nick Dedekind
data/CMakeLists.txt+3
@@ -8,3 +8,6 @@ install(FILES
8 ${CMAKE_CURRENT_BINARY_DIR}/${DASH_APP}.desktop
8 ${CMAKE_CURRENT_BINARY_DIR}/${DASH_APP}.desktop
9 DESTINATION ${CMAKE_INSTALL_DATADIR}/applications
9 DESTINATION ${CMAKE_INSTALL_DATADIR}/applications
10 )
10 )
11+
12+# install url dispatcher files
13+install(FILES unity8-dash.url-dispatcher DESTINATION ${CMAKE_INSTALL_DATADIR}/url-dispatcher/urls)
data/unity8-dash.conf+2
@@ -10,6 +10,8 @@ kill timeout 120
10
10
11respawn
11respawn
12
12
13+env APP_ID=unity8-dash
14+
13pre-start script
15pre-start script
14 if [ -z "$UNITY_SCOPES_LIST" ]; then
16 if [ -z "$UNITY_SCOPES_LIST" ]; then
15 # FIXME: remove once we have this in dconf
17 # FIXME: remove once we have this in dconf
data/unity8-dash.url-dispatchernew file+6
@@ -0,0 +1,6 @@
1+[
2+ {
3+ "protocol": "scope"
4+ }
5+]
6+
debian/changelog+43
@@ -1,3 +1,46 @@
1+unity8 (8.00+14.10.20140827.2-0ubuntu1) utopic; urgency=low
2+
3+ [ Michał Sawicz ]
4+ * Implement scope header customization options
5+ * Don't ignore empty attributes in CardAttributes.qml and improve its
6+ encapsulation (LP: #1355901)
7+ * Add support for preview button color customization. Deprecate
8+ support for action icons.
9+ * Add table preview widget
10+ * Make "See Less" get stuck at the bottom of the view
11+ * Support alternative navigation in the dash.
12+ * Add scope settings UI
13+ * Add scope favoriting support
14+ * Passcode, not PIN (LP: #1361114)
15+
16+ [ Jussi Pakkanen ]
17+ * Use nullptr instead of NULL.
18+
19+ [ Albert Astals ]
20+ * Add table preview widget
21+ * Make "See Less" get stuck at the bottom of the view
22+ * Support alternative navigation in the dash.
23+ * Make the PageHeaderLabelTest pass under valgrind
24+
25+ [ Benjamin Zeller ]
26+ * Add support for scope:// url in the dash (LP: #1361349)
27+
28+ [ Marcus Tomlinson ]
29+ * Handle the openScope signal in "tempScopeItem" (ScopesOverview.qml)
30+ as is done with "scopeItem" (Dash.qml) (LP: #1356410)
31+
32+ [ Daniel d'Andrada ]
33+ * Make "See Less" get stuck at the bottom of the view
34+
35+ [ Andrea Cimitan ]
36+ * Fix right padding on overlay card
37+ * Add scope settings UI
38+
39+ [ Michael Zanetti ]
40+ * use a smaller asset for the app's dropshadow (LP: #1359157)
41+
42+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Wed, 27 Aug 2014 15:37:05 +0000
43+
1unity8 (8.00+14.10.20140825.3-0ubuntu1) utopic; urgency=low
44unity8 (8.00+14.10.20140825.3-0ubuntu1) utopic; urgency=low
2
45
3 [ Daniel d'Andrada ]
46 [ Daniel d'Andrada ]
debian/unity8.install+1
@@ -10,3 +10,4 @@ usr/share/unity8/Launcher
10usr/share/unity8/Panel
10usr/share/unity8/Panel
11usr/share/unity8/Shell.qml
11usr/share/unity8/Shell.qml
12usr/share/unity8/Stages
12usr/share/unity8/Stages
13+usr/share/url-dispatcher/urls/unity8-dash.url-dispatcher
include/paths.h.in+1−1
@@ -91,7 +91,7 @@ inline QString mockPluginsDir() {
91inline QStringList shellDataDirs() {
91inline QStringList shellDataDirs() {
92 QStringList dirs = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation);
92 QStringList dirs = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation);
93 if (!isRunningInstalled()) {
93 if (!isRunningInstalled()) {
94− if (getenv("UNITY_TEST_ENV")==NULL) {
94+ if (getenv("UNITY_TEST_ENV")==nullptr) {
95 dirs.prepend("@CMAKE_BINARY_DIR@/share");
95 dirs.prepend("@CMAKE_BINARY_DIR@/share");
96 }
96 }
97 }
97 }
plugins/AccountsService/AccountsServiceDBusAdaptor.cpp+1−1
@@ -24,7 +24,7 @@
24
24
25AccountsServiceDBusAdaptor::AccountsServiceDBusAdaptor(QObject* parent)
25AccountsServiceDBusAdaptor::AccountsServiceDBusAdaptor(QObject* parent)
26 : QObject(parent),
26 : QObject(parent),
27− m_accountsManager(NULL),
27+ m_accountsManager(nullptr),
28 m_users()
28 m_users()
29{
29{
30 QDBusConnection connection = QDBusConnection::SM_BUSNAME();
30 QDBusConnection connection = QDBusConnection::SM_BUSNAME();
plugins/Dash/CardAttributes.qml+7−3
@@ -26,8 +26,10 @@ GridLayout {
26 right: parent.right;
26 right: parent.right;
27 }
27 }
28 columns: 2 + repeater.count % 2
28 columns: 2 + repeater.count % 2
29+ rowSpacing: units.gu(.5)
29 property alias model: repeater.model
30 property alias model: repeater.model
30− property var color
31+ property color color: Theme.palette.normal.baseText
32+ property real fontScale: 1.0
31
33
32 Repeater {
34 Repeater {
33 id: repeater
35 id: repeater
@@ -42,17 +44,19 @@ GridLayout {
42 Layout.columnSpan: index == repeater.count - 1 && grid.columns == 3 && column == 1 ? 2 : 1
44 Layout.columnSpan: index == repeater.count - 1 && grid.columns == 3 && column == 1 ? 2 : 1
43 Layout.maximumWidth: Math.max(icon.width, label.x + label.implicitWidth)
45 Layout.maximumWidth: Math.max(icon.width, label.x + label.implicitWidth)
44 Layout.fillWidth: true
46 Layout.fillWidth: true
47+ height: units.gu(2)
45 StatusIcon {
48 StatusIcon {
46 id: icon
49 id: icon
47 height: units.gu(2)
50 height: units.gu(2)
48 sets: ["actions", "status", "apps"]
51 sets: ["actions", "status", "apps"]
49− source: "icon" in modelData ? modelData["icon"] : ""
52+ source: "icon" in modelData && modelData["icon"] || ""
53+ color: grid.color
50 }
54 }
51 Label {
55 Label {
52 id: label
56 id: label
53 width: parent.width - x
57 width: parent.width - x
54 anchors.verticalCenter: parent.verticalCenter
58 anchors.verticalCenter: parent.verticalCenter
55− text: "value" in modelData ? modelData["value"] : "";
59+ text: "value" in modelData && modelData["value"] || "";
56 elide: Text.ElideRight
60 elide: Text.ElideRight
57 maximumLineCount: 1
61 maximumLineCount: 1
58 font.weight: "style" in modelData && modelData["style"] == "highlighted" ? Font.DemiBold : Font.Light
62 font.weight: "style" in modelData && modelData["style"] == "highlighted" ? Font.DemiBold : Font.Light
plugins/Dash/CardCreator.js+9−5
@@ -29,7 +29,7 @@ var kBackgroundLoaderCode = 'Loader {\n\
29 gradientColor: getColor(1) || color; \n\
29 gradientColor: getColor(1) || color; \n\
30 anchors.fill: parent; \n\
30 anchors.fill: parent; \n\
31 image: backgroundImage.source ? backgroundImage : null; \n\
31 image: backgroundImage.source ? backgroundImage : null; \n\
32− property real luminance: 0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b; \n\
32+ property real luminance: Style.luminance(color); \n\
33 property Image backgroundImage: Image { \n\
33 property Image backgroundImage: Image { \n\
34 objectName: "backgroundImage"; \n\
34 objectName: "backgroundImage"; \n\
35 source: { \n\
35 source: { \n\
@@ -108,7 +108,7 @@ var kOverlayLoaderCode = 'Loader { \n\
108 sourceComponent: ShaderEffect { \n\
108 sourceComponent: ShaderEffect { \n\
109 id: overlay; \n\
109 id: overlay; \n\
110 height: (fixedHeaderHeight > 0 ? fixedHeaderHeight : headerHeight) + units.gu(2); \n\
110 height: (fixedHeaderHeight > 0 ? fixedHeaderHeight : headerHeight) + units.gu(2); \n\
111− property real luminance: 0.2126 * overlayColor.r + 0.7152 * overlayColor.g + 0.0722 * overlayColor.b; \n\
111+ property real luminance: Style.luminance(overlayColor); \n\
112 property color overlayColor: cardData && cardData["overlayColor"] || "#99000000"; \n\
112 property color overlayColor: cardData && cardData["overlayColor"] || "#99000000"; \n\
113 property var source: ShaderEffectSource { \n\
113 property var source: ShaderEffectSource { \n\
114 id: shaderSource; \n\
114 id: shaderSource; \n\
@@ -274,6 +274,7 @@ var kAttributesRowCode = 'CardAttributes { \n\
274 objectName: "attributesRow"; \n\
274 objectName: "attributesRow"; \n\
275 anchors { %1 } \n\
275 anchors { %1 } \n\
276 color: %2; \n\
276 color: %2; \n\
277+ fontScale: root.fontScale; \n\
277 model: cardData && cardData["attributes"]; \n\
278 model: cardData && cardData["attributes"]; \n\
278 }\n';
279 }\n';
279
280
@@ -439,14 +440,14 @@ function cardString(template, components) {
439 mascotCode = kMascotImageCode.arg(mascotAnchors).arg(mascotImageVisible);
440 mascotCode = kMascotImageCode.arg(mascotAnchors).arg(mascotImageVisible);
440 }
441 }
441
442
442− var summaryColorWithBackground = 'backgroundLoader.active && backgroundLoader.item && backgroundLoader.item.luminance < (root.scopeStyle ? root.scopeStyle.threshold : 0.7) ? (root.scopeStyle ? root.scopeStyle.light : "white") : (root.scopeStyle ? root.scopeStyle.dark : Theme.palette.normal.baseText)';
443+ var summaryColorWithBackground = 'backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item.luminance > 0.7 ? Theme.palette.normal.baseText : "white")';
443
444
444 var hasTitleContainer = hasTitle && (hasEmblem || (hasMascot && (hasSubtitle || hasAttributes)));
445 var hasTitleContainer = hasTitle && (hasEmblem || (hasMascot && (hasSubtitle || hasAttributes)));
445 var titleSubtitleCode = '';
446 var titleSubtitleCode = '';
446 if (hasTitle) {
447 if (hasTitle) {
447 var titleColor;
448 var titleColor;
448 if (headerAsOverlay) {
449 if (headerAsOverlay) {
449− titleColor = 'overlayLoader.item.luminance < (root.scopeStyle ? root.scopeStyle.threshold : 0.7) ? (root.scopeStyle ? root.scopeStyle.light : "white") : (root.scopeStyle ? root.scopeStyle.dark : Theme.palette.normal.baseText)';
450+ titleColor = 'root.scopeStyle ? root.scopeStyle.getTextColor(overlayLoader.item.luminance) : (overlayLoader.item.luminance > 0.7 ? Theme.palette.normal.baseText : "white")';
450 } else if (hasSummary) {
451 } else if (hasSummary) {
451 titleColor = 'summary.color';
452 titleColor = 'summary.color';
452 } else if (hasBackground) {
453 } else if (hasBackground) {
@@ -466,6 +467,8 @@ function cardString(template, components) {
466 if (!touchdownOnArtShape) {
467 if (!touchdownOnArtShape) {
467 extraRightAnchor = 'rightMargin: units.gu(1); \n';
468 extraRightAnchor = 'rightMargin: units.gu(1); \n';
468 extraLeftAnchor = 'leftMargin: units.gu(1); \n';
469 extraLeftAnchor = 'leftMargin: units.gu(1); \n';
470+ } else if (headerAsOverlay && !hasEmblem) {
471+ extraRightAnchor = 'rightMargin: units.gu(1); \n';
469 }
472 }
470
473
471 if (hasMascot) {
474 if (hasMascot) {
@@ -652,7 +655,8 @@ function cardString(template, components) {
652function createCardComponent(parent, template, components) {
655function createCardComponent(parent, template, components) {
653 var imports = 'import QtQuick 2.2; \n\
656 var imports = 'import QtQuick 2.2; \n\
654 import Ubuntu.Components 1.1; \n\
657 import Ubuntu.Components 1.1; \n\
655− import Dash 0.1;\n';
658+ import Dash 0.1;\n\
659+ import Utils 0.1;\n';
656 var card = cardString(template, components);
660 var card = cardString(template, components);
657 var code = imports + 'Component {\n' + card + '}\n';
661 var code = imports + 'Component {\n' + card + '}\n';
658
662
plugins/Dash/ScopeStyle.qml+38−40
@@ -15,6 +15,8 @@
15 */
15 */
16
16
17import QtQuick 2.2
17import QtQuick 2.2
18+import Utils 0.1
19+import Ubuntu.Components 1.1
18
20
19/*! \brief Helper for processing scope customization options.
21/*! \brief Helper for processing scope customization options.
20
22
@@ -27,69 +29,65 @@ QtObject {
27 /// Style object passed from the scope
29 /// Style object passed from the scope
28 property var style: Object()
30 property var style: Object()
29
31
30− /*! \brief Calculate luminance of the passed color
31−
32− \note If not fully opaque, luminance is dependant on blending.
33− */
34− function luminance(color) {
35− return 0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b;
36− }
37−
38 /// Color used for text and symbolic icons
32 /// Color used for text and symbolic icons
39 readonly property color foreground: "foreground-color" in style ? style["foreground-color"] : d.defaultDark
33 readonly property color foreground: "foreground-color" in style ? style["foreground-color"] : d.defaultDark
40
34
41 /// Luminance of the foreground color
35 /// Luminance of the foreground color
42− readonly property real foregroundLuminance: foreground ? luminance(foreground) : d.defaultForegroundLuminance
36+ readonly property real foregroundLuminance: foreground ? Style.luminance(foreground) : Style.luminance(d.defaultDark)
43
37
44 /// Color used for the overall background
38 /// Color used for the overall background
45− readonly property color background: "background-color" in style ? style["background-color"] : "transparent"
39+ readonly property color background: "background-color" in style ? style["background-color"] : "#00f5f5f5"
46−
47− /// Luminance of the foreground color
48− readonly property real backgroundLuminance: background ? luminance(background) : d.defaultBackgroundLuminance
49−
50− /*! \brief Luminance threshold for switching between fore and background color
51−
52− \note If background colour is not fully opaque, the defaultLightLuminance it's taken into account instead of it.
53− */
54− readonly property real threshold: background.a !== 1.0 ? (foregroundLuminance + d.defaultLightLuminance) / 2
55− : (foregroundLuminance + backgroundLuminance) / 2
56−
57− /*! \brief The lighter of foreground and background colors
58−
59− \note If background color is not fully opaque, it's not taken into account
60− and defaults to the theme-provided light color.
61− */
62− readonly property color light: {
63− if (background.a !== 1.0) return foregroundLuminance > d.defaultLightLuminance ? foreground : d.defaultLight;
64− return foregroundLuminance > backgroundLuminance ? foreground : background;
65− }
66
40
67− /*! \brief The darker of foreground and background colors
41+ /// Luminance of the background color
42+ readonly property real backgroundLuminance: background ? Style.luminance(background) : Style.luminance(d.defaultLight)
68
43
44+ /*! \brief Get the most contrasting available color based on luminance
45+ *
69− \note If background color is not fully opaque, it's not taken into account
46+ * If background color is transparent, theme provided colors are taken into account
70− and defaults to the theme-provided dark color.
71 */
47 */
72− readonly property color dark: {
48+ function getTextColor(luminance) {
73− if (background.a !== 1.0) return foregroundLuminance < d.defaultDarkLuminance ? foreground : d.defaultDark;
49+ if (Math.abs(foregroundLuminance - luminance) >
74− return foregroundLuminance < backgroundLuminance ? foreground : background;
50+ Math.abs(d.opaqueBackgroundLuminance - luminance)) {
51+ return foreground;
52+ } else {
53+ return d.opaqueBackground;
54+ }
75 }
55 }
76
56
77 /// Source of the logo image for the header
57 /// Source of the logo image for the header
78 readonly property url headerLogo: "logo" in d.headerStyle ? d.headerStyle["logo"] : ""
58 readonly property url headerLogo: "logo" in d.headerStyle ? d.headerStyle["logo"] : ""
79
59
80 /// Background style for the header
60 /// Background style for the header
81− readonly property url headerBackground: "background" in d.headerStyle ? d.headerStyle["background"] : ""
61+ readonly property url headerBackground: "background" in d.headerStyle ? d.headerStyle["background"] : "color:///#f5f5f5"
82
62
83 /// Foreground color for the header
63 /// Foreground color for the header
84 readonly property color headerForeground: "foreground-color" in d.headerStyle ? d.headerStyle["foreground-color"] : foreground
64 readonly property color headerForeground: "foreground-color" in d.headerStyle ? d.headerStyle["foreground-color"] : foreground
85
65
66+ /// Color of the header divider
67+ readonly property color headerDividerColor: "divider-color" in d.headerStyle ? d.headerStyle["divider-color"] : "#e0e0e0"
68+
69+ /// Background style for the navigation
70+ readonly property url navigationBackground: "navigation-background" in d.headerStyle ? d.headerStyle["navigation-background"] : "color:///#f5f5f5"
71+
72+ /// Color of the primary preview button
73+ readonly property color previewButtonColor: "preview-button-color" in style ? style["preview-button-color"] : Theme.palette.selected.foreground
74+
86 //! @cond
75 //! @cond
87 property var d: QtObject {
76 property var d: QtObject {
88 // FIXME: should be taken from the theme
77 // FIXME: should be taken from the theme
89 readonly property color defaultLight: "white"
78 readonly property color defaultLight: "white"
90− readonly property color defaultDark: Theme.palette.normal.baseText
79+ readonly property color defaultDark: UbuntuColors.darkGrey
91− readonly property real defaultLightLuminance: luminance(defaultLight)
80+ readonly property real defaultLightLuminance: Style.luminance(defaultLight)
92− readonly property real defaultDarkLuminance: luminance(defaultDark)
81+ readonly property real defaultDarkLuminance: Style.luminance(defaultDark)
82+
83+ readonly property color opaqueBackground: {
84+ background.a > 0 ?
85+ background :
86+ (Math.abs(foregroundLuminance - defaultLightLuminance) >
87+ Math.abs(foregroundLuminance - defaultDarkLuminance)) ?
88+ defaultLight : defaultDark
89+ }
90+ readonly property real opaqueBackgroundLuminance: Style.luminance(opaqueBackground)
93
91
94 readonly property var headerStyle: "page-header" in style ? style["page-header"] : { }
92 readonly property var headerStyle: "page-header" in style ? style["page-header"] : { }
95 }
93 }
plugins/HudClient/hudclient.cpp+12−12
@@ -82,7 +82,7 @@ HudClient::HudClient()
82 m_results = new DeeListModel();
82 m_results = new DeeListModel();
83 m_clientQuery = hud_client_query_new("");
83 m_clientQuery = hud_client_query_new("");
84 m_toolBarModel = new HudToolBarModel(m_clientQuery);
84 m_toolBarModel = new HudToolBarModel(m_clientQuery);
85− m_currentActionParam = NULL;
85+ m_currentActionParam = nullptr;
86 m_results->setModel(hud_client_query_get_results_model(m_clientQuery));
86 m_results->setModel(hud_client_query_get_results_model(m_clientQuery));
87
87
88 g_signal_connect(G_OBJECT(m_clientQuery), "voice-query-loading", G_CALLBACK(loadingCB), this);
88 g_signal_connect(G_OBJECT(m_clientQuery), "voice-query-loading", G_CALLBACK(loadingCB), this);
@@ -151,13 +151,13 @@ void HudClient::executeParametrizedAction(const QVariant &values)
151 updateParametrizedAction(values);
151 updateParametrizedAction(values);
152 hud_client_param_send_commit(m_currentActionParam);
152 hud_client_param_send_commit(m_currentActionParam);
153 g_object_unref(m_currentActionParam);
153 g_object_unref(m_currentActionParam);
154− m_currentActionParam = NULL;
154+ m_currentActionParam = nullptr;
155 Q_EMIT commandExecuted();
155 Q_EMIT commandExecuted();
156}
156}
157
157
158void HudClient::updateParametrizedAction(const QVariant &values)
158void HudClient::updateParametrizedAction(const QVariant &values)
159{
159{
160− if (m_currentActionParam != NULL) {
160+ if (m_currentActionParam != nullptr) {
161 const QVariantMap map = values.value<QVariantMap>();
161 const QVariantMap map = values.value<QVariantMap>();
162 GActionGroup *ag = hud_client_param_get_actions(m_currentActionParam);
162 GActionGroup *ag = hud_client_param_get_actions(m_currentActionParam);
163
163
@@ -179,10 +179,10 @@ void HudClient::updateParametrizedAction(const QVariant &values)
179
179
180void HudClient::cancelParametrizedAction()
180void HudClient::cancelParametrizedAction()
181{
181{
182− if (m_currentActionParam != NULL) {
182+ if (m_currentActionParam != nullptr) {
183 hud_client_param_send_cancel(m_currentActionParam);
183 hud_client_param_send_cancel(m_currentActionParam);
184 g_object_unref(m_currentActionParam);
184 g_object_unref(m_currentActionParam);
185− m_currentActionParam = NULL;
185+ m_currentActionParam = nullptr;
186 }
186 }
187}
187}
188
188
@@ -212,9 +212,9 @@ void HudClient::executeCommand(int index)
212 GVariant *is_parametrized = dee_model_get_value(model, iter, 7);
212 GVariant *is_parametrized = dee_model_get_value(model, iter, 7);
213 if (g_variant_get_boolean(is_parametrized)) {
213 if (g_variant_get_boolean(is_parametrized)) {
214 m_currentActionParam = hud_client_query_execute_param_command(m_clientQuery, command_key, /* timestamp */ 0);
214 m_currentActionParam = hud_client_query_execute_param_command(m_clientQuery, command_key, /* timestamp */ 0);
215− if (m_currentActionParam != NULL) {
215+ if (m_currentActionParam != nullptr) {
216 GMenuModel *menuModel = hud_client_param_get_model (m_currentActionParam);
216 GMenuModel *menuModel = hud_client_param_get_model (m_currentActionParam);
217− if (menuModel == NULL) {
217+ if (menuModel == nullptr) {
218 g_signal_connect(m_currentActionParam, HUD_CLIENT_PARAM_SIGNAL_MODEL_READY, G_CALLBACK(modelReadyCB), this);
218 g_signal_connect(m_currentActionParam, HUD_CLIENT_PARAM_SIGNAL_MODEL_READY, G_CALLBACK(modelReadyCB), this);
219 } else {
219 } else {
220 modelReady(false);
220 modelReady(false);
@@ -244,9 +244,9 @@ void HudClient::modelReady(bool needDisconnect)
244}
244}
245
245
246static void addAttribute(QVariantMap &properties, GMenuModel *menuModel, int item, const char *attribute) {
246static void addAttribute(QVariantMap &properties, GMenuModel *menuModel, int item, const char *attribute) {
247− GVariant *v = g_menu_model_get_item_attribute_value(menuModel, item, attribute, NULL);
247+ GVariant *v = g_menu_model_get_item_attribute_value(menuModel, item, attribute, nullptr);
248
248
249− if (v == NULL)
249+ if (v == nullptr)
250 return;
250 return;
251
251
252 properties.insert(attribute, DeeListModel::VariantForData(v));
252 properties.insert(attribute, DeeListModel::VariantForData(v));
@@ -264,10 +264,10 @@ void HudClient::modelReallyReady(bool needDisconnect)
264 for (int i = 0; i < g_menu_model_get_n_items(menuModel); i++) {
264 for (int i = 0; i < g_menu_model_get_n_items(menuModel); i++) {
265 GVariant *v = g_menu_model_get_item_attribute_value(menuModel, i, "parameter-type", G_VARIANT_TYPE_STRING);
265 GVariant *v = g_menu_model_get_item_attribute_value(menuModel, i, "parameter-type", G_VARIANT_TYPE_STRING);
266
266
267− if (v == NULL)
267+ if (v == nullptr)
268 continue;
268 continue;
269
269
270− const QString type = QString::fromUtf8(g_variant_get_string(v, NULL));
270+ const QString type = QString::fromUtf8(g_variant_get_string(v, nullptr));
271 if (type == "slider") {
271 if (type == "slider") {
272 const char *sliderAttributes[] = { "label", "min", "max", "step", "value", "live", "action" };
272 const char *sliderAttributes[] = { "label", "min", "max", "step", "value", "live", "action" };
273 QVariantMap properties;
273 QVariantMap properties;
@@ -283,7 +283,7 @@ void HudClient::modelReallyReady(bool needDisconnect)
283 DeeModel *model = hud_client_query_get_results_model(m_clientQuery);
283 DeeModel *model = hud_client_query_get_results_model(m_clientQuery);
284 DeeModelIter *iter = dee_model_get_iter_at_row(model, m_currentActionIndex);
284 DeeModelIter *iter = dee_model_get_iter_at_row(model, m_currentActionIndex);
285 GVariant *actionTextVariant = dee_model_get_value(model, iter, 1);
285 GVariant *actionTextVariant = dee_model_get_value(model, iter, 1);
286− const QString actionText = QString::fromUtf8(g_variant_get_string(actionTextVariant, NULL));
286+ const QString actionText = QString::fromUtf8(g_variant_get_string(actionTextVariant, nullptr));
287 g_variant_unref(actionTextVariant);
287 g_variant_unref(actionTextVariant);
288 Q_EMIT showParametrizedAction(actionText, QVariant::fromValue(items));
288 Q_EMIT showParametrizedAction(actionText, QVariant::fromValue(items));
289}
289}
plugins/HudClient/volumepeakdetector.cpp+9−9
@@ -45,15 +45,15 @@ PulseAudioVolumePeakDetector::PulseAudioVolumePeakDetector()
45 : m_accumulatedValue(0)
45 : m_accumulatedValue(0)
46 , m_nAccumulatedValues(0)
46 , m_nAccumulatedValues(0)
47 , m_accumulatedValuesLimit(1)
47 , m_accumulatedValuesLimit(1)
48− , m_context(NULL)
48+ , m_context(nullptr)
49− , m_mainloop_api(NULL)
49+ , m_mainloop_api(nullptr)
50− , m_stream(NULL)
50+ , m_stream(nullptr)
51{
51{
52}
52}
53
53
54void PulseAudioVolumePeakDetector::start()
54void PulseAudioVolumePeakDetector::start()
55{
55{
56− pa_mainloop *mainloop = NULL;
56+ pa_mainloop *mainloop = nullptr;
57
57
58 /* Set up a new main loop */
58 /* Set up a new main loop */
59 mainloop = pa_mainloop_new();
59 mainloop = pa_mainloop_new();
@@ -63,7 +63,7 @@ void PulseAudioVolumePeakDetector::start()
63 m_mainloop_api = pa_mainloop_get_api(mainloop);
63 m_mainloop_api = pa_mainloop_get_api(mainloop);
64
64
65 /* Create a new connection context */
65 /* Create a new connection context */
66− m_context = pa_context_new(m_mainloop_api, NULL);
66+ m_context = pa_context_new(m_mainloop_api, nullptr);
67 if (!m_context) {
67 if (!m_context) {
68 goto quit;
68 goto quit;
69 }
69 }
@@ -71,12 +71,12 @@ void PulseAudioVolumePeakDetector::start()
71 pa_context_set_state_callback(m_context, context_state_callback, this);
71 pa_context_set_state_callback(m_context, context_state_callback, this);
72
72
73 /* Connect the context */
73 /* Connect the context */
74− if (pa_context_connect(m_context, NULL, PA_CONTEXT_NOFLAGS, NULL) < 0) {
74+ if (pa_context_connect(m_context, nullptr, PA_CONTEXT_NOFLAGS, nullptr) < 0) {
75 goto quit;
75 goto quit;
76 }
76 }
77
77
78 /* Run the main loop */
78 /* Run the main loop */
79− if (pa_mainloop_run(mainloop, NULL) < 0) {
79+ if (pa_mainloop_run(mainloop, nullptr) < 0) {
80 goto quit;
80 goto quit;
81 }
81 }
82
82
@@ -130,7 +130,7 @@ void PulseAudioVolumePeakDetector::startStream()
130 pa_channel_map_init_extend(&channel_map, sample_spec.channels, PA_CHANNEL_MAP_DEFAULT);
130 pa_channel_map_init_extend(&channel_map, sample_spec.channels, PA_CHANNEL_MAP_DEFAULT);
131 pa_proplist_sets(proplist, PA_PROP_MEDIA_NAME, "HUD Peak Detector");
131 pa_proplist_sets(proplist, PA_PROP_MEDIA_NAME, "HUD Peak Detector");
132
132
133− m_stream = pa_stream_new_with_proplist(m_context, NULL, &sample_spec, &channel_map, proplist);
133+ m_stream = pa_stream_new_with_proplist(m_context, nullptr, &sample_spec, &channel_map, proplist);
134 if (!m_stream) {
134 if (!m_stream) {
135 pa_proplist_free(proplist);
135 pa_proplist_free(proplist);
136 quit();
136 quit();
@@ -144,7 +144,7 @@ void PulseAudioVolumePeakDetector::startStream()
144 buffer_attr.maxlength = (uint32_t) -1;
144 buffer_attr.maxlength = (uint32_t) -1;
145 buffer_attr.fragsize = sizeof(float);
145 buffer_attr.fragsize = sizeof(float);
146
146
147− if (pa_stream_connect_record(m_stream, NULL, &buffer_attr, (pa_stream_flags_t)(PA_STREAM_PEAK_DETECT | PA_STREAM_ADJUST_LATENCY)) < 0) {
147+ if (pa_stream_connect_record(m_stream, nullptr, &buffer_attr, (pa_stream_flags_t)(PA_STREAM_PEAK_DETECT | PA_STREAM_ADJUST_LATENCY)) < 0) {
148 quit();
148 quit();
149 }
149 }
150}
150}
plugins/Powerd/Powerd.cpp+1−1
@@ -39,7 +39,7 @@ void dimTimeoutChanged(GSettings *settings, const gchar *key, QDBusInterface *un
39
39
40Powerd::Powerd(QObject* parent)
40Powerd::Powerd(QObject* parent)
41 : QObject(parent),
41 : QObject(parent),
42− unityScreen(NULL)
42+ unityScreen(nullptr)
43{
43{
44 unityScreen = new QDBusInterface("com.canonical.Unity.Screen",
44 unityScreen = new QDBusInterface("com.canonical.Unity.Screen",
45 "/com/canonical/Unity/Screen",
45 "/com/canonical/Unity/Screen",
plugins/Unity/Indicators/menucontentactivator.cpp+2−2
@@ -45,7 +45,7 @@ public:
45 m_baseIndex(0),
45 m_baseIndex(0),
46 m_delta(0),
46 m_delta(0),
47 m_count(0),
47 m_count(0),
48− m_timer(NULL),
48+ m_timer(nullptr),
49 q(parent)
49 q(parent)
50 {}
50 {}
51
51
@@ -55,7 +55,7 @@ public:
55 m_content.clear();
55 m_content.clear();
56 }
56 }
57
57
58− int findNextInactiveDelta(bool* finished = NULL);
58+ int findNextInactiveDelta(bool* finished = nullptr);
59
59
60 static int content_count(QQmlListProperty<MenuContentState> *prop);
60 static int content_count(QQmlListProperty<MenuContentState> *prop);
61 static MenuContentState* content_at(QQmlListProperty<MenuContentState> *prop, int index);
61 static MenuContentState* content_at(QQmlListProperty<MenuContentState> *prop, int index);
plugins/Unity/Indicators/menucontentactivator.h+1−1
@@ -71,7 +71,7 @@ class UNITYINDICATORS_EXPORT MenuContentActivator : public QObject
71 Q_PROPERTY(int count READ count WRITE setCount NOTIFY countChanged)
71 Q_PROPERTY(int count READ count WRITE setCount NOTIFY countChanged)
72 Q_PROPERTY(QQmlListProperty<MenuContentState> content READ content NOTIFY contentChanged DESIGNABLE false)
72 Q_PROPERTY(QQmlListProperty<MenuContentState> content READ content NOTIFY contentChanged DESIGNABLE false)
73public:
73public:
74− MenuContentActivator(QObject* parent = NULL);
74+ MenuContentActivator(QObject* parent = nullptr);
75 ~MenuContentActivator();
75 ~MenuContentActivator();
76
76
77 Q_INVOKABLE void restart();
77 Q_INVOKABLE void restart();
plugins/Unity/Indicators/modelprinter.cpp+3−3
@@ -27,13 +27,13 @@
27
27
28ModelPrinter::ModelPrinter(QObject *parent)
28ModelPrinter::ModelPrinter(QObject *parent)
29 : QObject(parent)
29 : QObject(parent)
30− , m_model(NULL)
30+ , m_model(nullptr)
31{
31{
32}
32}
33
33
34void ModelPrinter::setSourceModel(UnityMenuModel * sourceModel)
34void ModelPrinter::setSourceModel(UnityMenuModel * sourceModel)
35{
35{
36− if (m_model != NULL) {
36+ if (m_model != nullptr) {
37 disconnect(m_model);
37 disconnect(m_model);
38 }
38 }
39 if (m_model != sourceModel) {
39 if (m_model != sourceModel) {
@@ -41,7 +41,7 @@ void ModelPrinter::setSourceModel(UnityMenuModel * sourceModel)
41 Q_EMIT modelChanged();
41 Q_EMIT modelChanged();
42 Q_EMIT textChanged();
42 Q_EMIT textChanged();
43 }
43 }
44− if (m_model != NULL) {
44+ if (m_model != nullptr) {
45 connect(m_model, SIGNAL(rowsInserted(QModelIndex,int,int)), SIGNAL(textChanged()));
45 connect(m_model, SIGNAL(rowsInserted(QModelIndex,int,int)), SIGNAL(textChanged()));
46 connect(m_model, SIGNAL(rowsRemoved(QModelIndex,int,int)), SIGNAL(textChanged()));
46 connect(m_model, SIGNAL(rowsRemoved(QModelIndex,int,int)), SIGNAL(textChanged()));
47 connect(m_model, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&, const QVector<int>&)), SIGNAL(textChanged()));
47 connect(m_model, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&, const QVector<int>&)), SIGNAL(textChanged()));
plugins/Unity/Indicators/rootactionstate.cpp+4−4
@@ -31,7 +31,7 @@ extern "C" {
31
31
32RootActionState::RootActionState(QObject *parent)
32RootActionState::RootActionState(QObject *parent)
33 : ActionStateParser(parent),
33 : ActionStateParser(parent),
34− m_menu(NULL)
34+ m_menu(nullptr)
35{
35{
36}
36}
37
37
@@ -95,7 +95,7 @@ void RootActionState::onModelDataChanged(const QModelIndex& topLeft, const QMode
95void RootActionState::reset()
95void RootActionState::reset()
96{
96{
97 m_cachedState.clear();
97 m_cachedState.clear();
98− m_menu = NULL;
98+ m_menu = nullptr;
99
99
100 Q_EMIT menuChanged();
100 Q_EMIT menuChanged();
101 Q_EMIT updated();
101 Q_EMIT updated();
@@ -171,7 +171,7 @@ static QString iconUri(GIcon *icon)
171 const gchar* const* iconNames = g_themed_icon_get_names (G_THEMED_ICON (icon));
171 const gchar* const* iconNames = g_themed_icon_get_names (G_THEMED_ICON (icon));
172
172
173 QStringList iconNameList;
173 QStringList iconNameList;
174− for (uint index = 0; iconNames[index] != NULL; index++) {
174+ for (uint index = 0; iconNames[index] != nullptr; index++) {
175 iconNameList << iconNames[index];
175 iconNameList << iconNames[index];
176 }
176 }
177
177
@@ -282,7 +282,7 @@ QVariant RootActionState::toQVariant(GVariant* state) const
282 qmap["accessible-desc"] = accessible_name ? QString::fromUtf8(accessible_name) : "";
282 qmap["accessible-desc"] = accessible_name ? QString::fromUtf8(accessible_name) : "";
283 qmap["visible"] = visible;
283 qmap["visible"] = visible;
284
284
285− gicon = g_icon_new_for_string (icon, NULL);
285+ gicon = g_icon_new_for_string (icon, nullptr);
286 if (gicon) {
286 if (gicon) {
287 qmap["icons"] = QStringList() << iconUri(gicon);
287 qmap["icons"] = QStringList() << iconUri(gicon);
288 g_object_unref (gicon);
288 g_object_unref (gicon);
plugins/Unity/Indicators/unitymenumodelcache.h+1−1
@@ -31,7 +31,7 @@ class UNITYINDICATORS_EXPORT UnityMenuModelCache : public QObject
31{
31{
32 Q_OBJECT
32 Q_OBJECT
33public:
33public:
34− UnityMenuModelCache(QObject*parent=NULL);
34+ UnityMenuModelCache(QObject*parent=nullptr);
35 ~UnityMenuModelCache();
35 ~UnityMenuModelCache();
36
36
37 Q_INVOKABLE UnityMenuModel* model(const QByteArray& bus,
37 Q_INVOKABLE UnityMenuModel* model(const QByteArray& bus,
plugins/Unity/Indicators/unitymenumodelstack.cpp+4−4
@@ -90,7 +90,7 @@ UnityMenuModelStack::~UnityMenuModelStack()
90
90
91UnityMenuModel* UnityMenuModelStack::head() const
91UnityMenuModel* UnityMenuModelStack::head() const
92{
92{
93− return !m_menuModels.isEmpty() ? m_menuModels.first()->model() : NULL;
93+ return !m_menuModels.isEmpty() ? m_menuModels.first()->model() : nullptr;
94}
94}
95
95
96void UnityMenuModelStack::setHead(UnityMenuModel* model)
96void UnityMenuModelStack::setHead(UnityMenuModel* model)
@@ -106,7 +106,7 @@ void UnityMenuModelStack::setHead(UnityMenuModel* model)
106
106
107UnityMenuModel* UnityMenuModelStack::tail() const
107UnityMenuModel* UnityMenuModelStack::tail() const
108{
108{
109− return !m_menuModels.isEmpty() ? m_menuModels.last()->model() : NULL;
109+ return !m_menuModels.isEmpty() ? m_menuModels.last()->model() : nullptr;
110}
110}
111
111
112int UnityMenuModelStack::count() const
112int UnityMenuModelStack::count() const
@@ -127,7 +127,7 @@ void UnityMenuModelStack::push(UnityMenuModel* model, int index)
127UnityMenuModel* UnityMenuModelStack::pop()
127UnityMenuModel* UnityMenuModelStack::pop()
128{
128{
129 if (m_menuModels.isEmpty()) {
129 if (m_menuModels.isEmpty()) {
130− return NULL;
130+ return nullptr;
131 }
131 }
132 UnityMenuModelEntry* entry = m_menuModels.takeLast();
132 UnityMenuModelEntry* entry = m_menuModels.takeLast();
133 UnityMenuModel* model = entry->model();
133 UnityMenuModel* model = entry->model();
@@ -135,7 +135,7 @@ UnityMenuModel* UnityMenuModelStack::pop()
135
135
136 Q_EMIT tailChanged(tail());
136 Q_EMIT tailChanged(tail());
137 if (m_menuModels.isEmpty()) {
137 if (m_menuModels.isEmpty()) {
138− Q_EMIT headChanged(NULL);
138+ Q_EMIT headChanged(nullptr);
139 }
139 }
140 Q_EMIT countChanged(m_menuModels.count());
140 Q_EMIT countChanged(m_menuModels.count());
141
141
plugins/Unity/Indicators/unitymenumodelstack.h+1−1
@@ -40,7 +40,7 @@ class UNITYINDICATORS_EXPORT UnityMenuModelStack : public QObject
40 Q_PROPERTY(UnityMenuModel* tail READ tail NOTIFY tailChanged)
40 Q_PROPERTY(UnityMenuModel* tail READ tail NOTIFY tailChanged)
41 Q_PROPERTY(int count READ count NOTIFY countChanged)
41 Q_PROPERTY(int count READ count NOTIFY countChanged)
42public:
42public:
43− UnityMenuModelStack(QObject*parent=NULL);
43+ UnityMenuModelStack(QObject*parent=nullptr);
44 ~UnityMenuModelStack();
44 ~UnityMenuModelStack();
45
45
46 UnityMenuModel* head() const;
46 UnityMenuModel* head() const;
plugins/Utils/Style.jsnew file+37
@@ -0,0 +1,37 @@
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+.pragma library
18+
19+/*! \brief Calculate average luminance of the passed colors
20+
21+ \note If not fully opaque, luminance is dependant on blending.
22+ */
23+function luminance() {
24+ var sum = 0;
25+ // TODO this was originally
26+ // for (var k in arguments) {
27+ // but for some unkown reason was causing crashes in testDash/testDashContent
28+ // investigate when we have some time
29+ for (var k = 0; k < arguments.length; ++k) {
30+ // only way to convert string to color
31+ var c = Qt.lighter(arguments[k], 1.0);
32+
33+ sum += 0.2126 * c.r + 0.7152 * c.g + 0.0722 * c.b;
34+ }
35+
36+ return sum / arguments.length;
37+}
plugins/Utils/qlimitproxymodelqml.cpp+6−6
@@ -42,18 +42,18 @@ void
42QLimitProxyModelQML::setModel(QAbstractItemModel *itemModel)
42QLimitProxyModelQML::setModel(QAbstractItemModel *itemModel)
43{
43{
44 if (itemModel != sourceModel()) {
44 if (itemModel != sourceModel()) {
45− if (sourceModel() != NULL) {
45+ if (sourceModel() != nullptr) {
46 sourceModel()->disconnect(this);
46 sourceModel()->disconnect(this);
47 }
47 }
48
48
49 setSourceModel(itemModel);
49 setSourceModel(itemModel);
50
50
51− if (sourceModel() != NULL) {
51+ if (sourceModel() != nullptr) {
52 // Disconnect the QIdentityProxyModel handling for rows removed/added...
52 // Disconnect the QIdentityProxyModel handling for rows removed/added...
53− disconnect(sourceModel(), SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), this, NULL);
53+ disconnect(sourceModel(), SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), this, nullptr);
54− disconnect(sourceModel(), SIGNAL(rowsInserted(QModelIndex,int,int)), this, NULL);
54+ disconnect(sourceModel(), SIGNAL(rowsInserted(QModelIndex,int,int)), this, nullptr);
55− disconnect(sourceModel(), SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), this, NULL);
55+ disconnect(sourceModel(), SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), this, nullptr);
56− disconnect(sourceModel(), SIGNAL(rowsRemoved(QModelIndex,int,int)), this, NULL);
56+ disconnect(sourceModel(), SIGNAL(rowsRemoved(QModelIndex,int,int)), this, nullptr);
57
57
58 // ... and use our own
58 // ... and use our own
59 connect(sourceModel(), SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
59 connect(sourceModel(), SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
plugins/Utils/qmldir+1
@@ -1,3 +1,4 @@
1module Utils
1module Utils
2plugin Utils-qml
2plugin Utils-qml
3typeinfo Utils.qmltypes
3typeinfo Utils.qmltypes
4+Style 0.1 Style.js
plugins/Utils/qsortfilterproxymodelqml.cpp+7−7
@@ -34,7 +34,7 @@ QSortFilterProxyModelQML::QSortFilterProxyModelQML(QObject *parent)
34 */
34 */
35int QSortFilterProxyModelQML::mapRowToSource(int row)
35int QSortFilterProxyModelQML::mapRowToSource(int row)
36{
36{
37− if (sourceModel() == NULL)
37+ if (sourceModel() == nullptr)
38 return -1;
38 return -1;
39
39
40 return QSortFilterProxyModel::mapToSource(index(row, 0)).row();
40 return QSortFilterProxyModel::mapToSource(index(row, 0)).row();
@@ -48,12 +48,12 @@ QHash<int, QByteArray> QSortFilterProxyModelQML::roleNames() const
48void
48void
49QSortFilterProxyModelQML::setModel(QAbstractItemModel *itemModel)
49QSortFilterProxyModelQML::setModel(QAbstractItemModel *itemModel)
50{
50{
51− if (itemModel == NULL) {
51+ if (itemModel == nullptr) {
52 return;
52 return;
53 }
53 }
54
54
55 if (itemModel != sourceModel()) {
55 if (itemModel != sourceModel()) {
56− if (sourceModel() != NULL) {
56+ if (sourceModel() != nullptr) {
57 sourceModel()->disconnect(this);
57 sourceModel()->disconnect(this);
58 }
58 }
59
59
@@ -83,7 +83,7 @@ QSortFilterProxyModelQML::get(int row)
83QVariant
83QVariant
84QSortFilterProxyModelQML::data(int row, int role)
84QSortFilterProxyModelQML::data(int row, int role)
85{
85{
86− if (sourceModel() == NULL) {
86+ if (sourceModel() == nullptr) {
87 return QVariant();
87 return QVariant();
88 }
88 }
89
89
@@ -93,7 +93,7 @@ QSortFilterProxyModelQML::data(int row, int role)
93int
93int
94QSortFilterProxyModelQML::totalCount() const
94QSortFilterProxyModelQML::totalCount() const
95{
95{
96− if (sourceModel() != NULL) {
96+ if (sourceModel() != nullptr) {
97 return sourceModel()->rowCount();
97 return sourceModel()->rowCount();
98 } else {
98 } else {
99 return 0;
99 return 0;
@@ -149,7 +149,7 @@ QSortFilterProxyModelQML::findFirst(int role, const QVariant& value) const
149int
149int
150QSortFilterProxyModelQML::mapFromSource(int row)
150QSortFilterProxyModelQML::mapFromSource(int row)
151{
151{
152− if (sourceModel() != NULL) {
152+ if (sourceModel() != nullptr) {
153 return QSortFilterProxyModel::mapFromSource(sourceModel()->index(row, 0)).row();
153 return QSortFilterProxyModel::mapFromSource(sourceModel()->index(row, 0)).row();
154 } else {
154 } else {
155 return -1;
155 return -1;
@@ -159,7 +159,7 @@ QSortFilterProxyModelQML::mapFromSource(int row)
159int
159int
160QSortFilterProxyModelQML::mapToSource(int row)
160QSortFilterProxyModelQML::mapToSource(int row)
161{
161{
162− if (sourceModel() != NULL) {
162+ if (sourceModel() != nullptr) {
163 return QSortFilterProxyModel::mapToSource(index(row, 0)).row();
163 return QSortFilterProxyModel::mapToSource(index(row, 0)).row();
164 } else {
164 } else {
165 return -1;
165 return -1;
plugins/Utils/timeformatter.cpp+8−8
@@ -57,9 +57,9 @@ timedate1_properties_changed (GDBusConnection *connection,
57 if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(sa{sv}as)")))
57 if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(sa{sv}as)")))
58 return;
58 return;
59
59
60− g_variant_get (parameters, "(s@a{sv}as)", NULL, &changed, &iter);
60+ g_variant_get (parameters, "(s@a{sv}as)", nullptr, &changed, &iter);
61
61
62− if (g_variant_lookup (changed, "Timezone", "s", NULL)) {
62+ if (g_variant_lookup (changed, "Timezone", "s", nullptr)) {
63 priv->formatter->update();
63 priv->formatter->update();
64 }
64 }
65 else {
65 else {
@@ -81,10 +81,10 @@ got_bus(GObject *object, GAsyncResult *result, gpointer user_data)
81 Q_UNUSED(object);
81 Q_UNUSED(object);
82
82
83 TimeFormatterPrivate *priv = (TimeFormatterPrivate *)user_data;
83 TimeFormatterPrivate *priv = (TimeFormatterPrivate *)user_data;
84− GError *error = NULL;
84+ GError *error = nullptr;
85
85
86 priv->system_bus = g_bus_get_finish (result, &error);
86 priv->system_bus = g_bus_get_finish (result, &error);
87− if (priv->system_bus == NULL) {
87+ if (priv->system_bus == nullptr) {
88 if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
88 if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
89 qWarning("TimeFormatter: cannot connect to the system bus: %s", error->message);
89 qWarning("TimeFormatter: cannot connect to the system bus: %s", error->message);
90 g_error_free (error);
90 g_error_free (error);
@@ -98,14 +98,14 @@ got_bus(GObject *object, GAsyncResult *result, gpointer user_data)
98 * and keep the process alive.
98 * and keep the process alive.
99 */
99 */
100 priv->subscription_id = g_dbus_connection_signal_subscribe (priv->system_bus,
100 priv->subscription_id = g_dbus_connection_signal_subscribe (priv->system_bus,
101− NULL, /* sender */
101+ nullptr, /* sender */
102 "org.freedesktop.DBus.Properties",
102 "org.freedesktop.DBus.Properties",
103 "PropertiesChanged",
103 "PropertiesChanged",
104− NULL,
104+ nullptr,
105 "org.freedesktop.timedate1",
105 "org.freedesktop.timedate1",
106 G_DBUS_SIGNAL_FLAGS_NONE,
106 G_DBUS_SIGNAL_FLAGS_NONE,
107 timedate1_properties_changed,
107 timedate1_properties_changed,
108− priv, NULL);
108+ priv, nullptr);
109}
109}
110
110
111TimeFormatter::TimeFormatter(QObject *parent): QObject(parent)
111TimeFormatter::TimeFormatter(QObject *parent): QObject(parent)
@@ -114,7 +114,7 @@ TimeFormatter::TimeFormatter(QObject *parent): QObject(parent)
114 priv->formatter = this;
114 priv->formatter = this;
115 priv->time = 0;
115 priv->time = 0;
116 priv->format = "yyyy-MM-dd hh:mm";
116 priv->format = "yyyy-MM-dd hh:mm";
117− priv->system_bus = NULL;
117+ priv->system_bus = nullptr;
118 priv->subscription_id = 0;
118 priv->subscription_id = 0;
119 priv->cancellable = g_cancellable_new ();
119 priv->cancellable = g_cancellable_new ();
120
120
po/az.po+70−42
@@ -8,43 +8,43 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2014-08-21 11:36+0200\n"
10"POT-Creation-Date: 2014-08-21 11:36+0200\n"
11−"PO-Revision-Date: 2014-01-15 09:50+0000\n"
11+"PO-Revision-Date: 2014-08-26 22:12+0000\n"
12"Last-Translator: Turan Mahmudov <turan.mahmudov@gmail.com>\n"
12"Last-Translator: Turan Mahmudov <turan.mahmudov@gmail.com>\n"
13"Language-Team: Azerbaijani <az@li.org>\n"
13"Language-Team: Azerbaijani <az@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-08-23 07:16+0000\n"
17+"X-Launchpad-Export-Date: 2014-08-27 07:46+0000\n"
18−"X-Generator: Launchpad (build 17163)\n"
18+"X-Generator: Launchpad (build 17174)\n"
19
19
20#: plugins/LightDM/Greeter.cpp:129
20#: plugins/LightDM/Greeter.cpp:129
21msgid "Password: "
21msgid "Password: "
22−msgstr ""
22+msgstr "Parol: "
23
23
24#: plugins/Unity/Launcher/launcheritem.cpp:43
24#: plugins/Unity/Launcher/launcheritem.cpp:43
25#: plugins/Unity/Launcher/launcheritem.cpp:73
25#: plugins/Unity/Launcher/launcheritem.cpp:73
26msgid "Pin shortcut"
26msgid "Pin shortcut"
27−msgstr ""
27+msgstr "Pin qısayolu"
28
28
29#: plugins/Unity/Launcher/launcheritem.cpp:73
29#: plugins/Unity/Launcher/launcheritem.cpp:73
30msgid "Unpin shortcut"
30msgid "Unpin shortcut"
31−msgstr ""
31+msgstr "Açma qısayolu"
32
32
33#: qml/Components/Dialogs.qml:142
33#: qml/Components/Dialogs.qml:142
34msgid "Are you sure you would like to turn power off?"
34msgid "Are you sure you would like to turn power off?"
35−msgstr ""
35+msgstr "Söndürmək istədiyinizə əminsiniz?"
36
36
37#: qml/Components/Dialogs.qml:144
37#: qml/Components/Dialogs.qml:144
38msgid "Power off"
38msgid "Power off"
39−msgstr ""
39+msgstr "Söndür"
40
40
41#: qml/Components/Dialogs.qml:153
41#: qml/Components/Dialogs.qml:153
42msgid "Restart"
42msgid "Restart"
43−msgstr ""
43+msgstr "Yenidən Başlat"
44
44
45#: qml/Components/Dialogs.qml:162
45#: qml/Components/Dialogs.qml:162
46msgid "Cancel"
46msgid "Cancel"
47−msgstr ""
47+msgstr "İmtina"
48
48
49#: qml/Components/EdgeDemoOverlay.qml:151
49#: qml/Components/EdgeDemoOverlay.qml:151
50msgid "Skip intro"
50msgid "Skip intro"
@@ -92,14 +92,16 @@ msgid ""
92"You have now mastered the edge gestures and can start using the "
92"You have now mastered the edge gestures and can start using the "
93"phone<br><br>Tap on the screen to start"
93"phone<br><br>Tap on the screen to start"
94msgstr ""
94msgstr ""
95+"Siz künc jestlərini mənimsəmisiniz və telefonu istifadə etməyə başlaya "
96+"bilərsiniz.<br><br>Başlamaq üçün ekrana toxunun"
95
97
96#: qml/Components/Lockscreen.qml:167
98#: qml/Components/Lockscreen.qml:167
97msgid "Please wait"
99msgid "Please wait"
98−msgstr ""
100+msgstr "Lütfən gözləyin"
99
101
100#: qml/Components/Lockscreen.qml:172
102#: qml/Components/Lockscreen.qml:172
101msgid "Too many incorrect attempts"
103msgid "Too many incorrect attempts"
102−msgstr ""
104+msgstr "Çoxlu yanlış cəhd"
103
105
104#: qml/Components/Lockscreen.qml:206
106#: qml/Components/Lockscreen.qml:206
105msgid "Emergency Call"
107msgid "Emergency Call"
@@ -107,7 +109,7 @@ msgstr "Zərurət zəngi"
107
109
108#: qml/Components/Lockscreen.qml:226
110#: qml/Components/Lockscreen.qml:226
109msgid "OK"
111msgid "OK"
110−msgstr ""
112+msgstr "ОК"
111
113
112#: qml/Components/PassphraseLockscreen.qml:61
114#: qml/Components/PassphraseLockscreen.qml:61
113#, qt-format
115#, qt-format
@@ -120,11 +122,11 @@ msgstr "Xoş gördük"
120
122
121#: qml/Dash/GenericScopeView.qml:361
123#: qml/Dash/GenericScopeView.qml:361
122msgid "See less"
124msgid "See less"
123−msgstr ""
125+msgstr "Daha az gör"
124
126
125#: qml/Dash/GenericScopeView.qml:361
127#: qml/Dash/GenericScopeView.qml:361
126msgid "See all"
128msgid "See all"
127−msgstr ""
129+msgstr "Hamısını gör"
128
130
129#: qml/Dash/GenericScopeView.qml:424 qml/Panel/SearchIndicator.qml:27
131#: qml/Dash/GenericScopeView.qml:424 qml/Panel/SearchIndicator.qml:27
130msgid "Search"
132msgid "Search"
@@ -132,11 +134,11 @@ msgstr "Axtar"
132
134
133#: qml/Dash/Previews/PreviewActionCombo.qml:34
135#: qml/Dash/Previews/PreviewActionCombo.qml:34
134msgid "More..."
136msgid "More..."
135−msgstr ""
137+msgstr "Ətraflı..."
136
138
137#: qml/Dash/Previews/PreviewActionCombo.qml:34
139#: qml/Dash/Previews/PreviewActionCombo.qml:34
138msgid "Less..."
140msgid "Less..."
139−msgstr ""
141+msgstr "Az..."
140
142
141#: qml/Dash/Previews/PreviewRatingInput.qml:81
143#: qml/Dash/Previews/PreviewRatingInput.qml:81
142msgid "Rate this"
144msgid "Rate this"
@@ -156,23 +158,23 @@ msgstr ""
156
158
157#: qml/Dash/ScopesOverview.qml:408
159#: qml/Dash/ScopesOverview.qml:408
158msgid "Done"
160msgid "Done"
159−msgstr ""
161+msgstr "Başa çatdı"
160
162
161#: qml/Dash/ScopesOverview.qml:434
163#: qml/Dash/ScopesOverview.qml:434
162msgid "Store"
164msgid "Store"
163−msgstr ""
165+msgstr "Saxla"
164
166
165#: qml/Dash/ScopesOverviewTab.qml:36
167#: qml/Dash/ScopesOverviewTab.qml:36
166msgid "Favorites"
168msgid "Favorites"
167−msgstr ""
169+msgstr "Seçilmişlər"
168
170
169#: qml/Dash/ScopesOverviewTab.qml:54
171#: qml/Dash/ScopesOverviewTab.qml:54
170msgid "All"
172msgid "All"
171−msgstr ""
173+msgstr "Hamısı"
172
174
173#: qml/Greeter/Greeter.qml:157
175#: qml/Greeter/Greeter.qml:157
174msgid "Swipe to unlock"
176msgid "Swipe to unlock"
175−msgstr ""
177+msgstr "Kilidi açmaq üçün sürüşdürün"
176
178
177#: qml/Hud/HudParametrizedActionsPage.qml:132
179#: qml/Hud/HudParametrizedActionsPage.qml:132
178msgid "Confirm"
180msgid "Confirm"
@@ -200,94 +202,120 @@ msgstr "Parolu göstər"
200
202
201#: qml/Notifications/NotificationMenuItemFactory.qml:120
203#: qml/Notifications/NotificationMenuItemFactory.qml:120
202msgid "Enter SIM PIN"
204msgid "Enter SIM PIN"
203−msgstr ""
205+msgstr "SIM PIN kodunuzu daxil edin"
204
206
205#: qml/Notifications/NotificationMenuItemFactory.qml:121 qml/Shell.qml:270
207#: qml/Notifications/NotificationMenuItemFactory.qml:121 qml/Shell.qml:270
206msgid "Sorry, incorrect PIN"
208msgid "Sorry, incorrect PIN"
207−msgstr ""
209+msgstr "Təəssüf ki, PIN yanlışdır"
208
210
209#: qml/Panel/ActiveCallHint.qml:77
211#: qml/Panel/ActiveCallHint.qml:77
210msgid "Tap to return to call..."
212msgid "Tap to return to call..."
211−msgstr ""
213+msgstr "Zəngə qayıtmaq üçün toxunun..."
212
214
213#: qml/Panel/ActiveCallHint.qml:90
215#: qml/Panel/ActiveCallHint.qml:90
214msgid "Conference"
216msgid "Conference"
215−msgstr ""
217+msgstr "Konfrans"
216
218
217#: qml/Panel/Indicators/MenuItemFactory.qml:651
219#: qml/Panel/Indicators/MenuItemFactory.qml:651
218msgid "In queue…"
220msgid "In queue…"
219−msgstr ""
221+msgstr "Növbədədir..."
220
222
221#: qml/Panel/Indicators/MenuItemFactory.qml:655
223#: qml/Panel/Indicators/MenuItemFactory.qml:655
222msgid "Downloading"
224msgid "Downloading"
223−msgstr ""
225+msgstr "Endirilir"
224
226
225#: qml/Panel/Indicators/MenuItemFactory.qml:657
227#: qml/Panel/Indicators/MenuItemFactory.qml:657
226msgid "Paused, tap to resume"
228msgid "Paused, tap to resume"
227−msgstr ""
229+msgstr "Saxlanıldı, davam etmək üçün toxunun"
228
230
229#: qml/Panel/Indicators/MenuItemFactory.qml:659
231#: qml/Panel/Indicators/MenuItemFactory.qml:659
230msgid "Canceled"
232msgid "Canceled"
231−msgstr ""
233+msgstr "İmtina edildi"
232
234
233#: qml/Panel/Indicators/MenuItemFactory.qml:661
235#: qml/Panel/Indicators/MenuItemFactory.qml:661
234msgid "Finished"
236msgid "Finished"
235−msgstr ""
237+msgstr "Bitdi"
236
238
237#: qml/Panel/Indicators/MenuItemFactory.qml:663
239#: qml/Panel/Indicators/MenuItemFactory.qml:663
238msgid "Failed, tap to retry"
240msgid "Failed, tap to retry"
239−msgstr ""
241+msgstr "Alınmadı, davam etmək üçün toxunun"
240
242
241#: qml/Panel/Indicators/ModemInfoItem.qml:105
243#: qml/Panel/Indicators/ModemInfoItem.qml:105
242msgid "Unlock SIM"
244msgid "Unlock SIM"
243−msgstr ""
245+msgstr "SIM kilidini aç"
244
246
245#: qml/Panel/Indicators/RoamingIndication.qml:27
247#: qml/Panel/Indicators/RoamingIndication.qml:27
246msgid "Roaming"
248msgid "Roaming"
247−msgstr ""
249+msgstr "Rominq"
248
250
249#: qml/Shell.qml:266
251#: qml/Shell.qml:266
250msgid "Enter your passphrase"
252msgid "Enter your passphrase"
251−msgstr ""
253+msgstr "Açar sözünüzü daxil edin"
252
254
253#: qml/Shell.qml:267
255#: qml/Shell.qml:267
254msgid "Sorry, incorrect passphrase"
256msgid "Sorry, incorrect passphrase"
255−msgstr ""
257+msgstr "Təəssüf ki, açar söz yanlışdır"
256
258
257#: qml/Shell.qml:269
259#: qml/Shell.qml:269
258msgid "Enter your PIN"
260msgid "Enter your PIN"
259−msgstr ""
261+msgstr "PIN kodunuzu daxil edin"
260
262
261#: qml/Shell.qml:273
263#: qml/Shell.qml:273
262#, qt-format
264#, qt-format
263msgid "Enter your %1"
265msgid "Enter your %1"
264−msgstr ""
266+msgstr "%1 daxil edin"
265
267
266#: qml/Shell.qml:274
268#: qml/Shell.qml:274
267#, qt-format
269#, qt-format
268msgid "Sorry, incorrect %1"
270msgid "Sorry, incorrect %1"
269−msgstr ""
271+msgstr "Təəssüf ki, %1 yanlışdır"
270
272
271#: qml/Shell.qml:310
273#: qml/Shell.qml:310
272msgid "Sorry, incorrect passphrase."
274msgid "Sorry, incorrect passphrase."
273−msgstr ""
275+msgstr "Təəssüf ki, açar söz yanlışdır."
274
276
275#: qml/Shell.qml:311
277#: qml/Shell.qml:311
276msgid "Sorry, incorrect passcode."
278msgid "Sorry, incorrect passcode."
277−msgstr ""
279+msgstr "Təəssüf ki, açar kod yanlışdır."
278
280
279#: qml/Shell.qml:312
281#: qml/Shell.qml:312
280msgid "This will be your last attempt."
282msgid "This will be your last attempt."
281−msgstr ""
283+msgstr "Bu sizin son cəhdiniz olacaq."
282
284
283#: qml/Shell.qml:314
285#: qml/Shell.qml:314
284msgid ""
286msgid ""
285"If passphrase is entered incorrectly, your phone will conduct a factory "
287"If passphrase is entered incorrectly, your phone will conduct a factory "
286"reset and all personal data will be deleted."
288"reset and all personal data will be deleted."
287msgstr ""
289msgstr ""
290+"Əgər açar söz yanlış daxil edilibsə, onda telefonunuz fabrika parametrlərinə "
291+"geri qayıdacaq və bütün şəxsi məlumatlarınız silinəcək."
288
292
289#: qml/Shell.qml:315
293#: qml/Shell.qml:315
290msgid ""
294msgid ""
291"If passcode is entered incorrectly, your phone will conduct a factory reset "
295"If passcode is entered incorrectly, your phone will conduct a factory reset "
292"and all personal data will be deleted."
296"and all personal data will be deleted."
293msgstr ""
297msgstr ""
298+"Əgər açar kod yanlış daxil edilibsə, onda telefonunuz fabrika parametrlərinə "
299+"geri qayıdacaq və bütün şəxsi məlumatlarınız silinəcək."
300+
301+#~ msgid "DONE"
302+#~ msgstr "OLDU"
303+
304+#~ msgid "CANCEL"
305+#~ msgstr "İMTİNA"
306+
307+#~ msgid "Please enter SIM PIN"
308+#~ msgstr "SIM PIN kodunu yazın"
309+
310+#, qt-format
311+#~ msgid "Incorrect %1"
312+#~ msgstr "Yanlış %1"
313+
314+#~ msgid "Please re-enter"
315+#~ msgstr "Lütfən yenidən daxil edin"
316+
317+#~ msgid "passphrase"
318+#~ msgstr "açar söz"
319+
320+#~ msgid "passcode"
321+#~ msgstr "açar kod"
po/br.po+44−27
@@ -8,18 +8,18 @@ msgstr ""
8"Project-Id-Version: unity8\n"
8"Project-Id-Version: unity8\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2014-08-21 11:36+0200\n"
10"POT-Creation-Date: 2014-08-21 11:36+0200\n"
11−"PO-Revision-Date: 2014-07-28 06:44+0000\n"
11+"PO-Revision-Date: 2014-08-26 08:28+0000\n"
12"Last-Translator: Fohanno Thierry <thierry.fohanno@ofis-bzh.org>\n"
12"Last-Translator: Fohanno Thierry <thierry.fohanno@ofis-bzh.org>\n"
13"Language-Team: Breton <br@li.org>\n"
13"Language-Team: Breton <br@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-08-23 07:16+0000\n"
17+"X-Launchpad-Export-Date: 2014-08-27 07:46+0000\n"
18−"X-Generator: Launchpad (build 17163)\n"
18+"X-Generator: Launchpad (build 17174)\n"
19
19
20#: plugins/LightDM/Greeter.cpp:129
20#: plugins/LightDM/Greeter.cpp:129
21msgid "Password: "
21msgid "Password: "
22−msgstr ""
22+msgstr "Ger-tremen : "
23
23
24#: plugins/Unity/Launcher/launcheritem.cpp:43
24#: plugins/Unity/Launcher/launcheritem.cpp:43
25#: plugins/Unity/Launcher/launcheritem.cpp:73
25#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -32,19 +32,19 @@ msgstr "Dispilhennañ ar verradenn"
32
32
33#: qml/Components/Dialogs.qml:142
33#: qml/Components/Dialogs.qml:142
34msgid "Are you sure you would like to turn power off?"
34msgid "Are you sure you would like to turn power off?"
35−msgstr ""
35+msgstr "Ha sur oc'h e fell deoc'h lazhañ ar benveg ?"
36
36
37#: qml/Components/Dialogs.qml:144
37#: qml/Components/Dialogs.qml:144
38msgid "Power off"
38msgid "Power off"
39−msgstr ""
39+msgstr "Lazhañ"
40
40
41#: qml/Components/Dialogs.qml:153
41#: qml/Components/Dialogs.qml:153
42msgid "Restart"
42msgid "Restart"
43−msgstr ""
43+msgstr "Adloc'hañ"
44
44
45#: qml/Components/Dialogs.qml:162
45#: qml/Components/Dialogs.qml:162
46msgid "Cancel"
46msgid "Cancel"
47−msgstr ""
47+msgstr "Nullañ"
48
48
49#: qml/Components/EdgeDemoOverlay.qml:151
49#: qml/Components/EdgeDemoOverlay.qml:151
50msgid "Skip intro"
50msgid "Skip intro"
@@ -101,11 +101,11 @@ msgstr ""
101
101
102#: qml/Components/Lockscreen.qml:167
102#: qml/Components/Lockscreen.qml:167
103msgid "Please wait"
103msgid "Please wait"
104−msgstr ""
104+msgstr "Gortozit, mar plij"
105
105
106#: qml/Components/Lockscreen.qml:172
106#: qml/Components/Lockscreen.qml:172
107msgid "Too many incorrect attempts"
107msgid "Too many incorrect attempts"
108−msgstr ""
108+msgstr "Re a daolioù-esae direizh"
109
109
110#: qml/Components/Lockscreen.qml:206
110#: qml/Components/Lockscreen.qml:206
111msgid "Emergency Call"
111msgid "Emergency Call"
@@ -158,23 +158,23 @@ msgstr "Kas"
158
158
159#: qml/Dash/ScopesOverview.qml:201
159#: qml/Dash/ScopesOverview.qml:201
160msgid "Manage Dash"
160msgid "Manage Dash"
161−msgstr ""
161+msgstr "Merañ an daolenn-vourzh"
162
162
163#: qml/Dash/ScopesOverview.qml:408
163#: qml/Dash/ScopesOverview.qml:408
164msgid "Done"
164msgid "Done"
165−msgstr ""
165+msgstr "Graet eo"
166
166
167#: qml/Dash/ScopesOverview.qml:434
167#: qml/Dash/ScopesOverview.qml:434
168msgid "Store"
168msgid "Store"
169−msgstr ""
169+msgstr "Enrollañ"
170
170
171#: qml/Dash/ScopesOverviewTab.qml:36
171#: qml/Dash/ScopesOverviewTab.qml:36
172msgid "Favorites"
172msgid "Favorites"
173−msgstr ""
173+msgstr "Gwellañ deuet"
174
174
175#: qml/Dash/ScopesOverviewTab.qml:54
175#: qml/Dash/ScopesOverviewTab.qml:54
176msgid "All"
176msgid "All"
177−msgstr ""
177+msgstr "An holl anezho"
178
178
179#: qml/Greeter/Greeter.qml:157
179#: qml/Greeter/Greeter.qml:157
180msgid "Swipe to unlock"
180msgid "Swipe to unlock"
@@ -206,11 +206,11 @@ msgstr "Diskouez ar ger-tremen"
206
206
207#: qml/Notifications/NotificationMenuItemFactory.qml:120
207#: qml/Notifications/NotificationMenuItemFactory.qml:120
208msgid "Enter SIM PIN"
208msgid "Enter SIM PIN"
209−msgstr ""
209+msgstr "Ebarzhit kod PIN ar gartenn SIM"
210
210
211#: qml/Notifications/NotificationMenuItemFactory.qml:121 qml/Shell.qml:270
211#: qml/Notifications/NotificationMenuItemFactory.qml:121 qml/Shell.qml:270
212msgid "Sorry, incorrect PIN"
212msgid "Sorry, incorrect PIN"
213−msgstr ""
213+msgstr "Siwazh, kod PIN direizh"
214
214
215#: qml/Panel/ActiveCallHint.qml:77
215#: qml/Panel/ActiveCallHint.qml:77
216msgid "Tap to return to call..."
216msgid "Tap to return to call..."
@@ -246,57 +246,61 @@ msgstr "C'hwitet, touchit evit adkregiñ"
246
246
247#: qml/Panel/Indicators/ModemInfoItem.qml:105
247#: qml/Panel/Indicators/ModemInfoItem.qml:105
248msgid "Unlock SIM"
248msgid "Unlock SIM"
249−msgstr ""
249+msgstr "Dibrennañ ar gartenn SIM"
250
250
251#: qml/Panel/Indicators/RoamingIndication.qml:27
251#: qml/Panel/Indicators/RoamingIndication.qml:27
252msgid "Roaming"
252msgid "Roaming"
253−msgstr ""
253+msgstr "O kantren"
254
254
255#: qml/Shell.qml:266
255#: qml/Shell.qml:266
256msgid "Enter your passphrase"
256msgid "Enter your passphrase"
257−msgstr ""
257+msgstr "Ebarzhit ho frazenn-dremen"
258
258
259#: qml/Shell.qml:267
259#: qml/Shell.qml:267
260msgid "Sorry, incorrect passphrase"
260msgid "Sorry, incorrect passphrase"
261−msgstr ""
261+msgstr "Siwazh, frazenn-dremen direizh"
262
262
263#: qml/Shell.qml:269
263#: qml/Shell.qml:269
264msgid "Enter your PIN"
264msgid "Enter your PIN"
265−msgstr ""
265+msgstr "Ebarzhit ho kod PIN"
266
266
267#: qml/Shell.qml:273
267#: qml/Shell.qml:273
268#, qt-format
268#, qt-format
269msgid "Enter your %1"
269msgid "Enter your %1"
270−msgstr ""
270+msgstr "Ebarzhit ho %1"
271
271
272#: qml/Shell.qml:274
272#: qml/Shell.qml:274
273#, qt-format
273#, qt-format
274msgid "Sorry, incorrect %1"
274msgid "Sorry, incorrect %1"
275−msgstr ""
275+msgstr "Siwazh, %1 direizh"
276
276
277#: qml/Shell.qml:310
277#: qml/Shell.qml:310
278msgid "Sorry, incorrect passphrase."
278msgid "Sorry, incorrect passphrase."
279−msgstr ""
279+msgstr "Siwazh, frazenn-dremen direizh"
280
280
281#: qml/Shell.qml:311
281#: qml/Shell.qml:311
282msgid "Sorry, incorrect passcode."
282msgid "Sorry, incorrect passcode."
283−msgstr ""
283+msgstr "Siwazh, kod-tremen direizh"
284
284
285#: qml/Shell.qml:312
285#: qml/Shell.qml:312
286msgid "This will be your last attempt."
286msgid "This will be your last attempt."
287−msgstr ""
287+msgstr "Ho taol-esae diwezhañ e vo."
288
288
289#: qml/Shell.qml:314
289#: qml/Shell.qml:314
290msgid ""
290msgid ""
291"If passphrase is entered incorrectly, your phone will conduct a factory "
291"If passphrase is entered incorrectly, your phone will conduct a factory "
292"reset and all personal data will be deleted."
292"reset and all personal data will be deleted."
293msgstr ""
293msgstr ""
294+"Ma vez ebarzhet ur frazenn-dremen direizh, e vo adderaouekaet ho pellgomzer "
295+"gant arventennoù al labouradeg hag e vo diverket an holl roadennoù personel"
294
296
295#: qml/Shell.qml:315
297#: qml/Shell.qml:315
296msgid ""
298msgid ""
297"If passcode is entered incorrectly, your phone will conduct a factory reset "
299"If passcode is entered incorrectly, your phone will conduct a factory reset "
298"and all personal data will be deleted."
300"and all personal data will be deleted."
299msgstr ""
301msgstr ""
302+"Ma vez ebarzhet ur c'hod-tremen direizh, e vo adderaouekaet ho pellgomzer "
303+"gant arventennoù al labouradeg hag e vo diverket an holl roadennoù personel."
300
304
301#~ msgid "CANCEL"
305#~ msgid "CANCEL"
302#~ msgstr "NULLAÑ"
306#~ msgstr "NULLAÑ"
@@ -306,3 +310,16 @@ msgstr ""
306
310
307#~ msgid "Please enter SIM PIN"
311#~ msgid "Please enter SIM PIN"
308#~ msgstr "Ebarzhit kod PIN ho kartenn SIM, mar plij"
312#~ msgstr "Ebarzhit kod PIN ho kartenn SIM, mar plij"
313+
314+#~ msgid "passcode"
315+#~ msgstr "kod-tremen"
316+
317+#~ msgid "passphrase"
318+#~ msgstr "frazenn-dremen"
319+
320+#, qt-format
321+#~ msgid "Incorrect %1"
322+#~ msgstr "%1 direizh"
323+
324+#~ msgid "Please re-enter"
325+#~ msgstr "Ebarzhit en-dro, mar plij"
po/ca.po+4−4
@@ -8,14 +8,14 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2014-08-21 11:36+0200\n"
10"POT-Creation-Date: 2014-08-21 11:36+0200\n"
11−"PO-Revision-Date: 2014-08-17 03:42+0000\n"
11+"PO-Revision-Date: 2014-08-26 17:37+0000\n"
12"Last-Translator: David Planella <david.planella@ubuntu.com>\n"
12"Last-Translator: David Planella <david.planella@ubuntu.com>\n"
13"Language-Team: Catalan <ca@li.org>\n"
13"Language-Team: Catalan <ca@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-08-23 07:16+0000\n"
17+"X-Launchpad-Export-Date: 2014-08-27 07:46+0000\n"
18−"X-Generator: Launchpad (build 17163)\n"
18+"X-Generator: Launchpad (build 17174)\n"
19
19
20#: plugins/LightDM/Greeter.cpp:129
20#: plugins/LightDM/Greeter.cpp:129
21msgid "Password: "
21msgid "Password: "
@@ -207,7 +207,7 @@ msgstr "Mostra la contrasenya"
207
207
208#: qml/Notifications/NotificationMenuItemFactory.qml:120
208#: qml/Notifications/NotificationMenuItemFactory.qml:120
209msgid "Enter SIM PIN"
209msgid "Enter SIM PIN"
210−msgstr ""
210+msgstr "Introduïu el PIN de la tarjeta SIM"
211
211
212#: qml/Notifications/NotificationMenuItemFactory.qml:121 qml/Shell.qml:270
212#: qml/Notifications/NotificationMenuItemFactory.qml:121 qml/Shell.qml:270
213msgid "Sorry, incorrect PIN"
213msgid "Sorry, incorrect PIN"
po/de.po+9−9
@@ -8,14 +8,14 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2014-08-21 11:36+0200\n"
10"POT-Creation-Date: 2014-08-21 11:36+0200\n"
11−"PO-Revision-Date: 2014-08-21 16:18+0000\n"
11+"PO-Revision-Date: 2014-08-26 10:17+0000\n"
12"Last-Translator: Martin Pitt <martin.pitt@ubuntu.com>\n"
12"Last-Translator: Martin Pitt <martin.pitt@ubuntu.com>\n"
13"Language-Team: German <de@li.org>\n"
13"Language-Team: German <de@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-08-23 07:17+0000\n"
17+"X-Launchpad-Export-Date: 2014-08-27 07:46+0000\n"
18−"X-Generator: Launchpad (build 17163)\n"
18+"X-Generator: Launchpad (build 17174)\n"
19
19
20#: plugins/LightDM/Greeter.cpp:129
20#: plugins/LightDM/Greeter.cpp:129
21msgid "Password: "
21msgid "Password: "
@@ -204,11 +204,11 @@ msgstr "Passwort anzeigen"
204
204
205#: qml/Notifications/NotificationMenuItemFactory.qml:120
205#: qml/Notifications/NotificationMenuItemFactory.qml:120
206msgid "Enter SIM PIN"
206msgid "Enter SIM PIN"
207−msgstr ""
207+msgstr "Geben Sie die SIM-PIN ein"
208
208
209#: qml/Notifications/NotificationMenuItemFactory.qml:121 qml/Shell.qml:270
209#: qml/Notifications/NotificationMenuItemFactory.qml:121 qml/Shell.qml:270
210msgid "Sorry, incorrect PIN"
210msgid "Sorry, incorrect PIN"
211−msgstr ""
211+msgstr "Die PIN ist nicht korrekt"
212
212
213#: qml/Panel/ActiveCallHint.qml:77
213#: qml/Panel/ActiveCallHint.qml:77
214msgid "Tap to return to call..."
214msgid "Tap to return to call..."
@@ -252,15 +252,15 @@ msgstr "Roaming"
252
252
253#: qml/Shell.qml:266
253#: qml/Shell.qml:266
254msgid "Enter your passphrase"
254msgid "Enter your passphrase"
255−msgstr ""
255+msgstr "Geben Sie Ihr Passwort ein"
256
256
257#: qml/Shell.qml:267
257#: qml/Shell.qml:267
258msgid "Sorry, incorrect passphrase"
258msgid "Sorry, incorrect passphrase"
259−msgstr ""
259+msgstr "Das Passwort ist nicht korrekt"
260
260
261#: qml/Shell.qml:269
261#: qml/Shell.qml:269
262msgid "Enter your PIN"
262msgid "Enter your PIN"
263−msgstr ""
263+msgstr "Geben Sie Ihre PIN ein"
264
264
265#: qml/Shell.qml:273
265#: qml/Shell.qml:273
266#, qt-format
266#, qt-format
@@ -270,7 +270,7 @@ msgstr "%1 eingeben"
270#: qml/Shell.qml:274
270#: qml/Shell.qml:274
271#, qt-format
271#, qt-format
272msgid "Sorry, incorrect %1"
272msgid "Sorry, incorrect %1"
273−msgstr ""
273+msgstr "%1 falsch"
274
274
275#: qml/Shell.qml:310
275#: qml/Shell.qml:310
276msgid "Sorry, incorrect passphrase."
276msgid "Sorry, incorrect passphrase."
po/fi.po+10−10
@@ -8,14 +8,14 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2014-08-21 11:36+0200\n"
10"POT-Creation-Date: 2014-08-21 11:36+0200\n"
11−"PO-Revision-Date: 2014-08-22 08:55+0000\n"
11+"PO-Revision-Date: 2014-08-26 18:32+0000\n"
12−"Last-Translator: Timo Jyrinki <timo.jyrinki@canonical.com>\n"
12+"Last-Translator: Jiri Grönroos <Unknown>\n"
13"Language-Team: Finnish <fi@li.org>\n"
13"Language-Team: Finnish <fi@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-08-23 07:17+0000\n"
17+"X-Launchpad-Export-Date: 2014-08-27 07:46+0000\n"
18−"X-Generator: Launchpad (build 17163)\n"
18+"X-Generator: Launchpad (build 17174)\n"
19
19
20#: plugins/LightDM/Greeter.cpp:129
20#: plugins/LightDM/Greeter.cpp:129
21msgid "Password: "
21msgid "Password: "
@@ -201,11 +201,11 @@ msgstr "Näytä salasana"
201
201
202#: qml/Notifications/NotificationMenuItemFactory.qml:120
202#: qml/Notifications/NotificationMenuItemFactory.qml:120
203msgid "Enter SIM PIN"
203msgid "Enter SIM PIN"
204−msgstr ""
204+msgstr "Anna SIM-kortin PIN-koodi"
205
205
206#: qml/Notifications/NotificationMenuItemFactory.qml:121 qml/Shell.qml:270
206#: qml/Notifications/NotificationMenuItemFactory.qml:121 qml/Shell.qml:270
207msgid "Sorry, incorrect PIN"
207msgid "Sorry, incorrect PIN"
208−msgstr ""
208+msgstr "Väärä PIN-koodi"
209
209
210#: qml/Panel/ActiveCallHint.qml:77
210#: qml/Panel/ActiveCallHint.qml:77
211msgid "Tap to return to call..."
211msgid "Tap to return to call..."
@@ -249,15 +249,15 @@ msgstr "Verkkovierailu"
249
249
250#: qml/Shell.qml:266
250#: qml/Shell.qml:266
251msgid "Enter your passphrase"
251msgid "Enter your passphrase"
252−msgstr ""
252+msgstr "Anna tunnuslause"
253
253
254#: qml/Shell.qml:267
254#: qml/Shell.qml:267
255msgid "Sorry, incorrect passphrase"
255msgid "Sorry, incorrect passphrase"
256−msgstr ""
256+msgstr "Virheellinen tunnuslause"
257
257
258#: qml/Shell.qml:269
258#: qml/Shell.qml:269
259msgid "Enter your PIN"
259msgid "Enter your PIN"
260−msgstr ""
260+msgstr "Anna PIN-koodi"
261
261
262#: qml/Shell.qml:273
262#: qml/Shell.qml:273
263#, qt-format
263#, qt-format
@@ -267,7 +267,7 @@ msgstr "Anna %1"
267#: qml/Shell.qml:274
267#: qml/Shell.qml:274
268#, qt-format
268#, qt-format
269msgid "Sorry, incorrect %1"
269msgid "Sorry, incorrect %1"
270−msgstr ""
270+msgstr "Väärä %1"
271
271
272#: qml/Shell.qml:310
272#: qml/Shell.qml:310
273msgid "Sorry, incorrect passphrase."
273msgid "Sorry, incorrect passphrase."
po/fr.po+6−6
@@ -8,14 +8,14 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2014-08-21 11:36+0200\n"
10"POT-Creation-Date: 2014-08-21 11:36+0200\n"
11−"PO-Revision-Date: 2014-08-16 12:13+0000\n"
11+"PO-Revision-Date: 2014-08-27 07:33+0000\n"
12−"Last-Translator: Jean Marc <Unknown>\n"
12+"Last-Translator: Sébastien Maes <nautilussebastien@gmail.com>\n"
13"Language-Team: French <fr@li.org>\n"
13"Language-Team: French <fr@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-08-23 07:17+0000\n"
17+"X-Launchpad-Export-Date: 2014-08-27 07:46+0000\n"
18−"X-Generator: Launchpad (build 17163)\n"
18+"X-Generator: Launchpad (build 17174)\n"
19
19
20#: plugins/LightDM/Greeter.cpp:129
20#: plugins/LightDM/Greeter.cpp:129
21msgid "Password: "
21msgid "Password: "
@@ -212,7 +212,7 @@ msgstr ""
212
212
213#: qml/Notifications/NotificationMenuItemFactory.qml:121 qml/Shell.qml:270
213#: qml/Notifications/NotificationMenuItemFactory.qml:121 qml/Shell.qml:270
214msgid "Sorry, incorrect PIN"
214msgid "Sorry, incorrect PIN"
215−msgstr ""
215+msgstr "Désolé, code PIN incorrect"
216
216
217#: qml/Panel/ActiveCallHint.qml:77
217#: qml/Panel/ActiveCallHint.qml:77
218msgid "Tap to return to call..."
218msgid "Tap to return to call..."
@@ -264,7 +264,7 @@ msgstr ""
264
264
265#: qml/Shell.qml:269
265#: qml/Shell.qml:269
266msgid "Enter your PIN"
266msgid "Enter your PIN"
267−msgstr ""
267+msgstr "Entrez votre code PIN"
268
268
269#: qml/Shell.qml:273
269#: qml/Shell.qml:273
270#, qt-format
270#, qt-format
po/nl.po+9−9
@@ -8,14 +8,14 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2014-08-21 11:36+0200\n"
10"POT-Creation-Date: 2014-08-21 11:36+0200\n"
11−"PO-Revision-Date: 2014-08-14 19:08+0000\n"
11+"PO-Revision-Date: 2014-08-26 19:39+0000\n"
12"Last-Translator: rob <linuxned@gmail.com>\n"
12"Last-Translator: rob <linuxned@gmail.com>\n"
13"Language-Team: Dutch <nl@li.org>\n"
13"Language-Team: Dutch <nl@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-08-23 07:16+0000\n"
17+"X-Launchpad-Export-Date: 2014-08-27 07:46+0000\n"
18−"X-Generator: Launchpad (build 17163)\n"
18+"X-Generator: Launchpad (build 17174)\n"
19
19
20#: plugins/LightDM/Greeter.cpp:129
20#: plugins/LightDM/Greeter.cpp:129
21msgid "Password: "
21msgid "Password: "
@@ -201,11 +201,11 @@ msgstr "Wachtwoord tonen"
201
201
202#: qml/Notifications/NotificationMenuItemFactory.qml:120
202#: qml/Notifications/NotificationMenuItemFactory.qml:120
203msgid "Enter SIM PIN"
203msgid "Enter SIM PIN"
204−msgstr ""
204+msgstr "Voer SIM-pincode in"
205
205
206#: qml/Notifications/NotificationMenuItemFactory.qml:121 qml/Shell.qml:270
206#: qml/Notifications/NotificationMenuItemFactory.qml:121 qml/Shell.qml:270
207msgid "Sorry, incorrect PIN"
207msgid "Sorry, incorrect PIN"
208−msgstr ""
208+msgstr "Sorry, onjuiste pincode"
209
209
210#: qml/Panel/ActiveCallHint.qml:77
210#: qml/Panel/ActiveCallHint.qml:77
211msgid "Tap to return to call..."
211msgid "Tap to return to call..."
@@ -249,15 +249,15 @@ msgstr "Roaming"
249
249
250#: qml/Shell.qml:266
250#: qml/Shell.qml:266
251msgid "Enter your passphrase"
251msgid "Enter your passphrase"
252−msgstr ""
252+msgstr "Voer uw wachtwoordzin in"
253
253
254#: qml/Shell.qml:267
254#: qml/Shell.qml:267
255msgid "Sorry, incorrect passphrase"
255msgid "Sorry, incorrect passphrase"
256−msgstr ""
256+msgstr "Sorry, onjuiste wachtwoordzin"
257
257
258#: qml/Shell.qml:269
258#: qml/Shell.qml:269
259msgid "Enter your PIN"
259msgid "Enter your PIN"
260−msgstr ""
260+msgstr "Voer uw pincode in"
261
261
262#: qml/Shell.qml:273
262#: qml/Shell.qml:273
263#, qt-format
263#, qt-format
@@ -267,7 +267,7 @@ msgstr "Voer uw %1 in"
267#: qml/Shell.qml:274
267#: qml/Shell.qml:274
268#, qt-format
268#, qt-format
269msgid "Sorry, incorrect %1"
269msgid "Sorry, incorrect %1"
270−msgstr ""
270+msgstr "Sorry, onjuiste %1"
271
271
272#: qml/Shell.qml:310
272#: qml/Shell.qml:310
273msgid "Sorry, incorrect passphrase."
273msgid "Sorry, incorrect passphrase."
po/ro.po+6−6
@@ -8,14 +8,14 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2014-08-21 11:36+0200\n"
10"POT-Creation-Date: 2014-08-21 11:36+0200\n"
11−"PO-Revision-Date: 2014-08-14 19:34+0000\n"
11+"PO-Revision-Date: 2014-08-26 18:53+0000\n"
12−"Last-Translator: Marian Vasile <marianvasile1972@gmail.com>\n"
12+"Last-Translator: Meriuță Cornel <meriutacornel@neacornel.eu>\n"
13"Language-Team: Romanian <ro@li.org>\n"
13"Language-Team: Romanian <ro@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-08-23 07:17+0000\n"
17+"X-Launchpad-Export-Date: 2014-08-27 07:46+0000\n"
18−"X-Generator: Launchpad (build 17163)\n"
18+"X-Generator: Launchpad (build 17174)\n"
19
19
20#: plugins/LightDM/Greeter.cpp:129
20#: plugins/LightDM/Greeter.cpp:129
21msgid "Password: "
21msgid "Password: "
@@ -204,7 +204,7 @@ msgstr "Arată parola"
204
204
205#: qml/Notifications/NotificationMenuItemFactory.qml:120
205#: qml/Notifications/NotificationMenuItemFactory.qml:120
206msgid "Enter SIM PIN"
206msgid "Enter SIM PIN"
207−msgstr ""
207+msgstr "Introduceți codul PIN pentru SIM"
208
208
209#: qml/Notifications/NotificationMenuItemFactory.qml:121 qml/Shell.qml:270
209#: qml/Notifications/NotificationMenuItemFactory.qml:121 qml/Shell.qml:270
210msgid "Sorry, incorrect PIN"
210msgid "Sorry, incorrect PIN"
@@ -252,7 +252,7 @@ msgstr "Roaming"
252
252
253#: qml/Shell.qml:266
253#: qml/Shell.qml:266
254msgid "Enter your passphrase"
254msgid "Enter your passphrase"
255−msgstr ""
255+msgstr "Introduceți fraza dumneavoastră secretă"
256
256
257#: qml/Shell.qml:267
257#: qml/Shell.qml:267
258msgid "Sorry, incorrect passphrase"
258msgid "Sorry, incorrect passphrase"
po/ru.po+9−9
@@ -8,14 +8,14 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2014-08-21 11:36+0200\n"
10"POT-Creation-Date: 2014-08-21 11:36+0200\n"
11−"PO-Revision-Date: 2014-08-20 12:41+0000\n"
11+"PO-Revision-Date: 2014-08-26 10:01+0000\n"
12"Last-Translator: Jay ZDLin <Unknown>\n"
12"Last-Translator: Jay ZDLin <Unknown>\n"
13"Language-Team: Russian <ru@li.org>\n"
13"Language-Team: Russian <ru@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-08-23 07:17+0000\n"
17+"X-Launchpad-Export-Date: 2014-08-27 07:46+0000\n"
18−"X-Generator: Launchpad (build 17163)\n"
18+"X-Generator: Launchpad (build 17174)\n"
19
19
20#: plugins/LightDM/Greeter.cpp:129
20#: plugins/LightDM/Greeter.cpp:129
21msgid "Password: "
21msgid "Password: "
@@ -206,11 +206,11 @@ msgstr "Показать пароль"
206
206
207#: qml/Notifications/NotificationMenuItemFactory.qml:120
207#: qml/Notifications/NotificationMenuItemFactory.qml:120
208msgid "Enter SIM PIN"
208msgid "Enter SIM PIN"
209−msgstr ""
209+msgstr "Введите ПИН-код SIM-карты"
210
210
211#: qml/Notifications/NotificationMenuItemFactory.qml:121 qml/Shell.qml:270
211#: qml/Notifications/NotificationMenuItemFactory.qml:121 qml/Shell.qml:270
212msgid "Sorry, incorrect PIN"
212msgid "Sorry, incorrect PIN"
213−msgstr ""
213+msgstr "Введён неверный ПИН-код"
214
214
215#: qml/Panel/ActiveCallHint.qml:77
215#: qml/Panel/ActiveCallHint.qml:77
216msgid "Tap to return to call..."
216msgid "Tap to return to call..."
@@ -254,15 +254,15 @@ msgstr "Роуминг"
254
254
255#: qml/Shell.qml:266
255#: qml/Shell.qml:266
256msgid "Enter your passphrase"
256msgid "Enter your passphrase"
257−msgstr ""
257+msgstr "Введите кодовую фразу"
258
258
259#: qml/Shell.qml:267
259#: qml/Shell.qml:267
260msgid "Sorry, incorrect passphrase"
260msgid "Sorry, incorrect passphrase"
261−msgstr ""
261+msgstr "Введена неверная кодовая фраза"
262
262
263#: qml/Shell.qml:269
263#: qml/Shell.qml:269
264msgid "Enter your PIN"
264msgid "Enter your PIN"
265−msgstr ""
265+msgstr "Введите ПИН-код"
266
266
267#: qml/Shell.qml:273
267#: qml/Shell.qml:273
268#, qt-format
268#, qt-format
@@ -272,7 +272,7 @@ msgstr "Введите %1"
272#: qml/Shell.qml:274
272#: qml/Shell.qml:274
273#, qt-format
273#, qt-format
274msgid "Sorry, incorrect %1"
274msgid "Sorry, incorrect %1"
275−msgstr ""
275+msgstr "Некорректный ввод %1"
276
276
277#: qml/Shell.qml:310
277#: qml/Shell.qml:310
278msgid "Sorry, incorrect passphrase."
278msgid "Sorry, incorrect passphrase."
po/uk.po+9−9
@@ -8,14 +8,14 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2014-08-21 11:36+0200\n"
10"POT-Creation-Date: 2014-08-21 11:36+0200\n"
11−"PO-Revision-Date: 2014-08-17 14:49+0000\n"
11+"PO-Revision-Date: 2014-08-26 19:06+0000\n"
12"Last-Translator: Yuri Chornoivan <yurchor@gmail.com>\n"
12"Last-Translator: Yuri Chornoivan <yurchor@gmail.com>\n"
13"Language-Team: Ukrainian <uk@li.org>\n"
13"Language-Team: Ukrainian <uk@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-08-23 07:17+0000\n"
17+"X-Launchpad-Export-Date: 2014-08-27 07:46+0000\n"
18−"X-Generator: Launchpad (build 17163)\n"
18+"X-Generator: Launchpad (build 17174)\n"
19
19
20#: plugins/LightDM/Greeter.cpp:129
20#: plugins/LightDM/Greeter.cpp:129
21msgid "Password: "
21msgid "Password: "
@@ -204,11 +204,11 @@ msgstr "Показати пароль"
204
204
205#: qml/Notifications/NotificationMenuItemFactory.qml:120
205#: qml/Notifications/NotificationMenuItemFactory.qml:120
206msgid "Enter SIM PIN"
206msgid "Enter SIM PIN"
207−msgstr ""
207+msgstr "Введіть PIN-код SIM-картки"
208
208
209#: qml/Notifications/NotificationMenuItemFactory.qml:121 qml/Shell.qml:270
209#: qml/Notifications/NotificationMenuItemFactory.qml:121 qml/Shell.qml:270
210msgid "Sorry, incorrect PIN"
210msgid "Sorry, incorrect PIN"
211−msgstr ""
211+msgstr "Вибачте, помилковий PIN-код"
212
212
213#: qml/Panel/ActiveCallHint.qml:77
213#: qml/Panel/ActiveCallHint.qml:77
214msgid "Tap to return to call..."
214msgid "Tap to return to call..."
@@ -252,15 +252,15 @@ msgstr "Роумінг"
252
252
253#: qml/Shell.qml:266
253#: qml/Shell.qml:266
254msgid "Enter your passphrase"
254msgid "Enter your passphrase"
255−msgstr ""
255+msgstr "Введіть ваш пароль"
256
256
257#: qml/Shell.qml:267
257#: qml/Shell.qml:267
258msgid "Sorry, incorrect passphrase"
258msgid "Sorry, incorrect passphrase"
259−msgstr ""
259+msgstr "Вибачте, помилковий пароль"
260
260
261#: qml/Shell.qml:269
261#: qml/Shell.qml:269
262msgid "Enter your PIN"
262msgid "Enter your PIN"
263−msgstr ""
263+msgstr "Введіть ваш PIN-код"
264
264
265#: qml/Shell.qml:273
265#: qml/Shell.qml:273
266#, qt-format
266#, qt-format
@@ -270,7 +270,7 @@ msgstr "Вкажіть ваш %1"
270#: qml/Shell.qml:274
270#: qml/Shell.qml:274
271#, qt-format
271#, qt-format
272msgid "Sorry, incorrect %1"
272msgid "Sorry, incorrect %1"
273−msgstr ""
273+msgstr "Вибачте, помилковий %1"
274
274
275#: qml/Shell.qml:310
275#: qml/Shell.qml:310
276msgid "Sorry, incorrect passphrase."
276msgid "Sorry, incorrect passphrase."
po/unity8.pot+77−24
@@ -8,7 +8,7 @@ msgid ""
8msgstr ""
8msgstr ""
9"Project-Id-Version: unity8\n"
9"Project-Id-Version: unity8\n"
10"Report-Msgid-Bugs-To: \n"
10"Report-Msgid-Bugs-To: \n"
11−"POT-Creation-Date: 2014-08-21 11:36+0200\n"
11+"POT-Creation-Date: 2014-08-26 18:24+0200\n"
12"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
12"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14"Language-Team: LANGUAGE <LL@li.org>\n"
14"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -17,7 +17,7 @@ msgstr ""
17"Content-Type: text/plain; charset=UTF-8\n"
17"Content-Type: text/plain; charset=UTF-8\n"
18"Content-Transfer-Encoding: 8bit\n"
18"Content-Transfer-Encoding: 8bit\n"
19
19
20−#: plugins/LightDM/Greeter.cpp:129
20+#: plugins/LightDM/Greeter.cpp:130
21msgid "Password: "
21msgid "Password: "
22msgstr ""
22msgstr ""
23
23
@@ -30,19 +30,55 @@ msgstr ""
30msgid "Unpin shortcut"
30msgid "Unpin shortcut"
31msgstr ""
31msgstr ""
32
32
33−#: qml/Components/Dialogs.qml:142
33+#: qml/Components/Dialogs.qml:70
34−msgid "Are you sure you would like to turn power off?"
34+msgid "Log out"
35+msgstr ""
36+
37+#: qml/Components/Dialogs.qml:71
38+msgid "Are you sure you want to log out?"
39+msgstr ""
40+
41+#: qml/Components/Dialogs.qml:73 qml/Components/Dialogs.qml:97
42+#: qml/Components/Dialogs.qml:122
43+msgid "No"
44+msgstr ""
45+
46+#: qml/Components/Dialogs.qml:80 qml/Components/Dialogs.qml:104
47+#: qml/Components/Dialogs.qml:129
48+msgid "Yes"
49+msgstr ""
50+
51+#: qml/Components/Dialogs.qml:94
52+msgid "Shut down"
53+msgstr ""
54+
55+#: qml/Components/Dialogs.qml:95
56+msgid "Are you sure you want to shut down?"
57+msgstr ""
58+
59+#: qml/Components/Dialogs.qml:119
60+msgid "Reboot"
61+msgstr ""
62+
63+#: qml/Components/Dialogs.qml:120
64+msgid "Are you sure you want to reboot?"
35msgstr ""
65msgstr ""
36
66
37#: qml/Components/Dialogs.qml:144
67#: qml/Components/Dialogs.qml:144
38−msgid "Power off"
68+msgid "Power"
39msgstr ""
69msgstr ""
40
70
41−#: qml/Components/Dialogs.qml:153
71+#: qml/Components/Dialogs.qml:145
42−msgid "Restart"
72+msgid ""
73+"Are you sure you would like\n"
74+"to power off?"
43msgstr ""
75msgstr ""
44
76
45−#: qml/Components/Dialogs.qml:162
77+#: qml/Components/Dialogs.qml:147
78+msgid "Power off"
79+msgstr ""
80+
81+#: qml/Components/Dialogs.qml:157
46msgid "Cancel"
82msgid "Cancel"
47msgstr ""
83msgstr ""
48
84
@@ -125,10 +161,23 @@ msgstr ""
125msgid "See all"
161msgid "See all"
126msgstr ""
162msgstr ""
127
163
128−#: qml/Dash/GenericScopeView.qml:424 qml/Panel/SearchIndicator.qml:27
164+#: qml/Dash/GenericScopeView.qml:424 qml/Dash/PageHeader.qml:260
165+#: qml/Panel/SearchIndicator.qml:27
129msgid "Search"
166msgid "Search"
130msgstr ""
167msgstr ""
131
168
169+#: qml/Dash/PageHeader.qml:270
170+msgid "Settings"
171+msgstr ""
172+
173+#: qml/Dash/PageHeader.qml:279
174+msgid "Remove from Favorites"
175+msgstr ""
176+
177+#: qml/Dash/PageHeader.qml:279
178+msgid "Add to Favorites"
179+msgstr ""
180+
132#: qml/Dash/Previews/PreviewActionCombo.qml:34
181#: qml/Dash/Previews/PreviewActionCombo.qml:34
133msgid "More..."
182msgid "More..."
134msgstr ""
183msgstr ""
@@ -153,11 +202,11 @@ msgstr ""
153msgid "Manage Dash"
202msgid "Manage Dash"
154msgstr ""
203msgstr ""
155
204
156−#: qml/Dash/ScopesOverview.qml:408
205+#: qml/Dash/ScopesOverview.qml:417
157msgid "Done"
206msgid "Done"
158msgstr ""
207msgstr ""
159
208
160−#: qml/Dash/ScopesOverview.qml:434
209+#: qml/Dash/ScopesOverview.qml:443
161msgid "Store"
210msgid "Store"
162msgstr ""
211msgstr ""
163
212
@@ -173,7 +222,7 @@ msgstr ""
173msgid "Swipe to unlock"
222msgid "Swipe to unlock"
174msgstr ""
223msgstr ""
175
224
176−#: qml/Hud/HudParametrizedActionsPage.qml:132
225+#: qml/Hud/HudParametrizedActionsPage.qml:139
177msgid "Confirm"
226msgid "Confirm"
178msgstr ""
227msgstr ""
179
228
@@ -201,7 +250,7 @@ msgstr ""
201msgid "Enter SIM PIN"
250msgid "Enter SIM PIN"
202msgstr ""
251msgstr ""
203
252
204−#: qml/Notifications/NotificationMenuItemFactory.qml:121 qml/Shell.qml:270
253+#: qml/Notifications/NotificationMenuItemFactory.qml:121
205msgid "Sorry, incorrect PIN"
254msgid "Sorry, incorrect PIN"
206msgstr ""
255msgstr ""
207
256
@@ -245,47 +294,51 @@ msgstr ""
245msgid "Roaming"
294msgid "Roaming"
246msgstr ""
295msgstr ""
247
296
248−#: qml/Shell.qml:266
297+#: qml/Shell.qml:279
249msgid "Enter your passphrase"
298msgid "Enter your passphrase"
250msgstr ""
299msgstr ""
251
300
252−#: qml/Shell.qml:267
301+#: qml/Shell.qml:280
253msgid "Sorry, incorrect passphrase"
302msgid "Sorry, incorrect passphrase"
254msgstr ""
303msgstr ""
255
304
256−#: qml/Shell.qml:269
305+#: qml/Shell.qml:282
257−msgid "Enter your PIN"
306+msgid "Enter your passcode"
307+msgstr ""
308+
309+#: qml/Shell.qml:283
310+msgid "Sorry, incorrect passcode"
258msgstr ""
311msgstr ""
259
312
260−#: qml/Shell.qml:273
313+#: qml/Shell.qml:286
261#, qt-format
314#, qt-format
262msgid "Enter your %1"
315msgid "Enter your %1"
263msgstr ""
316msgstr ""
264
317
265−#: qml/Shell.qml:274
318+#: qml/Shell.qml:287
266#, qt-format
319#, qt-format
267msgid "Sorry, incorrect %1"
320msgid "Sorry, incorrect %1"
268msgstr ""
321msgstr ""
269
322
270−#: qml/Shell.qml:310
323+#: qml/Shell.qml:323
271msgid "Sorry, incorrect passphrase."
324msgid "Sorry, incorrect passphrase."
272msgstr ""
325msgstr ""
273
326
274−#: qml/Shell.qml:311
327+#: qml/Shell.qml:324
275msgid "Sorry, incorrect passcode."
328msgid "Sorry, incorrect passcode."
276msgstr ""
329msgstr ""
277
330
278−#: qml/Shell.qml:312
331+#: qml/Shell.qml:325
279msgid "This will be your last attempt."
332msgid "This will be your last attempt."
280msgstr ""
333msgstr ""
281
334
282−#: qml/Shell.qml:314
335+#: qml/Shell.qml:327
283msgid ""
336msgid ""
284"If passphrase is entered incorrectly, your phone will conduct a factory "
337"If passphrase is entered incorrectly, your phone will conduct a factory "
285"reset and all personal data will be deleted."
338"reset and all personal data will be deleted."
286msgstr ""
339msgstr ""
287
340
288−#: qml/Shell.qml:315
341+#: qml/Shell.qml:328
289msgid ""
342msgid ""
290"If passcode is entered incorrectly, your phone will conduct a factory reset "
343"If passcode is entered incorrectly, your phone will conduct a factory reset "
291"and all personal data will be deleted."
344"and all personal data will be deleted."
qml/Components/Background.qml+10
@@ -15,6 +15,8 @@
15 */
15 */
16
16
17import QtQuick 2.0
17import QtQuick 2.0
18+import Ubuntu.Components 1.1
19+import Utils 0.1 as Utils
18
20
19Loader {
21Loader {
20 id: root
22 id: root
@@ -23,6 +25,14 @@ Loader {
23 property url style
25 property url style
24 readonly property var parsedStyle: String(style)
26 readonly property var parsedStyle: String(style)
25 .match(/^(color|gradient):\/\/\/(?:(#(?:[0-9a-f]{3,4}){1,2}|[a-z]{3,}))(?:\/(#(?:[0-9a-f]{3,4}){1,2}|[a-z]{3,}))?\/?$/i)
27 .match(/^(color|gradient):\/\/\/(?:(#(?:[0-9a-f]{3,4}){1,2}|[a-z]{3,}))(?:\/(#(?:[0-9a-f]{3,4}){1,2}|[a-z]{3,}))?\/?$/i)
28+ readonly property var luminance: {
29+ if (!parsedStyle) return 0.5;
30+ if (parsedStyle[1] === "color") return Utils.Style.luminance(parsedStyle[2]);
31+ else if (parsedStyle[1] === "gradient") return Utils.Style.luminance(parsedStyle[2], parsedStyle[3]);
32+ }
33+
34+ // FIXME this is only here for highlight purposes (see DashNavigation.qml, too)
35+ readonly property color topColor: parsedStyle ? parsedStyle[2] : UbuntuColors.lightGrey
26
36
27 sourceComponent: {
37 sourceComponent: {
28 if (style == "") return null;
38 if (style == "") return null;
qml/Dash/Dash.qml+1−1
@@ -341,7 +341,7 @@ Showable {
341 objectName: "overviewDragHandle"
341 objectName: "overviewDragHandle"
342 z: 1
342 z: 1
343 direction: Direction.Upwards
343 direction: Direction.Upwards
344− enabled: !dashContent.previewShown &&
344+ enabled: !dashContent.subPageShown &&
345 dashContent.currentScope &&
345 dashContent.currentScope &&
346 dashContent.currentScope.searchQuery == "" &&
346 dashContent.currentScope.searchQuery == "" &&
347 (overviewController.progress == 0 || dragging)
347 (overviewController.progress == 0 || dragging)
qml/Dash/DashContent.qml+29−4
@@ -27,8 +27,8 @@ Item {
27 readonly property alias currentIndex: dashContentList.currentIndex
27 readonly property alias currentIndex: dashContentList.currentIndex
28 readonly property string currentScopeId: dashContentList.currentItem ? dashContentList.currentItem.scopeId : ""
28 readonly property string currentScopeId: dashContentList.currentItem ? dashContentList.currentItem.scopeId : ""
29 readonly property var currentScope: dashContentList.currentItem ? dashContentList.currentItem.theScope : null
29 readonly property var currentScope: dashContentList.currentItem ? dashContentList.currentItem.theScope : null
30− readonly property bool previewShown: dashContentList.currentItem && dashContentList.currentItem.item ?
30+ readonly property bool subPageShown: dashContentList.currentItem && dashContentList.currentItem.item ?
31− dashContentList.currentItem.item.previewShown : false
31+ dashContentList.currentItem.item.subPageShown : false
32 readonly property bool processing: dashContentList.currentItem && dashContentList.currentItem.item
32 readonly property bool processing: dashContentList.currentItem && dashContentList.currentItem.item
33 && dashContentList.currentItem.item.processing || false
33 && dashContentList.currentItem.item.processing || false
34 readonly property bool pageHeaderTotallyVisible: dashContentList.currentItem && dashContentList.currentItem.item
34 readonly property bool pageHeaderTotallyVisible: dashContentList.currentItem && dashContentList.currentItem.item
@@ -52,6 +52,11 @@ Item {
52 }
52 }
53 }
53 }
54
54
55+ Connections {
56+ target: UriHandler
57+ onOpened: dashContentList.currentItem.theScope.performQuery(uris[0])
58+ }
59+
55 function setCurrentScopeAtIndex(index, animate, reset) {
60 function setCurrentScopeAtIndex(index, animate, reset) {
56 // if the scopes haven't loaded yet, then wait until they are.
61 // if the scopes haven't loaded yet, then wait until they are.
57 if (!scopes.loaded) {
62 if (!scopes.loaded) {
@@ -96,8 +101,7 @@ Item {
96 id: dashContentList
101 id: dashContentList
97 objectName: "dashContentList"
102 objectName: "dashContentList"
98
103
99− interactive: dashContent.scopes.loaded && currentItem && !currentItem.moving && !currentItem.navigationShown
104+ interactive: dashContent.scopes.loaded && currentItem && !currentItem.moving && !currentItem.navigationShown && !currentItem.subPageShown
100−
101 anchors.fill: parent
105 anchors.fill: parent
102 orientation: ListView.Horizontal
106 orientation: ListView.Horizontal
103 boundsBehavior: Flickable.DragAndOvershootBounds
107 boundsBehavior: Flickable.DragAndOvershootBounds
@@ -111,6 +115,26 @@ Item {
111 onMovementStarted: currentItem.item.showHeader();
115 onMovementStarted: currentItem.item.showHeader();
112 clip: parent.x != 0
116 clip: parent.x != 0
113
117
118+ // TODO QTBUG-40846 and QTBUG-40848
119+ // The remove transition doesn't happen when removing the last item
120+ // And can't work around it because index is reset to -1 regardless of
121+ // ListView.delayRemove
122+
123+ remove: Transition {
124+ SequentialAnimation {
125+ PropertyAction { property: "layer.enabled"; value: true }
126+ PropertyAction { property: "ListView.delayRemove"; value: true }
127+ ParallelAnimation {
128+ PropertyAnimation { properties: "scale"; to: 0.25; duration: UbuntuAnimation.SnapDuration }
129+ PropertyAnimation { properties: "y"; to: dashContent.height; duration: UbuntuAnimation.SnapDuration }
130+ }
131+ PropertyAction { property: "ListView.delayRemove"; value: false }
132+ }
133+ }
134+ removeDisplaced: Transition {
135+ PropertyAnimation { property: "x"; duration: UbuntuAnimation.SnapDecision }
136+ }
137+
114 // If the number of items is less than the current index, then need to reset to another item.
138 // If the number of items is less than the current index, then need to reset to another item.
115 onCountChanged: {
139 onCountChanged: {
116 if (count > 0) {
140 if (count > 0) {
@@ -137,6 +161,7 @@ Item {
137
161
138 readonly property bool moving: item ? item.moving : false
162 readonly property bool moving: item ? item.moving : false
139 readonly property bool navigationShown: item ? item.navigationShown : false
163 readonly property bool navigationShown: item ? item.navigationShown : false
164+ readonly property bool subPageShown: item ? item.subPageShown : false
140 readonly property var categoryView: item ? item.categoryView : null
165 readonly property var categoryView: item ? item.categoryView : null
141 readonly property var theScope: scope
166 readonly property var theScope: scope
142
167
qml/Dash/DashNavigation.qml+62−159
@@ -16,195 +16,98 @@
16
16
17import QtQuick 2.2
17import QtQuick 2.2
18import Ubuntu.Components 1.1
18import Ubuntu.Components 1.1
19+import Dash 0.1
20+import "../Components"
19
21
20−AbstractButton {
22+Item {
21 id: root
23 id: root
22 objectName: "dashNavigation"
24 objectName: "dashNavigation"
23
25
24 property var scope: null
26 property var scope: null
25−
27+ property var scopeStyle: null
26− property bool showList: false
27−
28− readonly property var currentNavigation: scope && scope.hasNavigation ? scope.getNavigation(scope.currentNavigationId) : null
29
28
30 property alias windowWidth: blackRect.width
29 property alias windowWidth: blackRect.width
31 property alias windowHeight: blackRect.height
30 property alias windowHeight: blackRect.height
32− property var scopeStyle: null
31+ readonly property var openList: {
32+ if (navigationButton.showList) return navigationButton.listView;
33+ if (altNavigationButton.showList) return altNavigationButton.listView;
34+ return null;
35+ }
33
36
34− // Are we drilling down the tree or up?
37+ // FIXME this is only here for highlight purposes (see Background.qml, too)
35− property bool isGoingBack: false
38+ readonly property var background: backgroundItem
36
39
37− visible: root.currentNavigation != null
40+ visible: navigationButton.currentNavigation || altNavigationButton.currentNavigation
38
41
39 height: visible ? units.gu(5) : 0
42 height: visible ? units.gu(5) : 0
40
43
41− onClicked: {
44+ QtObject {
42− navigationListView.updateMaxHeight();
45+ id: d
43− root.showList = !root.showList;
46+ readonly property color foregroundColor: root.scopeStyle
47+ ? root.scopeStyle.getTextColor(backgroundItem.luminance)
48+ : Theme.palette.normal.baseText
49+ readonly property bool bothVisible: altNavigationButton.visible && navigationButton.visible
50+ readonly property real navigationWidth: root.width >= units.gu(60) ? units.gu(40) : root.width
51+ readonly property real buttonWidth: navigationWidth / (bothVisible ? 2 : 1)
44 }
52 }
45
53
46 Rectangle {
54 Rectangle {
47 id: blackRect
55 id: blackRect
48 color: "black"
56 color: "black"
49− opacity: navigationListView.currentItem && navigationListView.currentItem.visible ? 0.3 : 0
57+ opacity: openList && openList.currentItem && openList.currentItem.visible ? 0.5 : 0
50 Behavior on opacity { UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration } }
58 Behavior on opacity { UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration } }
51− anchors.top: navigationListView.top
52− anchors.right: parent.right
59+ anchors { left: parent.left; right: parent.right }
53− visible: opacity != 0
60+ visible: opacity > 0
54 }
61 }
55
62
56− Image {
63+ Background {
64+ id: backgroundItem
57− anchors {
65+ anchors.fill: parent
58− top: parent.top
66+ style: scopeStyle ? scopeStyle.navigationBackground : "color:///#f5f5f5"
59− left: parent.left
60− right: parent.right
61− }
62− fillMode: Image.Stretch
63− source: "graphics/dash_divider_top_lightgrad.png"
64− z: -1
65 }
67 }
66
68
67 Image {
69 Image {
68− anchors {
69− bottom: parent.bottom
70− left: parent.left
71− right: parent.right
72− }
73 fillMode: Image.Stretch
70 fillMode: Image.Stretch
74− source: "graphics/dash_divider_top_darkgrad.png"
71+ source: scopeStyle.backgroundLuminance > 0.2 ? "graphics/navigation_shadow.png" : "graphics/navigation_shadow_light.png"
75− z: -1
72+ anchors { top: parent.bottom; left: parent.left; right: parent.right }
76 }
73 }
77
74
78− Label {
75+ DashNavigationButton {
79− anchors.fill: parent
76+ id: altNavigationButton
80− anchors.margins: units.gu(2)
77+ objectName: "altNavigationButton"
81− verticalAlignment: Text.AlignVCenter
78+ height: root.height
82− text: root.currentNavigation ? root.currentNavigation.label : ""
79+ width: d.buttonWidth
83− color: root.scopeStyle ? root.scopeStyle.foreground : Theme.palette.normal.baseText
80+ scope: root.scope
81+ scopeStyle: root.scopeStyle
82+ foregroundColor: d.foregroundColor
83+ listView.width: d.navigationWidth
84+ isAltNavigation: true
85+ showDivider: navigationButton.visible || root.width > d.navigationWidth
86+ // needed so that InverseMouseArea is above navigationButton
87+ z: listView.height > 0 ? 1 : 0
84 }
88 }
85
89
86− Icon {
90+ DashNavigationButton {
87− anchors.verticalCenter: parent.verticalCenter
91+ id: navigationButton
88− anchors.right: parent.right
92+ objectName: "navigationButton"
89− anchors.rightMargin: units.gu(2)
93+ height: root.height
90− name: showList ? "up" : "down"
94+ width: altNavigationButton.visible ? d.buttonWidth : d.navigationWidth
91− height: units.gu(2)
95+ x: altNavigationButton.visible ? d.buttonWidth : 0
92− width: height
96+ scope: root.scope
93− color: root.scopeStyle ? root.scopeStyle.foreground : Theme.palette.normal.baseText
97+ scopeStyle: root.scopeStyle
98+ foregroundColor: d.foregroundColor
99+ listView.width: d.navigationWidth
100+ listView.x: -x
101+ showDivider: root.width > d.navigationWidth
94 }
102 }
95
103
96− // navigationListView is outside root
104+ Image {
97− ListView {
105+ fillMode: Image.Stretch
98− id: navigationListView
106+ source: backgroundItem.luminance > 0.7 ? "graphics/navigation_shadow.png" : "graphics/navigation_shadow_light.png"
99− objectName: "navigationListView"
107+ x: navigationButton.listView.height > 0 ? altNavigationButton.x : navigationButton.x
100− orientation: ListView.Horizontal
108+ width: d.buttonWidth
101− interactive: false
109+ rotation: 180
102− clip: root.width != windowWidth
110+ anchors.bottom: parent.bottom
103− model: ListModel {
111+ visible: d.bothVisible && (navigationButton.listView.height > 0 || altNavigationButton.listView.height > 0)
104− id: navigationModel
105− // We have two roles
106− // navigationId: the navigation id of the navigation the list represents
107− // nullifyNavigation: overrides navigationId to be null
108− // This is used to "clear" the delegate when going "right" on the tree
109− }
110− anchors {
111− left: parent.left
112− right: parent.right
113− top: root.bottom
114− }
115− property int maxHeight: -1
116− Component.onCompleted: updateMaxHeight();
117− function updateMaxHeight()
118− {
119− maxHeight = (windowHeight - mapToItem(null, 0, 0).y) - units.gu(8);
120− }
121− property int prevHeight: maxHeight
122− height: currentItem ? currentItem.height : maxHeight
123− onHeightChanged: {
124− if (root.showList) {
125− prevHeight = currentItem.desiredHeight;
126− }
127− }
128− highlightMoveDuration: UbuntuAnimation.FastDuration
129− delegate: DashNavigationList {
130− objectName: "navigation" + index
131− visible: height != 0
132− width: navigationListView.width
133− scopeStyle: root.scopeStyle
134− property real desiredHeight: {
135− if (root.showList) {
136− if (navigation && navigation.loaded && x == navigationListView.contentX)
137− {
138− navigationListView.updateMaxHeight();
139− return Math.min(implicitHeight, navigationListView.maxHeight);
140− } else {
141− return navigationListView.prevHeight;
142− }
143− } else {
144− return 0;
145− }
146− }
147− height: desiredHeight
148− navigation: (nullifyNavigation || !scope) ? null : scope.getNavigation(navigationId)
149− currentNavigation: root.currentNavigation
150− onEnterNavigation: {
151− scope.setNavigationState(newNavigationId, false);
152− // We only need to add a new item to the model
153− // if we have children, otherwise just load it
154− if (hasChildren) {
155− isGoingBack = false;
156− navigationModel.append({"navigationId": newNavigationId, "nullifyNavigation": false});
157− navigationListView.currentIndex++;
158− } else {
159− showList = false;
160− }
161− }
162− onGoBackToParentClicked: {
163− scope.setNavigationState(navigation.parentNavigationId, false);
164− isGoingBack = true;
165− navigationModel.setProperty(navigationListView.currentIndex - 1, "nullifyNavigation", false);
166− navigationListView.currentIndex--;
167− }
168− onAllNavigationClicked: {
169− showList = false;
170− if (root.currentNavigation.parentNavigationId == navigation.navigationId) {
171− // For leaves we have to go to the parent too
172− scope.setNavigationState(root.currentNavigation.parentNavigationId, false);
173− }
174− }
175− }
176− onContentXChanged: {
177− if (contentX == width * navigationListView.currentIndex) {
178− if (isGoingBack) {
179− navigationModel.remove(navigationListView.currentIndex + 1);
180− } else {
181− navigationModel.setProperty(navigationListView.currentIndex - 1, "nullifyNavigation", true);
182− }
183− }
184− }
185− }
186−
187− InverseMouseArea {
188− anchors.fill: navigationListView
189− enabled: root.showList
190− onClicked: root.showList = false
191− }
192−
193− onScopeChanged: {
194− navigationModel.clear();
195− if (scope && scope.hasNavigation) {
196− navigationModel.append({"navigationId": scope.currentNavigationId, "nullifyNavigation": false});
197− }
198− }
199−
200− Connections {
201− target: scope
202− onHasNavigationChanged: {
203− if (scope.hasNavigation) {
204− navigationModel.append({"navigationId": scope.currentNavigationId, "nullifyNavigation": false});
205− } else {
206− navigationModel.clear();
207− }
208− }
209 }
112 }
210}
113}
qml/Dash/DashNavigationButton.qmlnew file+226
@@ -0,0 +1,226 @@
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+import QtQuick 2.2
18+import Ubuntu.Components 1.1
19+
20+AbstractButton {
21+ id: root
22+ objectName: "dashNavigation"
23+
24+ // Set by parent
25+ property var scope: null
26+ property var scopeStyle: null
27+ property color foregroundColor: Theme.palette.normal.baseText
28+ property bool isAltNavigation: false
29+ property bool showDivider: false
30+
31+ // Used by parent
32+ readonly property var currentNavigation: scope && scope[hasNavigation] ? getNavigation(scope[currentNavigationId]) : null
33+ readonly property alias listView: navigationListView
34+ property bool showList: false
35+
36+ // Internal
37+ // Are we drilling down the tree or up?
38+ property bool isGoingBack: false
39+ readonly property string hasNavigation: isAltNavigation ? "hasAltNavigation" : "hasNavigation"
40+ readonly property string currentNavigationId: isAltNavigation ? "currentAltNavigationId" : "currentNavigationId"
41+ function getNavigation(navId) {
42+ if (isAltNavigation) {
43+ return scope.getAltNavigation(navId);
44+ } else {
45+ return scope.getNavigation(navId);
46+ }
47+ }
48+
49+ visible: root.currentNavigation != null
50+
51+ onClicked: {
52+ navigationListView.updateMaxHeight();
53+ root.showList = !root.showList;
54+ }
55+
56+ Label {
57+ anchors.fill: parent
58+ anchors.margins: units.gu(2)
59+ anchors.rightMargin: units.gu(5)
60+ verticalAlignment: Text.AlignVCenter
61+ text: root.currentNavigation ? root.currentNavigation.label : ""
62+ color: root.foregroundColor
63+ elide: Text.ElideRight
64+ maximumLineCount: 1
65+ }
66+
67+ Icon {
68+ anchors.verticalCenter: parent.verticalCenter
69+ anchors.right: parent.right
70+ anchors.rightMargin: units.gu(2)
71+ name: showList ? "up" : "down"
72+ height: units.gu(2)
73+ width: height
74+ color: root.foregroundColor
75+ }
76+
77+ // navigationListView is outside root
78+ ListView {
79+ id: navigationListView
80+ objectName: "navigationListView"
81+ visible: height > 0
82+ orientation: ListView.Horizontal
83+ interactive: false
84+ clip: root.width != windowWidth
85+ model: ListModel {
86+ id: navigationModel
87+ // We have two roles
88+ // navigationId: the navigation id of the navigation the list represents
89+ // nullifyNavigation: overrides navigationId to be null
90+ // This is used to "clear" the delegate when going "right" on the tree
91+ }
92+ anchors.top: root.bottom
93+ property int maxHeight: -1
94+ Component.onCompleted: updateMaxHeight();
95+ function updateMaxHeight()
96+ {
97+ maxHeight = (windowHeight - mapToItem(null, 0, 0).y) - units.gu(8);
98+ }
99+ property int prevHeight: maxHeight
100+ height: currentItem ? currentItem.height : maxHeight
101+ onHeightChanged: {
102+ if (root.showList) {
103+ prevHeight = currentItem.desiredHeight;
104+ }
105+ }
106+ highlightMoveDuration: UbuntuAnimation.FastDuration
107+ delegate: DashNavigationList {
108+ objectName: "navigation" + index
109+ visible: height > 0
110+ width: navigationListView.width
111+ scopeStyle: root.scopeStyle
112+ foregroundColor: root.foregroundColor
113+ property real desiredHeight: {
114+ if (root.showList) {
115+ if (navigation && navigation.loaded && x == navigationListView.contentX)
116+ {
117+ navigationListView.updateMaxHeight();
118+ return Math.min(implicitHeight, navigationListView.maxHeight);
119+ } else {
120+ return navigationListView.prevHeight;
121+ }
122+ } else {
123+ return 0;
124+ }
125+ }
126+ height: desiredHeight
127+ navigation: (nullifyNavigation || !scope) ? null : getNavigation(navigationId)
128+ currentNavigation: root.currentNavigation
129+ onEnterNavigation: {
130+ scope.setNavigationState(newNavigationId, isAltNavigation);
131+ // We only need to add a new item to the model
132+ // if we have children, otherwise just load it
133+ if (hasChildren) {
134+ isGoingBack = false;
135+ navigationModel.append({"navigationId": newNavigationId, "nullifyNavigation": false});
136+ navigationListView.currentIndex++;
137+ } else {
138+ showList = false;
139+ }
140+ }
141+ onGoBackToParentClicked: {
142+ scope.setNavigationState(navigation.parentNavigationId, isAltNavigation);
143+ isGoingBack = true;
144+ navigationModel.setProperty(navigationListView.currentIndex - 1, "nullifyNavigation", false);
145+ navigationListView.currentIndex--;
146+ }
147+ onAllNavigationClicked: {
148+ showList = false;
149+ if (root.currentNavigation.parentNavigationId == navigation.navigationId) {
150+ // For leaves we have to go to the parent too
151+ scope.setNavigationState(root.currentNavigation.parentNavigationId, isAltNavigation);
152+ }
153+ }
154+ }
155+ onContentXChanged: {
156+ if (contentX == width * navigationListView.currentIndex) {
157+ if (isGoingBack) {
158+ navigationModel.remove(navigationListView.currentIndex + 1);
159+ } else {
160+ navigationModel.setProperty(navigationListView.currentIndex - 1, "nullifyNavigation", true);
161+ }
162+ }
163+ }
164+ }
165+
166+ Image {
167+ anchors {
168+ top: navigationListView.bottom
169+ left: navigationListView.left
170+ right: navigationListView.right
171+ }
172+ fillMode: Image.Stretch
173+ source: "graphics/navigation_shadow.png"
174+ visible: root.showList
175+ }
176+
177+ onScopeChanged: {
178+ navigationModel.clear();
179+ if (scope && scope[hasNavigation]) {
180+ navigationModel.append({"navigationId": scope[currentNavigationId], "nullifyNavigation": false});
181+ }
182+ }
183+
184+ Connections {
185+ target: scope
186+ // This is duplicated since we can't have something based on the dynamic hasNavigation string property
187+ onHasNavigationChanged: {
188+ if (!root.isAltNavigation) {
189+ if (scope.hasNavigation) {
190+ navigationModel.append({"navigationId": scope.currentNavigationId, "nullifyNavigation": false});
191+ } else {
192+ navigationModel.clear();
193+ }
194+ }
195+ }
196+ onHasAltNavigationChanged: {
197+ if (root.isAltNavigation) {
198+ if (scope.hasAltNavigation) {
199+ navigationModel.append({"navigationId": scope.currentAltNavigationId, "nullifyNavigation": false});
200+ } else {
201+ navigationModel.clear();
202+ }
203+ }
204+ }
205+ }
206+
207+ InverseMouseArea {
208+ anchors.fill: navigationListView
209+ enabled: root.showList
210+ onPressed: root.showList = false
211+ }
212+
213+ Rectangle {
214+ visible: root.showDivider
215+ anchors {
216+ top: parent.top
217+ topMargin: units.dp(1)
218+ bottom: parent.bottom
219+ left: parent.right
220+ leftMargin: -units.dp(0.5)
221+ }
222+ width: units.dp(1)
223+ color: root.foregroundColor
224+ opacity: 0.2
225+ }
226+}
qml/Dash/DashNavigationList.qml+21−4
@@ -16,22 +16,23 @@
16
16
17import QtQuick 2.2
17import QtQuick 2.2
18import Ubuntu.Components 1.1
18import Ubuntu.Components 1.1
19+import "../Components"
19
20
20Item {
21Item {
21 id: root
22 id: root
22 property var navigation: null
23 property var navigation: null
23 property var currentNavigation: null
24 property var currentNavigation: null
24 property var scopeStyle: null
25 property var scopeStyle: null
26+ property color foregroundColor: Theme.palette.normal.baseText
25 signal enterNavigation(var newNavigationId, bool hasChildren)
27 signal enterNavigation(var newNavigationId, bool hasChildren)
26 signal goBackToParentClicked()
28 signal goBackToParentClicked()
27 signal allNavigationClicked()
29 signal allNavigationClicked()
28
30
29 readonly property int itemHeight: units.gu(5)
31 readonly property int itemHeight: units.gu(5)
30− readonly property color foregroundColor: root.scopeStyle ? root.scopeStyle.foreground : Theme.palette.normal.baseText
31 implicitHeight: flickable.contentHeight
32 implicitHeight: flickable.contentHeight
32
33
33− Rectangle {
34+ Background {
34− color: !root.scopeStyle || Qt.colorEqual(root.scopeStyle.background, "transparent") ? "white" : root.scopeStyle.background
35+ style: root.scopeStyle ? root.scopeStyle.navigationBackground : "color:///#f5f5f5"
35 anchors.fill: parent
36 anchors.fill: parent
36 }
37 }
37
38
@@ -86,10 +87,15 @@ Item {
86 anchors {
87 anchors {
87 verticalCenter: parent.verticalCenter
88 verticalCenter: parent.verticalCenter
88 left: backImage.right
89 left: backImage.right
90+ right: parent.right
89 leftMargin: units.gu(0.5)
91 leftMargin: units.gu(0.5)
92+ rightMargin: units.gu(2)
90 }
93 }
91 text: navigation ? navigation.parentLabel : ""
94 text: navigation ? navigation.parentLabel : ""
92 color: root.foregroundColor
95 color: root.foregroundColor
96+ wrapMode: Text.Wrap
97+ maximumLineCount: 2
98+ elide: Text.ElideMiddle
93 }
99 }
94
100
95 Rectangle {
101 Rectangle {
@@ -110,18 +116,23 @@ Item {
110 id: allButton
116 id: allButton
111 objectName: "allButton"
117 objectName: "allButton"
112 width: parent.width
118 width: parent.width
113− visible: navigation && (!navigation.isRoot || (root.currentNavigation && !root.currentNavigation.isRoot && root.currentNavigation.parentNavigationId == navigation.navigationId)) || false
119+ visible: navigation && (!navigation.isRoot || (!navigation.hidden && root.currentNavigation && !root.currentNavigation.isRoot && root.currentNavigation.parentNavigationId == navigation.navigationId)) || false
114 height: itemHeight
120 height: itemHeight
115
121
116 Label {
122 Label {
117 anchors {
123 anchors {
118 verticalCenter: parent.verticalCenter
124 verticalCenter: parent.verticalCenter
119 left: parent.left
125 left: parent.left
126+ right: parent.right
120 leftMargin: units.gu(2)
127 leftMargin: units.gu(2)
128+ rightMargin: units.gu(2)
121 }
129 }
122 text: navigation ? (navigation.allLabel != "" ? navigation.allLabel : navigation.label) : ""
130 text: navigation ? (navigation.allLabel != "" ? navigation.allLabel : navigation.label) : ""
123 font.bold: true
131 font.bold: true
124 color: root.foregroundColor
132 color: root.foregroundColor
133+ wrapMode: Text.Wrap
134+ maximumLineCount: 2
135+ elide: Text.ElideMiddle
125 }
136 }
126
137
127 Rectangle {
138 Rectangle {
@@ -155,12 +166,18 @@ Item {
155 verticalCenter: parent.verticalCenter
166 verticalCenter: parent.verticalCenter
156 left: parent.left
167 left: parent.left
157 leftMargin: units.gu(2)
168 leftMargin: units.gu(2)
169+ right: rightIcon.visible ? rightIcon.left : parent.right
170+ rightMargin: rightIcon.visible ? units.gu(0.5) : units.gu(2)
158 }
171 }
159 text: label
172 text: label
160 color: root.foregroundColor
173 color: root.foregroundColor
174+ wrapMode: Text.Wrap
175+ maximumLineCount: 2
176+ elide: Text.ElideMiddle
161 }
177 }
162
178
163 Icon {
179 Icon {
180+ id: rightIcon
164 anchors {
181 anchors {
165 verticalCenter: parent.verticalCenter
182 verticalCenter: parent.verticalCenter
166 right: parent.right
183 right: parent.right
qml/Dash/GenericScopeView.qml+136−38
@@ -34,7 +34,7 @@ FocusScope {
34 property bool enableHeightBehaviorOnNextCreation: false
34 property bool enableHeightBehaviorOnNextCreation: false
35 property var categoryView: categoryView
35 property var categoryView: categoryView
36 property bool showPageHeader: true
36 property bool showPageHeader: true
37− readonly property alias previewShown: previewListView.open
37+ readonly property alias subPageShown: subPageLoader.subPageShown
38 property int paginationCount: 0
38 property int paginationCount: 0
39 property int paginationIndex: 0
39 property int paginationIndex: 0
40 property alias pageHeaderTotallyVisible: categoryView.pageHeaderTotallyVisible
40 property alias pageHeaderTotallyVisible: categoryView.pageHeaderTotallyVisible
@@ -43,7 +43,7 @@ FocusScope {
43 style: scope ? scope.customizations : {}
43 style: scope ? scope.customizations : {}
44 }
44 }
45
45
46− readonly property bool processing: scope ? scope.searchInProgress || previewListView.processing : false
46+ readonly property bool processing: scope ? scope.searchInProgress || subPageLoader.processing : false
47
47
48 signal backClicked()
48 signal backClicked()
49
49
@@ -56,7 +56,7 @@ FocusScope {
56 }
56 }
57
57
58 function closePreview() {
58 function closePreview() {
59− previewListView.open = false;
59+ subPageLoader.closeSubPage()
60 }
60 }
61
61
62 function itemClicked(index, result, item, itemModel, resultsModel, limitedCategoryItemCount) {
62 function itemClicked(index, result, item, itemModel, resultsModel, limitedCategoryItemCount) {
@@ -80,19 +80,19 @@ FocusScope {
80 if (limitedCategoryItemCount > 0) {
80 if (limitedCategoryItemCount > 0) {
81 previewLimitModel.model = resultsModel;
81 previewLimitModel.model = resultsModel;
82 previewLimitModel.limit = limitedCategoryItemCount;
82 previewLimitModel.limit = limitedCategoryItemCount;
83− previewListView.model = previewLimitModel;
83+ subPageLoader.model = previewLimitModel;
84 } else {
84 } else {
85− previewListView.model = resultsModel;
85+ subPageLoader.model = resultsModel;
86 }
86 }
87− previewListView.currentIndex = -1;
87+ subPageLoader.initialIndex = -1;
88− previewListView.currentIndex = index;
88+ subPageLoader.initialIndex = index;
89− previewListView.open = true;
89+ subPageLoader.openSubPage("preview");
90 }
90 }
91
91
92 Binding {
92 Binding {
93 target: scope
93 target: scope
94 property: "isActive"
94 property: "isActive"
95− value: isCurrent && !previewListView.open
95+ value: isCurrent && !subPageLoader.open
96 }
96 }
97
97
98 SortFilterProxyModel {
98 SortFilterProxyModel {
@@ -105,10 +105,10 @@ FocusScope {
105 }
105 }
106
106
107 onIsCurrentChanged: {
107 onIsCurrentChanged: {
108− if (showPageHeader) {
108+ if (pageHeaderLoader.item && showPageHeader) {
109 pageHeaderLoader.item.resetSearch();
109 pageHeaderLoader.item.resetSearch();
110 }
110 }
111− previewListView.open = false;
111+ subPageLoader.closeSubPage();
112 }
112 }
113
113
114 Binding {
114 Binding {
@@ -127,8 +127,8 @@ FocusScope {
127
127
128 Connections {
128 Connections {
129 target: scopeView.scope
129 target: scopeView.scope
130− onShowDash: previewListView.open = false;
130+ onShowDash: subPageLoader.closeSubPage()
131− onHideDash: previewListView.open = false;
131+ onHideDash: subPageLoader.closeSubPage()
132 }
132 }
133
133
134 Rectangle {
134 Rectangle {
@@ -141,17 +141,19 @@ FocusScope {
141 id: categoryView
141 id: categoryView
142 objectName: "categoryListView"
142 objectName: "categoryListView"
143
143
144− x: previewListView.open ? -width : 0
144+ x: subPageLoader.open ? -width : 0
145 Behavior on x { UbuntuNumberAnimation { } }
145 Behavior on x { UbuntuNumberAnimation { } }
146 width: parent.width
146 width: parent.width
147+ height: floatingSeeLess.visible ? parent.height - floatingSeeLess.height + floatingSeeLess.yOffset
148+ : parent.height
147− height: parent.height
149+ clip: height != parent.height
148
150
149 model: scopeView.categories
151 model: scopeView.categories
150− forceNoClip: previewListView.open
152+ forceNoClip: subPageLoader.open
151 pixelAligned: true
153 pixelAligned: true
152 interactive: !navigationShown
154 interactive: !navigationShown
153
155
154− property string expandedCategoryId: ""
156+ property Item expandedCategoryItem: null
155
157
156 readonly property bool pageHeaderTotallyVisible: scopeView.showPageHeader &&
158 readonly property bool pageHeaderTotallyVisible: scopeView.showPageHeader &&
157 ((headerItemShownHeight == 0 && categoryView.contentY <= categoryView.originY) || (headerItemShownHeight == pageHeaderLoader.item.height))
159 ((headerItemShownHeight == 0 && categoryView.contentY <= categoryView.originY) || (headerItemShownHeight == pageHeaderLoader.item.height))
@@ -162,6 +164,8 @@ FocusScope {
162 highlightWhenPressed: false
164 highlightWhenPressed: false
163 showDivider: false
165 showDivider: false
164
166
167+ property Item seeAllButton: seeAll
168+
165 readonly property bool expandable: {
169 readonly property bool expandable: {
166 if (categoryView.model.count === 1) return false;
170 if (categoryView.model.count === 1) return false;
167 if (cardTool.template && cardTool.template["collapsed-rows"] === 0) return false;
171 if (cardTool.template && cardTool.template["collapsed-rows"] === 0) return false;
@@ -191,7 +195,7 @@ FocusScope {
191 // This can happen with the VJ that doesn't know how height it will be on creation
195 // This can happen with the VJ that doesn't know how height it will be on creation
192 // so doesn't set expandable until a bit too late for onLoaded
196 // so doesn't set expandable until a bit too late for onLoaded
193 if (expandable) {
197 if (expandable) {
194− var shouldExpand = baseItem.category === categoryView.expandedCategoryId;
198+ var shouldExpand = baseItem === categoryView.expandedCategoryItem;
195 baseItem.expand(shouldExpand, false /*animate*/);
199 baseItem.expand(shouldExpand, false /*animate*/);
196 }
200 }
197 }
201 }
@@ -242,7 +246,7 @@ FocusScope {
242 item.objectName = Qt.binding(function() { return categoryId })
246 item.objectName = Qt.binding(function() { return categoryId })
243 item.scopeStyle = scopeView.scopeStyle;
247 item.scopeStyle = scopeView.scopeStyle;
244 if (baseItem.expandable) {
248 if (baseItem.expandable) {
245− var shouldExpand = categoryId === categoryView.expandedCategoryId;
249+ var shouldExpand = baseItem === categoryView.expandedCategoryItem;
246 baseItem.expand(shouldExpand, false /*animate*/);
250 baseItem.expand(shouldExpand, false /*animate*/);
247 }
251 }
248 updateDelegateCreationRange();
252 updateDelegateCreationRange();
@@ -279,21 +283,21 @@ FocusScope {
279 }
283 }
280 Connections {
284 Connections {
281 target: categoryView
285 target: categoryView
282− onExpandedCategoryIdChanged: {
286+ onExpandedCategoryItemChanged: {
283 collapseAllButExpandedCategory();
287 collapseAllButExpandedCategory();
284 }
288 }
285 function collapseAllButExpandedCategory() {
289 function collapseAllButExpandedCategory() {
286 var item = rendererLoader.item;
290 var item = rendererLoader.item;
287 if (baseItem.expandable) {
291 if (baseItem.expandable) {
288− var shouldExpand = categoryId === categoryView.expandedCategoryId;
292+ var shouldExpand = baseItem === categoryView.expandedCategoryItem;
289 if (shouldExpand != baseItem.expanded) {
293 if (shouldExpand != baseItem.expanded) {
290 // If the filter animation will be seen start it, otherwise, just flip the switch
294 // If the filter animation will be seen start it, otherwise, just flip the switch
291 var shrinkingVisible = !shouldExpand && y + item.collapsedHeight + seeAll.height < categoryView.height;
295 var shrinkingVisible = !shouldExpand && y + item.collapsedHeight + seeAll.height < categoryView.height;
292 var growingVisible = shouldExpand && y + height < categoryView.height;
296 var growingVisible = shouldExpand && y + height < categoryView.height;
293− if (!previewListView.open || shouldExpand) {
297+ if (!subPageLoader.open || shouldExpand) {
294 var animate = shrinkingVisible || growingVisible;
298 var animate = shrinkingVisible || growingVisible;
295 baseItem.expand(shouldExpand, animate)
299 baseItem.expand(shouldExpand, animate)
296− if (shouldExpand && !previewListView.open) {
300+ if (shouldExpand && !subPageLoader.open) {
297 categoryView.maximizeVisibleArea(index, item.expandedHeight + seeAll.height);
301 categoryView.maximizeVisibleArea(index, item.expandedHeight + seeAll.height);
298 }
302 }
299 }
303 }
@@ -346,13 +350,13 @@ FocusScope {
346 left: parent.left
350 left: parent.left
347 right: parent.right
351 right: parent.right
348 }
352 }
349− height: seeAllLabel.visible ? seeAllLabel.font.pixelSize + units.gu(6) : 0
353+ height: seeAllLabel.visible ? seeAllLabel.font.pixelSize + units.gu(4) : 0
350
354
351 onClicked: {
355 onClicked: {
352− if (categoryView.expandedCategoryId != baseItem.category) {
356+ if (categoryView.expandedCategoryItem !== baseItem) {
353− categoryView.expandedCategoryId = baseItem.category;
357+ categoryView.expandedCategoryItem = baseItem;
354 } else {
358 } else {
355− categoryView.expandedCategoryId = "";
359+ categoryView.expandedCategoryItem = null;
356 }
360 }
357 }
361 }
358
362
@@ -424,44 +428,138 @@ FocusScope {
424 searchHint: scopeView.scope && scopeView.scope.searchHint || i18n.tr("Search")
428 searchHint: scopeView.scope && scopeView.scope.searchHint || i18n.tr("Search")
425 showBackButton: scopeView.hasBackAction
429 showBackButton: scopeView.hasBackAction
426 searchEntryEnabled: true
430 searchEntryEnabled: true
431+ settingsEnabled: scopeView.scope && scopeView.scope.settings && scopeView.scope.settings.count > 0 || false
432+ favoriteEnabled: scopeView.scope && scopeView.scope.id !== "clickscope"
433+ favorite: scopeView.scope && scopeView.scope.favorite
427 scopeStyle: scopeView.scopeStyle
434 scopeStyle: scopeView.scopeStyle
428 paginationCount: scopeView.paginationCount
435 paginationCount: scopeView.paginationCount
429 paginationIndex: scopeView.paginationIndex
436 paginationIndex: scopeView.paginationIndex
430
437
431 bottomItem: DashNavigation {
438 bottomItem: DashNavigation {
432 scope: scopeView.scope
439 scope: scopeView.scope
433− width: parent.width <= units.gu(60) ? parent.width : units.gu(40)
434− anchors.right: parent.right
440+ anchors { left: parent.left; right: parent.right }
435 windowHeight: scopeView.height
441 windowHeight: scopeView.height
436 windowWidth: scopeView.width
442 windowWidth: scopeView.width
437 scopeStyle: scopeView.scopeStyle
443 scopeStyle: scopeView.scopeStyle
438 }
444 }
439
445
440 onBackClicked: scopeView.backClicked()
446 onBackClicked: scopeView.backClicked()
447+ onSettingsClicked: subPageLoader.openSubPage("settings")
448+ onFavoriteClicked: scopeView.scope.favorite = !scopeView.scope.favorite
441 }
449 }
442 }
450 }
443 }
451 }
444 }
452 }
445
453
454+ AbstractButton {
455+ id: floatingSeeLess
456+ objectName: "floatingSeeLess"
457+
458+ property Item companionTo: companionBase ? companionBase.seeAllButton : null
459+ property Item companionBase: categoryView.expandedCategoryItem
460+ property bool showBecausePosition: false
461+ property real yOffset: 0
462+
463+ anchors {
464+ left: categoryView.left
465+ right: categoryView.right
466+ }
467+ y: parent.height - height + yOffset
468+ height: seeLessLabel.font.pixelSize + units.gu(4)
469+ visible: companionTo && showBecausePosition
470+
471+ onClicked: categoryView.expandedCategoryItem = null;
472+
473+ function updateVisibility() {
474+ var companionPos = companionTo.mapToItem(floatingSeeLess, 0, 0);
475+ showBecausePosition = companionPos.y > 0;
476+
477+ var posToBase = floatingSeeLess.mapToItem(companionBase, 0, -yOffset).y;
478+ yOffset = Math.max(0, companionBase.item.collapsedHeight - posToBase);
479+ yOffset = Math.min(yOffset, height);
480+ }
481+
482+ Label {
483+ id: seeLessLabel
484+ text: i18n.tr("See less")
485+ anchors {
486+ centerIn: parent
487+ verticalCenterOffset: units.gu(-0.5)
488+ }
489+ fontSize: "small"
490+ font.weight: Font.Bold
491+ color: scopeStyle ? scopeStyle.foreground : Theme.palette.normal.baseText
492+ }
493+
494+ Connections {
495+ target: floatingSeeLess.companionTo ? categoryView : null
496+ onContentYChanged: floatingSeeLess.updateVisibility();
497+ }
498+
499+ Connections {
500+ target: floatingSeeLess.companionTo
501+ onYChanged: floatingSeeLess.updateVisibility();
502+ }
503+ }
504+
446 LimitProxyModel {
505 LimitProxyModel {
447 id: previewLimitModel
506 id: previewLimitModel
448 }
507 }
449
508
450− PreviewListView {
509+ Loader {
451− id: previewListView
510+ id: subPageLoader
452− objectName: "previewListView"
511+ objectName: "subPageLoader"
453 visible: x != width
512 visible: x != width
454− scope: scopeView.scope
455− scopeStyle: scopeView.scopeStyle
456 width: parent.width
513 width: parent.width
457 height: parent.height
514 height: parent.height
458 anchors.left: categoryView.right
515 anchors.left: categoryView.right
459
516
460− onOpenChanged: {
517+ property bool open: false
461− if (showPageHeader) {
518+ property var scope: scopeView.scope
462− pageHeaderLoader.item.unfocus();
519+ property var scopeStyle: scopeView.scopeStyle
520+ property int initialIndex: -1
521+ property var model: null
522+
523+ readonly property bool processing: item && item.processing || false
524+ readonly property int count: item && item.count || 0
525+ readonly property int currentIndex: item && item.currentIndex || 0
526+ readonly property var currentItem: item && item.currentItem || null
527+
528+ property string subPage: ""
529+ readonly property bool subPageShown: visible && status === Loader.Ready
530+
531+ function openSubPage(page) {
532+ subPage = page;
533+ }
534+
535+ function closeSubPage() {
536+ open = false;
537+ }
538+
539+ source: switch(subPage) {
540+ case "preview": return "PreviewListView.qml";
541+ case "settings": return "ScopeSettingsPage.qml";
542+ default: return "";
543+ }
544+
545+ onLoaded: {
546+ item.scope = Qt.binding(function() { return subPageLoader.scope; } )
547+ item.scopeStyle = Qt.binding(function() { return subPageLoader.scopeStyle; } )
548+ if (subPage == "preview") {
549+ item.open = Qt.binding(function() { return subPageLoader.open; } )
550+ item.initialIndex = Qt.binding(function() { return subPageLoader.initialIndex; } )
551+ item.model = Qt.binding(function() { return subPageLoader.model; } )
463 }
552 }
553+ open = true;
464 }
554 }
465− }
466
555
556+ onOpenChanged: pageHeaderLoader.item.unfocus()
557+
558+ onVisibleChanged: if (!visible) subPage = ""
559+
560+ Connections {
561+ target: subPageLoader.item
562+ onBackClicked: subPageLoader.closeSubPage()
563+ }
564+ }
467}
565}
qml/Dash/PageHeader.qml+81−27
@@ -31,6 +31,9 @@ Item {
31 property string title
31 property string title
32
32
33 property bool searchEntryEnabled: false
33 property bool searchEntryEnabled: false
34+ property bool settingsEnabled: false
35+ property bool favoriteEnabled: false
36+ property bool favorite: false
34 property ListModel searchHistory: SearchHistoryModel
37 property ListModel searchHistory: SearchHistoryModel
35 property alias searchQuery: searchTextField.text
38 property alias searchQuery: searchTextField.text
36 property alias searchHint: searchTextField.placeholderText
39 property alias searchHint: searchTextField.placeholderText
@@ -40,12 +43,11 @@ Item {
40 property int paginationCount: 0
43 property int paginationCount: 0
41 property int paginationIndex: -1
44 property int paginationIndex: -1
42
45
43− // TODO We should use foreground for the icons
44− // of the toolbar but unfortunately Action does not have
45− // the keyColor property as Icon does :-/
46 property var scopeStyle: null
46 property var scopeStyle: null
47
47
48 signal backClicked()
48 signal backClicked()
49+ signal settingsClicked()
50+ signal favoriteClicked()
49
51
50 onScopeStyleChanged: refreshLogo()
52 onScopeStyleChanged: refreshLogo()
51 onSearchQueryChanged: {
53 onSearchQueryChanged: {
@@ -240,6 +242,7 @@ Item {
240 contentHeight: height
242 contentHeight: height
241 opacity: headerContainer.clip || !headerContainer.showSearch ? 1 : 0 // setting visible false cause column to relayout
243 opacity: headerContainer.clip || !headerContainer.showSearch ? 1 : 0 // setting visible false cause column to relayout
242 separatorSource: ""
244 separatorSource: ""
245+ separatorBottomSource: ""
243 property var styledItem: header
246 property var styledItem: header
244 property string title: root.title
247 property string title: root.title
245 property var config: PageHeadConfiguration {
248 property var config: PageHeadConfiguration {
@@ -247,20 +250,33 @@ Item {
247 backAction: Action {
250 backAction: Action {
248 iconName: "back"
251 iconName: "back"
249 visible: root.showBackButton
252 visible: root.showBackButton
250− onTriggered: {
251− root.backClicked();
253+ onTriggered: root.backClicked()
252− }
253 }
254 }
254
255
255 actions: [
256 actions: [
256 Action {
257 Action {
257 objectName: "search"
258 objectName: "search"
259+ text: i18n.tr("Search")
258 iconName: "search"
260 iconName: "search"
259 visible: root.searchEntryEnabled
261 visible: root.searchEntryEnabled
260 onTriggered: {
262 onTriggered: {
261 headerContainer.showSearch = true;
263 headerContainer.showSearch = true;
262 searchTextField.forceActiveFocus();
264 searchTextField.forceActiveFocus();
263 }
265 }
266+ },
267+ Action {
268+ objectName: "settings"
269+ text: i18n.tr("Settings")
270+ iconName: "settings"
271+ visible: root.settingsEnabled
272+ onTriggered: root.settingsClicked()
273+ },
274+ Action {
275+ objectName: "favorite"
276+ text: root.favorite ? i18n.tr("Remove from Favorites") : i18n.tr("Add to Favorites")
277+ iconName: root.favorite ? "starred" : "non-starred"
278+ visible: root.favoriteEnabled
279+ onTriggered: root.favoriteClicked()
264 }
280 }
265 ]
281 ]
266 }
282 }
@@ -288,25 +304,6 @@ Item {
288 }
304 }
289 }
305 }
290
306
291− Row {
292− spacing: units.gu(.5)
293− Repeater {
294− objectName: "paginationRepeater"
295− model: root.paginationCount
296− Image {
297− objectName: "paginationDots_" + index
298− height: units.gu(1)
299− width: height
300− source: (index == root.paginationIndex) ? "graphics/pagination_dot_on.png" : "graphics/pagination_dot_off.png"
301− }
302− }
303− anchors {
304− top: headerContainer.bottom
305− horizontalCenter: headerContainer.horizontalCenter
306− topMargin: units.gu(.5)
307− }
308− }
309−
310 Component {
307 Component {
311 id: popoverComponent
308 id: popoverComponent
312 Popover {
309 Popover {
@@ -344,7 +341,7 @@ Item {
344 }
341 }
345 }
342 }
346
343
347− BorderImage {
344+ Rectangle {
348 id: bottomBorder
345 id: bottomBorder
349 anchors {
346 anchors {
350 top: headerContainer.bottom
347 top: headerContainer.bottom
@@ -353,7 +350,64 @@ Item {
353 bottom: bottomContainer.top
350 bottom: bottomContainer.top
354 }
351 }
355
352
356− source: "graphics/PageHeaderBaseDivider.sci"
353+ color: scopeStyle ? scopeStyle.headerDividerColor : "#e0e0e0"
354+
355+ Rectangle {
356+ anchors {
357+ top: parent.top
358+ left: parent.left
359+ right: parent.right
360+ }
361+ height: units.dp(1)
362+ color: Qt.darker(parent.color, 1.1)
363+ }
364+ }
365+
366+ Row {
367+ visible: bottomBorder.visible
368+ spacing: units.gu(.5)
369+ Repeater {
370+ objectName: "paginationRepeater"
371+ model: root.paginationCount
372+ Image {
373+ objectName: "paginationDots_" + index
374+ height: units.gu(1)
375+ width: height
376+ source: (index == root.paginationIndex) ? "graphics/pagination_dot_on.png" : "graphics/pagination_dot_off.png"
377+ }
378+ }
379+ anchors {
380+ top: headerContainer.bottom
381+ horizontalCenter: headerContainer.horizontalCenter
382+ topMargin: units.gu(.5)
383+ }
384+ }
385+
386+ // FIXME this doesn't work with solid scope backgrounds due to z-ordering
387+ Item {
388+ id: bottomHighlight
389+ visible: bottomBorder.visible
390+ anchors {
391+ top: bottomContainer.top
392+ left: parent.left
393+ right: parent.right
394+ }
395+ z: 1
396+ height: units.dp(1)
397+ opacity: 0.6
398+
399+ // FIXME this should be a shader when bottomItem exists
400+ // to support image backgrounds
401+ Rectangle {
402+ anchors.fill: parent
403+ color: if (bottomItem && bottomItem.background) {
404+ Qt.lighter(Qt.rgba(bottomItem.background.topColor.r,
405+ bottomItem.background.topColor.g,
406+ bottomItem.background.topColor.b, 1.0), 1.2);
407+ } else if (!bottomItem && scopeStyle) {
408+ Qt.lighter(Qt.rgba(scopeStyle.background.r, scopeStyle.background.g, scopeStyle.background.b, 1.0), 1.2);
409+ } else "#CCFFFFFF"
410+ }
357 }
411 }
358
412
359 Item {
413 Item {
qml/Dash/PreviewListView.qml+13−1
@@ -23,9 +23,12 @@ import "Previews" as Previews
23Item {
23Item {
24 id: root
24 id: root
25
25
26+ property int initialIndex: -1
26 property var scope: null
27 property var scope: null
27 property var scopeStyle: null
28 property var scopeStyle: null
28
29
30+ property alias showSignatureLine: header.showSignatureLine
31+
29 property alias open: previewListView.open
32 property alias open: previewListView.open
30 property alias model: previewListView.model
33 property alias model: previewListView.model
31 property alias currentIndex: previewListView.currentIndex
34 property alias currentIndex: previewListView.currentIndex
@@ -35,6 +38,8 @@ Item {
35 readonly property bool processing: currentItem && (!currentItem.previewModel.loaded
38 readonly property bool processing: currentItem && (!currentItem.previewModel.loaded
36 || currentItem.previewModel.processingAction)
39 || currentItem.previewModel.processingAction)
37
40
41+ signal backClicked()
42+
38 PageHeader {
43 PageHeader {
39 id: header
44 id: header
40 objectName: "pageHeader"
45 objectName: "pageHeader"
@@ -44,7 +49,7 @@ Item {
44 searchEntryEnabled: false
49 searchEntryEnabled: false
45 scopeStyle: root.scopeStyle
50 scopeStyle: root.scopeStyle
46
51
47− onBackClicked: root.open = false
52+ onBackClicked: root.backClicked()
48 }
53 }
49
54
50 ListView {
55 ListView {
@@ -78,6 +83,13 @@ Item {
78 }
83 }
79 }
84 }
80
85
86+ onCountChanged: {
87+ if (count > 0 && initialIndex >= 0) {
88+ currentIndex = initialIndex;
89+ initialIndex = -1;
90+ }
91+ }
92+
81 delegate: Previews.Preview {
93 delegate: Previews.Preview {
82 id: preview
94 id: preview
83 objectName: "preview" + index
95 objectName: "preview" + index
qml/Dash/Previews/PreviewActionButton.qml+1−4
@@ -15,16 +15,13 @@
15 */
15 */
16
16
17import QtQuick 2.0
17import QtQuick 2.0
18−import Ubuntu.Components 0.1
18+import Ubuntu.Components 1.1
19
19
20Button {
20Button {
21 signal triggeredAction(var actionData)
21 signal triggeredAction(var actionData)
22
22
23 property var data: null
23 property var data: null
24 objectName: "button" + (data && data.id || "")
24 objectName: "button" + (data && data.id || "")
25− color: Theme.palette.selected.foreground
26 text: data && data.label || ""
25 text: data && data.label || ""
27− iconSource: data && data.icon || ""
28− iconPosition: "left"
29 onClicked: triggeredAction(data)
26 onClicked: triggeredAction(data)
30}
27}
qml/Dash/Previews/PreviewActionCombo.qml+4−2
@@ -15,7 +15,7 @@
15 */
15 */
16
16
17import QtQuick 2.0
17import QtQuick 2.0
18−import Ubuntu.Components 0.1
18+import Ubuntu.Components 1.1
19
19
20Item {
20Item {
21 id: root
21 id: root
@@ -25,6 +25,7 @@ Item {
25 signal triggeredAction(var actionData)
25 signal triggeredAction(var actionData)
26
26
27 property alias model: actionRepeater.model
27 property alias model: actionRepeater.model
28+ property alias strokeColor: moreButton.strokeColor
28
29
29 Button {
30 Button {
30 id: moreButton
31 id: moreButton
@@ -32,7 +33,7 @@ Item {
32
33
33 objectName: "moreLessButton"
34 objectName: "moreLessButton"
34 text: !expanded ? i18n.tr("More...") : i18n.tr("Less...")
35 text: !expanded ? i18n.tr("More...") : i18n.tr("Less...")
35− color: Theme.palette.selected.foreground
36+ strokeColor: Theme.palette.normal.baseText
36 onClicked: expanded = !expanded
37 onClicked: expanded = !expanded
37 width: parent.width
38 width: parent.width
38 }
39 }
@@ -60,6 +61,7 @@ Item {
60 data: modelData
61 data: modelData
61 width: implicitWidth < parent.width ? parent.width : implicitWidth
62 width: implicitWidth < parent.width ? parent.width : implicitWidth
62 onClicked: root.triggeredAction(modelData)
63 onClicked: root.triggeredAction(modelData)
64+ strokeColor: moreButton.strokeColor
63 }
65 }
64 }
66 }
65 }
67 }
qml/Dash/Previews/PreviewActions.qml+6
@@ -46,6 +46,11 @@ PreviewWidget {
46 item.model = row.actions.slice(1);
46 item.model = row.actions.slice(1);
47 }
47 }
48 }
48 }
49+ Binding {
50+ target: loader.item
51+ property: "strokeColor"
52+ value: root.scopeStyle ? root.scopeStyle.foreground : Theme.palette.normal.baseText
53+ }
49 Connections {
54 Connections {
50 target: loader.item
55 target: loader.item
51 onTriggeredAction: {
56 onTriggeredAction: {
@@ -59,6 +64,7 @@ PreviewWidget {
59 visible: row.actions && row.actions.length > 0
64 visible: row.actions && row.actions.length > 0
60 onTriggeredAction: root.triggered(root.widgetId, actionData.id, actionData)
65 onTriggeredAction: root.triggered(root.widgetId, actionData.id, actionData)
61 width: (root.width - units.gu(1)) / 2
66 width: (root.width - units.gu(1)) / 2
67+ color: root.scopeStyle ? root.scopeStyle.previewButtonColor : Theme.palette.selected.foreground
62 }
68 }
63 }
69 }
64}
70}
qml/Dash/Previews/PreviewExpandable.qml+3−2
@@ -59,9 +59,10 @@ PreviewWidget {
59 }
59 }
60 Icon {
60 Icon {
61 anchors.fill: parent
61 anchors.fill: parent
62− width: 64
62+ width: units.gu(3)
63− height: 64
63+ height: units.gu(3)
64 name: root.expanded ? "view-collapse" : "view-expand"
64 name: root.expanded ? "view-collapse" : "view-expand"
65+ color: root.scopeStyle ? root.scopeStyle.foreground : Theme.palette.normal.baseText
65 }
66 }
66 }
67 }
67
68
qml/Dash/Previews/PreviewTable.qmlnew file+80
@@ -0,0 +1,80 @@
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+import QtQuick 2.0
18+import QtQuick.Layouts 1.1
19+import Ubuntu.Components 0.1
20+import "../../Components"
21+
22+/*! \brief Preview widget for table.
23+
24+ This widget shows two columns contained in widgetData["values"]
25+ as arrays of label,value along with a title that comes from widgetData["title"].
26+
27+ In case the widget is collapsed it only shows 3 lines of values.
28+ */
29+
30+PreviewWidget {
31+ id: root
32+ implicitHeight: column.implicitHeight
33+
34+ readonly property int maximumCollapsedRowCount: 3
35+
36+ Column {
37+ id: column
38+ objectName: "column"
39+ spacing: units.gu(1)
40+
41+ Label {
42+ id: titleLabel
43+ objectName: "titleLabel"
44+ anchors {
45+ left: parent.left
46+ right: parent.right
47+ }
48+ height: visible ? implicitHeight : 0
49+ fontSize: "large"
50+ color: root.scopeStyle ? root.scopeStyle.foreground : Theme.palette.normal.baseText
51+ visible: text !== ""
52+ opacity: .8
53+ text: widgetData["title"] || ""
54+ }
55+
56+ GridLayout {
57+ objectName: "gridLayout"
58+ columns: 2
59+ columnSpacing: units.gu(2)
60+ Repeater {
61+ id: rowsRepeater
62+ model: widgetData["values"]
63+
64+ delegate: Repeater {
65+ id: perRowRepeater
66+ readonly property int rowIndex: index
67+ model: widgetData["values"][index]
68+ delegate: Label {
69+ objectName: "label"+rowIndex+index
70+ fontSize: "small"
71+ text: perRowRepeater.model[index]
72+ visible: root.expanded || rowIndex < maximumCollapsedRowCount
73+ color: root.scopeStyle ? root.scopeStyle.foreground : Theme.palette.normal.baseText
74+ font.bold: index == 0
75+ }
76+ }
77+ }
78+ }
79+ }
80+}
qml/Dash/Previews/PreviewWidgetFactory.qml+2−1
@@ -58,6 +58,7 @@ Loader {
58 case "payments": return "PreviewPayments.qml";
58 case "payments": return "PreviewPayments.qml";
59 case "rating-input": return "PreviewRatingInput.qml";
59 case "rating-input": return "PreviewRatingInput.qml";
60 case "reviews": return "PreviewRatingDisplay.qml";
60 case "reviews": return "PreviewRatingDisplay.qml";
61+ case "table": return "PreviewTable.qml";
61 case "text": return "PreviewTextSummary.qml";
62 case "text": return "PreviewTextSummary.qml";
62 case "video": return "PreviewVideoPlayback.qml";
63 case "video": return "PreviewVideoPlayback.qml";
63 default: return "";
64 default: return "";
@@ -70,7 +71,7 @@ Loader {
70 item.widgetData = Qt.binding(function() { return root.widgetData } )
71 item.widgetData = Qt.binding(function() { return root.widgetData } )
71 item.isCurrentPreview = Qt.binding(function() { return root.isCurrentPreview } )
72 item.isCurrentPreview = Qt.binding(function() { return root.isCurrentPreview } )
72 item.expanded = Qt.binding(function() { return root.expanded } )
73 item.expanded = Qt.binding(function() { return root.expanded } )
73− if (item.hasOwnProperty("scopeStyle")) item.scopeStyle = root.scopeStyle;
74+ item.scopeStyle = Qt.binding(function() { return root.scopeStyle } )
74 }
75 }
75
76
76 Connections {
77 Connections {
qml/Dash/ScopeSettings/ScopeSetting.qmlnew file+37
@@ -0,0 +1,37 @@
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+import QtQuick 2.2
18+import Ubuntu.Components 1.1
19+
20+/*! Interface for settings widgets. */
21+
22+Item {
23+ //! The ScopeStyle component.
24+ property var scopeStyle: null
25+
26+ //! Variable used to contain widget's data
27+ property var widgetData: null
28+
29+ /*! \brief This signal should be emitted when a setting action was updated.
30+ *
31+ * \param value the new setting value.
32+ */
33+ signal updated(var value)
34+
35+ //! \internal
36+ readonly property real settingMargins: units.gu(2)
37+}
qml/Dash/ScopeSettings/ScopeSettingBoolean.qmlnew file+61
@@ -0,0 +1,61 @@
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+import QtQuick 2.2
18+import Ubuntu.Components 1.1
19+import Ubuntu.Components.ListItems 1.0 as ListItem
20+
21+ScopeSetting {
22+ id: root
23+ height: listItem.height
24+
25+ ListItem.Empty {
26+ id: listItem
27+
28+ onClicked: {
29+ control.checked = !control.checked;
30+ updated(control.checked);
31+ }
32+
33+ Label {
34+ anchors {
35+ left: parent.left
36+ leftMargin: settingMargins
37+ right: control.left
38+ rightMargin: units.gu(1)
39+ verticalCenter: parent.verticalCenter
40+ }
41+ text: widgetData.displayName
42+ elide: Text.ElideMiddle
43+ maximumLineCount: 2
44+ wrapMode: Text.Wrap
45+ color: scopeStyle ? scopeStyle.foreground : Theme.palette.normal.baseText
46+ }
47+
48+ CheckBox {
49+ id: control
50+ objectName: "control"
51+ anchors {
52+ right: parent.right
53+ rightMargin: settingMargins
54+ verticalCenter: parent.verticalCenter
55+ }
56+ checked: widgetData.value
57+
58+ onTriggered: root.updated(checked)
59+ }
60+ }
61+}
qml/Dash/ScopeSettings/ScopeSettingList.qmlnew 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
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.2
18+import Ubuntu.Components 1.1
19+import Ubuntu.Components.ListItems 1.0 as ListItem
20+
21+ScopeSetting {
22+ id: root
23+
24+ // FIXME workaround for: https://bugs.launchpad.net/ubuntu/+source/ubuntu-ui-toolkit/+bug/1355830
25+ height: listItem.currentlyExpanded ? listItem.itemHeight * widgetData.properties["values"].length + units.gu(6) : listItem.height
26+
27+ property int initialValue: -1
28+
29+ ListItem.ItemSelector {
30+ id: listItem
31+ objectName: "control"
32+ anchors {
33+ left: parent.left
34+ right: parent.right
35+ }
36+ text: widgetData.displayName
37+ model: widgetData.properties["values"]
38+
39+ onSelectedIndexChanged: {
40+ if (root.initialValue >= 0) {
41+ var tmpValue = root.initialValue;
42+ root.initialValue = -1;
43+ selectedIndex = tmpValue;
44+ return;
45+ }
46+
47+ root.updated(selectedIndex);
48+ }
49+ }
50+}
qml/Dash/ScopeSettings/ScopeSettingNumber.qmlnew file+21
@@ -0,0 +1,21 @@
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+import QtQuick 2.2
18+
19+ScopeSettingString {
20+ mode: "number"
21+}
qml/Dash/ScopeSettings/ScopeSettingString.qmlnew file+83
@@ -0,0 +1,83 @@
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+import QtQuick 2.2
18+import Ubuntu.Components 1.1
19+import Ubuntu.Components.ListItems 1.0 as ListItem
20+
21+ScopeSetting {
22+ id: root
23+ height: listItem.height
24+
25+ property string mode: "string"
26+
27+ ListItem.Empty {
28+ id: listItem
29+ onClicked: {
30+ control.forceActiveFocus();
31+ control.selectAll();
32+ }
33+
34+ Label {
35+ id: label
36+ anchors {
37+ left: parent.left
38+ leftMargin: settingMargins
39+ right: control.left
40+ rightMargin: units.gu(1)
41+ verticalCenter: parent.verticalCenter
42+ }
43+ text: widgetData.displayName
44+ elide: Text.ElideMiddle
45+ maximumLineCount: 2
46+ wrapMode: Text.Wrap
47+ color: scopeStyle ? scopeStyle.foreground : Theme.palette.normal.baseText
48+ }
49+
50+ TextField {
51+ id: control
52+ objectName: "control"
53+ anchors {
54+ right: parent.right
55+ rightMargin: settingMargins
56+ verticalCenter: parent.verticalCenter
57+ }
58+ width: root.mode == "number" ? units.gu(8) : units.gu(12)
59+ text: widgetData.value
60+ color: scopeStyle ? scopeStyle.foreground : Theme.palette.normal.fieldText
61+ validator: root.mode == "number" ? doubleValidator : null
62+ hasClearButton: root.mode == "number" ? false : true
63+
64+ DoubleValidator {
65+ id: doubleValidator
66+ }
67+
68+ function updateText() {
69+ if (acceptableInput) {
70+ text = displayText;
71+ root.updated(text);
72+ }
73+ }
74+
75+ onAccepted: updateText()
76+ onActiveFocusChanged: {
77+ if (!activeFocus) {
78+ updateText();
79+ }
80+ }
81+ }
82+ }
83+}
qml/Dash/ScopeSettings/ScopeSettingsWidgetFactory.qmlnew file+57
@@ -0,0 +1,57 @@
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+import QtQuick 2.2
18+
19+//! \brief This component loads the widgets based on type.
20+
21+Loader {
22+ id: root
23+
24+ //! The ScopeStyle component.
25+ property var scopeStyle: null
26+
27+ //! Variable used to contain widget's data
28+ property var widgetData: null
29+
30+ //! Triggered signal forwarded from the widgets.
31+ signal updated(var value)
32+
33+ source: widgetSource
34+
35+ //! \cond private
36+ property url widgetSource: {
37+ switch (widgetData.type) {
38+ case "boolean": return "ScopeSettingBoolean.qml";
39+ case "list": return "ScopeSettingList.qml";
40+ case "number": return "ScopeSettingNumber.qml";
41+ case "string": return "ScopeSettingString.qml";
42+ default: return "";
43+ }
44+ }
45+ //! \endcond
46+
47+ onLoaded: {
48+ if (item.hasOwnProperty("initialValue")) item.initialValue = root.widgetData.value;
49+ item.widgetData = Qt.binding(function() { return root.widgetData; } )
50+ item.scopeStyle = Qt.binding(function() { return root.scopeStyle; } )
51+ }
52+
53+ Connections {
54+ target: root.item
55+ onUpdated: if (value !== widgetData.value) root.updated(value)
56+ }
57+}
qml/Dash/ScopeSettingsPage.qmlnew file+62
@@ -0,0 +1,62 @@
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+import QtQuick 2.2
18+import Ubuntu.Components 1.1
19+import Unity 0.2
20+import "../Components"
21+import "ScopeSettings"
22+
23+Item {
24+ id: root
25+
26+ property var scope: null
27+ property var scopeStyle: null
28+
29+ signal backClicked()
30+
31+ PageHeader {
32+ id: header
33+ objectName: "pageHeader"
34+ width: parent.width
35+ title: scope ? scope.name : ""
36+ showBackButton: true
37+ scopeStyle: root.scopeStyle
38+
39+ onBackClicked: root.backClicked()
40+ }
41+
42+ ListView {
43+ id: scopeSettings
44+ objectName: "scopeSettings"
45+ anchors {
46+ top: header.bottom
47+ bottom: parent.bottom
48+ left: parent.left
49+ right: parent.right
50+ }
51+ model: root.scope ? root.scope.settings : null
52+
53+ delegate: ScopeSettingsWidgetFactory {
54+ objectName: "scopeSettingItem" + index
55+ width: root.width
56+ widgetData: model
57+ scopeStyle: root.scopeStyle
58+
59+ onUpdated: model.value = value;
60+ }
61+ }
62+}
qml/Dash/ScopesOverview.qml+22−1
@@ -148,7 +148,12 @@ Item {
148
148
149 ScopeStyle {
149 ScopeStyle {
150 id: overviewScopeStyle
150 id: overviewScopeStyle
151+ style: { "foreground-color" : "white",
151− style: { "foreground-color" : "white", "background-color" : "transparent" }
152+ "background-color" : "transparent",
153+ "page-header": {
154+ "background": "color:///transparent"
155+ }
156+ }
152 }
157 }
153
158
154 DashBackground {
159 DashBackground {
@@ -458,10 +463,13 @@ Item {
458 objectName: "scopesOverviewPreviewListView"
463 objectName: "scopesOverviewPreviewListView"
459 scope: root.scope
464 scope: root.scope
460 scopeStyle: overviewScopeStyle
465 scopeStyle: overviewScopeStyle
466+ showSignatureLine: false
461 visible: x != width
467 visible: x != width
462 width: parent.width
468 width: parent.width
463 height: parent.height
469 height: parent.height
464 anchors.left: scopesOverviewContent.right
470 anchors.left: scopesOverviewContent.right
471+
472+ onBackClicked: open = false
465 }
473 }
466
474
467 Item {
475 Item {
@@ -535,6 +543,19 @@ Item {
535 scopesOverviewXYScaler.opacity = 0;
543 scopesOverviewXYScaler.opacity = 0;
536 middleItems.overrideOpacity = -1;
544 middleItems.overrideOpacity = -1;
537 }
545 }
546+ // TODO Add tests for these connections
547+ Connections {
548+ target: tempScopeItem.scope
549+ onOpenScope: {
550+ // TODO Animate the newly opened scope into the foreground (stacked on top of the current scope)
551+ tempScopeItem.scope = scope;
552+ }
553+ onGotoScope: {
554+ tempScopeItem.backClicked();
555+ root.currentTab = 0;
556+ root.scope.gotoScope(scopeId);
557+ }
558+ }
538 }
559 }
539 }
560 }
540}
561}
qml/Dash/graphics/PageHeaderBaseDivider@18.pngdeleted

Binary file not shown.

qml/Dash/graphics/PageHeaderBaseDivider@18.scideleted−5
@@ -1,5 +0,0 @@
1−border.top: 4
2−border.bottom: 4
3−border.left: 0
4−border.right: 0
5−source: PageHeaderBaseDivider@18.png
qml/Dash/graphics/navigation_shadow@18.pngnew file

Binary file not shown.

qml/Dash/graphics/navigation_shadow_light@18.pngnew file

Binary file not shown.

qml/Shell.qml+2−2
@@ -279,8 +279,8 @@ Item {
279 lockscreen.infoText = i18n.tr("Enter your passphrase")
279 lockscreen.infoText = i18n.tr("Enter your passphrase")
280 lockscreen.errorText = i18n.tr("Sorry, incorrect passphrase")
280 lockscreen.errorText = i18n.tr("Sorry, incorrect passphrase")
281 } else {
281 } else {
282− lockscreen.infoText = i18n.tr("Enter your PIN")
282+ lockscreen.infoText = i18n.tr("Enter your passcode")
283− lockscreen.errorText = i18n.tr("Sorry, incorrect PIN")
283+ lockscreen.errorText = i18n.tr("Sorry, incorrect passcode")
284 }
284 }
285 } else {
285 } else {
286 lockscreen.infoText = i18n.tr("Enter your %1").arg(text.toLowerCase())
286 lockscreen.infoText = i18n.tr("Enter your %1").arg(text.toLowerCase())
qml/Stages/SpreadDelegate.qml+3−7
@@ -47,14 +47,10 @@ Item {
47 BorderImage {
47 BorderImage {
48 anchors {
48 anchors {
49 fill: appWindow
49 fill: appWindow
50− leftMargin: -units.gu(2)
51− rightMargin: -units.gu(2)
52− bottomMargin: -units.gu(2)
53− topMargin: -units.gu(2)
50+ margins: -units.gu(2)
54 }
51 }
55− source: "graphics/dropshadow.png"
52+ source: "graphics/dropshadow2gu.sci"
56− border { left: 50; right: 50; top: 50; bottom: 50 }
57− opacity: root.dropShadow ? .4 : 0
53+ opacity: root.dropShadow ? .3 : 0
58 Behavior on opacity { UbuntuNumberAnimation {} }
54 Behavior on opacity { UbuntuNumberAnimation {} }
59 }
55 }
60
56
qml/Stages/graphics/dropshadow.pngdeleted

Binary file not shown.

qml/Stages/graphics/dropshadow2gu@30.pngnew file

Binary file not shown.

qml/Stages/graphics/dropshadow2gu@30.scinew file+5
@@ -0,0 +1,5 @@
1+border.left: 60
2+border.top: 60
3+border.bottom: 60
4+border.right: 60
5+source: dropshadow2gu@30.png
tests/autopilot/unity8/shell/emulators/dash.py+5−5
@@ -140,10 +140,9 @@ class Dash(emulators.UnityEmulatorBase):
140
140
141 def enter_search_query(self, query):
141 def enter_search_query(self, query):
142 current_header = self._get_current_page_header()
142 current_header = self._get_current_page_header()
143+ search_button = current_header.select_single(objectName="search_header_button")
143− self.pointing_device.move(current_header.globalRect.x +
144+ self.pointing_device.move(search_button.globalRect.x + search_button.width / 2,
144− current_header.width - current_header.height / 4,
145+ search_button.globalRect.y + search_button.height / 2)
145− current_header.globalRect.y +
146− current_header.height / 4)
147 self.pointing_device.click()
146 self.pointing_device.click()
148 headerContainer = current_header.select_single(
147 headerContainer = current_header.select_single(
149 objectName="headerContainer")
148 objectName="headerContainer")
@@ -186,7 +185,8 @@ class GenericScopeView(emulators.UnityEmulatorBase):
186 # --elopio - 2014-1-14
185 # --elopio - 2014-1-14
187 self.click_scope_item(category, app_name)
186 self.click_scope_item(category, app_name)
188 preview_list = self.wait_select_single(
187 preview_list = self.wait_select_single(
189− 'PreviewListView', objectName='previewListView')
188+ 'QQuickLoader', objectName='subPageLoader')
189+ preview_list.subPageShown.wait_for(True)
190 preview_list.x.wait_for(0)
190 preview_list.x.wait_for(0)
191 return preview_list.select_single(
191 return preview_list.select_single(
192 Preview, objectName='preview{}'.format(preview_list.currentIndex))
192 Preview, objectName='preview{}'.format(preview_list.currentIndex))
tests/mocks/GSettings.1.0/fake_gsettings.h+2−2
@@ -27,7 +27,7 @@ class GSettingsSchemaQml: public QObject
27 Q_PROPERTY(QByteArray id READ id WRITE setId)
27 Q_PROPERTY(QByteArray id READ id WRITE setId)
28
28
29public:
29public:
30− GSettingsSchemaQml(QObject *parent = NULL);
30+ GSettingsSchemaQml(QObject *parent = nullptr);
31
31
32 QByteArray id() const;
32 QByteArray id() const;
33 void setId(const QByteArray &id);
33 void setId(const QByteArray &id);
@@ -48,7 +48,7 @@ class GSettingsQml: public QObject
48 Q_PROPERTY(QString pictureUri READ pictureUri WRITE setPictureUri NOTIFY pictureUriChanged)
48 Q_PROPERTY(QString pictureUri READ pictureUri WRITE setPictureUri NOTIFY pictureUriChanged)
49
49
50public:
50public:
51− GSettingsQml(QObject *parent = NULL);
51+ GSettingsQml(QObject *parent = nullptr);
52 ~GSettingsQml();
52 ~GSettingsQml();
53
53
54 GSettingsSchemaQml * schema() const;
54 GSettingsSchemaQml * schema() const;
tests/mocks/HudClient/fake_libhud_client.cpp+9−9
@@ -48,7 +48,7 @@ static void hud_client_query_class_init(HudClientQueryClass * /*klass*/)
48 HUD_CLIENT_TYPE_QUERY,
48 HUD_CLIENT_TYPE_QUERY,
49 G_SIGNAL_RUN_LAST,
49 G_SIGNAL_RUN_LAST,
50 0, /* offset */
50 0, /* offset */
51− NULL, NULL, /* Accumulator */
51+ nullptr, nullptr, /* Accumulator */
52 g_cclosure_marshal_VOID__VOID,
52 g_cclosure_marshal_VOID__VOID,
53 G_TYPE_NONE, 0, G_TYPE_NONE);
53 G_TYPE_NONE, 0, G_TYPE_NONE);
54}
54}
@@ -56,7 +56,7 @@ static void hud_client_query_class_init(HudClientQueryClass * /*klass*/)
56HudClientQuery *hud_client_query_new(const gchar *query)
56HudClientQuery *hud_client_query_new(const gchar *query)
57{
57{
58 HudClientStub::m_lastSetQuery = QString::fromUtf8(query);
58 HudClientStub::m_lastSetQuery = QString::fromUtf8(query);
59− HudClientStub::m_query = HUD_CLIENT_QUERY(g_object_new(HUD_CLIENT_TYPE_QUERY, NULL));
59+ HudClientStub::m_query = HUD_CLIENT_QUERY(g_object_new(HUD_CLIENT_TYPE_QUERY, nullptr));
60 return HudClientStub::m_query;
60 return HudClientStub::m_query;
61}
61}
62
62
@@ -70,13 +70,13 @@ DeeModel *hud_client_query_get_results_model(HudClientQuery *cquery)
70 GVariant * columns[G_N_ELEMENTS(results_model_schema) + 1];
70 GVariant * columns[G_N_ELEMENTS(results_model_schema) + 1];
71 columns[0] = g_variant_new_variant(g_variant_new_uint64(0));
71 columns[0] = g_variant_new_variant(g_variant_new_uint64(0));
72 columns[1] = g_variant_new_string("Help");
72 columns[1] = g_variant_new_string("Help");
73− columns[2] = g_variant_new_array(G_VARIANT_TYPE("(ii)"), NULL, 0);
73+ columns[2] = g_variant_new_array(G_VARIANT_TYPE("(ii)"), nullptr, 0);
74 columns[3] = g_variant_new_string("Get Help");
74 columns[3] = g_variant_new_string("Get Help");
75− columns[4] = g_variant_new_array(G_VARIANT_TYPE("(ii)"), NULL, 0);
75+ columns[4] = g_variant_new_array(G_VARIANT_TYPE("(ii)"), nullptr, 0);
76 columns[5] = g_variant_new_string("");
76 columns[5] = g_variant_new_string("");
77 columns[6] = g_variant_new_uint32(3);
77 columns[6] = g_variant_new_uint32(3);
78 columns[7] = g_variant_new_boolean(false);
78 columns[7] = g_variant_new_boolean(false);
79− columns[8] = NULL;
79+ columns[8] = nullptr;
80 dee_model_append_row(resultsModel, columns);
80 dee_model_append_row(resultsModel, columns);
81
81
82 columns[0] = g_variant_new_variant(g_variant_new_uint64(1));
82 columns[0] = g_variant_new_variant(g_variant_new_uint64(1));
@@ -153,13 +153,13 @@ HudClientParam *hud_client_query_execute_param_command(HudClientQuery *cquery, G
153 HudClientStub::m_lastExecutedParametrizedCommandRow = i;
153 HudClientStub::m_lastExecutedParametrizedCommandRow = i;
154 g_variant_unref(it_command);
154 g_variant_unref(it_command);
155 // No need to create a real HudClientParam since it's always passed down to us
155 // No need to create a real HudClientParam since it's always passed down to us
156− return (HudClientParam *)g_object_new(G_TYPE_OBJECT, NULL);
156+ return (HudClientParam *)g_object_new(G_TYPE_OBJECT, nullptr);
157 }
157 }
158 g_variant_unref(it_command);
158 g_variant_unref(it_command);
159 }
159 }
160 }
160 }
161 HudClientStub::m_lastExecutedParametrizedCommandRow = -1;
161 HudClientStub::m_lastExecutedParametrizedCommandRow = -1;
162− return NULL;
162+ return nullptr;
163}
163}
164
164
165void hud_client_query_voice_query(HudClientQuery *cquery)
165void hud_client_query_voice_query(HudClientQuery *cquery)
@@ -183,7 +183,7 @@ GMenuModel *hud_client_param_get_model(HudClientParam *param)
183
183
184 if (!parametrizedActionModel) {
184 if (!parametrizedActionModel) {
185 GMenu *menu = g_menu_new();
185 GMenu *menu = g_menu_new();
186− GMenuItem *item = g_menu_item_new("Item1Label", NULL);
186+ GMenuItem *item = g_menu_item_new("Item1Label", nullptr);
187 g_menu_item_set_attribute_value(item, "parameter-type", g_variant_new_string("slider"));
187 g_menu_item_set_attribute_value(item, "parameter-type", g_variant_new_string("slider"));
188 g_menu_item_set_attribute_value(item, "min", g_variant_new_double(10));
188 g_menu_item_set_attribute_value(item, "min", g_variant_new_double(10));
189 g_menu_item_set_attribute_value(item, "max", g_variant_new_double(80));
189 g_menu_item_set_attribute_value(item, "max", g_variant_new_double(80));
@@ -220,7 +220,7 @@ GActionGroup *hud_client_param_get_actions(HudClientParam *param)
220 GSimpleAction *action = g_simple_action_new("costAction", G_VARIANT_TYPE_DOUBLE);
220 GSimpleAction *action = g_simple_action_new("costAction", G_VARIANT_TYPE_DOUBLE);
221 g_simple_action_group_insert(actionGroup, G_ACTION(action));
221 g_simple_action_group_insert(actionGroup, G_ACTION(action));
222
222
223− g_signal_connect (action, "activate", G_CALLBACK (on_signal_activated), NULL);
223+ g_signal_connect (action, "activate", G_CALLBACK (on_signal_activated), nullptr);
224
224
225
225
226 parametrizedActionGroup = G_ACTION_GROUP(actionGroup);
226 parametrizedActionGroup = G_ACTION_GROUP(actionGroup);
tests/mocks/LightDM/demo/GreeterPrivate.cpp+5−5
@@ -46,7 +46,7 @@ public:
46 : QObject(parent),
46 : QObject(parent),
47 greeter(parent),
47 greeter(parent),
48 greeterPrivate(greeterPrivate),
48 greeterPrivate(greeterPrivate),
49− pamHandle(NULL)
49+ pamHandle(nullptr)
50 {
50 {
51 qRegisterMetaType<QLightDM::GreeterImpl::ResponseFuture>("QLightDM::GreeterImpl::ResponseFuture");
51 qRegisterMetaType<QLightDM::GreeterImpl::ResponseFuture>("QLightDM::GreeterImpl::ResponseFuture");
52
52
@@ -206,14 +206,14 @@ Q_SIGNALS:
206private Q_SLOTS:
206private Q_SLOTS:
207 void finishPam()
207 void finishPam()
208 {
208 {
209− if (pamHandle == NULL) {
209+ if (pamHandle == nullptr) {
210 return;
210 return;
211 }
211 }
212
212
213 int pamStatus = futureWatcher.result();
213 int pamStatus = futureWatcher.result();
214
214
215 pam_end(pamHandle, pamStatus);
215 pam_end(pamHandle, pamStatus);
216− pamHandle = NULL;
216+ pamHandle = nullptr;
217
217
218 greeterPrivate->authenticated = (pamStatus == PAM_SUCCESS);
218 greeterPrivate->authenticated = (pamStatus == PAM_SUCCESS);
219 Q_EMIT greeter->authenticationComplete();
219 Q_EMIT greeter->authenticationComplete();
@@ -243,9 +243,9 @@ private:
243 void cancelPam()
243 void cancelPam()
244 {
244 {
245 // Unfortunately we can't simply cancel our QFuture because QtConcurrent::run doesn't support cancel
245 // Unfortunately we can't simply cancel our QFuture because QtConcurrent::run doesn't support cancel
246− if (pamHandle != NULL) {
246+ if (pamHandle != nullptr) {
247 pam_handle *handle = pamHandle;
247 pam_handle *handle = pamHandle;
248− pamHandle = NULL; // to disable normal finishPam() handling
248+ pamHandle = nullptr; // to disable normal finishPam() handling
249 while (respond(QString())); // clear our local queue of QFutures
249 while (respond(QString())); // clear our local queue of QFutures
250 pam_end(handle, PAM_CONV_ERR);
250 pam_end(handle, PAM_CONV_ERR);
251 }
251 }
tests/mocks/QMenuModel/unitymenumodel.cpp+4−4
@@ -118,7 +118,7 @@ void UnityMenuModel::setMenuObjectPath(const QByteArray &path)
118
118
119ActionStateParser* UnityMenuModel::actionStateParser() const
119ActionStateParser* UnityMenuModel::actionStateParser() const
120{
120{
121− return NULL;
121+ return nullptr;
122}
122}
123
123
124void UnityMenuModel::setActionStateParser(ActionStateParser*)
124void UnityMenuModel::setActionStateParser(ActionStateParser*)
@@ -190,11 +190,11 @@ QHash<int, QByteArray> UnityMenuModel::roleNames() const
190QObject * UnityMenuModel::submenu(int position, QQmlComponent*)
190QObject * UnityMenuModel::submenu(int position, QQmlComponent*)
191{
191{
192 if (position < 0 || m_modelData.count() < position) {
192 if (position < 0 || m_modelData.count() < position) {
193− return NULL;
193+ return nullptr;
194 }
194 }
195
195
196 while (submenus.count() <= position) {
196 while (submenus.count() <= position) {
197− submenus.append(NULL);
197+ submenus.append(nullptr);
198 }
198 }
199
199
200 QVariant submenuData = subMenuData(position);
200 QVariant submenuData = subMenuData(position);
@@ -209,7 +209,7 @@ QObject * UnityMenuModel::submenu(int position, QQmlComponent*)
209 return model;
209 return model;
210 }
210 }
211
211
212− return NULL;
212+ return nullptr;
213}
213}
214
214
215bool UnityMenuModel::loadExtendedAttributes(int, const QVariantMap &)
215bool UnityMenuModel::loadExtendedAttributes(int, const QVariantMap &)
tests/mocks/QMenuModel/unitymenumodel.h+2−2
@@ -35,7 +35,7 @@ class Q_DECL_EXPORT UnityMenuModel : public QAbstractListModel
35 Q_PROPERTY(QString nameOwner READ nameOwner NOTIFY nameOwnerChanged)
35 Q_PROPERTY(QString nameOwner READ nameOwner NOTIFY nameOwnerChanged)
36
36
37public:
37public:
38− UnityMenuModel(QObject *parent = NULL);
38+ UnityMenuModel(QObject *parent = nullptr);
39 virtual ~UnityMenuModel();
39 virtual ~UnityMenuModel();
40
40
41 Q_INVOKABLE void insertRow(int row, const QVariant& data);
41 Q_INVOKABLE void insertRow(int row, const QVariant& data);
@@ -66,7 +66,7 @@ public:
66 QModelIndex parent(const QModelIndex &index) const;
66 QModelIndex parent(const QModelIndex &index) const;
67 QHash<int, QByteArray> roleNames() const;
67 QHash<int, QByteArray> roleNames() const;
68
68
69− Q_INVOKABLE QObject * submenu(int position, QQmlComponent* actionStateParser = NULL);
69+ Q_INVOKABLE QObject * submenu(int position, QQmlComponent* actionStateParser = nullptr);
70 Q_INVOKABLE bool loadExtendedAttributes(int position, const QVariantMap &schema);
70 Q_INVOKABLE bool loadExtendedAttributes(int position, const QVariantMap &schema);
71 Q_INVOKABLE QVariant get(int row, const QByteArray &role);
71 Q_INVOKABLE QVariant get(int row, const QByteArray &role);
72
72
tests/mocks/QtMultimedia/audio.cpp+1−1
@@ -22,7 +22,7 @@ Audio::Audio(QObject* parent):
22 QObject(parent),
22 QObject(parent),
23 m_playbackState(StoppedState)
23 m_playbackState(StoppedState)
24{
24{
25− qsrand(time(NULL));
25+ qsrand(time(nullptr));
26 m_timer.setInterval(1000);
26 m_timer.setInterval(1000);
27 connect(&m_timer, SIGNAL(timeout()), SLOT(timerEvent()));
27 connect(&m_timer, SIGNAL(timeout()), SLOT(timerEvent()));
28}
28}
tests/mocks/Unity/Application/ApplicationInfo.h+3−3
@@ -42,11 +42,11 @@ class ApplicationInfo : public ApplicationInfoInterface {
42 Q_PROPERTY(bool manualSessionCreation READ manualSessionCreation WRITE setManualSessionCreation NOTIFY manualSessionCreationChanged)
42 Q_PROPERTY(bool manualSessionCreation READ manualSessionCreation WRITE setManualSessionCreation NOTIFY manualSessionCreationChanged)
43
43
44public:
44public:
45+ ApplicationInfo(QObject *parent = nullptr);
45− ApplicationInfo(const QString &appId, QObject *parent = NULL);
46+ ApplicationInfo(const QString &appId, QObject *parent = nullptr);
46− ApplicationInfo(QObject *parent = NULL);
47 ~ApplicationInfo();
47 ~ApplicationInfo();
48
48
49− void setIconId(const QString &iconId);
49+ void setIconId(const QString &iconId);
50 void setScreenshotId(const QString &screenshotId);
50 void setScreenshotId(const QString &screenshotId);
51
51
52 void setAppId(const QString &value) { m_appId = value; }
52 void setAppId(const QString &value) { m_appId = value; }
tests/mocks/Unity/Application/ApplicationManager.h+1−1
@@ -46,7 +46,7 @@ class ApplicationManager : public ApplicationManagerInterface {
46 Q_PROPERTY(bool fake READ fake CONSTANT)
46 Q_PROPERTY(bool fake READ fake CONSTANT)
47
47
48 public:
48 public:
49− ApplicationManager(QObject *parent = NULL);
49+ ApplicationManager(QObject *parent = nullptr);
50 virtual ~ApplicationManager();
50 virtual ~ApplicationManager();
51
51
52 static ApplicationManager *singleton();
52 static ApplicationManager *singleton();
tests/mocks/Unity/CMakeLists.txt+2
@@ -24,6 +24,7 @@ set(UnityQML_SOURCES
24 fake_scope.cpp
24 fake_scope.cpp
25 fake_scopes.cpp
25 fake_scopes.cpp
26 fake_scopesoverview.cpp
26 fake_scopesoverview.cpp
27+ fake_settingsmodel.cpp
27 fake_categories.cpp
28 fake_categories.cpp
28 fake_navigation.cpp
29 fake_navigation.cpp
29 fake_resultsmodel.cpp
30 fake_resultsmodel.cpp
@@ -39,6 +40,7 @@ set(UnityQML_SOURCES
39 ${SCOPES_API_INCLUDEDIR}/unity/shell/scopes/ResultsModelInterface.h
40 ${SCOPES_API_INCLUDEDIR}/unity/shell/scopes/ResultsModelInterface.h
40 ${SCOPES_API_INCLUDEDIR}/unity/shell/scopes/ScopeInterface.h
41 ${SCOPES_API_INCLUDEDIR}/unity/shell/scopes/ScopeInterface.h
41 ${SCOPES_API_INCLUDEDIR}/unity/shell/scopes/ScopesInterface.h
42 ${SCOPES_API_INCLUDEDIR}/unity/shell/scopes/ScopesInterface.h
43+ ${SCOPES_API_INCLUDEDIR}/unity/shell/scopes/SettingsModelInterface.h
42)
44)
43
45
44add_library(FakeUnityQml MODULE ${UnityQML_SOURCES})
46add_library(FakeUnityQml MODULE ${UnityQML_SOURCES})
tests/mocks/Unity/fake_navigation.cpp+6−1
@@ -32,6 +32,7 @@ Navigation::Navigation(const QString& navigationId, const QString& label, const
32{
32{
33 QTimer::singleShot(1500, this, SLOT(slotLoaded()));
33 QTimer::singleShot(1500, this, SLOT(slotLoaded()));
34 connect(scope, SIGNAL(currentNavigationIdChanged()), this, SLOT(slotCurrentNavigationChanged()));
34 connect(scope, SIGNAL(currentNavigationIdChanged()), this, SLOT(slotCurrentNavigationChanged()));
35+ connect(scope, SIGNAL(currentAltNavigationIdChanged()), this, SLOT(slotCurrentNavigationChanged()));
35}
36}
36
37
37QString Navigation::navigationId() const
38QString Navigation::navigationId() const
@@ -106,7 +107,11 @@ QVariant Navigation::data(const QModelIndex &index, int role) const
106 case RoleHasChildren:
107 case RoleHasChildren:
107 return m_navigationId == "root" && index.row() != 3;
108 return m_navigationId == "root" && index.row() != 3;
108 case RoleIsActive:
109 case RoleIsActive:
110+ if (m_navigationId.startsWith("alt")) {
111+ return m_scope->currentAltNavigationId() == data(index, RoleNavigationId);
112+ } else {
109− return m_scope->currentNavigationId() == data(index, RoleNavigationId);
113+ return m_scope->currentNavigationId() == data(index, RoleNavigationId);
114+ }
110 }
115 }
111 return QVariant();
116 return QVariant();
112}
117}
tests/mocks/Unity/fake_scope.cpp+18−3
@@ -22,6 +22,7 @@
22#include "fake_navigation.h"
22#include "fake_navigation.h"
23#include "fake_resultsmodel.h"
23#include "fake_resultsmodel.h"
24#include "fake_scopes.h"
24#include "fake_scopes.h"
25+#include "fake_settingsmodel.h"
25
26
26Scope::Scope(Scopes* parent) : Scope(QString(), QString(), false, parent)
27Scope::Scope(Scopes* parent) : Scope(QString(), QString(), false, parent)
27{
28{
@@ -39,6 +40,7 @@ Scope::Scope(QString const& id, QString const& name, bool favorite, Scopes* pare
39 , m_previewRendererName("preview-generic")
40 , m_previewRendererName("preview-generic")
40 , m_categories(new Categories(categories, this))
41 , m_categories(new Categories(categories, this))
41 , m_openScope(nullptr)
42 , m_openScope(nullptr)
43+ , m_settings(new SettingsModel(this))
42{
44{
43}
45}
44
46
@@ -94,7 +96,7 @@ unity::shell::scopes::CategoriesInterface* Scope::categories() const
94
96
95unity::shell::scopes::SettingsModelInterface* Scope::settings() const
97unity::shell::scopes::SettingsModelInterface* Scope::settings() const
96{
98{
97− return nullptr;
99+ return m_settings;
98}
100}
99
101
100QString Scope::noResultsHint() const
102QString Scope::noResultsHint() const
@@ -224,9 +226,17 @@ QVariantMap Scope::customizations() const
224 m["background-color"] = "red";
226 m["background-color"] = "red";
225 m["foreground-color"] = "blue";
227 m["foreground-color"] = "blue";
226 m["page-header"] = h;
228 m["page-header"] = h;
229+ } else if (m_id == "MockScope4") {
230+ h["navigation-background"] = QUrl("../../../tests/qmltests/Dash/artwork/background.png");
231+ m["page-header"] = h;
227 } else if (m_id == "MockScope5") {
232 } else if (m_id == "MockScope5") {
228 h["background"] = "gradient:///lightgrey/grey";
233 h["background"] = "gradient:///lightgrey/grey";
229 h["logo"] = QUrl("../../../tests/qmltests/Dash/tst_PageHeader/logo-ubuntu-orange.svg");
234 h["logo"] = QUrl("../../../tests/qmltests/Dash/tst_PageHeader/logo-ubuntu-orange.svg");
235+ h["divider-color"] = "red";
236+ h["navigation-background"] = "color:///black";
237+ m["page-header"] = h;
238+ } else if (m_id == "MockScope6") {
239+ h["navigation-background"] = "gradient:///blue/red";
230 m["page-header"] = h;
240 m["page-header"] = h;
231 }
241 }
232 return m;
242 return m;
@@ -261,11 +271,16 @@ unity::shell::scopes::NavigationInterface* Scope::getAltNavigation(QString const
261
271
262 QString parentId;
272 QString parentId;
263 QString parentLabel;
273 QString parentLabel;
264− if (id.startsWith("altmiddle")) {
274+ if (id != "altroot") {
265 parentId = "altroot";
275 parentId = "altroot";
266 parentLabel = "altroot";
276 parentLabel = "altroot";
267 }
277 }
268− return new Navigation(id, id, "all"+id, parentId, parentLabel, this);
278+ auto result = new Navigation(id, id, "all"+id, parentId, parentLabel, this);
279+ if (id == "altroot") {
280+ m_currentAltNavigationId = "altrootChild1";
281+ Q_EMIT currentAltNavigationIdChanged();
282+ }
283+ return result;
269}
284}
270
285
271void Scope::setNavigationState(const QString &navigationId, bool isAltNavigation)
286void Scope::setNavigationState(const QString &navigationId, bool isAltNavigation)
tests/mocks/Unity/fake_scope.h+1
@@ -96,6 +96,7 @@ protected:
96
96
97 unity::shell::scopes::CategoriesInterface* m_categories;
97 unity::shell::scopes::CategoriesInterface* m_categories;
98 unity::shell::scopes::ScopeInterface* m_openScope;
98 unity::shell::scopes::ScopeInterface* m_openScope;
99+ unity::shell::scopes::SettingsModelInterface* m_settings;
99};
100};
100
101
101#endif // FAKE_SCOPE_H
102#endif // FAKE_SCOPE_H
tests/mocks/Unity/fake_scopes.h+1−1
@@ -56,7 +56,7 @@ public:
56 // This is used as part of implementation of the other C++ code, not API
56 // This is used as part of implementation of the other C++ code, not API
57 QList<Scope*> scopes() const;
57 QList<Scope*> scopes() const;
58 QList<Scope*> allScopes() const;
58 QList<Scope*> allScopes() const;
59− Scope* getScopeFromAll(const QString& scope_id) const;
59+ Q_INVOKABLE Scope* getScopeFromAll(const QString& scope_id) const;
60
60
61private Q_SLOTS:
61private Q_SLOTS:
62 void updateScopes();
62 void updateScopes();
tests/mocks/Unity/fake_settingsmodel.cppnew file+95
@@ -0,0 +1,95 @@
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+#include "fake_settingsmodel.h"
18+
19+SettingsModel::SettingsModel(QObject* parent) :
20+ SettingsModelInterface(parent) {
21+ {
22+ QVariantMap parameters;
23+ m_data << QSharedPointer<Data>(new Data("boolean-setting", "Boolean Setting", "boolean", parameters, true));
24+ }
25+ {
26+ QVariantMap parameters;
27+ parameters["values"] = QVariantList() << "First" << "Second" << "Third";
28+ m_data << QSharedPointer<Data>(new Data("list-setting", "List Setting", "list", parameters, 1));
29+ }
30+ {
31+ QVariantMap parameters;
32+ m_data << QSharedPointer<Data>(new Data("number-setting", "Number Setting", "number", parameters, 1.23));
33+ }
34+ {
35+ QVariantMap parameters;
36+ m_data << QSharedPointer<Data>(new Data("string-setting", "String Setting", "string", parameters, "flibble"));
37+ }
38+}
39+
40+QVariant SettingsModel::data(const QModelIndex& index, int role) const {
41+ int row = index.row();
42+ QVariant result;
43+
44+ if (row < m_data.size()) {
45+ auto data = m_data[row];
46+
47+ switch (role) {
48+ case Roles::RoleSettingId:
49+ result = data->id;
50+ break;
51+ case Roles::RoleDisplayName:
52+ result = data->displayName;
53+ break;
54+ case Roles::RoleType:
55+ result = data->type;
56+ break;
57+ case Roles::RoleProperties:
58+ result = data->properties;
59+ break;
60+ case Roles::RoleValue: {
61+ result = data->value;
62+ break;
63+ }
64+ default:
65+ break;
66+ }
67+ }
68+
69+ return result;
70+}
71+
72+bool SettingsModel::setData(const QModelIndex &index, const QVariant &value, int role) {
73+ int row = index.row();
74+ if (row < m_data.size()) {
75+ switch (role) {
76+ case SettingsModelInterface::RoleValue: {
77+ auto data = m_data[row];
78+ data->value = value;
79+ return true;
80+ }
81+ default:
82+ break;
83+ }
84+ }
85+
86+ return false;
87+}
88+
89+int SettingsModel::rowCount(const QModelIndex&) const {
90+ return count();
91+}
92+
93+int SettingsModel::count() const {
94+ return m_data.size();
95+}
tests/mocks/Unity/fake_settingsmodel.hnew file+54
@@ -0,0 +1,54 @@
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 FAKE_SETTINGSMODEL_H
18+#define FAKE_SETTINGSMODEL_H
19+
20+#include <unity/shell/scopes/SettingsModelInterface.h>
21+
22+#include <QList>
23+#include <QSharedPointer>
24+
25+class SettingsModel: public unity::shell::scopes::SettingsModelInterface {
26+Q_OBJECT
27+
28+ struct Data {
29+ QString id;
30+ QString displayName;
31+ QString type;
32+ QVariant properties;
33+ QVariant value;
34+
35+ Data(QString const& id_, QString const& displayName_,
36+ QString const& type_, QVariant const& properties_,
37+ QVariant const& value_) :
38+ id(id_), displayName(displayName_), type(type_),
39+ properties(properties_), value(value_) {}
40+ };
41+
42+public:
43+ explicit SettingsModel(QObject* parent = 0);
44+ ~SettingsModel() = default;
45+ QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
46+ bool setData(const QModelIndex&index, const QVariant& value, int role = Qt::EditRole) override;
47+ int rowCount(const QModelIndex& parent = QModelIndex()) const override;
48+ int count() const override;
49+
50+protected:
51+ QList<QSharedPointer<Data>> m_data;
52+};
53+
54+#endif // FAKE_SETTINGSMODEL_H
tests/mocks/Unity/fake_unity_plugin.cpp+2
@@ -26,6 +26,7 @@
26#include "fake_previewmodel.h"
26#include "fake_previewmodel.h"
27#include "fake_previewwidgetmodel.h"
27#include "fake_previewwidgetmodel.h"
28#include "fake_resultsmodel.h"
28#include "fake_resultsmodel.h"
29+#include "fake_settingsmodel.h"
29
30
30// External
31// External
31#include <glib-object.h>
32#include <glib-object.h>
@@ -43,6 +44,7 @@ void FakeUnityPlugin::registerTypes(const char *uri)
43 qmlRegisterType<Scopes>(uri, 0, 2, "Scopes");
44 qmlRegisterType<Scopes>(uri, 0, 2, "Scopes");
44 qmlRegisterType<Scope>(uri, 0, 2, "MockScope");
45 qmlRegisterType<Scope>(uri, 0, 2, "MockScope");
45 qmlRegisterUncreatableType<unity::shell::scopes::ScopeInterface>(uri, 0, 2, "Scope", "Can't create Scope object in QML.");
46 qmlRegisterUncreatableType<unity::shell::scopes::ScopeInterface>(uri, 0, 2, "Scope", "Can't create Scope object in QML.");
47+ qmlRegisterUncreatableType<unity::shell::scopes::SettingsModelInterface>(uri, 0, 2, "SettingsModel", "Can't create SettingsModel object in QML.");
46 qmlRegisterUncreatableType<unity::shell::scopes::NavigationInterface>(uri, 0, 2, "Navigation", "Can't create Navigation object in QML.");
48 qmlRegisterUncreatableType<unity::shell::scopes::NavigationInterface>(uri, 0, 2, "Navigation", "Can't create Navigation object in QML.");
47 qmlRegisterUncreatableType<unity::shell::scopes::CategoriesInterface>(uri, 0, 2, "Categories", "Can't create Categories object in QML.");
49 qmlRegisterUncreatableType<unity::shell::scopes::CategoriesInterface>(uri, 0, 2, "Categories", "Can't create Categories object in QML.");
48 qmlRegisterUncreatableType<unity::shell::scopes::PreviewModelInterface>(uri, 0, 2, "PreviewModel", "Can't create new PreviewModel in QML. Get them from PreviewStack instance.");
50 qmlRegisterUncreatableType<unity::shell::scopes::PreviewModelInterface>(uri, 0, 2, "PreviewModel", "Can't create new PreviewModel in QML. Get them from PreviewStack instance.");
tests/plugins/Dash/cardcreator/2.res+3−3
@@ -26,7 +26,7 @@ Loader {
26 gradientColor: getColor(1) || color;
26 gradientColor: getColor(1) || color;
27 anchors.fill: parent;
27 anchors.fill: parent;
28 image: backgroundImage.source ? backgroundImage : null;
28 image: backgroundImage.source ? backgroundImage : null;
29− property real luminance: 0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b;
29+ property real luminance: Style.luminance(color);
30 property Image backgroundImage: Image {
30 property Image backgroundImage: Image {
31 objectName: "backgroundImage";
31 objectName: "backgroundImage";
32 source: {
32 source: {
@@ -94,7 +94,7 @@ Image {
94 wrapMode: Text.Wrap;
94 wrapMode: Text.Wrap;
95 maximumLineCount: 2;
95 maximumLineCount: 2;
96 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
96 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
97− color: backgroundLoader.active && backgroundLoader.item && backgroundLoader.item.luminance < (root.scopeStyle ? root.scopeStyle.threshold : 0.7) ? (root.scopeStyle ? root.scopeStyle.light : "white") : (root.scopeStyle ? root.scopeStyle.dark : Theme.palette.normal.baseText);
97+ color: backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item.luminance > 0.7 ? Theme.palette.normal.baseText : "white");
98 visible: showHeader ;
98 visible: showHeader ;
99 text: root.title;
99 text: root.title;
100 font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
100 font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
@@ -112,7 +112,7 @@ Image {
112 elide: Text.ElideRight;
112 elide: Text.ElideRight;
113 fontSize: "small";
113 fontSize: "small";
114 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
114 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
115− color: backgroundLoader.active && backgroundLoader.item && backgroundLoader.item.luminance < (root.scopeStyle ? root.scopeStyle.threshold : 0.7) ? (root.scopeStyle ? root.scopeStyle.light : "white") : (root.scopeStyle ? root.scopeStyle.dark : Theme.palette.normal.baseText);
115+ color: backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item.luminance > 0.7 ? Theme.palette.normal.baseText : "white");
116 visible: titleLabel.visible && titleLabel.text;
116 visible: titleLabel.visible && titleLabel.text;
117 text: cardData && cardData["subtitle"] || "";
117 text: cardData && cardData["subtitle"] || "";
118 font.weight: Font.Light;
118 font.weight: Font.Light;
tests/plugins/Dash/cardcreator/5.res+5−3
@@ -69,7 +69,7 @@ Loader {
69 sourceComponent: ShaderEffect {
69 sourceComponent: ShaderEffect {
70 id: overlay;
70 id: overlay;
71 height: (fixedHeaderHeight > 0 ? fixedHeaderHeight : headerHeight) + units.gu(2);
71 height: (fixedHeaderHeight > 0 ? fixedHeaderHeight : headerHeight) + units.gu(2);
72− property real luminance: 0.2126 * overlayColor.r + 0.7152 * overlayColor.g + 0.0722 * overlayColor.b;
72+ property real luminance: Style.luminance(overlayColor);
73 property color overlayColor: cardData && cardData["overlayColor"] || "#99000000";
73 property color overlayColor: cardData && cardData["overlayColor"] || "#99000000";
74 property var source: ShaderEffectSource {
74 property var source: ShaderEffectSource {
75 id: shaderSource;
75 id: shaderSource;
@@ -103,6 +103,7 @@ Label {
103 id: titleLabel;
103 id: titleLabel;
104 objectName: "titleLabel";
104 objectName: "titleLabel";
105 anchors { right: parent.right;
105 anchors { right: parent.right;
106+ rightMargin: units.gu(1);
106 left: parent.left;
107 left: parent.left;
107 leftMargin: units.gu(1);
108 leftMargin: units.gu(1);
108 top: overlayLoader.top;
109 top: overlayLoader.top;
@@ -113,7 +114,7 @@ Label {
113 wrapMode: Text.Wrap;
114 wrapMode: Text.Wrap;
114 maximumLineCount: 2;
115 maximumLineCount: 2;
115 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
116 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
116− color: overlayLoader.item.luminance < (root.scopeStyle ? root.scopeStyle.threshold : 0.7) ? (root.scopeStyle ? root.scopeStyle.light : "white") : (root.scopeStyle ? root.scopeStyle.dark : Theme.palette.normal.baseText);
117+ color: root.scopeStyle ? root.scopeStyle.getTextColor(overlayLoader.item.luminance) : (overlayLoader.item.luminance > 0.7 ? Theme.palette.normal.baseText : "white");
117 visible: showHeader && overlayLoader.active;
118 visible: showHeader && overlayLoader.active;
118 text: root.title;
119 text: root.title;
119 font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
120 font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
@@ -124,6 +125,7 @@ Label {
124 objectName: "subtitleLabel";
125 objectName: "subtitleLabel";
125 anchors { left: titleLabel.left;
126 anchors { left: titleLabel.left;
126 leftMargin: titleLabel.leftMargin;
127 leftMargin: titleLabel.leftMargin;
128+ rightMargin: units.gu(1);
127 right: titleLabel.right;
129 right: titleLabel.right;
128 top: titleLabel.bottom;
130 top: titleLabel.bottom;
129 }
131 }
@@ -131,7 +133,7 @@ Label {
131 elide: Text.ElideRight;
133 elide: Text.ElideRight;
132 fontSize: "small";
134 fontSize: "small";
133 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
135 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
134− color: overlayLoader.item.luminance < (root.scopeStyle ? root.scopeStyle.threshold : 0.7) ? (root.scopeStyle ? root.scopeStyle.light : "white") : (root.scopeStyle ? root.scopeStyle.dark : Theme.palette.normal.baseText);
136+ color: root.scopeStyle ? root.scopeStyle.getTextColor(overlayLoader.item.luminance) : (overlayLoader.item.luminance > 0.7 ? Theme.palette.normal.baseText : "white");
135 visible: titleLabel.visible && titleLabel.text;
137 visible: titleLabel.visible && titleLabel.text;
136 text: cardData && cardData["subtitle"] || "";
138 text: cardData && cardData["subtitle"] || "";
137 font.weight: Font.Light;
139 font.weight: Font.Light;
tests/plugins/Dash/cardcreator/6.res+4−4
@@ -26,7 +26,7 @@ Loader {
26 gradientColor: getColor(1) || color;
26 gradientColor: getColor(1) || color;
27 anchors.fill: parent;
27 anchors.fill: parent;
28 image: backgroundImage.source ? backgroundImage : null;
28 image: backgroundImage.source ? backgroundImage : null;
29− property real luminance: 0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b;
29+ property real luminance: Style.luminance(color);
30 property Image backgroundImage: Image {
30 property Image backgroundImage: Image {
31 objectName: "backgroundImage";
31 objectName: "backgroundImage";
32 source: {
32 source: {
@@ -70,7 +70,7 @@ Item {
70 wrapMode: Text.Wrap;
70 wrapMode: Text.Wrap;
71 maximumLineCount: 2;
71 maximumLineCount: 2;
72 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
72 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
73− color: backgroundLoader.active && backgroundLoader.item && backgroundLoader.item.luminance < (root.scopeStyle ? root.scopeStyle.threshold : 0.7) ? (root.scopeStyle ? root.scopeStyle.light : "white") : (root.scopeStyle ? root.scopeStyle.dark : Theme.palette.normal.baseText);
73+ color: backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item.luminance > 0.7 ? Theme.palette.normal.baseText : "white");
74 visible: showHeader ;
74 visible: showHeader ;
75 text: root.title;
75 text: root.title;
76 font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
76 font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
@@ -88,7 +88,7 @@ Item {
88 elide: Text.ElideRight;
88 elide: Text.ElideRight;
89 fontSize: "small";
89 fontSize: "small";
90 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
90 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
91− color: backgroundLoader.active && backgroundLoader.item && backgroundLoader.item.luminance < (root.scopeStyle ? root.scopeStyle.threshold : 0.7) ? (root.scopeStyle ? root.scopeStyle.light : "white") : (root.scopeStyle ? root.scopeStyle.dark : Theme.palette.normal.baseText);
91+ color: backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item.luminance > 0.7 ? Theme.palette.normal.baseText : "white");
92 visible: titleLabel.visible && titleLabel.text;
92 visible: titleLabel.visible && titleLabel.text;
93 text: cardData && cardData["subtitle"] || "";
93 text: cardData && cardData["subtitle"] || "";
94 font.weight: Font.Light;
94 font.weight: Font.Light;
@@ -103,7 +103,7 @@ Item {
103 rightMargin: units.gu(1);
103 rightMargin: units.gu(1);
104 }
104 }
105 source: cardData && cardData["emblem"] || "";
105 source: cardData && cardData["emblem"] || "";
106− color: backgroundLoader.active && backgroundLoader.item && backgroundLoader.item.luminance < (root.scopeStyle ? root.scopeStyle.threshold : 0.7) ? (root.scopeStyle ? root.scopeStyle.light : "white") : (root.scopeStyle ? root.scopeStyle.dark : Theme.palette.normal.baseText);
106+ color: backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item.luminance > 0.7 ? Theme.palette.normal.baseText : "white");
107 width: height;
107 width: height;
108 height: source != "" ? titleLabel.font.pixelSize : 0;
108 height: source != "" ? titleLabel.font.pixelSize : 0;
109 }
109 }
tests/plugins/Dash/cardcreator/7.res+5−4
@@ -26,7 +26,7 @@ Loader {
26 gradientColor: getColor(1) || color;
26 gradientColor: getColor(1) || color;
27 anchors.fill: parent;
27 anchors.fill: parent;
28 image: backgroundImage.source ? backgroundImage : null;
28 image: backgroundImage.source ? backgroundImage : null;
29− property real luminance: 0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b;
29+ property real luminance: Style.luminance(color);
30 property Image backgroundImage: Image {
30 property Image backgroundImage: Image {
31 objectName: "backgroundImage";
31 objectName: "backgroundImage";
32 source: {
32 source: {
@@ -95,7 +95,7 @@ Image {
95 wrapMode: Text.Wrap;
95 wrapMode: Text.Wrap;
96 maximumLineCount: 2;
96 maximumLineCount: 2;
97 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
97 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
98− color: backgroundLoader.active && backgroundLoader.item && backgroundLoader.item.luminance < (root.scopeStyle ? root.scopeStyle.threshold : 0.7) ? (root.scopeStyle ? root.scopeStyle.light : "white") : (root.scopeStyle ? root.scopeStyle.dark : Theme.palette.normal.baseText);
98+ color: backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item.luminance > 0.7 ? Theme.palette.normal.baseText : "white");
99 visible: showHeader ;
99 visible: showHeader ;
100 text: root.title;
100 text: root.title;
101 font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
101 font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
@@ -113,7 +113,7 @@ Image {
113 elide: Text.ElideRight;
113 elide: Text.ElideRight;
114 fontSize: "small";
114 fontSize: "small";
115 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
115 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
116− color: backgroundLoader.active && backgroundLoader.item && backgroundLoader.item.luminance < (root.scopeStyle ? root.scopeStyle.threshold : 0.7) ? (root.scopeStyle ? root.scopeStyle.light : "white") : (root.scopeStyle ? root.scopeStyle.dark : Theme.palette.normal.baseText);
116+ color: backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item.luminance > 0.7 ? Theme.palette.normal.baseText : "white");
117 visible: titleLabel.visible && titleLabel.text;
117 visible: titleLabel.visible && titleLabel.text;
118 text: cardData && cardData["subtitle"] || "";
118 text: cardData && cardData["subtitle"] || "";
119 font.weight: Font.Light;
119 font.weight: Font.Light;
@@ -127,7 +127,8 @@ Image {
127 rightMargin: units.gu(1);
127 rightMargin: units.gu(1);
128 top: subtitleLabel.bottom;
128 top: subtitleLabel.bottom;
129 }
129 }
130− color: backgroundLoader.active && backgroundLoader.item && backgroundLoader.item.luminance < (root.scopeStyle ? root.scopeStyle.threshold : 0.7) ? (root.scopeStyle ? root.scopeStyle.light : "white") : (root.scopeStyle ? root.scopeStyle.dark : Theme.palette.normal.baseText);
130+ color: backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item.luminance > 0.7 ? Theme.palette.normal.baseText : "white");
131+ fontScale: root.fontScale;
131 model: cardData && cardData["attributes"];
132 model: cardData && cardData["attributes"];
132 }
133 }
133
134
tests/plugins/Dash/tst_CardAttributes.qml+4−1
@@ -26,7 +26,8 @@ Item {
26 [{"value":"text1","icon":"image://theme/ok"},{"value":"text2","icon":"image://theme/cancel"}],
26 [{"value":"text1","icon":"image://theme/ok"},{"value":"text2","icon":"image://theme/cancel"}],
27 [{"value":"text1","icon":"image://theme/ok"},{"value":"text2","icon":"image://theme/cancel"},{"value":"text3"}],
27 [{"value":"text1","icon":"image://theme/ok"},{"value":"text2","icon":"image://theme/cancel"},{"value":"text3"}],
28 [{"value":"text1","icon":"image://theme/ok"},{"value":"text2","icon":"image://theme/cancel"},{"value":"text3"},{"value":"text4"}],
28 [{"value":"text1","icon":"image://theme/ok"},{"value":"text2","icon":"image://theme/cancel"},{"value":"text3"},{"value":"text4"}],
29− [{"value":"text1","icon":"image://theme/ok"},{"value":"text2","icon":"image://theme/cancel"},{"value":"text3","style":"highlighted"},{"value":"text4","icon":"image://theme/close","style":"highlighted"},{"value":"text5"}]
29+ [{"value":"text1","icon":"image://theme/ok"},{"value":"text2","icon":"image://theme/cancel"},{"value":"text3","style":"highlighted"},{"value":"text4","icon":"image://theme/close","style":"highlighted"},{"value":"text5"}],
30+ [{"value":"text1","icon":"image://theme/ok"},{},{},{},{"value":"text5", "icon": "image://theme/search"}],
30 ]
31 ]
31
32
32 CardAttributes {
33 CardAttributes {
@@ -49,6 +50,8 @@ Item {
49 function test_columns(data) {
50 function test_columns(data) {
50 cardAttributes.model = data;
51 cardAttributes.model = data;
51 compare(cardAttributes.columns, 2 + data.length % 2);
52 compare(cardAttributes.columns, 2 + data.length % 2);
53+ var rows = Math.ceil(data.length / 3);
54+ tryCompare(cardAttributes, "height", rows * units.gu(2) + (rows - 1) * cardAttributes.rowSpacing);
52 }
55 }
53 }
56 }
54}
57}
tests/plugins/Dash/tst_ScopeStyle.qml+73−68
@@ -18,6 +18,7 @@ import QtQuick 2.2
18import QtTest 1.0
18import QtTest 1.0
19import Dash 0.1
19import Dash 0.1
20import Ubuntu.Components 1.1
20import Ubuntu.Components 1.1
21+import Utils 0.1
21
22
22Rectangle {
23Rectangle {
23 width: units.gu(40)
24 width: units.gu(40)
@@ -35,39 +36,23 @@ Rectangle {
35 property color color
36 property color color
36 property var styles: [
37 property var styles: [
37 {},
38 {},
38− { "foreground-color": "red", "background-color": "black", "page-header": { "logo": "/foo/bar" } },
39+ { "foreground-color": "red", "background-color": "black", "page-header": { "logo": "/foo/bar" },
40+ "preview-button-color": "red"},
39− { "foreground-color": "green", "background-color": "white", "page-header": { "foreground-color": "black" } },
41+ { "foreground-color": "green", "background-color": "white",
42+ "page-header": { "foreground-color": "black",
43+ "divider-color": "blue" } },
40− { "foreground-color": "blue", "background-color": "darkgrey", "page-header": { "background": "gradient:///white/blue" } },
44+ { "foreground-color": "blue", "background-color": "darkgrey",
45+ "page-header": { "background": "gradient:///white/blue",
46+ "navigation-background": "gradient:///white/blue" } },
41 ]
47 ]
42
48
43 function cleanup() {
49 function cleanup() {
44 testCase.color = "transparent";
50 testCase.color = "transparent";
45 }
51 }
46
52
47− function test_luminance_data() {
48− return [
49− { tag: "#F00", luminance: 0.2126 },
50− { tag: "#0F0", luminance: 0.7152 },
51− { tag: "#00F", luminance: 0.0722 },
52− { tag: "white", luminance: 1.0 },
53− { tag: "black", luminance: 0.0 },
54− { tag: "lightgrey", luminance: 0.8275 },
55− { tag: "grey", luminance: 0.5020 },
56− { tag: "darkgrey", luminance: 0.6627 },
57− { tag: "red", luminance: 0.2126 },
58− { tag: "green", luminance: 0.3590 },
59− { tag: "blue", luminance: 0.0722 },
60− ];
61− }
62−
63− function test_luminance(data) {
64− testCase.color = data.tag;
65− compare(tool.luminance(testCase.color).toFixed(4), data.luminance.toFixed(4));
66− }
67−
68 function test_foreground_data() {
53 function test_foreground_data() {
69 return [
54 return [
70− { tag: "default", index: 0, foreground: Theme.palette.normal.foreground, luminance: 0.5725 },
55+ { tag: "default", index: 0, foreground: UbuntuColors.darkGrey, luminance: 0.3647 },
71 { tag: "red on black", index: 1, foreground: "red", luminance: 0.2126 },
56 { tag: "red on black", index: 1, foreground: "red", luminance: 0.2126 },
72 { tag: "green on white", index: 2, foreground: "green", luminance: 0.3590 },
57 { tag: "green on white", index: 2, foreground: "green", luminance: 0.3590 },
73 { tag: "blue on darkgrey", index: 3, foreground: "blue", luminance: 0.0722 },
58 { tag: "blue on darkgrey", index: 3, foreground: "blue", luminance: 0.0722 },
@@ -83,7 +68,7 @@ Rectangle {
83
68
84 function test_background_data() {
69 function test_background_data() {
85 return [
70 return [
86− { tag: "default", index: 0, background: "transparent" },
71+ { tag: "default", index: 0, background: "#00f5f5f5", luminance: 0.9608 },
87 { tag: "red on black", index: 1, background: "black", luminance: 0 },
72 { tag: "red on black", index: 1, background: "black", luminance: 0 },
88 { tag: "green on white", index: 2, background: "white", luminance: 1 },
73 { tag: "green on white", index: 2, background: "white", luminance: 1 },
89 { tag: "blue on darkgrey", index: 3, background: "darkgrey", luminance: 0.6627 },
74 { tag: "blue on darkgrey", index: 3, background: "darkgrey", luminance: 0.6627 },
@@ -94,53 +79,35 @@ Rectangle {
94 tool.style = testCase.styles[data.index];
79 tool.style = testCase.styles[data.index];
95 verify(Qt.colorEqual(tool.background, data.background),
80 verify(Qt.colorEqual(tool.background, data.background),
96 "Background color not equal: %1 != %2".arg(tool.background).arg(data.background));
81 "Background color not equal: %1 != %2".arg(tool.background).arg(data.background));
97− if (data.hasOwnProperty("luminance")) {
98− compare(tool.backgroundLuminance.toFixed(4), data.luminance.toFixed(4));
82+ compare(tool.backgroundLuminance.toFixed(4), data.luminance.toFixed(4));
99− }
100 }
83 }
101
84
102− function test_threshold_data() {
85+ function test_getTextColor_data() {
103 return [
86 return [
104− { tag: "default", index: 0, threshold: 0.7863 },
87+ { tag: "default on black", background: "black", index: 0, textColor: "white" },
105− { tag: "red on black", index: 1, threshold: 0.1063 },
88+ { tag: "default on lightgrey", background: "lightgrey", index: 0, textColor: UbuntuColors.darkGrey },
106− { tag: "green on white", index: 2, threshold: 0.6795 },
89+ { tag: "default on white", background: "white", index: 0, textColor: UbuntuColors.darkGrey },
107− { tag: "blue on darkgrey", index: 3, threshold: 0.3675 },
90+ { tag: "default on yellow", background: "yellow", index: 0, textColor: UbuntuColors.darkGrey },
91+ { tag: "red/black on black", background: "black", index: 1, textColor: "red" },
92+ { tag: "red/black on lightgrey", background: "lightgrey", index: 1, textColor: "black" },
93+ { tag: "red/black on white", background: "white", index: 1, textColor: "black" },
94+ { tag: "red/black on yellow", background: "yellow", index: 1, textColor: "black" },
95+ { tag: "green/white on black", background: "black", index: 2, textColor: "white" },
96+ { tag: "green/white on lightgrey", background: "lightgrey", index: 2, textColor: "green" },
97+ { tag: "green/white on white", background: "white", index: 2, textColor: "green" },
98+ { tag: "green/white on yellow", background: "yellow", index: 2, textColor: "green" },
99+ { tag: "blue/darkgrey on black", background: "black", index: 3, textColor: "darkgrey" },
100+ { tag: "blue/darkgrey on lightgrey", background: "lightgrey", index: 3, textColor: "blue" },
101+ { tag: "blue/darkgrey on white", background: "white", index: 3, textColor: "blue" },
102+ { tag: "blue/darkgrey on yellow", background: "yellow", index: 3, textColor: "blue" },
108 ];
103 ];
109 }
104 }
110
105
111− function test_threshold(data) {
106+ function test_getTextColor(data) {
112 tool.style = testCase.styles[data.index];
107 tool.style = testCase.styles[data.index];
113− compare(tool.threshold.toFixed(4), data.threshold.toFixed(4), "Luminance threshold was incorrect.");
108+ var textColor = tool.getTextColor(Style.luminance(data.background));
114− }
115−
116− function test_light_data() {
117− return [
118− { tag: "default", index: 0, light: "white" },
119− { tag: "red on black", index: 1, light: "red" },
120− { tag: "green on white", index: 2, light: "white" },
121− { tag: "blue on darkgrey", index: 3, light: "darkgrey" },
122− ];
123− }
124−
125− function test_light(data) {
126− tool.style = testCase.styles[data.index];
127− verify(Qt.colorEqual(tool.light, data.light),
128− "Light color not equal: %1 != %2".arg(tool.light).arg(data.light));
129− }
130−
131− function test_dark_data() {
132− return [
133− { tag: "default", index: 0, dark: Theme.palette.normal.baseText },
134− { tag: "red on black", index: 1, dark: "black" },
135− { tag: "green on white", index: 2, dark: "green" },
136− { tag: "blue on darkgrey", index: 3, dark: "blue" },
137− ];
138− }
139−
140− function test_dark(data) {
141− tool.style = testCase.styles[data.index];
142− verify(Qt.colorEqual(tool.dark, data.dark),
109+ verify(Qt.colorEqual(textColor, data.textColor),
143− "Dark color not equal: %1 != %2".arg(tool.dark).arg(data.dark));
110+ "TextColor not equal: %1 != %2".arg(textColor).arg(data.textColor));
144 }
111 }
145
112
146 function test_headerLogo_data() {
113 function test_headerLogo_data() {
@@ -157,7 +124,7 @@ Rectangle {
157
124
158 function test_headerForeground_data() {
125 function test_headerForeground_data() {
159 return [
126 return [
160− { tag: "default", index: 0, headerForeground: Theme.palette.normal.baseText },
127+ { tag: "default", index: 0, headerForeground: UbuntuColors.darkGrey },
161 { tag: "black", index: 2, headerForeground: "black" },
128 { tag: "black", index: 2, headerForeground: "black" },
162 ];
129 ];
163 }
130 }
@@ -170,7 +137,7 @@ Rectangle {
170
137
171 function test_headerBackground_data() {
138 function test_headerBackground_data() {
172 return [
139 return [
173− { tag: "default", index: 0, headerBackground: "" },
140+ { tag: "default", index: 0, headerBackground: "color:///#f5f5f5" },
174 { tag: "black", index: 3, headerBackground: "gradient:///white/blue" },
141 { tag: "black", index: 3, headerBackground: "gradient:///white/blue" },
175 ];
142 ];
176 }
143 }
@@ -179,5 +146,43 @@ Rectangle {
179 tool.style = testCase.styles[data.index];
146 tool.style = testCase.styles[data.index];
180 compare(tool.headerBackground, data.headerBackground, "Header background was incorrect.");
147 compare(tool.headerBackground, data.headerBackground, "Header background was incorrect.");
181 }
148 }
149+
150+ function test_headerDividerColor_data() {
151+ return [
152+ { tag: "default", index: 0, headerDividerColor: "#e0e0e0" },
153+ { tag: "blue", index: 2, headerDividerColor: "blue" },
154+ ];
155+ }
156+
157+ function test_headerDividerColor(data) {
158+ tool.style = testCase.styles[data.index];
159+ verify(Qt.colorEqual(tool.headerDividerColor, data.headerDividerColor),
160+ "Header divider color not equal: %1 != %2".arg(tool.headerDividerColor).arg(data.headerDividerColor));
161+ }
162+
163+ function test_navigationBackground_data() {
164+ return [
165+ { tag: "default", index: 0, navigationBackground: "color:///#f5f5f5" },
166+ { tag: "black", index: 3, navigationBackground: "gradient:///white/blue" },
167+ ];
168+ }
169+
170+ function test_navigationBackground(data) {
171+ tool.style = testCase.styles[data.index];
172+ compare(tool.navigationBackground, data.navigationBackground, "Navigation background was incorrect.");
173+ }
174+
175+ function test_previewButtonColor_data() {
176+ return [
177+ { tag: "default", index: 0, previewButtonColor: Theme.palette.selected.foreground },
178+ { tag: "red", index: 1, previewButtonColor: "red" },
179+ ];
180+ }
181+
182+ function test_previewButtonColor(data) {
183+ tool.style = testCase.styles[data.index];
184+ verify(Qt.colorEqual(tool.previewButtonColor, data.previewButtonColor),
185+ "Preview button color not equal: %1 != %2".arg(tool.previewButtonColor).arg(data.previewButtonColor));
186+ }
182 }
187 }
183}
188}
tests/plugins/Unity/Indicators/rootactionstatetest.cpp+4−4
@@ -50,7 +50,7 @@ private Q_SLOTS:
50
50
51 QCOMPARE(rootState->menu(), menuModel);
51 QCOMPARE(rootState->menu(), menuModel);
52 delete menuModel;
52 delete menuModel;
53− QVERIFY(rootState->menu() == NULL);
53+ QVERIFY(rootState->menu() == nullptr);
54 delete rootState;
54 delete rootState;
55 }
55 }
56
56
@@ -60,8 +60,8 @@ private Q_SLOTS:
60 g_variant_builder_init(&builderIcons, G_VARIANT_TYPE("av"));
60 g_variant_builder_init(&builderIcons, G_VARIANT_TYPE("av"));
61 for (int i = 0; i < 3; i ++) {
61 for (int i = 0; i < 3; i ++) {
62
62
63− GIcon* icon = NULL;
63+ GIcon* icon = nullptr;
64− icon = g_icon_new_for_string (QString("testIcon%1").arg(i).toUtf8().constData(), NULL);
64+ icon = g_icon_new_for_string (QString("testIcon%1").arg(i).toUtf8().constData(), nullptr);
65
65
66 g_variant_builder_add(&builderIcons,
66 g_variant_builder_add(&builderIcons,
67 "v",
67 "v",
@@ -73,7 +73,7 @@ private Q_SLOTS:
73 g_variant_builder_init(&builderParams, G_VARIANT_TYPE_ARRAY);
73 g_variant_builder_init(&builderParams, G_VARIANT_TYPE_ARRAY);
74 GVariant* icons = g_variant_builder_end (&builderIcons);
74 GVariant* icons = g_variant_builder_end (&builderIcons);
75 g_variant_ref_sink (icons);
75 g_variant_ref_sink (icons);
76− g_variant_builder_add (&builderParams, "{sv}", g_strdup ("icons"), icons, NULL);
76+ g_variant_builder_add (&builderParams, "{sv}", g_strdup ("icons"), icons, nullptr);
77
77
78 GVariant* params = g_variant_builder_end (&builderParams);
78 GVariant* params = g_variant_builder_end (&builderParams);
79
79
tests/plugins/Unity/Indicators/unitymenumodelstacktest.cpp+1−1
@@ -42,7 +42,7 @@ private Q_SLOTS:
42 void cleanup()
42 void cleanup()
43 {
43 {
44 delete m_model;
44 delete m_model;
45− m_model = NULL;
45+ m_model = nullptr;
46 }
46 }
47
47
48 void testHeadOnSetHead()
48 void testHeadOnSetHead()
tests/plugins/Utils/CMakeLists.txt+5
@@ -27,3 +27,8 @@ run_tests(
27 qsortfilterproxymodeltest
27 qsortfilterproxymodeltest
28 timeformattertest
28 timeformattertest
29 )
29 )
30+
31+# plain qml test
32+set(qmltest_DEFAULT_TARGETS qmltests)
33+set(qmltest_DEFAULT_PROPERTIES ENVIRONMENT "QT_QPA_PLATFORM=minimal")
34+add_qml_test(. UtilsStyle IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins)
tests/plugins/Utils/tst_UtilsStyle.qmlnew file+47
@@ -0,0 +1,47 @@
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+import QtQuick 2.2
18+import QtTest 1.0
19+import Utils 0.1
20+
21+TestCase {
22+ id: testCase
23+ name: "UtilsStyle"
24+
25+ property color color
26+
27+ function test_luminance_data() {
28+ return [
29+ { tag: "#F00", luminance: 0.2126 },
30+ { tag: "#0F0", luminance: 0.7152 },
31+ { tag: "#00F", luminance: 0.0722 },
32+ { tag: "white", luminance: 1.0 },
33+ { tag: "black", luminance: 0.0 },
34+ { tag: "lightgrey", luminance: 0.8275 },
35+ { tag: "grey", luminance: 0.5020 },
36+ { tag: "darkgrey", luminance: 0.6627 },
37+ { tag: "red", luminance: 0.2126 },
38+ { tag: "green", luminance: 0.3590 },
39+ { tag: "blue", luminance: 0.0722 },
40+ ];
41+ }
42+
43+ function test_luminance(data) {
44+ testCase.color = data.tag;
45+ compare(Style.luminance(testCase.color).toFixed(4), data.luminance.toFixed(4));
46+ }
47+}
tests/qmltests/CMakeLists.txt+6
@@ -50,10 +50,16 @@ add_qml_test(Dash/Previews PreviewPayments)
50add_qml_test(Dash/Previews PreviewProgress)
50add_qml_test(Dash/Previews PreviewProgress)
51add_qml_test(Dash/Previews PreviewRatingDisplay)
51add_qml_test(Dash/Previews PreviewRatingDisplay)
52add_qml_test(Dash/Previews PreviewRatingInput)
52add_qml_test(Dash/Previews PreviewRatingInput)
53+add_qml_test(Dash/Previews PreviewTable)
53add_qml_test(Dash/Previews PreviewTextSummary)
54add_qml_test(Dash/Previews PreviewTextSummary)
54add_qml_test(Dash/Previews PreviewVideoPlayback)
55add_qml_test(Dash/Previews PreviewVideoPlayback)
55add_qml_test(Dash/Previews PreviewWidgetFactory)
56add_qml_test(Dash/Previews PreviewWidgetFactory)
56add_qml_test(Dash/Previews PreviewZoomableImage)
57add_qml_test(Dash/Previews PreviewZoomableImage)
58+add_qml_test(Dash/ScopeSettings ScopeSettingBoolean)
59+add_qml_test(Dash/ScopeSettings ScopeSettingList)
60+add_qml_test(Dash/ScopeSettings ScopeSettingNumber)
61+add_qml_test(Dash/ScopeSettings ScopeSettingString)
62+add_qml_test(Dash/ScopeSettings ScopeSettingsWidgetFactory)
57add_qml_test(Greeter Lockscreen ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/libusermetrics:${CMAKE_BINARY_DIR}/tests/mocks/LightDM/full")
63add_qml_test(Greeter Lockscreen ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/libusermetrics:${CMAKE_BINARY_DIR}/tests/mocks/LightDM/full")
58add_qml_test(Greeter MultiGreeter ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/libusermetrics:${CMAKE_BINARY_DIR}/tests/mocks/LightDM/full")
64add_qml_test(Greeter MultiGreeter ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/libusermetrics:${CMAKE_BINARY_DIR}/tests/mocks/LightDM/full")
59add_qml_test(Greeter SingleGreeter ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/libusermetrics:${CMAKE_BINARY_DIR}/tests/mocks/LightDM/single")
65add_qml_test(Greeter SingleGreeter ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/libusermetrics:${CMAKE_BINARY_DIR}/tests/mocks/LightDM/single")
tests/qmltests/Components/tst_Background.qml+5−4
@@ -46,10 +46,10 @@ Rectangle {
46
46
47 function test_style_data() {
47 function test_style_data() {
48 return [
48 return [
49− { tag: "empty", style: "" },
49+ { tag: "empty", style: "", luminance: 0.5 },
50− { tag: "solid", style: "color:///black" },
50+ { tag: "solid", style: "color:///black", luminance: 0 },
51− { tag: "gradient", style: "gradient:///black/red" },
51+ { tag: "gradient", style: "gradient:///black/red", luminance: 0.1063 },
52− { tag: "image", style: "/some/path" },
52+ { tag: "image", style: "/some/path", luminance: 0.5 },
53 ];
53 ];
54 }
54 }
55
55
@@ -58,6 +58,7 @@ Rectangle {
58 expectFail("empty", "Empty style should not create a background.");
58 expectFail("empty", "Empty style should not create a background.");
59 loadedSpy.wait();
59 loadedSpy.wait();
60 compare(background.item.objectName, data.tag, "Background should be %1".arg(data.style));
60 compare(background.item.objectName, data.tag, "Background should be %1".arg(data.style));
61+ compare(background.luminance, data.luminance);
61 }
62 }
62
63
63 function test_solid() {
64 function test_solid() {
tests/qmltests/Dash/Previews/tst_PreviewActions.qml+8−8
@@ -27,21 +27,21 @@ Rectangle {
27 height: units.gu(80)
27 height: units.gu(80)
28
28
29 property var actionDataOneAction: {
29 property var actionDataOneAction: {
30− "actions": [{"label": "Some Label", "icon": "../graphics/play_button.png", "id": "someid"}]
30+ "actions": [{"label": "Some Label", "id": "someid"}]
31 }
31 }
32
32
33 property var actionDataTwoActions: {
33 property var actionDataTwoActions: {
34− "actions": [{"label": "Some Label A", "icon": "../graphics/icon_clear.png", "id": "someid1"},
34+ "actions": [{"label": "Some Label A", "id": "someid1"},
35− {"label": "Some Label B", "icon": "../graphics/play_button.png", "id": "someid2"}
35+ {"label": "Some Label B", "id": "someid2"}
36 ]
36 ]
37 }
37 }
38
38
39 property var actionDataFiveActions: {
39 property var actionDataFiveActions: {
40− "actions": [{"label": "Some Label C", "icon": "../graphics/play_button.png", "id": "someid3"},
40+ "actions": [{"label": "Some Label C", "id": "someid3"},
41− {"label": "Some Label D", "icon": "../graphics/icon_clear.png", "id": "someid4"},
41+ {"label": "Some Label D", "id": "someid4"},
42− {"label": "Some Label E", "icon": "../graphics/play_button.png", "id": "someid5"},
42+ {"label": "Some Label E", "id": "someid5"},
43− {"label": "Some Label F", "icon": "../graphics/icon_clear.png", "id": "someid6"},
43+ {"label": "Some Label F", "id": "someid6"},
44− {"label": "Some Label G", "icon": "../graphics/play_button.png", "id": "someid7"}
44+ {"label": "Some Label G", "id": "someid7"}
45 ]
45 ]
46 }
46 }
47
47
tests/qmltests/Dash/Previews/tst_PreviewExpandable.qml+5−1
@@ -30,6 +30,10 @@ Rectangle {
30 property string longText2: "This is a very very very long text. 1 This is a very very very long text. 2 This is a very very very long text. 3 This is a very very very long text. 4 This is a very very very long text. 5 This is a very very very long text. 6 This is a very very very long text. 7 This is a very very very long text. 8 This is a very very very long text. 9 This is a very very very long text. 10 This is a very very very long text. 11 This is a very very very long text."
30 property string longText2: "This is a very very very long text. 1 This is a very very very long text. 2 This is a very very very long text. 3 This is a very very very long text. 4 This is a very very very long text. 5 This is a very very very long text. 6 This is a very very very long text. 7 This is a very very very long text. 8 This is a very very very long text. 9 This is a very very very long text. 10 This is a very very very long text. 11 This is a very very very long text."
31 property string shortText: "This is a short text :)"
31 property string shortText: "This is a short text :)"
32
32
33+ property var tableData: {
34+ "values": [ [ "Long Label 1", "Value 1"], [ "Label 2", "Long Value 2"], [ "Label 3", "Value 3"], [ "Label 4", "Value 4"], [ "Label 5", "Value 5"] ]
35+ }
36+
33 ListModel {
37 ListModel {
34 id: widgetsModel
38 id: widgetsModel
35 }
39 }
@@ -42,7 +46,7 @@ Rectangle {
42
46
43 Component.onCompleted: {
47 Component.onCompleted: {
44 widgetsModel.append({"type": "text", "widgetId": "text1", "properties": { "text": longText }});
48 widgetsModel.append({"type": "text", "widgetId": "text1", "properties": { "text": longText }});
45− widgetsModel.append({"type": "text", "widgetId": "text2", "properties": { "text": longText2 }});
49+ widgetsModel.append({"type": "text", "widgetId": "table1", "properties": { "text": tableData }});
46 widgetsModel.append({"type": "text", "widgetId": "text3", "properties": { "text": shortText }});
50 widgetsModel.append({"type": "text", "widgetId": "text3", "properties": { "text": shortText }});
47 widgetsModel.append({"type": "text", "widgetId": "text4", "properties": { "text": longText }});
51 widgetsModel.append({"type": "text", "widgetId": "text4", "properties": { "text": longText }});
48 }
52 }
tests/qmltests/Dash/Previews/tst_PreviewTable.qmlnew file+114
@@ -0,0 +1,114 @@
1+/*
2+ * Copyright 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+import QtQuick 2.0
18+import QtTest 1.0
19+import Ubuntu.Components 0.1
20+import "../../../../qml/Dash/Previews"
21+import Unity.Test 0.1 as UT
22+
23+Rectangle {
24+ id: root
25+ width: units.gu(40)
26+ height: units.gu(80)
27+ color: Theme.palette.selected.background
28+
29+ property var widgetDataComplete: {
30+ "title": "Title here",
31+ "values": [ [ "Long Label 1", "Value 1"], [ "Label 2", "Long Value 2"], [ "Label 3", "Value 3"], [ "Label 4", "Value 4"], [ "Label 5", "Value 5"] ]
32+ }
33+
34+ property var widgetDataNoTitle: {
35+ "values": [ [ "Long Label 1", "Value 1"], [ "Label 2", "Long Value 2"], [ "Label 3", "Value 3"], [ "Label 4", "Value 4"], [ "Label 5", "Value 5"] ]
36+ }
37+
38+ PreviewTable {
39+ id: previewTable
40+ anchors { left: parent.left; right: parent.right }
41+ widgetData: widgetDataComplete
42+
43+ Rectangle {
44+ color: "red"
45+ anchors.fill: parent
46+ opacity: 0.5
47+ }
48+ }
49+
50+ UT.UnityTestCase {
51+ name: "PreviewTableTest"
52+ when: windowShown
53+
54+ function init() {
55+ previewTable.widgetData = widgetDataComplete;
56+ }
57+
58+ function test_values() {
59+ compare(findChild(previewTable, "label00").text, "Long Label 1");
60+ compare(findChild(previewTable, "label01").text, "Value 1");
61+ compare(findChild(previewTable, "label10").text, "Label 2");
62+ compare(findChild(previewTable, "label11").text, "Long Value 2");
63+ compare(findChild(previewTable, "label20").text, "Label 3");
64+ compare(findChild(previewTable, "label21").text, "Value 3");
65+ compare(findChild(previewTable, "label30").text, "Label 4");
66+ compare(findChild(previewTable, "label31").text, "Value 4");
67+ compare(findChild(previewTable, "label40").text, "Label 5");
68+ compare(findChild(previewTable, "label41").text, "Value 5");
69+ }
70+
71+ function test_optional_title() {
72+ var titleLabel = findChild(previewTable, "titleLabel");
73+ compare(titleLabel.visible, true);
74+ var titleHeight = titleLabel.height;
75+ var prevHeight = previewTable.height;
76+
77+ previewTable.widgetData = widgetDataNoTitle;
78+ var column = findChild(previewTable, "column");
79+ tryCompare(previewTable, "height", prevHeight - titleHeight - column.spacing );
80+ }
81+
82+ function test_show_collapsed() {
83+ verify(findChild(previewTable, "label00").visible);
84+ verify(findChild(previewTable, "label01").visible);
85+ verify(findChild(previewTable, "label10").visible);
86+ verify(findChild(previewTable, "label11").visible);
87+ verify(findChild(previewTable, "label20").visible);
88+ verify(findChild(previewTable, "label21").visible);
89+ verify(findChild(previewTable, "label30").visible);
90+ verify(findChild(previewTable, "label31").visible);
91+ verify(findChild(previewTable, "label40").visible);
92+ verify(findChild(previewTable, "label41").visible);
93+
94+ waitForRendering(previewTable);
95+ var prevHeight = previewTable.height;
96+ previewTable.expanded = false;
97+
98+ verify(findChild(previewTable, "label00").visible);
99+ verify(findChild(previewTable, "label01").visible);
100+ verify(findChild(previewTable, "label10").visible);
101+ verify(findChild(previewTable, "label11").visible);
102+ verify(findChild(previewTable, "label20").visible);
103+ verify(findChild(previewTable, "label21").visible);
104+ verify(!findChild(previewTable, "label30").visible);
105+ verify(!findChild(previewTable, "label31").visible);
106+ verify(!findChild(previewTable, "label40").visible);
107+ verify(!findChild(previewTable, "label41").visible);
108+
109+ var labelHeight = findChild(previewTable, "label00").height;
110+ var gridLayout = findChild(previewTable, "gridLayout");
111+ tryCompare(previewTable, "height", prevHeight - labelHeight * 2 - gridLayout.rowSpacing * 2);
112+ }
113+ }
114+}
tests/qmltests/Dash/Previews/tst_PreviewWidgetFactory.qml+2−1
@@ -84,6 +84,7 @@ Rectangle {
84 { tag: "Progress", type: "progress", source: "PreviewProgress.qml" },
84 { tag: "Progress", type: "progress", source: "PreviewProgress.qml" },
85 { tag: "Rating Input", type: "rating-input", source: "PreviewRatingInput.qml" },
85 { tag: "Rating Input", type: "rating-input", source: "PreviewRatingInput.qml" },
86 { tag: "Rating Display", type: "reviews", source: "PreviewRatingDisplay.qml" },
86 { tag: "Rating Display", type: "reviews", source: "PreviewRatingDisplay.qml" },
87+ { tag: "Table", type: "table", source: "PreviewTable.qml" },
87 { tag: "Text", type: "text", source: "PreviewTextSummary.qml" },
88 { tag: "Text", type: "text", source: "PreviewTextSummary.qml" },
88 { tag: "Video", type: "video", source: "PreviewVideoPlayback.qml" },
89 { tag: "Video", type: "video", source: "PreviewVideoPlayback.qml" },
89 ];
90 ];
@@ -93,7 +94,7 @@ Rectangle {
93 factory.widgetData = { type: data.type };
94 factory.widgetData = { type: data.type };
94 factory.widgetType = data.type;
95 factory.widgetType = data.type;
95
96
96− verify(("" + factory.source).indexOf(data.source) != -1);
97+ verify((String(factory.source)).indexOf(data.source) != -1);
97 }
98 }
98 }
99 }
99}
100}
tests/qmltests/Dash/ScopeSettings/tst_ScopeSettingBoolean.qmlnew file+62
@@ -0,0 +1,62 @@
1+/*
2+ * Copyright 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+import QtQuick 2.0
18+import Ubuntu.Components 1.1
19+import QtTest 1.0
20+import "../../../../qml/Dash/ScopeSettings"
21+import Unity.Test 0.1 as UT
22+
23+Rectangle {
24+ id: root
25+ width: units.gu(40)
26+ height: units.gu(80)
27+
28+ property var settingData: {
29+ "displayName" : "Mock boolean setting",
30+ "value": true
31+ }
32+
33+ ScopeSettingBoolean {
34+ id: scopeSetting
35+ widgetData: settingData
36+ width: parent.width
37+ }
38+
39+ SignalSpy {
40+ id: spy
41+ target: scopeSetting
42+ signalName: "updated"
43+ }
44+
45+ UT.UnityTestCase {
46+ id: testCase
47+ name: "ScopeSettingBoolean"
48+ when: windowShown
49+
50+ function test_updated() {
51+ var control = findChild(scopeSetting, "control");
52+ mouseClick(control, control.width / 2, control.height / 2);
53+ spy.wait();
54+ compare(spy.signalArguments[0][0], false);
55+
56+ spy.clear();
57+ mouseClick(scopeSetting, scopeSetting.width / 2, scopeSetting.height / 2);
58+ spy.wait();
59+ compare(spy.signalArguments[0][0], true);
60+ }
61+ }
62+}
tests/qmltests/Dash/ScopeSettings/tst_ScopeSettingList.qmlnew file+84
@@ -0,0 +1,84 @@
1+/*
2+ * Copyright 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+import QtQuick 2.0
18+import Ubuntu.Components 1.1
19+import QtTest 1.0
20+import "../../../../qml/Dash/ScopeSettings"
21+import Unity.Test 0.1 as UT
22+
23+Rectangle {
24+ id: root
25+ width: units.gu(40)
26+ height: units.gu(80)
27+
28+ property var settingData: {
29+ "displayName" : "Mock list setting",
30+ "properties": { "values" : [ "first", "second", "third" ] }
31+ }
32+
33+ ScopeSettingList {
34+ id: scopeSetting
35+ width: parent.width
36+ widgetData: settingData
37+ }
38+
39+ SignalSpy {
40+ id: spy
41+ target: scopeSetting
42+ signalName: "updated"
43+ }
44+
45+ UT.UnityTestCase {
46+ id: testCase
47+ name: "ScopeSettingList"
48+ when: windowShown
49+
50+ property var control: findChild(scopeSetting, "control")
51+
52+ function cleanup() {
53+ control.selectedIndex = 0;
54+ spy.clear();
55+ }
56+
57+ function test_initialValue() {
58+ // there's no initialIndex, so we workaround, testing is difficult too https://bugs.launchpad.net/ubuntu-ui-toolkit/+bug/1362031
59+ var newObject = Qt.createQmlObject('import "../../../../qml/Dash/ScopeSettings" \n\
60+ ScopeSettingList { initialValue: 2; }', root, "dynamicScopeSettingList");
61+ newObject.widgetData = settingData;
62+ var controlDynamic = findChild(newObject, "control");
63+ tryCompare(controlDynamic, "selectedIndex", 2);
64+ }
65+
66+ function test_updated_data() {
67+ return [
68+ { tag: "current", index: 0, updated: false },
69+ { tag: "second", index: 1, updated: true },
70+ { tag: "third", index: 2, updated: true }
71+ ]
72+ }
73+
74+ function test_updated(data) {
75+ control.selectedIndex = data.index;
76+ if (data.updated) {
77+ spy.wait();
78+ compare(spy.signalArguments[0][0], data.index);
79+ } else {
80+ compare(spy.count, 0);
81+ }
82+ }
83+ }
84+}
tests/qmltests/Dash/ScopeSettings/tst_ScopeSettingNumber.qmlnew file+98
@@ -0,0 +1,98 @@
1+/*
2+ * Copyright 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+import QtQuick 2.0
18+import Ubuntu.Components 1.1
19+import QtTest 1.0
20+import "../../../../qml/Dash/ScopeSettings"
21+import Unity.Test 0.1 as UT
22+
23+Rectangle {
24+ id: root
25+ width: units.gu(40)
26+ height: units.gu(80)
27+
28+ property var settingData: {
29+ "displayName" : "Mock number setting",
30+ "value": 0.2
31+ }
32+
33+ ScopeSettingNumber {
34+ id: scopeSetting
35+ widgetData: settingData
36+ width: parent.width
37+ }
38+
39+ SignalSpy {
40+ id: spy
41+ target: scopeSetting
42+ signalName: "updated"
43+ }
44+
45+ UT.UnityTestCase {
46+ id: testCase
47+ name: "ScopeSettingNumber"
48+ when: windowShown
49+
50+ property var control: findChild(scopeSetting, "control")
51+ property real newNumber: 11.7
52+
53+ function cleanup() {
54+ control.focus = false;
55+ control.text = settingData.value;
56+ spy.clear();
57+ }
58+
59+ function test_updated_on_unfocus() {
60+ mouseClick(control, control.width / 2, control.height / 2);
61+ control.selectAll();
62+ control.cut();
63+ control.insert(0, newNumber);
64+ control.focus = false;
65+ spy.wait();
66+ verify(spy.signalArguments[0][0] == newNumber);
67+ }
68+
69+ function test_updated_on_accepted() {
70+ mouseClick(control, control.width / 2, control.height / 2);
71+ control.selectAll();
72+ control.cut();
73+ control.insert(0, newNumber);
74+ control.accepted();
75+ spy.wait();
76+ verify(spy.signalArguments[0][0] == newNumber);
77+ }
78+
79+ function test_selection_on_listitem_click() {
80+ mouseClick(scopeSetting, 0, scopeSetting.height / 2);
81+ compare(control.focus, true);
82+ // we're checking that selectAll() is being called by omitting it here
83+ control.cut();
84+ control.insert(0, newNumber);
85+ verify(control.displayText == newNumber);
86+ }
87+
88+ function test_unacceptable_input() {
89+ mouseClick(control, control.width / 2, control.height / 2);
90+ control.selectAll();
91+ control.cut();
92+ control.insert(0, "not valid");
93+ control.accepted();
94+ compare(spy.count, 0);
95+ compare(control.displayText, "");
96+ }
97+ }
98+}
tests/qmltests/Dash/ScopeSettings/tst_ScopeSettingString.qmlnew file+88
@@ -0,0 +1,88 @@
1+/*
2+ * Copyright 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+import QtQuick 2.0
18+import Ubuntu.Components 1.1
19+import QtTest 1.0
20+import "../../../../qml/Dash/ScopeSettings"
21+import Unity.Test 0.1 as UT
22+
23+Rectangle {
24+ id: root
25+ width: units.gu(40)
26+ height: units.gu(80)
27+
28+ property var settingData: {
29+ "displayName" : "Mock string setting",
30+ "value": "mock string"
31+ }
32+
33+ ScopeSettingString {
34+ id: scopeSetting
35+ widgetData: settingData
36+ width: parent.width
37+ }
38+
39+ SignalSpy {
40+ id: spy
41+ target: scopeSetting
42+ signalName: "updated"
43+ }
44+
45+ UT.UnityTestCase {
46+ id: testCase
47+ name: "ScopeSettingString"
48+ when: windowShown
49+
50+ property var control: findChild(scopeSetting, "control")
51+ property string newText: "new text to compare"
52+
53+ function cleanup() {
54+ control.focus = false;
55+ control.text = settingData.value;
56+ spy.clear();
57+ }
58+
59+ function test_updated_on_unfocus() {
60+ mouseClick(control, control.width / 2, control.height / 2);
61+ control.selectAll();
62+ control.cut();
63+ control.insert(0, newText);
64+ control.focus = false;
65+ spy.wait();
66+ compare(spy.signalArguments[0][0], newText);
67+ }
68+
69+ function test_updated_on_accepted() {
70+ mouseClick(control, control.width / 2, control.height / 2);
71+ control.selectAll();
72+ control.cut();
73+ control.insert(0, newText);
74+ control.accepted();
75+ spy.wait();
76+ compare(spy.signalArguments[0][0], newText);
77+ }
78+
79+ function test_selection_on_listitem_click() {
80+ mouseClick(scopeSetting, 0, scopeSetting.height / 2);
81+ compare(control.focus, true);
82+ // we're checking that selectAll() is being called by omitting it here
83+ control.cut();
84+ control.insert(0, newText);
85+ compare(control.displayText, newText);
86+ }
87+ }
88+}
tests/qmltests/Dash/ScopeSettings/tst_ScopeSettingsWidgetFactory.qmlnew file+65
@@ -0,0 +1,65 @@
1+/*
2+ * Copyright 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+import QtQuick 2.0
18+import Ubuntu.Components 1.1
19+import QtTest 1.0
20+import "../../../../qml/Dash/ScopeSettings"
21+import Unity.Test 0.1 as UT
22+
23+Rectangle {
24+ id: root
25+ width: units.gu(40)
26+ height: units.gu(80)
27+
28+ property var settingData: {
29+ "type": "",
30+ "displayName" : "Mock setting",
31+ "value": "1",
32+ "properties": { "values" : [ "first", "second", "third" ] }
33+ }
34+
35+ ScopeSettingsWidgetFactory {
36+ id: scopeSettingsWidgetFactory
37+ anchors {
38+ left: parent.left
39+ right: parent.right
40+ }
41+ }
42+
43+ UT.UnityTestCase {
44+ id: testCase
45+ name: "ScopeSettingWidgetFactory"
46+ when: windowShown
47+
48+ function test_mapping_data() {
49+ return [
50+ { tag: "Boolean", type: "boolean", source: "ScopeSettingBoolean.qml" },
51+ { tag: "List", type: "list", source: "ScopeSettingList.qml" },
52+ { tag: "Number", type: "number", source: "ScopeSettingNumber.qml" },
53+ { tag: "String", type: "string", source: "ScopeSettingString.qml" }
54+ ];
55+ }
56+
57+ function test_mapping(data) {
58+ var newSettingData = settingData;
59+ newSettingData.type = data.type;
60+ scopeSettingsWidgetFactory.widgetData = newSettingData;
61+
62+ verify((String(scopeSettingsWidgetFactory.source)).indexOf(data.source) != -1);
63+ }
64+ }
65+}
tests/qmltests/Dash/artwork/background.pngnew file

Binary file not shown.

tests/qmltests/Dash/tst_Card.qml+62−1
@@ -96,6 +96,11 @@ Rectangle {
96 "layout": { "template": { "card-background": Qt.resolvedUrl("artwork/checkers.png") },
96 "layout": { "template": { "card-background": Qt.resolvedUrl("artwork/checkers.png") },
97 "components": JSON.parse(Helpers.fullMapping) }
97 "components": JSON.parse(Helpers.fullMapping) }
98 },
98 },
99+ {
100+ "name": "Art, title - overlaid",
101+ "layout": { "template": { "overlay": true },
102+ "components": { "art": "art", "title": "title" } }
103+ },
99 ]
104 ]
100
105
101 CardTool {
106 CardTool {
@@ -217,6 +222,7 @@ Rectangle {
217
222
218 function test_card_binding(data) {
223 function test_card_binding(data) {
219 selector.selectedIndex = data.index;
224 selector.selectedIndex = data.index;
225+ waitForRendering(selector);
220 waitForRendering(card);
226 waitForRendering(card);
221
227
222 tryCompareFunction(function() { return testCase[data.object] !== null }, true);
228 tryCompareFunction(function() { return testCase[data.object] !== null }, true);
@@ -247,6 +253,8 @@ Rectangle {
247
253
248 function test_card_size(data) {
254 function test_card_size(data) {
249 selector.selectedIndex = data.index;
255 selector.selectedIndex = data.index;
256+ waitForRendering(selector);
257+ waitForRendering(card);
250
258
251 if (data.hasOwnProperty("card_layout")) {
259 if (data.hasOwnProperty("card_layout")) {
252 cardTool.template['card-layout'] = data.card_layout;
260 cardTool.template['card-layout'] = data.card_layout;
@@ -279,6 +287,7 @@ Rectangle {
279
287
280 function test_art_size(data) {
288 function test_art_size(data) {
281 selector.selectedIndex = data.index;
289 selector.selectedIndex = data.index;
290+ waitForRendering(selector);
282 if (data.hasOwnProperty("size")) {
291 if (data.hasOwnProperty("size")) {
283 cardTool.template['card-size'] = data.size;
292 cardTool.template['card-size'] = data.size;
284 cardTool.templateChanged();
293 cardTool.templateChanged();
@@ -310,6 +319,7 @@ Rectangle {
310
319
311 function test_art_shape_fixed_size() {
320 function test_art_shape_fixed_size() {
312 selector.selectedIndex = 6;
321 selector.selectedIndex = 6;
322+ waitForRendering(selector);
313 card.fixedArtShapeSize = Qt.size( units.gu(8), units.gu(4) );
323 card.fixedArtShapeSize = Qt.size( units.gu(8), units.gu(4) );
314 waitForRendering(card);
324 waitForRendering(card);
315 tryCompare(art, "width", units.gu(8));
325 tryCompare(art, "width", units.gu(8));
@@ -326,6 +336,7 @@ Rectangle {
326
336
327 function test_art_layout(data) {
337 function test_art_layout(data) {
328 selector.selectedIndex = data.index;
338 selector.selectedIndex = data.index;
339+ waitForRendering(selector);
329 waitForRendering(card);
340 waitForRendering(card);
330
341
331 tryCompare(headerRow, "x", data.left());
342 tryCompare(headerRow, "x", data.left());
@@ -344,6 +355,7 @@ Rectangle {
344
355
345 function test_header_layout(data) {
356 function test_header_layout(data) {
346 selector.selectedIndex = data.index;
357 selector.selectedIndex = data.index;
358+ waitForRendering(selector);
347 waitForRendering(card);
359 waitForRendering(card);
348
360
349 tryCompareFunction(function() { return testCase.headerRow.y === data.top() }, true);
361 tryCompareFunction(function() { return testCase.headerRow.y === data.top() }, true);
@@ -359,7 +371,7 @@ Rectangle {
359
371
360 function test_summary_layout(data) {
372 function test_summary_layout(data) {
361 selector.selectedIndex = data.index;
373 selector.selectedIndex = data.index;
362−
374+ waitForRendering(selector);
363 waitForRendering(card);
375 waitForRendering(card);
364
376
365 tryCompareFunction(function() { return art.height > 0 && testCase.summary.y === data.top() }, true);
377 tryCompareFunction(function() { return art.height > 0 && testCase.summary.y === data.top() }, true);
@@ -367,6 +379,8 @@ Rectangle {
367
379
368 function test_art_visibility() {
380 function test_art_visibility() {
369 selector.selectedIndex = 8;
381 selector.selectedIndex = 8;
382+ waitForRendering(selector);
383+ waitForRendering(card);
370
384
371 compare(testCase.artImage, null);
385 compare(testCase.artImage, null);
372 compare(testCase.art, null);
386 compare(testCase.art, null);
@@ -389,6 +403,7 @@ Rectangle {
389
403
390 function test_background(data) {
404 function test_background(data) {
391 selector.selectedIndex = data.index;
405 selector.selectedIndex = data.index;
406+ waitForRendering(selector);
392
407
393 if (data.hasOwnProperty("background")) {
408 if (data.hasOwnProperty("background")) {
394 card.cardData["background"] = data.background;
409 card.cardData["background"] = data.background;
@@ -425,6 +440,8 @@ Rectangle {
425
440
426 function test_font_weights(data) {
441 function test_font_weights(data) {
427 selector.selectedIndex = data.index;
442 selector.selectedIndex = data.index;
443+ waitForRendering(selector);
444+ waitForRendering(card);
428
445
429 tryCompare(testCase.title.font, "weight", data.weight);
446 tryCompare(testCase.title.font, "weight", data.weight);
430 }
447 }
@@ -448,6 +465,7 @@ Rectangle {
448
465
449 function test_fontColor(data) {
466 function test_fontColor(data) {
450 selector.selectedIndex = 10;
467 selector.selectedIndex = 10;
468+ waitForRendering(selector);
451 waitForRendering(card);
469 waitForRendering(card);
452
470
453 background.color = data.tag;
471 background.color = data.tag;
@@ -470,6 +488,7 @@ Rectangle {
470
488
471 function test_emblemIcon(data) {
489 function test_emblemIcon(data) {
472 selector.selectedIndex = data.index;
490 selector.selectedIndex = data.index;
491+ waitForRendering(selector);
473 waitForRendering(card);
492 waitForRendering(card);
474
493
475 var emblemIcon = findChild(card, "emblemIcon");
494 var emblemIcon = findChild(card, "emblemIcon");
@@ -486,6 +505,7 @@ Rectangle {
486
505
487 function test_mascotShape(data) {
506 function test_mascotShape(data) {
488 selector.selectedIndex = data.index;
507 selector.selectedIndex = data.index;
508+ waitForRendering(selector);
489 waitForRendering(card);
509 waitForRendering(card);
490
510
491 var shape = findChild(card, "mascotShapeLoader");
511 var shape = findChild(card, "mascotShapeLoader");
@@ -496,6 +516,8 @@ Rectangle {
496
516
497 function test_touchdown_visibility() {
517 function test_touchdown_visibility() {
498 selector.selectedIndex = 0;
518 selector.selectedIndex = 0;
519+ waitForRendering(selector);
520+ waitForRendering(card);
499
521
500 var touchdown = findChild(card, "touchdown");
522 var touchdown = findChild(card, "touchdown");
501
523
@@ -505,5 +527,44 @@ Rectangle {
505 mouseRelease(card, card.width/2, card.height/2);
527 mouseRelease(card, card.width/2, card.height/2);
506 compare(touchdown.visible, false);
528 compare(touchdown.visible, false);
507 }
529 }
530+
531+ function test_paddings_data() {
532+ return [
533+ { tag: "Art and summary", index: 0 },
534+ { tag: "No Summary", index: 6 },
535+ { tag: "No header", index: 7 },
536+ { tag: "Header only", index: 8 },
537+ { tag: "Art, header, summary - overlaid", index: 9 },
538+ { tag: "Art, title - overlaid", index: 13 },
539+ ];
540+ }
541+
542+ function test_paddings(data) {
543+ selector.selectedIndex = data.index;
544+ waitForRendering(selector);
545+ waitForRendering(card);
546+
547+ if (title) var titleToCard = title.mapToItem(card, 0, 0, title.width, title.height);
548+
549+ // left margin
550+ if (mascotImage) {
551+ var mascotToCard = mascotImage.mapToItem(card, 0, 0, mascotImage.width, mascotImage.height);
552+ verify(mascotToCard.x === units.gu(1));
553+ if (title) {
554+ verify((titleToCard.x - mascotToCard.x - mascotToCard.width) === units.gu(1));
555+ }
556+ } else if (title) {
557+ verify(titleToCard.x === units.gu(1));
558+ }
559+
560+ // right margin
561+ var emblemIcon = findChild(card, "emblemIcon");
562+ if (emblemIcon) {
563+ var emblemToCard = emblemIcon.mapToItem(card, 0, 0, emblemIcon.width, emblemIcon.height);
564+ verify((card.width - emblemToCard.x - emblemToCard.width) === units.gu(1));
565+ } else if (title) {
566+ verify((card.width - titleToCard.x - titleToCard.width) === units.gu(1));
567+ }
568+ }
508 }
569 }
509}
570}
tests/qmltests/Dash/tst_DashContent.qml+152−48
@@ -200,8 +200,12 @@ Item {
200 dashContent.setCurrentScopeAtIndex(data.index, true, false);
200 dashContent.setCurrentScopeAtIndex(data.index, true, false);
201 tryCompareFunction(get_current_item_object_name, data.objectName)
201 tryCompareFunction(get_current_item_object_name, data.objectName)
202 var scopeView = findChild(dashContent, data.objectName);
202 var scopeView = findChild(dashContent, data.objectName);
203+ verify(scopeView, "Could not find the scope view.");
203− var pageHeader = findChild(scopeView, "innerPageHeader");
204+ var pageHeader = findChild(scopeView, "scopePageHeader");
205+ verify(pageHeader, "Could not find the scope page header.");
206+ var innerHeader = findChild(pageHeader, "innerPageHeader");
207+ verify(innerHeader, "Could not find the scope page header.");
204− compare(pageHeader.title, scopesModel.getScope(data.index).name);
208+ compare(innerHeader.title, scopesModel.getScope(data.index).name);
205 }
209 }
206
210
207 function test_is_active_data() {
211 function test_is_active_data() {
@@ -266,56 +270,57 @@ Item {
266 verify(carouselLV.tileWidth / carouselLV.tileHeight == cardTool.components["art"]["aspect-ratio"]);
270 verify(carouselLV.tileWidth / carouselLV.tileHeight == cardTool.components["art"]["aspect-ratio"]);
267 }
271 }
268
272
269− function test_navigations() {
273+ function test_mainNavigation() {
270 var dashContentList = findChild(dashContent, "dashContentList");
274 var dashContentList = findChild(dashContent, "dashContentList");
271 tryCompareFunction(function() { return findChild(dashContentList.currentItem, "dashNavigation") != null; }, true);
275 tryCompareFunction(function() { return findChild(dashContentList.currentItem, "dashNavigation") != null; }, true);
272 var dashNavigation = findChild(dashContentList.currentItem, "dashNavigation");
276 var dashNavigation = findChild(dashContentList.currentItem, "dashNavigation");
273 tryCompare(dashNavigation, "visible", true);
277 tryCompare(dashNavigation, "visible", true);
278+ var dashNavigationButton = findChild(dashContentList.currentItem, "navigationButton");
274− compare(dashNavigation.showList, false);
279+ compare(dashNavigationButton.showList, false);
275− waitForRendering(dashNavigation);
280+ waitForRendering(dashNavigationButton);
276− mouseClick(dashNavigation, 0, 0);
281+ mouseClick(dashNavigationButton, 0, 0);
277− compare(dashNavigation.showList, true);
282+ compare(dashNavigationButton.showList, true);
278
283
279− var navigationListView = findChild(dashNavigation, "navigationListView");
284+ var navigationListView = findChild(dashNavigationButton, "navigationListView");
280 compare(navigationListView.count, 1);
285 compare(navigationListView.count, 1);
281 tryCompare(navigationListView.currentItem.navigation, "loaded", true);
286 tryCompare(navigationListView.currentItem.navigation, "loaded", true);
282
287
283 waitForRendering(navigationListView);
288 waitForRendering(navigationListView);
284 waitForRendering(navigationListView.currentItem);
289 waitForRendering(navigationListView.currentItem);
285
290
286− var allButton = findChild(dashNavigation, "allButton");
291+ var allButton = findChild(dashNavigationButton, "allButton");
287 compare(allButton.visible, false);
292 compare(allButton.visible, false);
288
293
289− var navigation = findChild(dashNavigation, "navigation0child3");
294+ var navigation = findChild(dashNavigationButton, "navigation0child3");
290 mouseClick(navigation, 0, 0);
295 mouseClick(navigation, 0, 0);
291− compare(dashNavigation.showList, false);
296+ compare(dashNavigationButton.showList, false);
292− tryCompare(dashNavigation.currentNavigation, "navigationId", "middle3");
297+ tryCompare(dashNavigationButton.currentNavigation, "navigationId", "middle3");
293 tryCompare(navigationListView.currentItem.navigation, "navigationId", "root");
298 tryCompare(navigationListView.currentItem.navigation, "navigationId", "root");
294
299
295− mouseClick(dashNavigation, 0, 0);
300+ mouseClick(dashNavigationButton, 0, 0);
296− compare(dashNavigation.showList, true);
301+ compare(dashNavigationButton.showList, true);
297 waitForRendering(navigationListView);
302 waitForRendering(navigationListView);
298 waitForRendering(navigationListView.currentItem);
303 waitForRendering(navigationListView.currentItem);
299 compare(allButton.visible, true);
304 compare(allButton.visible, true);
300
305
301 mouseClick(allButton, 0, 0);
306 mouseClick(allButton, 0, 0);
302− compare(dashNavigation.showList, false);
307+ compare(dashNavigationButton.showList, false);
303− tryCompare(dashNavigation.currentNavigation, "navigationId", "root");
308+ tryCompare(dashNavigationButton.currentNavigation, "navigationId", "root");
304 tryCompare(navigationListView.currentItem.navigation, "navigationId", "root");
309 tryCompare(navigationListView.currentItem.navigation, "navigationId", "root");
305
310
306− mouseClick(dashNavigation, 0, 0);
311+ mouseClick(dashNavigationButton, 0, 0);
307− compare(dashNavigation.showList, true);
312+ compare(dashNavigationButton.showList, true);
308 waitForRendering(navigationListView);
313 waitForRendering(navigationListView);
309 waitForRendering(navigationListView.currentItem);
314 waitForRendering(navigationListView.currentItem);
310 compare(allButton.visible, false);
315 compare(allButton.visible, false);
311
316
312− navigation = findChild(dashNavigation, "navigation0child2");
317+ navigation = findChild(dashNavigationButton, "navigation0child2");
313 mouseClick(navigation, 0, 0);
318 mouseClick(navigation, 0, 0);
314− compare(dashNavigation.showList, true);
319+ compare(dashNavigationButton.showList, true);
315− tryCompare(dashNavigation.currentNavigation, "navigationId", "middle2");
320+ tryCompare(dashNavigationButton.currentNavigation, "navigationId", "middle2");
316 tryCompare(navigationListView.currentItem.navigation, "navigationId", "middle2");
321 tryCompare(navigationListView.currentItem.navigation, "navigationId", "middle2");
317
322
318− var navigationList1 = findChild(dashNavigation, "navigation1");
323+ var navigationList1 = findChild(dashNavigationButton, "navigation1");
319 allButton = findChild(navigationList1, "allButton");
324 allButton = findChild(navigationList1, "allButton");
320 var backButton = findChild(findChild(navigationList1, "navigation1"), "backButton");
325 var backButton = findChild(findChild(navigationList1, "navigation1"), "backButton");
321 compare(allButton.visible, true);
326 compare(allButton.visible, true);
@@ -324,61 +329,160 @@ Item {
324 tryCompare(navigationListView, "contentX", navigationList1.x);
329 tryCompare(navigationListView, "contentX", navigationList1.x);
325 waitForRendering(navigationListView);
330 waitForRendering(navigationListView);
326 mouseClick(allButton, 0, 0);
331 mouseClick(allButton, 0, 0);
327− compare(dashNavigation.showList, false);
332+ compare(dashNavigationButton.showList, false);
328− tryCompare(dashNavigation.currentNavigation, "navigationId", "middle2");
333+ tryCompare(dashNavigationButton.currentNavigation, "navigationId", "middle2");
329 tryCompare(navigationListView.currentItem.navigation, "navigationId", "middle2");
334 tryCompare(navigationListView.currentItem.navigation, "navigationId", "middle2");
330
335
331− mouseClick(dashNavigation, 0, 0);
336+ mouseClick(dashNavigationButton, 0, 0);
332− compare(dashNavigation.showList, true);
337+ compare(dashNavigationButton.showList, true);
333 waitForRendering(navigationListView);
338 waitForRendering(navigationListView);
334 waitForRendering(navigationListView.currentItem);
339 waitForRendering(navigationListView.currentItem);
335 compare(allButton.visible, true);
340 compare(allButton.visible, true);
336 compare(backButton.visible, true);
341 compare(backButton.visible, true);
337
342
338 tryCompare(navigationList1.navigation, "loaded", true);
343 tryCompare(navigationList1.navigation, "loaded", true);
339− navigation = findChild(dashNavigation, "navigation1child2");
344+ navigation = findChild(dashNavigationButton, "navigation1child2");
340 mouseClick(navigation, 0, 0);
345 mouseClick(navigation, 0, 0);
341− compare(dashNavigation.showList, false);
346+ compare(dashNavigationButton.showList, false);
342− tryCompare(dashNavigation.currentNavigation, "navigationId", "childmiddle22");
347+ tryCompare(dashNavigationButton.currentNavigation, "navigationId", "childmiddle22");
343 tryCompare(navigationListView.currentItem.navigation, "navigationId", "middle2");
348 tryCompare(navigationListView.currentItem.navigation, "navigationId", "middle2");
344
349
345− mouseClick(dashNavigation, 0, 0);
350+ mouseClick(dashNavigationButton, 0, 0);
346− compare(dashNavigation.showList, true);
351+ compare(dashNavigationButton.showList, true);
347 waitForRendering(navigationListView);
352 waitForRendering(navigationListView);
348 waitForRendering(navigationListView.currentItem);
353 waitForRendering(navigationListView.currentItem);
349
354
350 tryCompare(navigationList1.navigation, "loaded", true);
355 tryCompare(navigationList1.navigation, "loaded", true);
351− navigation = findChild(dashNavigation, "navigation1child3");
356+ navigation = findChild(dashNavigationButton, "navigation1child3");
352 mouseClick(navigation, 0, 0);
357 mouseClick(navigation, 0, 0);
353− compare(dashNavigation.showList, false);
358+ compare(dashNavigationButton.showList, false);
354− tryCompare(dashNavigation.currentNavigation, "navigationId", "childmiddle23");
359+ tryCompare(dashNavigationButton.currentNavigation, "navigationId", "childmiddle23");
355 tryCompare(navigationListView.currentItem.navigation, "navigationId", "middle2");
360 tryCompare(navigationListView.currentItem.navigation, "navigationId", "middle2");
356
361
357− mouseClick(dashNavigation, 0, 0);
362+ mouseClick(dashNavigationButton, 0, 0);
358− compare(dashNavigation.showList, true);
363+ compare(dashNavigationButton.showList, true);
359 waitForRendering(navigationListView);
364 waitForRendering(navigationListView);
360 waitForRendering(navigationListView.currentItem);
365 waitForRendering(navigationListView.currentItem);
361 mouseClick(backButton, 0, 0);
366 mouseClick(backButton, 0, 0);
362
367
363− tryCompare(dashNavigation.currentNavigation, "navigationId", "root");
368+ tryCompare(dashNavigationButton.currentNavigation, "navigationId", "root");
364 tryCompare(navigationListView.currentItem.navigation, "navigationId", "root");
369 tryCompare(navigationListView.currentItem.navigation, "navigationId", "root");
365− compare(dashNavigation.showList, true);
370+ compare(dashNavigationButton.showList, true);
366− mouseClick(dashNavigation, 0, 0);
371+ mouseClick(dashNavigationButton, 0, 0);
367− compare(dashNavigation.showList, false);
372+ compare(dashNavigationButton.showList, false);
368
373
369− mouseClick(dashNavigation, 0, 0);
374+ mouseClick(dashNavigationButton, 0, 0);
370− compare(dashNavigation.showList, true);
375+ compare(dashNavigationButton.showList, true);
371 tryCompare(navigationListView.currentItem.navigation, "loaded", true);
376 tryCompare(navigationListView.currentItem.navigation, "loaded", true);
372− navigation = findChild(dashNavigation, "navigation0child2");
377+ navigation = findChild(dashNavigationButton, "navigation0child2");
373 mouseClick(navigation, 0, 0);
378 mouseClick(navigation, 0, 0);
374− compare(dashNavigation.showList, true);
379+ compare(dashNavigationButton.showList, true);
375− navigationList1 = findChild(dashNavigation, "navigation1");
380+ navigationList1 = findChild(dashNavigationButton, "navigation1");
376 compare(navigationList1.navigation.loaded, false);
381 compare(navigationList1.navigation.loaded, false);
377− tryCompare(dashNavigation.currentNavigation, "navigationId", "middle2");
382+ tryCompare(dashNavigationButton.currentNavigation, "navigationId", "middle2");
378 allButton = findChild(navigationList1, "allButton");
383 allButton = findChild(navigationList1, "allButton");
379− tryCompare(dashNavigation.currentNavigation, "navigationId", "middle2");
384+ tryCompare(dashNavigationButton.currentNavigation, "navigationId", "middle2");
380 mouseClick(allButton, 0, 0);
385 mouseClick(allButton, 0, 0);
381− tryCompare(dashNavigation.currentNavigation, "navigationId", "middle2");
386+ tryCompare(dashNavigationButton.currentNavigation, "navigationId", "middle2");
387+ }
388+
389+ function test_altNavigation() {
390+ var dashContentList = findChild(dashContent, "dashContentList");
391+ tryCompareFunction(function() { return findChild(dashContentList.currentItem, "dashNavigation") != null; }, true);
392+ var dashNavigation = findChild(dashContentList.currentItem, "dashNavigation");
393+ tryCompare(dashNavigation, "visible", true);
394+ var dashNavigationButton = findChild(dashContentList.currentItem, "altNavigationButton");
395+ verify(dashNavigationButton, "Can't find navigation button");
396+
397+ compare(dashNavigationButton.showList, false);
398+ waitForRendering(dashNavigationButton);
399+ mouseClick(dashNavigationButton, 0, 0);
400+ compare(dashNavigationButton.showList, true);
401+
402+ var navigationListView = findChild(dashNavigationButton, "navigationListView");
403+ compare(navigationListView.count, 1);
404+ tryCompare(navigationListView.currentItem.navigation, "loaded", true);
405+
406+ waitForRendering(navigationListView);
407+ waitForRendering(navigationListView.currentItem);
408+
409+ tryCompare(dashNavigationButton.currentNavigation, "navigationId", "altrootChild1");
410+ tryCompare(navigationListView.currentItem.navigation, "navigationId", "altroot");
411+
412+ var allButton = findChild(dashNavigationButton, "allButton");
413+ compare(allButton.visible, false);
414+ var backButton = findChild(navigationListView, "backButton");
415+ compare(backButton.visible, false);
416+
417+ var navigation = findChild(dashNavigationButton, "navigation0child3");
418+ mouseClick(navigation, 0, 0);
419+ compare(dashNavigationButton.showList, false);
420+ tryCompare(dashNavigationButton.currentNavigation, "navigationId", "altrootChild3");
421+ tryCompare(navigationListView.currentItem.navigation, "navigationId", "altroot");
422+
423+ mouseClick(dashNavigationButton, 0, 0);
424+ compare(dashNavigationButton.showList, true);
425+ waitForRendering(navigationListView);
426+ waitForRendering(navigationListView.currentItem);
427+ compare(allButton.visible, false);
428+
429+ navigation = findChild(dashNavigationButton, "navigation0child2");
430+ mouseClick(navigation, 0, 0);
431+ compare(dashNavigationButton.showList, false);
432+ tryCompare(dashNavigationButton.currentNavigation, "navigationId", "altrootChild2");
433+ tryCompare(navigationListView.currentItem.navigation, "navigationId", "altroot");
434+
435+ mouseClick(dashNavigationButton, 0, 0);
436+ compare(dashNavigationButton.showList, true);
437+ waitForRendering(navigationListView);
438+ waitForRendering(navigationListView.currentItem);
439+ verify(!backButton.visible, "Back button should not be visible");
440+
441+ compare(navigationListView.count, 1, "There should be no second-level navigation");
442+
443+ mouseClick(dashNavigationButton, 0, 0);
444+ compare(dashNavigationButton.showList, false);
445+ }
446+
447+ function test_navigationsClosing() {
448+ var dashContentList = findChild(dashContent, "dashContentList");
449+ tryCompareFunction(function() { return findChild(dashContentList.currentItem, "dashNavigation") != null; }, true);
450+ var dashNavigation = findChild(dashContentList.currentItem, "dashNavigation");
451+ tryCompare(dashNavigation, "visible", true);
452+ var dashNavigationButton = findChild(dashContentList.currentItem, "navigationButton");
453+ verify(dashNavigationButton, "Can't find navigation button");
454+ var dashAltNavigationButton = findChild(dashContentList.currentItem, "altNavigationButton");
455+ verify(dashAltNavigationButton, "Can't find alternative navigation button");
456+
457+ waitForRendering(dashNavigationButton);
458+ waitForRendering(dashAltNavigationButton);
459+
460+ compare(dashNavigationButton.showList, false);
461+ compare(dashAltNavigationButton.showList, false);
462+
463+ mouseClick(dashNavigation, 0, 0);
464+ compare(dashNavigationButton.showList, false);
465+ compare(dashAltNavigationButton.showList, true);
466+
467+ var navigationListView = findChild(dashAltNavigationButton, "navigationListView");
468+ tryCompare(navigationListView.currentItem.navigation, "loaded", true);
469+
470+ mouseClick(dashNavigation, dashNavigationButton.x, 0);
471+ compare(dashNavigationButton.showList, false);
472+ compare(dashAltNavigationButton.showList, false);
473+
474+ tryCompare(navigationListView, "visible", false);
475+
476+ mouseClick(dashNavigation, dashNavigationButton.x, 0);
477+ compare(dashNavigationButton.showList, true);
478+ compare(dashAltNavigationButton.showList, false);
479+
480+ navigationListView = findChild(dashNavigationButton, "navigationListView");
481+ tryCompare(navigationListView.currentItem.navigation, "loaded", true);
482+
483+ mouseClick(dashNavigation, 0, 0);
484+ compare(dashNavigationButton.showList, false);
485+ compare(dashAltNavigationButton.showList, false);
382 }
486 }
383
487
384 function test_searchHint() {
488 function test_searchHint() {
tests/qmltests/Dash/tst_GenericScopeView.qml+102−39
@@ -20,7 +20,7 @@ import Unity 0.2
20import ".."
20import ".."
21import "../../../qml/Dash"
21import "../../../qml/Dash"
22import "../../../qml/Components"
22import "../../../qml/Components"
23−import Ubuntu.Components 0.1
23+import Ubuntu.Components 1.1
24import Unity.Test 0.1 as UT
24import Unity.Test 0.1 as UT
25
25
26Item {
26Item {
@@ -39,6 +39,8 @@ Item {
39
39
40 Scopes {
40 Scopes {
41 id: scopes
41 id: scopes
42+ // for tryGenericScopeView
43+ onLoadedChanged: if (loaded) genericScopeView.scope = scopes.getScope(2);
42 }
44 }
43
45
44 SignalSpy {
46 SignalSpy {
@@ -59,7 +61,7 @@ Item {
59 name: "GenericScopeView"
61 name: "GenericScopeView"
60 when: scopes.loaded && windowShown
62 when: scopes.loaded && windowShown
61
63
62− property Item previewListView: findChild(genericScopeView, "previewListView")
64+ property Item subPageLoader: findChild(genericScopeView, "subPageLoader")
63 property Item header: findChild(genericScopeView, "scopePageHeader")
65 property Item header: findChild(genericScopeView, "scopePageHeader")
64
66
65 function init() {
67 function init() {
@@ -94,24 +96,24 @@ Item {
94 tryCompare(genericScopeView.scope, "isActive", false)
96 tryCompare(genericScopeView.scope, "isActive", false)
95 genericScopeView.isCurrent = true
97 genericScopeView.isCurrent = true
96 tryCompare(genericScopeView.scope, "isActive", true)
98 tryCompare(genericScopeView.scope, "isActive", true)
97− testCase.previewListView.open = true
99+ testCase.subPageLoader.open = true
98 tryCompare(genericScopeView.scope, "isActive", false)
100 tryCompare(genericScopeView.scope, "isActive", false)
99− testCase.previewListView.open = false
101+ testCase.subPageLoader.open = false
100 tryCompare(genericScopeView.scope, "isActive", true)
102 tryCompare(genericScopeView.scope, "isActive", true)
101 genericScopeView.isCurrent = false
103 genericScopeView.isCurrent = false
102 tryCompare(genericScopeView.scope, "isActive", false)
104 tryCompare(genericScopeView.scope, "isActive", false)
103 }
105 }
104
106
105 function test_showDash() {
107 function test_showDash() {
106− testCase.previewListView.open = true;
108+ testCase.subPageLoader.open = true;
107 genericScopeView.scope.showDash();
109 genericScopeView.scope.showDash();
108− tryCompare(testCase.previewListView, "open", false);
110+ tryCompare(testCase.subPageLoader, "open", false);
109 }
111 }
110
112
111 function test_hideDash() {
113 function test_hideDash() {
112− testCase.previewListView.open = true;
114+ testCase.subPageLoader.open = true;
113 genericScopeView.scope.hideDash();
115 genericScopeView.scope.hideDash();
114− tryCompare(testCase.previewListView, "open", false);
116+ tryCompare(testCase.subPageLoader, "open", false);
115 }
117 }
116
118
117 function test_searchQuery() {
119 function test_searchQuery() {
@@ -214,7 +216,7 @@ Item {
214
216
215 openPreview(4, 0);
217 openPreview(4, 0);
216
218
217− compare(testCase.previewListView.count, 12, "There should only be 12 items in preview.");
219+ compare(testCase.subPageLoader.count, 12, "There should only be 12 items in preview.");
218
220
219 closePreview();
221 closePreview();
220 }
222 }
@@ -227,11 +229,15 @@ Item {
227 shell.width = units.gu(20)
229 shell.width = units.gu(20)
228 var categoryListView = findChild(genericScopeView, "categoryListView");
230 var categoryListView = findChild(genericScopeView, "categoryListView");
229 categoryListView.contentY = units.gu(20);
231 categoryListView.contentY = units.gu(20);
230− var seeAll = findChild(category, "seeAll")
232+ var seeAll = findChild(category, "seeAll");
233+ var floatingSeeLess = findChild(genericScopeView, "floatingSeeLess");
231 mouseClick(seeAll, seeAll.width / 2, seeAll.height / 2);
234 mouseClick(seeAll, seeAll.width / 2, seeAll.height / 2);
232 tryCompare(category, "expanded", true);
235 tryCompare(category, "expanded", true);
236+ tryCompareFunction(function() {
237+ return category.item.height + floatingSeeLess.height ==
233− tryCompareFunction(function() { return category.item.height == genericScopeView.height - category.item.displayMarginBeginning - category.item.displayMarginEnd; }, true);
238+ genericScopeView.height - category.item.displayMarginBeginning - category.item.displayMarginEnd;
239+ }, true);
234− mouseClick(seeAll, seeAll.width / 2, seeAll.height / 2);
240+ mouseClick(floatingSeeLess, floatingSeeLess.width / 2, floatingSeeLess.height / 2);
235 tryCompare(category, "expanded", false);
241 tryCompare(category, "expanded", false);
236 }
242 }
237
243
@@ -272,19 +278,21 @@ Item {
272 true);
278 true);
273 var tile = findChild(findChild(genericScopeView, category), "delegate"+delegate);
279 var tile = findChild(findChild(genericScopeView, category), "delegate"+delegate);
274 mouseClick(tile, tile.width / 2, tile.height / 2);
280 mouseClick(tile, tile.width / 2, tile.height / 2);
275− tryCompare(testCase.previewListView, "open", true);
281+ tryCompare(testCase.subPageLoader, "open", true);
276− tryCompare(testCase.previewListView, "x", 0);
282+ tryCompare(testCase.subPageLoader, "x", 0);
277 }
283 }
278
284
279 function closePreview() {
285 function closePreview() {
280− var closePreviewMouseArea = findChild(genericScopeView, "innerPageHeader");
286+ var closePreviewMouseArea = findChild(subPageLoader.item, "pageHeader");
281 mouseClick(closePreviewMouseArea, units.gu(2), units.gu(2));
287 mouseClick(closePreviewMouseArea, units.gu(2), units.gu(2));
282
288
283− tryCompare(testCase.previewListView, "open", false);
289+ tryCompare(testCase.subPageLoader, "open", false);
290+ tryCompare(testCase.subPageLoader, "visible", false);
284 }
291 }
285
292
286 function test_previewOpenClose() {
293 function test_previewOpenClose() {
287− tryCompare(testCase.previewListView, "open", false);
294+ tryCompare(testCase.subPageLoader, "open", false);
295+ tryCompare(testCase.subPageLoader, "visible", false);
288
296
289 var categoryListView = findChild(genericScopeView, "categoryListView");
297 var categoryListView = findChild(genericScopeView, "categoryListView");
290 categoryListView.positionAtBeginning();
298 categoryListView.positionAtBeginning();
@@ -296,7 +304,7 @@ Item {
296 function test_showPreviewCarousel() {
304 function test_showPreviewCarousel() {
297 var category = scrollToCategory("dashCategory1");
305 var category = scrollToCategory("dashCategory1");
298
306
299− tryCompare(testCase.previewListView, "open", false);
307+ tryCompare(testCase.subPageLoader, "open", false);
300
308
301 var tile = findChild(category, "carouselDelegate1");
309 var tile = findChild(category, "carouselDelegate1");
302 verify(tile, "Could not find delegate");
310 verify(tile, "Could not find delegate");
@@ -304,14 +312,14 @@ Item {
304 mouseClick(tile, tile.width / 2, tile.height / 2);
312 mouseClick(tile, tile.width / 2, tile.height / 2);
305 tryCompare(tile, "explicitlyScaled", true);
313 tryCompare(tile, "explicitlyScaled", true);
306 mouseClick(tile, tile.width / 2, tile.height / 2);
314 mouseClick(tile, tile.width / 2, tile.height / 2);
307− tryCompare(testCase.previewListView, "open", true);
315+ tryCompare(testCase.subPageLoader, "open", true);
308− tryCompare(testCase.previewListView, "x", 0);
316+ tryCompare(testCase.subPageLoader, "x", 0);
309
317
310 closePreview();
318 closePreview();
311
319
312 mousePress(tile, tile.width / 2, tile.height / 2);
320 mousePress(tile, tile.width / 2, tile.height / 2);
313− tryCompare(testCase.previewListView, "open", true);
321+ tryCompare(testCase.subPageLoader, "open", true);
314− tryCompare(testCase.previewListView, "x", 0);
322+ tryCompare(testCase.subPageLoader, "x", 0);
315 mouseRelease(tile, tile.width / 2, tile.height / 2);
323 mouseRelease(tile, tile.width / 2, tile.height / 2);
316
324
317 closePreview();
325 closePreview();
@@ -320,20 +328,20 @@ Item {
320 function test_showPreviewHorizontalList() {
328 function test_showPreviewHorizontalList() {
321 var category = scrollToCategory("dashCategory18");
329 var category = scrollToCategory("dashCategory18");
322
330
323− tryCompare(testCase.previewListView, "open", false);
331+ tryCompare(testCase.subPageLoader, "open", false);
324
332
325 var tile = findChild(category, "delegate1");
333 var tile = findChild(category, "delegate1");
326 verify(tile, "Could not find delegate");
334 verify(tile, "Could not find delegate");
327
335
328 mouseClick(tile, tile.width / 2, tile.height / 2);
336 mouseClick(tile, tile.width / 2, tile.height / 2);
329− tryCompare(testCase.previewListView, "open", true);
337+ tryCompare(testCase.subPageLoader, "open", true);
330− tryCompare(testCase.previewListView, "x", 0);
338+ tryCompare(testCase.subPageLoader, "x", 0);
331
339
332 closePreview();
340 closePreview();
333
341
334 mousePress(tile, tile.width / 2, tile.height / 2);
342 mousePress(tile, tile.width / 2, tile.height / 2);
335− tryCompare(testCase.previewListView, "open", true);
343+ tryCompare(testCase.subPageLoader, "open", true);
336− tryCompare(testCase.previewListView, "x", 0);
344+ tryCompare(testCase.subPageLoader, "x", 0);
337 mouseRelease(tile, tile.width / 2, tile.height / 2);
345 mouseRelease(tile, tile.width / 2, tile.height / 2);
338
346
339 closePreview();
347 closePreview();
@@ -343,30 +351,57 @@ Item {
343 var categoryListView = findChild(genericScopeView, "categoryListView");
351 var categoryListView = findChild(genericScopeView, "categoryListView");
344 categoryListView.positionAtBeginning();
352 categoryListView.positionAtBeginning();
345
353
346− tryCompare(testCase.previewListView, "open", false);
354+ tryCompare(testCase.subPageLoader, "open", false);
347− var previewListViewList = findChild(previewListView, "listView");
348
355
349 openPreview();
356 openPreview();
357+ var previewListViewList = findChild(subPageLoader.item, "listView");
350
358
351 // flick to the next previews
359 // flick to the next previews
352− tryCompare(testCase.previewListView, "count", 15);
360+ tryCompare(testCase.subPageLoader, "count", 15);
353− for (var i = 1; i < testCase.previewListView.count; ++i) {
361+ for (var i = 1; i < testCase.subPageLoader.count; ++i) {
354− mouseFlick(testCase.previewListView, testCase.previewListView.width - units.gu(1),
362+ mouseFlick(testCase.subPageLoader.item, testCase.subPageLoader.width - units.gu(1),
355− testCase.previewListView.height / 2,
363+ testCase.subPageLoader.height / 2,
356 units.gu(2),
364 units.gu(2),
357− testCase.previewListView.height / 2);
365+ testCase.subPageLoader.height / 2);
358 tryCompare(previewListViewList, "moving", false);
366 tryCompare(previewListViewList, "moving", false);
359− tryCompare(testCase.previewListView.currentItem, "objectName", "preview" + i);
367+ tryCompare(testCase.subPageLoader.currentItem, "objectName", "preview" + i);
360−
361 }
368 }
362 closePreview();
369 closePreview();
363 }
370 }
364
371
372+ function test_settingsOpenClose() {
373+ waitForRendering(genericScopeView);
374+ verify(header, "Could not find the header.");
375+ var innerHeader = findChild(header, "innerPageHeader");
376+ verify(innerHeader, "Could not find the inner header");
377+
378+ // open
379+ tryCompare(testCase.subPageLoader, "open", false);
380+ tryCompare(testCase.subPageLoader, "visible", false);
381+ var settings = findChild(innerHeader, "settings_header_button");
382+ mouseClick(settings, settings.width / 2, settings.height / 2);
383+ tryCompare(testCase.subPageLoader, "open", true);
384+ tryCompareFunction(function() { return (String(subPageLoader.source)).indexOf("ScopeSettingsPage.qml") != -1; }, true);
385+ tryCompare(genericScopeView, "subPageShown", true);
386+ compare(testCase.subPageLoader.subPage, "settings");
387+ tryCompare(testCase.subPageLoader, "x", 0);
388+
389+ // close
390+ var settingsHeader = findChild(testCase.subPageLoader.item, "pageHeader");
391+ mouseClick(settingsHeader, units.gu(2), units.gu(2));
392+ tryCompare(testCase.subPageLoader, "open", false);
393+ tryCompare(genericScopeView, "subPageShown", false);
394+ var categoryListView = findChild(genericScopeView, "categoryListView");
395+ tryCompare(categoryListView, "x", 0);
396+ tryCompare(testCase.subPageLoader, "visible", false);
397+ tryCompare(testCase.subPageLoader, "source", "");
398+ }
399+
365 function test_header_style_data() {
400 function test_header_style_data() {
366 return [
401 return [
367− { tag: "Default", index: 0, foreground: Theme.palette.normal.baseText, background: "", logo: "" },
402+ { tag: "Default", index: 0, foreground: UbuntuColors.darkGrey, background: "color:///#f5f5f5", logo: "" },
368− { tag: "Foreground", index: 1, foreground: "yellow", background: "", logo: "" },
403+ { tag: "Foreground", index: 1, foreground: "yellow", background: "color:///#f5f5f5", logo: "" },
369− { tag: "Logo+Background", index: 2, foreground: Theme.palette.normal.baseText, background: "gradient:///lightgrey/grey",
404+ { tag: "Logo+Background", index: 2, foreground: UbuntuColors.darkGrey, background: "gradient:///lightgrey/grey",
370 logo: Qt.resolvedUrl("../Dash/tst_PageHeader/logo-ubuntu-orange.svg") },
405 logo: Qt.resolvedUrl("../Dash/tst_PageHeader/logo-ubuntu-orange.svg") },
371 ];
406 ];
372 }
407 }
@@ -390,6 +425,34 @@ Item {
390 verify(image, "Could not find the title image.");
425 verify(image, "Could not find the title image.");
391 compare(image.source, data.logo, "Title image has the wrong source");
426 compare(image.source, data.logo, "Title image has the wrong source");
392 }
427 }
428+
429+ function test_favorite_data() {
430+ return [
431+ { tag: "People", id: "MockScope1", favorite: true },
432+ { tag: "Music", id: "MockScope2", favorite: false },
433+ { tag: "Apps", id: "clickscope", favorite: true },
434+ ];
435+ }
436+
437+ function test_favorite(data) {
438+ genericScopeView.scope = scopes.getScopeFromAll(data.id);
439+ waitForRendering(genericScopeView);
440+ verify(header, "Could not find the header.");
441+
442+ compare(genericScopeView.scope.favorite, data.favorite, "Unexpected initial favorite value");
443+
444+ var innerHeader = findChild(header, "innerPageHeader");
445+ verify(innerHeader, "Could not find the inner header");
446+
447+ expectFail("Apps", "Click scope should not have a favorite button");
448+ var favoriteAction = findChild(innerHeader, "favorite_header_button");
449+ verify(favoriteAction, "Could not find the favorite action.");
450+ mouseClick(favoriteAction, favoriteAction.width / 2, favoriteAction.height / 2);
451+
452+ tryCompare(genericScopeView.scope, "favorite", !data.favorite);
453+
454+ genericScopeView.scope = !genericScopeView.scope;
455+ }
393 }
456 }
394 }
457 }
395}
458}
tests/qmltests/Dash/tst_PageHeader.qml+3−1
@@ -94,7 +94,7 @@ Item {
94 typeString("humppa1")
94 typeString("humppa1")
95 pageHeader.resetSearch()
95 pageHeader.resetSearch()
96
96
97− compare(pageHeader.searchHistory.count, 1)
97+ tryCompare(pageHeader.searchHistory, "count", 1)
98 compare(pageHeader.searchHistory.get(0).query, "humppa1")
98 compare(pageHeader.searchHistory.get(0).query, "humppa1")
99
99
100 pageHeader.triggerSearch()
100 pageHeader.triggerSearch()
@@ -155,6 +155,8 @@ Item {
155 compare(searchTextField.focus, true);
155 compare(searchTextField.focus, true);
156
156
157 var recentSearches = findChild(headerContainer.popover, "recentSearches");
157 var recentSearches = findChild(headerContainer.popover, "recentSearches");
158+ verify(recentSearches, "Could not find recent searches in the popover");
159+ waitForRendering(recentSearches);
158 mouseClick(recentSearches.itemAt(0), 0, 0);
160 mouseClick(recentSearches.itemAt(0), 0, 0);
159
161
160 compare(pageHeader.searchQuery, "Search2");
162 compare(pageHeader.searchQuery, "Search2");
tests/qmltests/tst_ShellWithPin.qml+2−2
@@ -220,10 +220,10 @@ Item {
220 tryCompare(placeHolder, "text", "")
220 tryCompare(placeHolder, "text", "")
221
221
222 enterPin("1111")
222 enterPin("1111")
223− tryCompare(placeHolder, "text", "Sorry, incorrect PIN")
223+ tryCompare(placeHolder, "text", "Sorry, incorrect passcode")
224
224
225 enterPin("1111")
225 enterPin("1111")
226− tryCompare(placeHolder, "text", "Sorry, incorrect PIN")
226+ tryCompare(placeHolder, "text", "Sorry, incorrect passcode")
227
227
228 enterPin("1111")
228 enterPin("1111")
229 tryCompare(placeHolder, "text", "Too many incorrect attempts")
229 tryCompare(placeHolder, "text", "Too many incorrect attempts")
tests/uqmlscene/main.cpp+1−1
@@ -495,7 +495,7 @@ int main(int argc, char ** argv)
495 if (!window) {
495 if (!window) {
496 QQuickItem *contentItem = qobject_cast<QQuickItem *>(topLevel);
496 QQuickItem *contentItem = qobject_cast<QQuickItem *>(topLevel);
497 if (contentItem) {
497 if (contentItem) {
498− qxView = new QQuickView(&engine, NULL);
498+ qxView = new QQuickView(&engine, nullptr);
499 window = qxView;
499 window = qxView;
500 // Set window default properties; the qml can still override them
500 // Set window default properties; the qml can still override them
501 QString oname = contentItem->objectName();
501 QString oname = contentItem->objectName();