on xenial help sign in
Merged trunk, resolving conflict in tests/autopilot/unity8/shell/emulators/main_window.py.
commit9b06d1675f10aa03090560dcf087d6e2c77c105c authorAllan LeSage <allan.lesage@canonical.com> dateTue 26 Nov 2013, 15:12 (13 years ago) parenta3474ad4d4c90e
273 files changed+4903−8750
Bottombar/Bottombar.qml+4−4 CMakeLists.txt+10−1 Components/Carousel.qml+4−6 Components/DragHandle.qml+22−24 Components/DraggingArea.qml+1−2 Components/EdgeDemoOverlay.qml+2 Components/EdgeDragArea.qml+12−4 Components/PageHeader.qml+26−7 Components/PinPadButton.qml+40−13 Components/Revealer.qml+1−2 Components/Stage.qml+8−7 Components/Time.js−49 Dash/Apps/AppInfo.qml−89 Dash/Apps/ApplicationsFilterGrid.qml−64 Dash/Apps/DashPluginFilterGrid.qml+2−2 Dash/Apps/RunningApplicationTile.qml−2 Dash/Dash.qml+3 Dash/DashApps.qml+3 Dash/DashContent.qml+2−1 Components/Math.js → Dash/Generic/GenericCarouselLoader.qml+11−7 Dash/Generic/GenericFilterGrid.qml+4−4 Dash/Generic/WeatherFilterGrid.qml+2−2 Dash/GenericScopeView.qml+73−19 tests/mocks/QMenuModel/UnityMenuModel.qml → Dash/Music/MusicCarouselLoader.qml+5−7 Dash/Music/MusicFilterGrid.qml+2−2 Dash/ScopeView.qml−65 Dash/Video/VideosCarousel.qml → Dash/Video/VideoCarousel.qml plugins/Unity/abstractfilteroption.cpp → Dash/Video/VideoCarouselLoader.qml+6−7 Dash/Video/VideoFilterGrid.qml+2−2 Dash/Video/VideoInfo.qml−84 Greeter/Greeter.qml+4−7 Greeter/GreeterContent.qml+23−20 Greeter/Lockscreen.qml+14−22 Greeter/PassphraseLockscreen.qml+1 Greeter/PinLockscreen.qml+35−4 Launcher/Launcher.qml+1−1 Launcher/LauncherDelegate.qml+1 Launcher/LauncherPanel.qml+1−1 Notifications/Notification.qml+3−7 Notifications/NotificationMenuItemFactory.qml+20−6 plugins/Unity/ratingoptionsmodel.cpp → Notifications/ShapedIcon.qml+20−13 Panel/Indicators.qml+37−10 Panel/Indicators/DefaultIndicatorWidget.qml+32−10 Panel/Indicators/client/IndicatorsTree.qml+2−3 Shell.qml+21−6 build+1 cmake/modules/Plugins.cmake+3−3 cmake/modules/autopilot.cmake+1−1 data/unity8.conf+20 debian/changelog+72 debian/control+4−5 paths.h.in+4−2 plugins/AccountsService/plugin.cpp+1−1 plugins/ListViewWithPageHeader/listviewwithpageheader.cpp+32−6 plugins/ListViewWithPageHeader/listviewwithpageheader.h+5 plugins/SessionBroadcast/plugin.cpp+1−1 plugins/Ubuntu/Gestures/AxisVelocityCalculator.cpp+9−18 plugins/Ubuntu/Gestures/AxisVelocityCalculator.h+9−16 plugins/Ubuntu/Gestures/CMakeLists.txt+1 plugins/Ubuntu/Gestures/DirectionalDragArea.cpp+307−71 plugins/Ubuntu/Gestures/DirectionalDragArea.h+50−13 plugins/Ubuntu/Gestures/TimeSource.cpp+49 plugins/Ubuntu/Gestures/TimeSource.h+54 plugins/Unity/CMakeLists.txt−69 plugins/Unity/Indicators/indicator.cpp+8−16 plugins/Unity/Indicators/indicator.h+1−1 plugins/Unity/Indicators/indicatorsmanager.cpp+3−1 plugins/Unity/Indicators/qml/IndicatorBase.qml+3−4 plugins/Unity/Indicators/qml/IndicatorWidget.qml+1−1 plugins/Unity/Indicators/unitymenumodelstack.cpp+98−7 plugins/Unity/Indicators/unitymenumodelstack.h+10−2 plugins/Unity/Launcher/launcheritem.cpp+4−2 plugins/Unity/abstractfilteroption.h−58 plugins/Unity/applicationpreview.cpp−100 plugins/Unity/applicationpreview.h−66 plugins/Unity/categories.cpp−299 plugins/Unity/categories.h−95 plugins/Unity/checkoptionfilter.cpp−65 plugins/Unity/checkoptionfilter.h−57 plugins/Unity/filter.cpp−129 plugins/Unity/filter.h−75 plugins/Unity/filteroption.cpp−91 plugins/Unity/filteroption.h−61 plugins/Unity/filters.cpp−165 plugins/Unity/filters.h−77 plugins/Unity/genericoptionsmodel.cpp−187 plugins/Unity/genericoptionsmodel.h−79 plugins/Unity/moviepreview.cpp−67 plugins/Unity/moviepreview.h−60 plugins/Unity/multirangefilter.cpp−65 plugins/Unity/multirangefilter.h−60 plugins/Unity/musicpreview.cpp−54 plugins/Unity/musicpreview.h−62 plugins/Unity/plugin.cpp−74 plugins/Unity/preview.cpp−199 plugins/Unity/preview.h−89 plugins/Unity/previewaction.cpp−75 plugins/Unity/previewaction.h−71 plugins/Unity/previewinfohint.cpp−67 plugins/Unity/previewinfohint.h−58 plugins/Unity/qmldir−3 plugins/Unity/radiooptionfilter.cpp−61 plugins/Unity/radiooptionfilter.h−59 plugins/Unity/ratingfilteroption.cpp−62 plugins/Unity/ratingfilteroption.h−53 plugins/Unity/ratingsfilter.cpp−73 plugins/Unity/ratingsfilter.h−66 plugins/Unity/result.cpp−82 plugins/Unity/result.h−69 plugins/Unity/scope.cpp−413 plugins/Unity/scope.h−154 plugins/Unity/scopes.cpp−176 plugins/Unity/scopes.h−94 plugins/Unity/showallfilteroption.cpp−60 plugins/Unity/showallfilteroption.h−51 plugins/Unity/signalslist.cpp−39 plugins/Unity/signalslist.h−38 plugins/Unity/socialpreview.cpp−87 plugins/Unity/socialpreview.h−63 plugins/Unity/socialpreviewcomment.cpp−63 plugins/Unity/socialpreviewcomment.h−57 plugins/Unity/unityoptionsmodel.cpp−68 plugins/Unity/unityoptionsmodel.h−50 plugins/Unity/variantutils.cpp−82 plugins/Unity/variantutils.h−35 plugins/Utils/CMakeLists.txt+1−2 plugins/Utils/albumartprovider.cpp+10−7 plugins/Utils/applicationpaths.h−38 plugins/Unity/bottombarvisibilitycommunicatorshell.cpp → plugins/Utils/bottombarvisibilitycommunicatorshell.cpp plugins/Unity/bottombarvisibilitycommunicatorshell.h → plugins/Utils/bottombarvisibilitycommunicatorshell.h plugins/Utils/plugin.cpp+11−9 plugins/Utils/ubuntuwindow.cpp−36 plugins/Utils/ubuntuwindow.h−42 po/ar.po+23−10 po/ast.po+22−30 po/az.po+22−15 po/bg.po+22−21 po/ca.po+22−30 po/cs.po+22−24 po/de.po+22−9 po/el.po+22−15 po/en_AU.po+22−30 po/en_GB.po+22−30 po/eo.po+22−9 po/es.po+23−31 po/fa.po+22−9 po/fi.po+23−31 po/fo.po+22−15 po/fr.po+22−15 po/gd.po+22−30 po/gl.po+22−27 po/he.po+26−32 po/hr.po+22−15 po/hu.po+22−15 po/hy.po+22−15 po/id.po+22−9 po/is.po+22−30 po/it.po+22−30 po/ja.po+22−9 po/km.po+23−31 po/kn.po+22−15 po/ko.po+22−12 po/ky.po+22−15 po/lo.po+22−15 po/lv.po+22−15 po/ml.po+240 po/my.po+22−24 po/nb.po+22−15 po/nl.po+22−15 po/pl.po+22−9 po/pt_BR.po+22−30 po/ro.po+22−15 po/ru.po+22−30 po/shn.po+22−9 po/si.po+22−9 po/sl.po+22−30 po/sr.po+22−15 po/sv.po+22−9 po/ta.po+22−9 po/te.po+22−12 po/tr.po+22−30 po/ug.po+22−24 po/uk.po+24−11 po/unity8.pot+20−7 po/xh.po+22−9 po/zh_CN.po+22−30 po/zh_TW.po+22−15 run+2 run_on_device+1−1 tests/autopilot/unity8/process_helpers.py+65−38 tests/autopilot/unity8/shell/emulators/create_interactive_notification.py tests/autopilot/unity8/shell/emulators/dash.py+7−17 tests/autopilot/unity8/shell/emulators/hud.py+12−4 tests/autopilot/unity8/shell/emulators/main_window.py+7−7 tests/autopilot/unity8/shell/tests/__init__.py+54−36 tests/autopilot/unity8/shell/tests/test_greeter.py+38 tests/autopilot/unity8/shell/tests/test_hud.py+11−10 tests/autopilot/unity8/shell/tests/test_notifications.py+74−72 tests/mocks/AccountsService/CMakeLists.txt+2−2 tests/mocks/AccountsService/plugin.cpp+1−1 tests/mocks/LightDM/CMakeLists.txt+2−2 tests/mocks/LightDM/full/CMakeLists.txt+1−1 tests/mocks/LightDM/single-passphrase/CMakeLists.txt+1−1 tests/mocks/LightDM/single-pin/CMakeLists.txt+1−1 tests/mocks/LightDM/single/CMakeLists.txt+1−1 tests/mocks/Powerd/CMakeLists.txt+2−2 tests/mocks/QMenuModel/CMakeLists.txt+23 plugins/Unity/genericpreview.cpp → tests/mocks/QMenuModel/UnityMenuAction.qml+11−12 tests/plugins/Unity/signalslisttest.h → tests/mocks/QMenuModel/actionstateparser.cpp+3−14 tests/plugins/Unity/resultstest.h → tests/mocks/QMenuModel/actionstateparser.h+11−15 plugins/Unity/ratingoptionsmodel.h → tests/mocks/QMenuModel/plugin.cpp+12−15 plugins/Unity/plugin.h → tests/mocks/QMenuModel/plugin.h+7−8 tests/mocks/QMenuModel/qmldir+3−1 tests/mocks/QMenuModel/unitymenumodel.cpp+239 tests/mocks/QMenuModel/unitymenumodel.h+96 tests/mocks/Ubuntu/DownloadDaemonListener/CMakeLists.txt+1−1 tests/mocks/Unity/Application/CMakeLists.txt+2−2 tests/mocks/Unity/CMakeLists.txt+2−3 tests/mocks/Unity/Indicators/IndicatorBase.qml+37 tests/mocks/Unity/Indicators/IndicatorWidget.qml+28 tests/mocks/Unity/Indicators/RootActionState.qml+17−9 tests/mocks/Unity/Indicators/qmldir+2 plugins/Unity/categoryresults.cpp → tests/mocks/Unity/categoryresults.cpp plugins/Unity/categoryresults.h → tests/mocks/Unity/categoryresults.h tests/mocks/Unity/fake_scope.cpp+3−20 plugins/Unity/iconutils.cpp → tests/mocks/Unity/iconutils.cpp+10−10 plugins/Unity/iconutils.h → tests/mocks/Unity/iconutils.h tests/mocks/libusermetrics/CMakeLists.txt+1−1 tests/plugins/ListViewWithPageHeader/CMakeLists.txt+7 tests/plugins/ListViewWithPageHeader/listviewwithpageheadertest.cpp+42 tests/plugins/ListViewWithPageHeader/listviewwithpageheadertestsection.cpp+81−1 tests/plugins/ListViewWithPageHeader/tst_listviewwithpageheaderqml.qml+138 tests/plugins/Ubuntu/Gestures/CMakeLists.txt+20−18 tests/plugins/Ubuntu/Gestures/DownwardsLauncher.qml+2−10 tests/plugins/Ubuntu/Gestures/GestureTest.cpp+54 plugins/Unity/genericpreview.h → tests/plugins/Ubuntu/Gestures/GestureTest.h+19−19 tests/plugins/Ubuntu/Gestures/LeftwardsLauncher.qml+5−13 tests/plugins/Ubuntu/Gestures/RightwardsLauncher.qml+3−10 tests/plugins/Ubuntu/Gestures/UpwardsLauncher.qml+5−13 tests/plugins/Ubuntu/Gestures/tst_AxisVelocityCalculator.cpp+3−3 tests/plugins/Ubuntu/Gestures/tst_DirectionalDragArea.cpp+326−168 tests/plugins/Ubuntu/Gestures/edgeDragExample.qml → tests/plugins/Ubuntu/Gestures/tst_DirectionalDragArea.qml+9−3 tests/plugins/Unity/CMakeLists.txt−51 tests/plugins/Unity/Indicators/CMakeLists.txt+36−27 tests/plugins/Unity/Indicators/indicatorsmanagertest.cpp+1−3 tests/plugins/Unity/Indicators/unitymenumodelstacktest.cpp+206 tests/plugins/Unity/filtersbindingstest.cpp−515 tests/plugins/Unity/filtersbindingstest.h−47 tests/plugins/Unity/previewbindingstest.cpp−194 tests/plugins/Unity/previewbindingstest.h−35 tests/plugins/Unity/resultstest.cpp−248 tests/plugins/Unity/signalslisttest.cpp−57 tests/qmltests/CMakeLists.txt+5−5 tests/qmltests/Components/tst_DragHandle.cpp+4−5 tests/qmltests/Components/tst_EdgeDemoOverlay.qml+2−2 tests/qmltests/Components/tst_MathLocal.qml−91 tests/qmltests/Components/tst_PageHeader.qml+44−3 tests/qmltests/Components/tst_TimeLocal.qml−117 tests/qmltests/Dash/Apps/tst_RunningApplicationsGrid.qml+1 tests/qmltests/Dash/qml/FakeScopeView.qml+3−68 tests/qmltests/Dash/tst_Dash.qml+7−1 tests/qmltests/Dash/tst_DashContent.qml+37−3 tests/qmltests/Dash/tst_FilterGrids.qml+1−2 tests/qmltests/Dash/tst_GenericScopeView.qml+27−2 tests/qmltests/Dash/tst_ScopeView.qml−52 tests/qmltests/Greeter/tst_Clock.qml+16 tests/qmltests/Greeter/tst_Lockscreen.qml+81−15 tests/qmltests/Greeter/tst_Phone.qml+5−5 tests/qmltests/Notifications/tst_Notifications.qml+56 tests/qmltests/Panel/Indicators/tst_DefaultIndicatorWidget.qml+97 tests/qmltests/Panel/tst_Panel.qml+13−5 tests/qmltests/tst_Shell.qml+74−13 tests/utils/modules/Unity/Test/UnityTestCase.qml+36
Bottombar/Bottombar.qml+4−4
@@ -16,10 +16,10 @@
1616
1717import QtQuick 2.0
1818import "../Components"
19−import "../Components/Math.js" as MathLocal
20−import Unity 0.1
19+import Utils 0.1
2120import Unity.Application 0.1
2221import Ubuntu.Gestures 0.1
22+import Ubuntu.Components 0.1
2323
2424Item {
2525 id: bottombar
@@ -82,7 +82,7 @@ Item {
8282
8383 readonly property bool centeredHud: parent.width < units.gu(68) // Nexus 7 has 67 gu width
8484
85− x: centeredHud ? parent.width / 2 - width / 2 : MathLocal.clamp(dragArea.touchStartX - (width / 2), 0, bottombar.width - width)
85+ x: centeredHud ? parent.width / 2 - width / 2 : MathUtils.clamp(dragArea.touchStartX - (width / 2), 0, bottombar.width - width)
8686 y: bottombar.height - bottomEdgeButtonCenterDistance - (height / 2) - bottomMargin
8787 z: 1
8888 visible: opacity != 0
@@ -136,7 +136,7 @@ Item {
136136 readonly property real distanceFromThreshold: (-distance) - distanceThreshold // distance is negative
137137 readonly property real revealDistance: units.gu(2)
138138 readonly property real commitDistance: units.gu(6)
139− readonly property real commitProgress: MathLocal.clamp(distanceFromThreshold / commitDistance, 0, 1)
139+ readonly property real commitProgress: MathUtils.clamp(distanceFromThreshold / commitDistance, 0, 1)
140140
141141 onStatusChanged: {
142142 if (status === DirectionalDragArea.WaitingForTouch) {
CMakeLists.txt+10−1
@@ -58,7 +58,16 @@ find_package(Qt5DBus)
5858include(GNUInstallDirs)
5959
6060set(SHELL_APP_DIR ${CMAKE_INSTALL_DATADIR}/unity8)
61−set(SHELL_PRIVATE_LIBDIR ${CMAKE_INSTALL_LIBDIR}/unity8)
61+
62+execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE} --variable=plugindir_suffix unity-shell-api OUTPUT_VARIABLE SHELL_INSTALL_QML OUTPUT_STRIP_TRAILING_WHITESPACE)
63+if(SHELL_INSTALL_QML STREQUAL "")
64+ message(FATAL_ERROR "Could not determine plugin installation dir.")
65+endif()
66+
67+execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE} --variable=plugindir unity-shell-api OUTPUT_VARIABLE SHELL_PLUGINDIR OUTPUT_STRIP_TRAILING_WHITESPACE)
68+if(SHELL_PLUGINDIR STREQUAL "")
69+ message(FATAL_ERROR "Could not determine plugin import dir.")
70+endif()
6271
6372configure_file(paths.h.in ${CMAKE_CURRENT_BINARY_DIR}/paths.h @ONLY)
6473
Components/Carousel.qml+4−6
@@ -54,15 +54,13 @@ Item {
5454
5555 /// Emitted when the user clicked on an item
5656 /// @param index is the index of the clicked item
57− /// @param model is the model of all the items in the carousel
5857 /// @param itemY is y of the clicked delegate
59− signal clicked(int index, var model, real itemY)
58+ signal clicked(int index, real itemY)
6059
6160 /// Emitted when the user pressed and held on an item
6261 /// @param index is the index of the held item
63− /// @param model is the model of all the items in the carousel
6462 /// @param itemY is y of the held delegate
65− signal pressAndHold(int index, var model, real itemY)
63+ signal pressAndHold(int index, real itemY)
6664
6765 implicitHeight: listView.tileHeight * selectedItemScaleFactor
6866
@@ -163,7 +161,7 @@ Item {
163161 /* We're clicking the selected item and
164162 we're in the neighbourhood of radius 1 pixel from it.
165163 Let's emit the clicked signal. */
166− carousel.clicked(index, listView.model, delegateItem.y)
164+ carousel.clicked(index, delegateItem.y)
167165 return
168166 }
169167
@@ -187,7 +185,7 @@ Item {
187185 /* We're pressAndHold the selected item and
188186 we're in the neighbourhood of radius 1 pixel from it.
189187 Let's emit the pressAndHold signal. */
190− carousel.pressAndHold(index, listView.model, delegateItem.y);
188+ carousel.pressAndHold(index, delegateItem.y);
191189 return;
192190 }
193191
Components/DragHandle.qml+22−24
@@ -17,7 +17,6 @@
1717import QtQuick 2.0
1818import Ubuntu.Components 0.1
1919import Ubuntu.Gestures 0.1
20−import "Math.js" as MathLocal
2120
2221/*
2322 Put a DragHandle inside a Showable to enable the user to drag it from that handle.
@@ -48,9 +47,12 @@ EdgeDragArea {
4847 id: dragArea
4948 objectName: "dragHandle"
5049
51− // Disable gesture detection by default when hinting is used.
52− // It doesn't make sense to have both.
53− distanceThreshold: hintDisplacement > 0 ? 0 : units.gu(1.5)
50+ // Disable most of the gesture recognition parameters by default when hinting is used as
51+ // it conflicts with the hinting idea.
52+ // The only part we keep in this situation is that it must be a single-finger gesture.
53+ distanceThreshold: hintDisplacement > 0 ? 0 : defaultDistanceThreshold
54+ maxSilenceTime: hintDisplacement > 0 ? 60*60*1000 : defaultMaxSilenceTime
55+ maxDeviation: hintDisplacement > 0 ? 999999 : defaultMaxDeviation
5456
5557 property bool stretch: false
5658
@@ -113,8 +115,8 @@ EdgeDragArea {
113115 }
114116 }
115117
116− function limitMovement(step) {
117− var targetValue = MathLocal.clamp(dragParent[targetProp] + step, minValue, maxValue);
118+ function limitMovement(inputStep) {
119+ var targetValue = MathUtils.clamp(dragParent[targetProp] + inputStep, minValue, maxValue);
118120 var step = targetValue - dragParent[targetProp];
119121
120122 if (hintDisplacement == 0) {
@@ -181,29 +183,25 @@ EdgeDragArea {
181183 }
182184 }
183185
184− onDraggingChanged: {
185− if (dragging) {
186− if (hintDisplacement > 0) {
187− hintingAnimation.targetValue = d.startValue;
188− hintingAnimation.start();
189− }
190− } else {
191− hintingAnimation.stop();
192− }
193− }
194−
195186 onStatusChanged: {
196187 if (status === DirectionalDragArea.WaitingForTouch) {
188+ hintingAnimation.stop();
197189 if (d.previousStatus === DirectionalDragArea.Recognized) {
198190 d.onFinishedRecognizedGesture();
191+ } else /* d.previousStatus === DirectionalDragArea.Undecided */ {
192+ // Gesture was rejected.
193+ d.rollbackDrag();
194+ }
195+ } else /* Undecided || Recognized */ {
196+ if (d.previousStatus === DirectionalDragArea.WaitingForTouch ||
197+ d.previousStatus === undefined) {
198+ dragEvaluator.reset();
199+ d.startValue = parent[d.targetProp];
200+ }
201+ if (hintDisplacement > 0) {
202+ hintingAnimation.targetValue = d.startValue;
203+ hintingAnimation.start();
199204 }
200− d.startValue = parent[d.targetProp];
201− }
202−
203− if (d.previousStatus === DirectionalDragArea.WaitingForTouch ||
204− d.previousStatus === undefined) {
205− dragEvaluator.reset();
206− d.startValue = parent[d.targetProp];
207205 }
208206
209207 d.previousStatus = status;
Components/DraggingArea.qml+1−2
@@ -16,7 +16,6 @@
1616
1717import QtQuick 2.0
1818import Ubuntu.Components 0.1
19−import "Math.js" as MathLocal
2019
2120MouseArea {
2221 id: draggingArea
@@ -26,7 +25,7 @@ MouseArea {
2625 property real dragVelocity: 0
2726 property real dragValue: (orientation == Qt.Vertical ? (mouseY - __pressedPosition.y)
2827 : (mouseX - __pressedPosition.x))
29− property real lateralPosition: orientation == Qt.Horizontal ? MathLocal.clamp(mouseY, 0, height) : MathLocal.clamp(mouseX, 0, width)
28+ property real lateralPosition: orientation == Qt.Horizontal ? MathUtils.clamp(mouseY, 0, height) : MathUtils.clamp(mouseX, 0, width)
3029 property point __pressedPosition: Qt.point(0, 0)
3130 property var __dragEvents: []
3231 property bool clickValidated: true
Components/EdgeDemoOverlay.qml+2
@@ -105,6 +105,8 @@ Showable {
105105 visible: overlay.active
106106
107107 MouseArea {
108+ objectName: "backgroundShadeMouseArea"
109+
108110 anchors.fill: parent
109111 enabled: overlay.edge == "none" && overlay.opacity == 1.0
110112 onClicked: overlay.doSkip()
Components/EdgeDragArea.qml+12−4
@@ -29,8 +29,16 @@ DirectionalDragArea {
2929 //
3030 // The idea here is that it's better having lax rules than false negatives.
3131 // False negatives are very frustrating to the user.
32− maxDeviation: units.gu(3)
33− wideningAngle: 50
34− distanceThreshold: units.gu(1.5)
35− minSpeed: units.gu(0) // some people were getting false negatives with it enabled.
32+ maxDeviation: defaultMaxDeviation
33+ wideningAngle: defaultWideningAngle
34+ distanceThreshold: defaultDistanceThreshold
35+ minSpeed: defaultMinSpeed
36+ maxSilenceTime: defaultMaxSilenceTime
37+
38+ readonly property real defaultMaxDeviation: units.gu(3)
39+ readonly property real defaultWideningAngle: 50
40+ readonly property real defaultDistanceThreshold: units.gu(1.5)
41+ // some people were getting false negatives with it enabled.
42+ readonly property real defaultMinSpeed: units.gu(0)
43+ readonly property int defaultMaxSilenceTime: 200
3644}
Components/PageHeader.qml+26−7
@@ -30,7 +30,7 @@ Item {
3030
3131 property bool searchEntryEnabled: false
3232 property alias searchQuery: searchField.text
33− property ListModel searchHistory: SearchHistoryModel {}
33+ property ListModel searchHistory
3434 property Scope scope
3535
3636 height: units.gu(8.5)
@@ -44,8 +44,8 @@ Item {
4444 if (!searchHistory) return;
4545
4646 searchHistory.addQuery(searchField.text);
47+ unfocus();
4748 searchField.text = "";
48− searchField.focus = false;
4949 }
5050
5151 function unfocus() {
@@ -112,6 +112,8 @@ Item {
112112 objectName: "searchContainer"
113113
114114 visible: searchEntryEnabled
115+ property bool popoverShouldOpen: false
116+ property bool popoverShouldClose: false
115117
116118 property bool narrowMode: parent.width < label.contentWidth + units.gu(50)
117119
@@ -127,6 +129,16 @@ Item {
127129 else if (active && !narrowMode) "active"
128130 else if (!active && !narrowMode) "inactive"
129131
132+ onStateChanged: {
133+ if (state == "active" || state == "narrowActive") {
134+ popoverShouldOpen = true;
135+ popoverShouldClose = false;
136+ } else {
137+ popoverShouldOpen = false;
138+ popoverShouldClose = true;
139+ }
140+ }
141+
130142 function openPopover() {
131143 if (searchHistory.count > 0) {
132144 searchContainer.popover = PopupUtils.open(popoverComponent, searchField,
@@ -137,10 +149,17 @@ Item {
137149 }
138150 )
139151 }
152+ popoverShouldOpen = false;
153+ popoverShouldClose = false;
140154 }
141155
142156 function closePopover() {
143− if (searchContainer.popover) PopupUtils.close(searchContainer.popover)
157+ if (searchContainer.popover) {
158+ PopupUtils.close(searchContainer.popover);
159+ searchContainer.popover = null;
160+ }
161+ popoverShouldOpen = false;
162+ popoverShouldClose = false;
144163 }
145164
146165 onActiveFocusChanged: if (!activeFocus) { searchHistory.addQuery(searchField.text) }
@@ -283,12 +302,12 @@ Item {
283302 PropertyAction { target: primaryImage; property: "source" }
284303 AnchorAnimation { targets: [searchContainer, textContainer]; duration: 200; easing.type: Easing.InOutQuad }
285304 }
286− ScriptAction { script: searchContainer.openPopover() }
305+ ScriptAction { script: if (searchContainer.popoverShouldOpen) { searchContainer.openPopover(); } }
287306 }
288307 },
289308 Transition {
290309 to: "inactive"
291− ScriptAction { script: searchContainer.closePopover() }
310+ ScriptAction { script: if (searchContainer.popoverShouldClose) { searchContainer.closePopover(); } }
292311 NumberAnimation { targets: [searchContainer, searchField] ; property: "width"; duration: 200; easing.type: Easing.InOutQuad }
293312 AnchorAnimation { targets: [searchContainer, textContainer]; duration: 200; easing.type: Easing.InOutQuad }
294313 },
@@ -299,12 +318,12 @@ Item {
299318 NumberAnimation { targets: [searchContainer, searchField] ; property: "width"; duration: 200; easing.type: Easing.OutQuad }
300319 AnchorAnimation { targets: [searchContainer, textContainer]; duration: 200; easing.type: Easing.InOutQuad }
301320 }
302− ScriptAction { script: searchContainer.openPopover() }
321+ ScriptAction { script: if (searchContainer.popoverShouldOpen) { searchContainer.openPopover(); } }
303322 }
304323 },
305324 Transition {
306325 to: "narrowInactive"
307− ScriptAction { script: searchContainer.closePopover() }
326+ ScriptAction { script: if (searchContainer.popoverShouldClose) { searchContainer.closePopover(); } }
308327 NumberAnimation { targets: [searchContainer, searchField] ; property: "width"; duration: 200; easing.type: Easing.OutQuad }
309328 AnchorAnimation { targets: [searchContainer, textContainer]; duration: 200; easing.type: Easing.InOutQuad }
310329 }
Components/PinPadButton.qml+40−13
@@ -21,24 +21,51 @@ Item {
2121 id: root
2222
2323 property alias text: label.text
24− property alias iconName: icon.name
24+ property alias subText: subTextLabel.text
25+ property string iconName
2526
2627 signal clicked()
2728
28− Label {
29− id: label
29+ Column {
3030 anchors.centerIn: parent
31− color: "#f3f3e7"
32− fontSize: "large"
33− font.weight: Font.DemiBold
34− }
31+ width: parent.width
32+ height: childrenRect.height
3533
36− Icon {
37− id: icon
38− height: units.gu(3)
39− width: height
40− anchors.centerIn: parent
41− color: "#f3f3e7"
34+ Item {
35+ anchors {
36+ left: parent.left
37+ right: parent.right
38+ }
39+ height: label.visible || icon.visible ? Math.max(label.height, icon.height) : 0
40+
41+ Label {
42+ id: label
43+ anchors.centerIn: parent
44+ width: parent.width
45+ horizontalAlignment: Text.AlignHCenter
46+ color: "#f3f3e7"
47+ fontSize: "large"
48+ font.weight: Font.DemiBold
49+ visible: text.length > 0
50+ }
51+
52+ Icon {
53+ id: icon
54+ height: units.gu(3)
55+ width: height
56+ anchors.centerIn: parent
57+ name: root.iconName
58+ color: "#f3f3e7"
59+ visible: name.length > 0
60+ }
61+ }
62+ Label {
63+ id: subTextLabel
64+ fontSize: "small"
65+ color: "grey"
66+ anchors.horizontalCenter: parent.horizontalCenter
67+ visible: text.length > 0
68+ }
4269 }
4370
4471 MouseArea {
Components/Revealer.qml+1−2
@@ -16,7 +16,6 @@
1616
1717import QtQuick 2.0
1818import Ubuntu.Components 0.1
19−import "Math.js" as MathLocal
2019
2120Item {
2221 id: revealer
@@ -95,7 +94,7 @@ Item {
9594 onClosedValueChanged: if (!__opened && !dragging) target[boundProperty] = closedValue
9695
9796 function __computeValue(dragPosition) {
98− return MathLocal.clamp(dragToValue(dragPosition), __hintValue, openedValue)
97+ return MathUtils.clamp(dragToValue(dragPosition), __hintValue, openedValue)
9998 }
10099
101100 function __open() {
Components/Stage.qml+8−7
@@ -482,19 +482,20 @@ Showable {
482482 switchToApplicationAnimationController.progress += 0.4 * delta
483483 }
484484
485− property bool gotRejected: false
485+ property int lastStatus: -1
486486
487487 onStatusChanged: {
488488 if (status == DirectionalDragArea.Undecided) {
489− gotRejected = false
490489 onUndecided();
491− } else if (status == DirectionalDragArea.Rejected) {
492− switchToApplicationAnimationController.completeToBeginningWithSignal();
493− gotRejected = true;
494490 } else if (status == DirectionalDragArea.WaitingForTouch) {
495− if (!gotRejected)
496− onGestureEnded()
491+ if (lastStatus == DirectionalDragArea.Undecided) {
492+ // got rejected
493+ switchToApplicationAnimationController.completeToBeginningWithSignal();
494+ } else {
495+ onGestureEnded();
496+ }
497497 }
498+ lastStatus = status;
498499 }
499500
500501 function onUndecided() {
Components/Time.jsdeleted−49
@@ -1,49 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−.pragma library
18−
19−var factors = {
20− "second": [ 1000, "a second ago", "in a second", "%1 seconds ago", "in %1 seconds" ],
21− "minute": [ 60, "a minute ago", "in a minute", "%1 minutes ago", "in %1 minutes" ],
22− "hour": [ 60, "an hour ago", "in an hour", "%1 hours ago", "in %1 hours" ],
23− "day": [ 24, "yesterday", "tomorrow", "%1 days ago", "in %1 days" ],
24− "week": [ 7, "a week ago", "in a week", "about %1 weeks ago", "in about %1 weeks" ],
25− "month": [ 4.35, "a month ago", "in a month", "%1 months ago", "in %1 months" ], // == 365.25 days / 12 months / 7 days
26− "year": [ 12, "a year ago", "in a year", "%1 years ago", "in %1 years" ]
27−}
28−
29−function readableFromNow(date, now) {
30− var then = new Date(date);
31− if (isNaN(then)) return "";
32− if (now === undefined) {
33− now = new Date();
34− } else if (isNaN(now)) throw "now is NaN";
35− var diff = Math.abs(now - then);
36− if (diff < 1000) return "just now";
37−
38− var future = now < then;
39− var humanDiff;
40− for (var k in factors) {
41− diff /= factors[k][0];
42− if (Math.floor(diff) == 1) {
43− humanDiff = factors[k][future ? 2 : 1];
44− } else if (Math.floor(diff) > 1) {
45− humanDiff = factors[k][future ? 4 : 3].arg(Math.round(diff));
46− } else break;
47− }
48− return humanDiff;
49−}
Dash/Apps/AppInfo.qmldeleted−89
@@ -1,89 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.0
18−import Ubuntu.Components 0.1
19−import "../../Components"
20−
21−Row {
22− id: root
23− property alias icon: image.source
24− property alias appName: appNameLabel.text
25− property alias rating: ratingStars.rating
26− property int rated: 0
27− property int reviews: 0
28−
29− spacing: units.gu(2)
30−
31− UbuntuShape {
32− id: imageShape
33− width: units.gu(6)
34− height: units.gu(6)
35− image: Image {
36− id: image
37− sourceSize { width: imageShape.width; height: imageShape.height }
38− asynchronous: true
39− fillMode: Image.PreserveAspectFit
40− }
41− }
42−
43− Column {
44− spacing: units.gu(1)
45−
46− Label {
47− id: appNameLabel
48− fontSize: "large"
49− color: "white"
50− style: Text.Raised
51− styleColor: "black"
52− opacity: .9
53− }
54−
55− Row {
56− visible: root.rating >= 0
57− spacing: units.gu(1)
58−
59− RatingStars {
60− id: ratingStars
61− maximumRating: 10
62− }
63−
64− Label {
65− id: ratedLabel
66− objectName: "ratedLabel"
67− fontSize: "medium"
68− color: "white"
69− style: Text.Raised
70− styleColor: "black"
71− opacity: .6
72− //TRANSLATORS: Number of persons who rated this app
73− text: i18n.tr("(%1)").arg(root.rated)
74− }
75−
76− Label {
77− id: reviewsLabel
78− objectName: "reviewsLabel"
79− fontSize: "medium"
80− color: "white"
81− style: Text.Raised
82− styleColor: "black"
83− opacity: .6
84− //TRANSLATORS: Number of persons who wrote reviews for this app
85− text: i18n.tr("%1 review", "%1 reviews", root.reviews).arg(root.reviews)
86− }
87− }
88− }
89−}
Dash/Apps/ApplicationsFilterGrid.qmldeleted−64
@@ -1,64 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.0
18−import "../../Components"
19−import "../../Applications"
20−
21−FilterGrid {
22− id: filtergrid
23−
24− filter: false
25− minimumHorizontalSpacing: units.gu(0.5)
26− maximumNumberOfColumns: 6
27− delegateWidth: units.gu(11)
28− delegateHeight: units.gu(9.5)
29− verticalSpacing: units.gu(2)
30−
31− signal clicked(int index, var model, real itemY)
32− signal pressAndHold(int index, var model, real itemY)
33−
34− delegate: Tile {
35− id: tile
36− objectName: "delegate" + index
37− Application {
38− id: application
39− desktopFile: model.dndUri ? stripProtocol(model.dndUri) : model.desktopFile // FIXME: this is temporary
40−
41− function stripProtocol(uri) {
42− var chunks = uri.split('file://')
43− return chunks[chunks.length-1]
44− }
45− }
46−
47− property string icon: model.icon ? model.icon : "../../graphics/applicationIcons/" + application.icon + ".png" // FIXME: this is temporary
48−
49− width: filtergrid.cellWidth
50− height: filtergrid.cellHeight
51− text: model.title ? model.title : application.name // FIXME: this is temporary
52− imageWidth: units.gu(8)
53− imageHeight: units.gu(7.5)
54− source: icon
55−
56− onClicked: {
57− filtergrid.clicked(index, filtergrid.model, tile.y)
58− }
59−
60− onPressAndHold: {
61− filtergrid.pressAndHold(index, filtergrid.model, tile.y)
62− }
63− }
64−}
Dash/Apps/DashPluginFilterGrid.qml+2−2
@@ -37,11 +37,11 @@ GenericFilterGrid {
3737 }
3838
3939 onClicked: {
40− filtergrid.clicked(index, filtergrid.model, tile.y)
40+ filtergrid.clicked(index, tile.y)
4141 }
4242
4343 onPressAndHold: {
44− filtergrid.pressAndHold(index, filtergrid.model, tile.y)
44+ filtergrid.pressAndHold(index, tile.y)
4545 }
4646 }
4747}
Dash/Apps/RunningApplicationTile.qml−2
@@ -105,8 +105,6 @@ AbstractButton {
105105 baseline: parent.bottom
106106 left: parent.left
107107 right: parent.right
108− leftMargin: units.gu(1)
109− rightMargin: units.gu(1)
110108 }
111109 text: (application) ? application.name : ""
112110
Dash/Dash.qml+3
@@ -26,6 +26,8 @@ Showable {
2626
2727 visible: shown
2828
29+ property ListModel searchHistory: SearchHistoryModel {}
30+
2931 property alias contentProgress: dashContent.contentProgress
3032 property string showScopeOnLoaded: "home.scope"
3133 property real contentScale: 1.0
@@ -63,6 +65,7 @@ Showable {
6365 anchors.fill: parent
6466 model: filteredScopes
6567 scopes: scopes
68+ searchHistory: dash.searchHistory
6669 onMovementStarted: dashbar.startNavigation()
6770 onMovementEnded: dashbar.stopNavigation()
6871 onContentFlickStarted: dashbar.finishNavigation()
Dash/DashApps.qml+3
@@ -30,6 +30,9 @@ GenericScopeView {
3030 property var mainStageApplicationsModel: shell.applicationManager.mainStageApplications
3131 property var sideStageApplicationModel: shell.applicationManager.sideStageApplications
3232
33+ //FIXME an alias to itself shouldn't be required. More than likely a Qt bug. Try removing with newer Qt.
34+ property alias searchHistory: scopeView.searchHistory
35+
3336 ListModel {
3437 id: dummyVisibilityModifier
3538
Dash/DashContent.qml+2−1
@@ -27,6 +27,7 @@ Item {
2727 property alias currentIndex: dashContentList.currentIndex
2828
2929 property ScopeDelegateMapper scopeMapper : ScopeDelegateMapper {}
30+ property ListModel searchHistory
3031
3132 signal movementStarted()
3233 signal movementEnded()
@@ -127,7 +128,7 @@ Item {
127128 onLoaded: {
128129 item.scope = Qt.binding(function() { return scope })
129130 item.isCurrent = Qt.binding(function() { return visible && ListView.isCurrentItem })
130− item.searchHistory = Qt.binding(function() { return shell.searchHistory })
131+ item.searchHistory = Qt.binding(function() { return dashContent.searchHistory })
131132 dashContentList.movementStarted.connect(item.movementStarted)
132133 dashContent.positionedAtBeginning.connect(item.positionedAtBeginning)
133134 dashContent.scopeLoaded(item.scope.id)
Components/Math.js → Dash/Generic/GenericCarouselLoader.qmlrenamed+11−7
@@ -14,13 +14,17 @@
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1515 */
1616
17−.pragma library
17+import QtQuick 2.0
18+import Ubuntu.Components 0.1
1819
19−function clamp(value, min, max) {
20− if (min <= max) {
21− return Math.max(min, Math.min(max, value))
22− } else {
23− // swap min/max if min > max
24− return clamp(value, max, min)
20+Loader {
21+ property var model: null
22+ property url carouselUrl: "GenericCarousel.qml"
23+ property url filtergridUrl: "GenericFilterGrid.qml"
24+
25+ source: model.count > 6 ? carouselUrl : filtergridUrl // FIXME do not hardcode 6, but retrieve correct minimum required count
26+
27+ onLoaded: {
28+ item.model = Qt.binding(function() { return model; })
2529 }
2630}
Dash/Generic/GenericFilterGrid.qml+4−4
@@ -28,8 +28,8 @@ FilterGrid {
2828 property int iconWidth: units.gu(8)
2929 property int iconHeight: units.gu(7.5)
3030
31− signal clicked(int index, var model, real itemY)
32− signal pressAndHold(int index, var model, real itemY)
31+ signal clicked(int index, real itemY)
32+ signal pressAndHold(int index, real itemY)
3333
3434 delegate: Tile {
3535 id: tile
@@ -42,11 +42,11 @@ FilterGrid {
4242 source: model.icon
4343
4444 onClicked: {
45− filtergrid.clicked(index, filtergrid.model, tile.y)
45+ filtergrid.clicked(index, tile.y)
4646 }
4747
4848 onPressAndHold: {
49− filtergrid.pressAndHold(index, filtergrid.model, tile.y)
49+ filtergrid.pressAndHold(index, tile.y)
5050 }
5151 }
5252}
Dash/Generic/WeatherFilterGrid.qml+2−2
@@ -37,11 +37,11 @@ GenericFilterGrid {
3737 style: FlatTileStyle {}
3838
3939 onClicked: {
40− filtergrid.clicked(index, filtergrid.model, tile.y)
40+ filtergrid.clicked(index, tile.y)
4141 }
4242
4343 onPressAndHold: {
44− filtergrid.pressAndHold(index, filtergrid.model, tile.y)
44+ filtergrid.pressAndHold(index, tile.y)
4545 }
4646 }
4747}
Dash/GenericScopeView.qml+73−19
@@ -16,15 +16,60 @@
1616
1717import QtQuick 2.0
1818import Ubuntu.Components 0.1
19+import Utils 0.1
20+import Unity 0.1
1921import "../Components"
2022import "../Components/ListItems" as ListItems
2123
22−ScopeView {
24+FocusScope {
2325 id: scopeView
26+
27+ property Scope scope
28+ property SortFilterProxyModel categories: categoryFilter
29+ property bool isCurrent
30+ property ListModel searchHistory
31+ property alias moving: categoryView.moving
32+
33+ signal endReached
34+ signal movementStarted
35+ signal positionedAtBeginning
36+
2437 readonly property alias previewShown: previewListView.onScreen
2538 property bool enableHeightBehaviorOnNextCreation: false
2639
27− moving: categoryView.moving
40+ // FIXME delay the search so that daemons have time to settle, note that
41+ // removing this will break ScopeView::test_changeScope
42+ onScopeChanged: {
43+ if (scope) {
44+ timer.restart();
45+ scope.activateApplication.connect(activateApp);
46+ }
47+ }
48+
49+ function activateApp(desktopFilePath) {
50+ shell.activateApplication(desktopFilePath);
51+ }
52+
53+ Binding {
54+ target: scope
55+ property: "isActive"
56+ value: isCurrent
57+ }
58+
59+ Timer {
60+ id: timer
61+ interval: 2000
62+ onTriggered: scope.searchQuery = ""
63+ }
64+
65+ SortFilterProxyModel {
66+ id: categoryFilter
67+ model: scope ? scope.categories : null
68+ dynamicSortFilter: true
69+ filterRole: Categories.RoleCount
70+ filterRegExp: /^0$/
71+ invertMatch: true
72+ }
2873
2974 onIsCurrentChanged: {
3075 pageHeader.resetSearch();
@@ -130,14 +175,14 @@ ScopeView {
130175 target: rendererLoader.item
131176 onClicked: {
132177 // Prepare the preview in case activate() triggers a preview only
133− effect.positionPx = mapToItem(categoryView, 0, itemY).y
178+ effect.positionPx = Math.max(mapToItem(categoryView, 0, itemY).y, pageHeader.height + categoryView.stickyHeaderHeight);
134179 previewListView.categoryId = categoryId
135180 previewListView.categoryDelegate = rendererLoader.item
136− previewListView.model = model;
181+ previewListView.model = target.model;
137182 previewListView.init = true;
138183 previewListView.currentIndex = index;
139184
140− var item = model.get(index);
185+ var item = target.model.get(index);
141186
142187 if ((scopeView.scope.id == "applications.scope" && categoryId == "installed")
143188 || (scopeView.scope.id == "home.scope" && categoryId == "applications.scope")) {
@@ -151,15 +196,15 @@ ScopeView {
151196 }
152197 }
153198 onPressAndHold: {
154− effect.positionPx = mapToItem(categoryView, 0, itemY).y
199+ effect.positionPx = Math.max(mapToItem(categoryView, 0, itemY).y, pageHeader.height + categoryView.stickyHeaderHeight);
155200 previewListView.categoryId = categoryId
156201 previewListView.categoryDelegate = rendererLoader.item
157− previewListView.model = model;
202+ previewListView.model = target.model;
158203 previewListView.init = true;
159204 previewListView.currentIndex = index;
160205 previewListView.open = true
161206
162− var item = model.get(index)
207+ var item = target.model.get(index)
163208 scopeView.scope.preview( item.uri, item.icon, item.category, 0, item.mimetype, item.title,
164209 item.comment, item.dndUri, item.metadata)
165210 }
@@ -248,6 +293,7 @@ ScopeView {
248293 text: scopeView.scope.name
249294 searchEntryEnabled: true
250295 scope: scopeView.scope
296+ searchHistory: scopeView.searchHistory
251297 }
252298 }
253299
@@ -262,26 +308,27 @@ ScopeView {
262308 rendererId = getDefaultRendererId(contentType);
263309 }
264310 switch (rendererId) {
311+ case "carousel": {
312+ switch (contentType) {
313+ case "music": return "Music/MusicCarouselLoader.qml";
314+ case "video": return "Video/VideoCarouselLoader.qml";
315+ default: return "Generic/GenericCarouselLoader.qml";
316+ }
317+ }
265318 case "grid": {
266319 switch (contentType) {
267− case "video": return "Video/VideoFilterGrid.qml";
268− case "music": return "Music/MusicFilterGrid.qml";
269320 case "apps": {
270321 if (rendererHint == "toggled")
271322 return "Apps/DashPluginFilterGrid.qml";
272323 else
273324 return "Generic/GenericFilterGrid.qml";
274325 }
326+ case "music": return "Music/MusicFilterGrid.qml";
327+ case "video": return "Video/VideoFilterGrid.qml";
275328 case "weather": return "Generic/WeatherFilterGrid.qml";
276329 default: return "Generic/GenericFilterGrid.qml";
277330 }
278331 }
279− case "carousel": {
280− switch (contentType) {
281− case "music": return "Music/MusicCarousel.qml";
282− default: return "Generic/GenericCarousel.qml";
283− }
284− }
285332 case "special": {
286333 switch (contentType) {
287334 case "apps": return "Apps/RunningApplicationsGrid.qml";
@@ -392,12 +439,19 @@ ScopeView {
392439
393440 if (!init && model !== undefined) {
394441 var item = model.get(currentIndex)
395− scopeView.scope.preview( item.uri, item.icon, item.category, 0, item.mimetype, item.title, item.comment, item.dndUri, item.metadata)
442+ scopeView.scope.preview(item.uri, item.icon, item.category, 0, item.mimetype, item.title, item.comment, item.dndUri, item.metadata)
396443 }
397444
398445 var itemY = categoryView.contentItem.mapFromItem(categoryDelegate.currentItem).y;
446+
447+ // Find new contentY and effect.postionPx
399448 var newContentY = itemY - effect.positionPx - categoryDelegate.verticalSpacing;
400− var effectAdjust = effect.positionPx;
449+
450+ // Make sure the item is not covered by a header. Move the effect split down if necessary
451+ var headerHeight = pageHeader.height + categoryView.stickyHeaderHeight;
452+ var effectAdjust = Math.max(effect.positionPx, headerHeight);
453+
454+ // Make sure we don't overscroll the listview. If yes, adjust effect position
401455 if (newContentY < 0) {
402456 effectAdjust += newContentY;
403457 newContentY = 0;
@@ -408,7 +462,7 @@ ScopeView {
408462 }
409463
410464 effect.positionPx = effectAdjust;
411− categoryView.contentY = newContentY - categoryView.originY;
465+ categoryView.contentY = newContentY;
412466 }
413467
414468 property bool open: false
tests/mocks/QMenuModel/UnityMenuModel.qml → Dash/Music/MusicCarouselLoader.qmlrenamed+5−7
@@ -1,9 +1,6 @@
11/*
22 * Copyright (C) 2013 Canonical, Ltd.
33 *
4− * Authors:
5− * Mirco Müller <mirco.mueller@canonical.com>
6− *
74 * This program is free software; you can redistribute it and/or modify
85 * it under the terms of the GNU General Public License as published by
96 * the Free Software Foundation; version 3.
@@ -18,9 +15,10 @@
1815 */
1916
2017import QtQuick 2.0
18+import Ubuntu.Components 0.1
19+import "../Generic"
2120
22−QtObject {
23− property variant busName
24− property variant actions
25− property variant menuObjectPath
21+GenericCarouselLoader {
22+ carouselUrl: "MusicCarousel.qml"
23+ filtergridUrl: "MusicFilterGrid.qml"
2624}
Dash/Music/MusicFilterGrid.qml+2−2
@@ -44,11 +44,11 @@ GenericFilterGrid {
4444 }
4545
4646 onClicked: {
47− filtergrid.clicked(index, filtergrid.model, tile.y)
47+ filtergrid.clicked(index, tile.y)
4848 }
4949
5050 onPressAndHold: {
51− filtergrid.pressAndHold(index, filtergrid.model, tile.y)
51+ filtergrid.pressAndHold(index, tile.y)
5252 }
5353 }
5454}
Dash/ScopeView.qmldeleted−65
@@ -1,65 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.0
18−import Utils 0.1
19−import Unity 0.1
20−
21−FocusScope {
22− property Scope scope
23− property SortFilterProxyModel categories: categoryFilter
24− property bool isCurrent
25− property ListModel searchHistory
26− property bool moving: false
27−
28− signal endReached
29− signal movementStarted
30− signal positionedAtBeginning
31−
32− // FIXME delay the search so that daemons have time to settle, note that
33− // removing this will break ScopeView::test_changeScope
34− onScopeChanged: {
35− if (scope) {
36− timer.restart();
37− scope.activateApplication.connect(activateApp);
38− }
39− }
40−
41− function activateApp(desktopFilePath) {
42− shell.activateApplication(desktopFilePath);
43− }
44−
45− Binding {
46− target: scope
47− property: "isActive"
48− value: isCurrent
49− }
50−
51− Timer {
52− id: timer
53− interval: 2000
54− onTriggered: scope.searchQuery = ""
55− }
56−
57− SortFilterProxyModel {
58− id: categoryFilter
59− model: scope ? scope.categories : null
60− dynamicSortFilter: true
61− filterRole: Categories.RoleCount
62− filterRegExp: /^0$/
63− invertMatch: true
64− }
65−}
Dash/Video/VideosCarousel.qml → Dash/Video/VideoCarousel.qmlrenamed

The content is the same.

plugins/Unity/abstractfilteroption.cpp → Dash/Video/VideoCarouselLoader.qmlrenamed+6−7
@@ -1,9 +1,6 @@
11/*
22 * Copyright (C) 2013 Canonical, Ltd.
33 *
4− * Authors:
5− * Pawel Stolowski <pawel.stolowski@canonical.com>
6− *
74 * This program is free software; you can redistribute it and/or modify
85 * it under the terms of the GNU General Public License as published by
96 * the Free Software Foundation; version 3.
@@ -17,9 +14,11 @@
1714 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1815 */
1916
20−#include "abstractfilteroption.h"
17+import QtQuick 2.0
18+import Ubuntu.Components 0.1
19+import "../Generic"
2120
22−AbstractFilterOption::AbstractFilterOption(QObject *parent)
23− : QObject(parent)
24−{
21+GenericCarouselLoader {
22+ carouselUrl: "VideoCarousel.qml"
23+ filtergridUrl: "VideoFilterGrid.qml"
2524}
Dash/Video/VideoFilterGrid.qml+2−2
@@ -42,11 +42,11 @@ GenericFilterGrid {
4242 style: VideoTileStyle {}
4343
4444 onClicked: {
45− filtergrid.clicked(index, filtergrid.model, tile.y)
45+ filtergrid.clicked(index, tile.y)
4646 }
4747
4848 onPressAndHold: {
49− filtergrid.pressAndHold(index, filtergrid.model, tile.y)
49+ filtergrid.pressAndHold(index, tile.y)
5050 }
5151 }
5252}
Dash/Video/VideoInfo.qmldeleted−84
@@ -1,84 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.0
18−import QtQuick.XmlListModel 2.0
19−
20−Item {
21− id: info
22− property string source
23−
24− property bool ready: nfo.status == XmlListModel.Ready || nfoTV.status == XmlListModel.Ready
25− property bool isMovie: true
26− property variant video: null
27− property variant tvShow: null
28−
29− function getActors() {
30− var c = []
31− if (video.actor1) c.push(video.actor1)
32− if (video.actor2) c.push(video.actor2)
33− if (video.actor3) c.push(video.actor3)
34− return c
35− }
36−
37− onSourceChanged: isMovie = true
38−
39− XmlListModel {
40− id: nfo
41− source: info.source
42− query: (isMovie) ? "/movie" : "/episodedetails"
43−
44− XmlRole { name: "title"; query: "title/string()" }
45− XmlRole { name: "year"; query: "year/number()" }
46− XmlRole { name: "runtime"; query: "runtime/number()" }
47− XmlRole { name: "rating"; query: "rating/number()" }
48− XmlRole { name: "plot"; query: "plot/string()" }
49− XmlRole { name: "director"; query: "director[1]/string()" }
50− XmlRole { name: "actor1"; query: "actor[1]/name/string()" }
51− XmlRole { name: "actor2"; query: "actor[2]/name/string()" }
52− XmlRole { name: "actor3"; query: "actor[3]/name/string()" }
53− XmlRole { name: "author"; query: "author[1]/string()" }
54− XmlRole { name: "season"; query: "season/number()" }
55− XmlRole { name: "episode"; query: "episode/number()" }
56−
57− XmlRole { name: "rentPrice"; query: "rent_price/string()" }
58− XmlRole { name: "buyPrice"; query: "buy_price/string()" }
59− XmlRole { name: "expires"; query: "expires/string()" }
60−
61− onStatusChanged: if (status == XmlListModel.Ready) {
62− if (count > 0) info.video = nfo.get(0)
63− else info.isMovie = false
64− } else if (status == XmlListModel.Error) info.isMovie = false
65− }
66−
67− XmlListModel {
68− id: nfoTV
69− source: (nfo.isMovie) ? "" : info.source.substring(0, info.source.lastIndexOf("/") + 1) + "tvshow.nfo"
70− query: "/tvshow"
71−
72− XmlRole { name: "title"; query: "title/string()" }
73−
74− onStatusChanged: if (status == XmlListModel.Ready) {
75− if (count > 0) info.tvShow = nfoTV.get(0)
76− } else if (status == XmlListModel.Error) {
77− // Search for tvshow.nfo in the directory above this one to cater
78− // for directory layout Show/Season
79− var path = info.source.split("/")
80− path.splice(-2, 2, "tvshow.nfo")
81− source = path.join("/")
82− }
83− }
84−}
Greeter/Greeter.qml+4−7
@@ -19,7 +19,6 @@ import Ubuntu.Components 0.1
1919import Ubuntu.Gestures 0.1
2020import LightDM 0.1 as LightDM
2121import "../Components"
22−import "../Components/Math.js" as MathLocal
2322
2423Showable {
2524 id: greeter
@@ -29,7 +28,7 @@ Showable {
2928 property url defaultBackground
3029
3130 // 1 when fully shown and 0 when fully hidden
32− property real showProgress: MathLocal.clamp((width + x) / width, 0, 1)
31+ property real showProgress: MathUtils.clamp((width + x) / width, 0, 1)
3332
3433 showAnimation: StandardAnimation { property: "x"; to: 0 }
3534 hideAnimation: StandardAnimation { property: "x"; to: -width }
@@ -64,6 +63,7 @@ Showable {
6463 property var model: LightDM.Users
6564 property int currentIndex: 0
6665 property var infographicModel: LightDM.Infographic
66+ readonly property int backgroundTopMargin: -greeter.y
6767
6868 source: required ? "GreeterContent.qml" : ""
6969
@@ -89,7 +89,7 @@ Showable {
8989 when: teasingTimer.running
9090 PropertyChanges {
9191 target: greeter
92− x: -units.gu(2)
92+ x: -dragHandle.hintDisplacement
9393 }
9494 }
9595 ]
@@ -113,10 +113,7 @@ Showable {
113113 anchors.bottom: parent.bottom
114114 anchors.right: parent.right
115115
116− // no need for requiring a directional drag since we are covering the screen
117− // anyway (i.e., no change user could be trying to interact with some other
118− // UI element)
119− distanceThreshold: 0
116+ hintDisplacement: units.gu(2)
120117
121118 enabled: greeter.narrowMode || !greeter.locked
122119
Greeter/GreeterContent.qml+23−20
@@ -24,7 +24,7 @@ MouseArea {
2424 id: root
2525 anchors.fill: parent
2626
27− property bool ready: wallpaper.source == "" || wallpaper.status == Image.Ready || wallpaper.status == Image.Error
27+ property bool ready: background.source == "" || background.status == Image.Ready || background.status == Image.Error
2828 property bool leftTeaserPressed: teasingMouseArea.pressed &&
2929 teasingMouseArea.mouseX < teasingMouseArea.width / 2
3030 property bool rightTeaserPressed: teasingMouseArea.pressed &&
@@ -34,33 +34,36 @@ MouseArea {
3434 signal unlocked(int uid)
3535
3636 Rectangle {
37− // In case wallpaper fails to load
38− id: wallpaperBackup
37+ // In case background fails to load
38+ id: backgroundBackup
3939 anchors.fill: parent
4040 color: "black"
4141 }
4242
4343 property url backgroundValue: AccountsService.backgroundFile != undefined && AccountsService.backgroundFile.length > 0 ? AccountsService.backgroundFile : greeter.defaultBackground
44− onBackgroundValueChanged: wallpaper.source = backgroundValue
44+ onBackgroundValueChanged: background.source = backgroundValue
4545
4646 CrossFadeImage {
47− id: wallpaper
48− objectName: "wallpaper"
49− anchors.fill: parent
47+ id: background
48+ objectName: "greeterBackground"
49+ anchors {
50+ fill: parent
51+ topMargin: backgroundTopMargin
52+ }
5053 fillMode: Image.PreserveAspectCrop
5154 }
5255
5356 // See Shell.qml's backgroundSettings treatment for why we need a separate
5457 // Image, but it boils down to avoiding binding loop detection.
5558 Image {
56− source: wallpaper.source
59+ source: background.source
5760 height: 0
5861 width: 0
5962 sourceSize.height: 0
6063 sourceSize.width: 0
6164 onStatusChanged: {
6265 if (status == Image.Error && source != greeter.defaultBackground) {
63− wallpaper.source = greeter.defaultBackground
66+ background.source = greeter.defaultBackground
6467 }
6568 }
6669 }
@@ -71,17 +74,6 @@ MouseArea {
7174 opacity: 0.4
7275 }
7376
74− Clock {
75− id: clock
76− visible: narrowMode
77−
78− anchors {
79− top: parent.top
80− topMargin: units.gu(2)
81− horizontalCenter: parent.horizontalCenter
82− }
83− }
84−
8577 MouseArea {
8678 id: teasingMouseArea
8779 anchors.fill: parent
@@ -160,4 +152,15 @@ MouseArea {
160152 right: root.right
161153 }
162154 }
155+
156+ Clock {
157+ id: clock
158+ visible: narrowMode
159+
160+ anchors {
161+ top: parent.top
162+ topMargin: units.gu(2)
163+ horizontalCenter: parent.horizontalCenter
164+ }
165+ }
163166}
Greeter/Lockscreen.qml+14−22
@@ -17,7 +17,6 @@
1717import QtQuick 2.0
1818import Ubuntu.Components 0.1
1919import "../Components"
20−import LightDM 0.1 as LightDM
2120
2221Showable {
2322 id: root
@@ -37,7 +36,7 @@ Showable {
3736
3837 property url background: ""
3938
40− signal unlocked()
39+ signal entered(string passphrase)
4140 signal cancel()
4241 signal emergencyCall()
4342
@@ -53,16 +52,24 @@ Showable {
5352 pinPadLoader.resetting = false;
5453 }
5554
55+ function clear(showAnimation) {
56+ pinPadLoader.item.clear(showAnimation);
57+ }
58+
5659 Rectangle {
57− // In case wallpaper fails to load or is undefined
58− id: wallpaperBackup
60+ // In case background fails to load or is undefined
61+ id: backgroundBackup
5962 anchors.fill: parent
6063 color: "black"
6164 }
6265
6366 Image {
64− id: wallpaper
65− anchors.fill: parent
67+ id: backgroundImage
68+ objectName: "lockscreenBackground"
69+ anchors {
70+ fill: parent
71+ topMargin: backgroundTopMargin
72+ }
6673 source: root.required ? root.background : ""
6774 fillMode: Image.PreserveAspectCrop
6875 }
@@ -88,7 +95,7 @@ Showable {
8895 target: pinPadLoader.item
8996
9097 onEntered: {
91− LightDM.Greeter.respond(passphrase);
98+ root.entered(passphrase);
9299 }
93100
94101 onCancel: {
@@ -146,19 +153,4 @@ Showable {
146153 anchors.horizontalCenter: parent.horizontalCenter
147154 }
148155 }
149−
150− Connections {
151− target: LightDM.Greeter
152−
153− onAuthenticationComplete: {
154− if (LightDM.Greeter.promptless) {
155− return;
156− }
157− if (LightDM.Greeter.authenticated) {
158− root.unlocked();
159− } else {
160− pinPadLoader.item.clear(true);
161− }
162− }
163− }
164156}
Greeter/PassphraseLockscreen.qml+1
@@ -82,6 +82,7 @@ Item {
8282
8383 WrongPasswordAnimation {
8484 id: wrongPasswordAnimation
85+ objectName: "wrongPasswordAnimation"
8586 target: pinentryField
8687 }
8788}
Greeter/PinLockscreen.qml+35−4
@@ -27,7 +27,7 @@ Column {
2727 property alias placeholderText: pinentryField.placeholderText
2828 property int padWidth: units.gu(34)
2929 property int padHeight: units.gu(28)
30− property int pinLength: 4
30+ property int pinLength: -1
3131
3232 signal entered(string passphrase)
3333 signal cancel()
@@ -65,6 +65,9 @@ Column {
6565 Label {
6666 id: pinentryFieldLabel
6767 anchors.centerIn: parent
68+ width: parent.width - (backspaceIcon.width + backspaceIcon.anchors.rightMargin) * 2
69+ elide: Text.ElideMiddle
70+ horizontalAlignment: Text.AlignHCenter
6871 font.pixelSize: units.dp(44)
6972 color: "#f3f3e7"
7073 opacity: 0.6
@@ -76,6 +79,26 @@ Column {
7679 text: parent.placeholderText
7780 visible: pinentryFieldLabel.text.length == 0
7881 }
82+
83+ Icon {
84+ id: backspaceIcon
85+ objectName: "backspaceIcon"
86+ anchors {
87+ top: parent.top
88+ topMargin: units.gu(1)
89+ right: parent.right
90+ rightMargin: units.gu(2)
91+ bottom: parent.bottom
92+ bottomMargin: units.gu(1)
93+ }
94+ visible: root.pinLength == -1
95+ width: height
96+ name: "erase"
97+ MouseArea {
98+ anchors.fill: parent
99+ onClicked: pinentryField.text = pinentryField.text.substring(0, pinentryField.text.length-1);
100+ }
101+ }
79102 }
80103
81104 UbuntuShape {
@@ -154,7 +177,7 @@ Column {
154177 objectName: "pinPadButtonBack"
155178 width: root.padWidth / 3
156179 height: root.padHeight / 4
157− iconName: "back"
180+ subText: "CANCEL"
158181 onClicked: root.cancel();
159182 }
160183
@@ -171,8 +194,15 @@ Column {
171194 objectName: "pinPadButtonErase"
172195 width: root.padWidth / 3
173196 height: root.padHeight / 4
174− iconName: "erase"
175− onClicked: pinentryField.text = pinentryField.text.substring(0, pinentryField.text.length-1)
197+ iconName: root.pinLength == -1 ? "" : "erase"
198+ subText: root.pinLength == -1 ? "DONE" : ""
199+ onClicked: {
200+ if (root.pinLength !== -1) {
201+ pinentryField.text = pinentryField.text.substring(0, pinentryField.text.length-1);
202+ } else {
203+ root.entered(pinentryField.text);
204+ }
205+ }
176206 enabled: entryEnabled
177207 }
178208 }
@@ -180,6 +210,7 @@ Column {
180210
181211 WrongPasswordAnimation {
182212 id: wrongPasswordAnimation
213+ objectName: "wrongPasswordAnimation"
183214 target: pinentryField
184215 }
185216}
Launcher/Launcher.qml+1−1
@@ -29,7 +29,7 @@ Item {
2929 property int panelWidth: units.gu(8)
3030 property int dragAreaWidth: units.gu(1)
3131 property int minimizeDistance: units.gu(26)
32− property real progress: dragArea.dragging && dragArea.touchX > panelWidth ?
32+ property real progress: dragArea.dragging && dragArea.touchX > panelWidth ?
3333 (width * (dragArea.touchX-panelWidth) / (width - panelWidth)) : 0
3434
3535 readonly property bool shown: panel.x > -panel.width
Launcher/LauncherDelegate.qml+1
@@ -57,6 +57,7 @@ Item {
5757 anchors.fill: parent
5858 anchors.margins: units.gu(1)
5959 radius: "medium"
60+ borderSource: "none"
6061
6162 image: Image {
6263 id: iconImage
Launcher/LauncherPanel.qml+1−1
@@ -367,7 +367,7 @@ Item {
367367 var yOffset = draggedIndex > 0 ? (mouseY + launcherListView.realContentY) % (draggedIndex * launcherListView.realItemHeight) : mouseY + launcherListView.realContentY
368368
369369 fakeDragItem.iconName = launcherListView.model.get(draggedIndex).icon
370− fakeDragItem.x = 0
370+ fakeDragItem.x = units.gu(0.5)
371371 fakeDragItem.y = mouseY - yOffset + launcherListView.anchors.topMargin + launcherListView.topMargin
372372 fakeDragItem.angle = selectedItem.angle * (root.inverted ? -1 : 1)
373373 fakeDragItem.offset = selectedItem.offset * (root.inverted ? -1 : 1)
Notifications/Notification.qml+3−7
@@ -23,7 +23,7 @@ import Utils 0.1
2323UbuntuShape {
2424 id: notification
2525
26− property alias iconSource: avatarIcon.source
26+ property alias iconSource: icon.fileSource
2727 property alias secondaryIconSource: secondaryIcon.source
2828 property alias summary: summaryLabel.text
2929 property alias body: bodyLabel.text
@@ -102,18 +102,14 @@ UbuntuShape {
102102 right: parent.right
103103 }
104104
105− UbuntuShape {
105+ ShapedIcon {
106106 id: icon
107107
108108 objectName: "icon"
109109 width: units.gu(6)
110110 height: units.gu(6)
111+ shaped: notification.hints["x-canonical-non-shaped-icon"] == "true" ? false : true
111112 visible: iconSource !== undefined && iconSource != ""
112− image: Image {
113− id: avatarIcon
114−
115− fillMode: Image.PreserveAspectCrop
116− }
117113 }
118114
119115 Image {
Notifications/NotificationMenuItemFactory.qml+20−6
@@ -54,7 +54,8 @@ Loader {
5454
5555 Component.onCompleted: {
5656 menuModel.loadExtendedAttributes(menuIndex, {"x-echo-mode-password": "bool"});
57− textfield.echoMode = menuData.ext.xEchoModePassword ? TextInput.Password : TextInput.Normal
57+ checkBox.checked = menuData.ext.xEchoModePassword ? false : true
58+ checkBoxRow.visible = menuData.ext.xEchoModePassword
5859 }
5960
6061 Label {
@@ -65,11 +66,29 @@ Loader {
6566 id: textfield
6667
6768 anchors.left: parent.left; anchors.right: parent.right
69+ echoMode: checkBox.checked ? TextInput.Normal : TextInput.Password
6870 height: units.gu(5)
6971 onTextChanged: {
7072 menuModel.changeState(menuIndex, text);
7173 }
7274 }
75+
76+ Row {
77+ id: checkBoxRow
78+
79+ spacing: units.gu(.5)
80+
81+ CheckBox {
82+ id: checkBox
83+
84+ checked: false
85+ }
86+
87+ Label {
88+ anchors.verticalCenter: checkBox.verticalCenter
89+ text: i18n.tr("Show password")
90+ }
91+ }
7392 }
7493 }
7594
@@ -78,11 +97,6 @@ Loader {
7897 PinLockscreen {
7998 anchors.left: parent.left; anchors.right: parent.right
8099
81− Component.onCompleted: {
82− menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-pin-length': 'int'});
83− pinLength = menuData.ext.xCanonicalPinLength;
84− }
85−
86100 onEntered: {
87101 menuModel.changeState(menuIndex, passphrase);
88102 entryEnabled = false;
plugins/Unity/ratingoptionsmodel.cpp → Notifications/ShapedIcon.qmlrenamed+20−13
@@ -1,9 +1,6 @@
11/*
22 * Copyright (C) 2013 Canonical, Ltd.
33 *
4− * Authors:
5− * Pawel Stolowski <pawel.stolowski@canonical.com>
6− *
74 * This program is free software; you can redistribute it and/or modify
85 * it under the terms of the GNU General Public License as published by
96 * the Free Software Foundation; version 3.
@@ -17,17 +14,27 @@
1714 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1815 */
1916
20−// self
21−#include "ratingoptionsmodel.h"
17+import QtQuick 2.0
18+import Ubuntu.Components 0.1
19+
20+Item {
21+ property string fileSource
22+ property bool shaped
23+
24+ UbuntuShape {
25+ objectName: "shapedIcon"
26+ anchors.fill: parent
27+ visible: shaped
28+ image: realImage
29+ }
2230
23−// local
24−#include "ratingfilteroption.h"
31+ Image {
32+ id: realImage
2533
26−RatingOptionsModel::RatingOptionsModel(bool showAllOption, QObject *parent) :
27− GenericOptionsModel(showAllOption, parent)
28−{
29− for (int i=1; i<=5; i++) {
30− auto opt = new RatingFilterOption(QString::number(i), i*0.2f, this);
31− addOption(opt);
34+ objectName: "nonShapedIcon"
35+ anchors.fill: parent
36+ visible: !shaped
37+ source: fileSource
38+ fillMode: Image.PreserveAspectCrop
3239 }
3340}
Panel/Indicators.qml+37−10
@@ -21,7 +21,6 @@ import Unity.Indicators 0.1 as Indicators
2121
2222import "../Components"
2323import "../Components/ListItems"
24−import "../Components/Math.js" as MathLocal
2524
2625Showable {
2726 id: indicators
@@ -38,6 +37,7 @@ Showable {
3837 property bool partiallyOpened: height > panelHeight && !fullyOpened
3938 property real visualBottom: Math.max(y+height, y+indicatorRow.y+indicatorRow.height)
4039 property bool contentEnabled: true
40+ property bool initalizeItem: true
4141 readonly property alias content: menuContent
4242
4343 // TODO: Perhaps we need a animation standard for showing/hiding? Each showable seems to
@@ -64,14 +64,13 @@ Showable {
6464 }
6565
6666 height: panelHeight
67+ onHeightChanged: updateRevealProgressState(indicators.height - panelHeight, true)
6768
68− onHeightChanged: {
69− // need to use handle.get_height(). As the handle height depends on indicators.height changes (but this is called first!)
70− var revealProgress = indicators.height - panelHeight
69+ function updateRevealProgressState(revealProgress, enableRelease) {
7170 if (!showAnimation.running && !hideAnimation.running) {
72− if (revealProgress == 0) {
71+ if (revealProgress === 0) {
7372 indicators.state = "initial";
74− } else if (revealProgress <= hintValue) {
73+ } else if (revealProgress > 0 && revealProgress <= hintValue) {
7574 indicators.state = "hint";
7675 } else if (revealProgress > hintValue && revealProgress < lockThreshold) {
7776 indicators.state = "reveal";
@@ -80,7 +79,7 @@ Showable {
8079 }
8180 }
8281
83− if (revealProgress == 0) {
82+ if (enableRelease && revealProgress === 0) {
8483 menuContent.releaseContent();
8584 }
8685 }
@@ -100,14 +99,14 @@ Showable {
10099 Otherwise it contains the bar's location as a fraction of the distance between hintValue (is 0) and lockThreshold (is 1).
101100 */
102101 var verticalProgress =
103− MathLocal.clamp((indicators.height - handle.height - hintValue) /
102+ MathUtils.clamp((indicators.height - handle.height - hintValue) /
104103 (lockThreshold - hintValue), 0, 1);
105104
106105 /*
107106 Vertical velocity check. Don't change the indicator if we're moving too quickly.
108107 */
109108 var verticalSpeed = Math.abs(yVelocityCalculator.calculate());
110− if (verticalSpeed >= 0.05 && indicatorRow.currentItem!=null) {
109+ if (verticalSpeed >= 0.05 && !initalizeItem) {
111110 return;
112111 }
113112
@@ -147,6 +146,7 @@ Showable {
147146 } else if (!currentItem) {
148147 indicatorRow.setDefaultItem();
149148 }
149+ initalizeItem = indicatorRow.currentItem == null;
150150 }
151151
152152 // eater
@@ -282,6 +282,33 @@ Showable {
282282 enableIndexChangeSignal = oldActive;
283283 }
284284 }
285+
286+ EdgeDragArea {
287+ id: rowDragArea
288+ anchors.fill: indicatorRow
289+ direction: Direction.Downwards
290+ maxSilenceTime: 2000
291+ distanceThreshold: 0
292+
293+ enabled: fullyOpened
294+ onDraggingChanged: {
295+ if (dragging) {
296+ initalizeItem = true;
297+ updateRevealProgressState(Math.max(touchSceneY - panelHeight, hintValue), false);
298+ indicators.calculateCurrentItem(touchX, false);
299+ } else {
300+ indicators.state = "commit";
301+ }
302+ }
303+
304+ onTouchXChanged: {
305+ indicators.calculateCurrentItem(touchX, true);
306+ }
307+ onTouchSceneYChanged: {
308+ updateRevealProgressState(Math.max(touchSceneY - panelHeight, hintValue), false);
309+ yVelocityCalculator.trackedPosition = touchSceneY;
310+ }
311+ }
285312 }
286313
287314 Connections {
@@ -298,7 +325,7 @@ Showable {
298325 onRunningChanged: {
299326 if (hideAnimation.running) {
300327 indicators.state = "initial";
301− indicatorRow.currentItem = null;
328+ initalizeItem = true;
302329 }
303330 }
304331 }
Panel/Indicators/DefaultIndicatorWidget.qml+32−10
@@ -24,7 +24,7 @@ import Unity.Indicators 0.1 as Indicators
2424Indicators.IndicatorWidget {
2525 id: indicatorWidget
2626
27− width: itemRow.width + units.gu(0.5)
27+ width: itemRow.width
2828
2929 property alias leftLabel: itemLeftLabel.text
3030 property alias rightLabel: itemRightLabel.text
@@ -32,16 +32,17 @@ Indicators.IndicatorWidget {
3232
3333 Row {
3434 id: itemRow
35+ width: childrenRect.width
3536 objectName: "itemRow"
3637 anchors {
3738 top: parent.top
3839 bottom: parent.bottom
3940 horizontalCenter: parent.horizontalCenter
4041 }
41− spacing: units.gu(0.5)
4242
4343 Label {
4444 id: itemLeftLabel
45+ width: guRoundUp(implicitWidth)
4546 objectName: "leftLabel"
4647 color: Theme.palette.selected.backgroundText
4748 opacity: 0.8
@@ -57,25 +58,35 @@ Indicators.IndicatorWidget {
5758 top: parent.top
5859 bottom: parent.bottom
5960 }
60− spacing: units.gu(0.5)
6161
6262 Repeater {
6363 model: indicatorWidget.icons
6464
65− Image {
66− id: itemImage
67− objectName: "itemImage"
68− visible: source != ""
69− source: modelData
65+ Item {
66+ width: guRoundUp(itemImage.width)
7067 height: indicatorWidget.iconSize
71− width: indicatorWidget.iconSize
72− anchors.verticalCenter: parent.verticalCenter
68+
69+ Image {
70+ id: itemImage
71+ objectName: "itemImage"
72+ visible: source != ""
73+ source: modelData
74+ height: parent.height
75+ anchors.horizontalCenter: parent.horizontalCenter
76+ fillMode: Image.PreserveAspectFit
77+
78+ sourceSize {
79+ width: indicatorWidget.iconSize
80+ height: indicatorWidget.iconSize
81+ }
82+ }
7383 }
7484 }
7585 }
7686
7787 Label {
7888 id: itemRightLabel
89+ width: guRoundUp(implicitWidth)
7990 objectName: "rightLabel"
8091 color: Theme.palette.selected.backgroundText
8192 opacity: 0.8
@@ -86,6 +97,17 @@ Indicators.IndicatorWidget {
8697 }
8798 }
8899
100+ // TODO: Use toolkit function https://bugs.launchpad.net/ubuntu-ui-toolkit/+bug/1242575
101+ function guRoundUp(width) {
102+ if (width == 0) {
103+ return 0;
104+ }
105+ var gu1 = units.gu(1.0);
106+ var mod = (width % gu1);
107+
108+ return mod == 0 ? width : width + (gu1 - mod);
109+ }
110+
89111 onRootActionStateChanged: {
90112 if (rootActionState == undefined) {
91113 leftLabel = "";
Panel/Indicators/client/IndicatorsTree.qml+2−3
@@ -29,10 +29,9 @@ Page {
2929
3030 property string busName: unityModel.busName
3131 property string actionsObjectPath
32− property var menuObjectPaths: undefined
33− readonly property string device: "phone"
32+ property string menuObjectPath
3433
35− property string deviceMenuObjectPath: menuObjectPaths.hasOwnProperty(device) ? menuObjectPaths[device] : ""
34+ property string deviceMenuObjectPath: menuObjectPath
3635
3736 function start() {
3837 }
Shell.qml+21−6
@@ -30,7 +30,6 @@ import "Launcher"
3030import "Panel"
3131import "Hud"
3232import "Components"
33−import "Components/Math.js" as MathLocal
3433import "Bottombar"
3534import "SideStage"
3635import "Notifications"
@@ -62,8 +61,6 @@ FocusScope {
6261 }
6362 }
6463
65− property ListModel searchHistory: SearchHistoryModel {}
66−
6764 property var applicationManager: ApplicationManagerWrapper {}
6865
6966 Binding {
@@ -237,7 +234,7 @@ FocusScope {
237234 Behavior on x {SmoothedAnimation{velocity: 600}}
238235
239236 property real showProgress:
240− MathLocal.clamp(1 - (x + stages.x) / shell.width, 0, 1)
237+ MathUtils.clamp(1 - (x + stages.x) / shell.width, 0, 1)
241238
242239 Showable {
243240 id: stages
@@ -402,6 +399,10 @@ FocusScope {
402399
403400 Lockscreen {
404401 id: lockscreen
402+ objectName: "lockscreen"
403+
404+ readonly property int backgroundTopMargin: -panel.panelHeight
405+
405406 hides: [launcher, panel.indicators, hud]
406407 shown: false
407408 enabled: true
@@ -413,7 +414,7 @@ FocusScope {
413414 height: parent.height - panel.panelHeight
414415 background: shell.background
415416
416− onUnlocked: lockscreen.hide()
417+ onEntered: LightDM.Greeter.respond(passphrase);
417418 onCancel: greeter.show()
418419
419420 Component.onCompleted: {
@@ -439,6 +440,17 @@ FocusScope {
439440 lockscreen.show();
440441 }
441442 }
443+
444+ onAuthenticationComplete: {
445+ if (LightDM.Greeter.promptless) {
446+ return;
447+ }
448+ if (LightDM.Greeter.authenticated) {
449+ lockscreen.hide();
450+ } else {
451+ lockscreen.clear(true);
452+ }
453+ }
442454 }
443455
444456 Greeter {
@@ -647,19 +659,22 @@ FocusScope {
647659 Launcher {
648660 id: launcher
649661
662+ readonly property bool dashSwipe: progress > 0
663+
650664 anchors.top: parent.top
651665 anchors.bottom: parent.bottom
652666 width: parent.width
653667 dragAreaWidth: shell.edgeSize
654668 available: (!greeter.shown || greeter.narrowMode) && edgeDemo.launcherEnabled
669+
655670 onDashItemSelected: showHome()
656671 onDash: {
657672 if (stages.shown) {
658− dash.setCurrentScope("applications.scope", true /* animate */, true /* reset */)
659673 stages.hide();
660674 launcher.hide();
661675 }
662676 }
677+ onDashSwipeChanged: if (dashSwipe && stages.shown) dash.setCurrentScope("applications.scope", false, true)
663678 onLauncherApplicationSelected:{
664679 greeter.hide()
665680 shell.activateApplication(appId)
build+1
@@ -50,6 +50,7 @@ install_dependencies() {
5050 ubuntu-mobile-icons \
5151 unity-scope-home \
5252 unity-lens-applications \
53+ unity-plugin-scopes \
5354 || exit 5
5455}
5556
cmake/modules/Plugins.cmake+3−3
@@ -28,7 +28,7 @@ macro(export_qmlfiles PLUGIN PLUGIN_SUBPATH)
2828
2929 # install the qmlfiles file.
3030 install(FILES ${QMLFILES}
31− DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/${PLUGIN_SUBPATH}
31+ DESTINATION ${SHELL_INSTALL_QML}/${PLUGIN_SUBPATH}
3232 )
3333endmacro(export_qmlfiles)
3434
@@ -56,12 +56,12 @@ macro(export_qmlplugin PLUGIN VERSION PLUGIN_SUBPATH)
5656
5757 # install the qmltypes file.
5858 install(FILES ${CMAKE_BINARY_DIR}/plugins/${PLUGIN_SUBPATH}/plugin.qmltypes
59− DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/${PLUGIN_SUBPATH}
59+ DESTINATION ${SHELL_INSTALL_QML}/${PLUGIN_SUBPATH}
6060 )
6161 endif()
6262
6363 # install the additional targets
6464 install(TARGETS ${qmlplugin_TARGETS}
65− DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/${PLUGIN_SUBPATH}
65+ DESTINATION ${SHELL_INSTALL_QML}/${PLUGIN_SUBPATH}
6666 )
6767endmacro(export_qmlplugin)
cmake/modules/autopilot.cmake+1−1
@@ -2,7 +2,7 @@ add_custom_target(autopilot)
22
33function(declare_autopilot_test TEST_NAME TEST_SUITE WORKING_DIR)
44 add_custom_target(autopilot-${TEST_NAME}
5− COMMAND LANG=C UBUNTU_ICON_THEME=ubuntu-mobile QML2_IMPORT_PATH=${SHELL_PRIVATE_LIBDIR}/qml/mocks autopilot run ${TEST_SUITE}
5+ COMMAND LANG=C UBUNTU_ICON_THEME=ubuntu-mobile QML2_IMPORT_PATH=${SHELL_INSTALL_QML}/mocks autopilot run ${TEST_SUITE}
66 WORKING_DIRECTORY ${WORKING_DIR}
77 DEPENDS install
88 )
data/unity8.conf+20
@@ -6,4 +6,24 @@ stop on desktop-end
66
77respawn
88
9+pre-start script
10+ if [ -n "$MIR_SOCKET" ]; then
11+ if [ -z "$UNITY_MIR_SOCKET" ]; then
12+ # Save original value of MIR_SOCKET in case we are restarted,
13+ # as we modify the variable for future jobs, including ourself.
14+ UNITY_MIR_SOCKET=$MIR_SOCKET
15+ initctl set-env --global UNITY_MIR_SOCKET=$UNITY_MIR_SOCKET
16+ fi
17+
18+ # Point unity8 at unity-system-compositor
19+ MIR_SERVER_FILE=$XDG_RUNTIME_DIR/mir_socket
20+ initctl set-env MIR_SERVER_FILE=$MIR_SERVER_FILE
21+ initctl set-env MIR_SERVER_HOST_SOCKET=$UNITY_MIR_SOCKET
22+
23+ # Point all future jobs in this session to our Mir socket instead of
24+ # unity-system-compositor's socket.
25+ initctl set-env --global MIR_SOCKET=$MIR_SERVER_FILE
26+ fi
27+end script
28+
929exec ${BINARY:-unity8} $ARGS
debian/changelog+72
@@ -1,3 +1,75 @@
1+unity8 (7.84-0ubuntu1) UNRELEASED; urgency=low
2+
3+ * Depend on the separate scopes plugin
4+
5+ -- Michal Hruby <michal.hruby@canonical.com> Wed, 13 Nov 2013 12:43:39 +0000
6+
7+unity8 (7.83+14.04.20131106-0ubuntu1) trusty; urgency=low
8+
9+ [ Andrea Cimitan ]
10+ * Place ShaderEffectSource of UbuntuShapeForItem under the Shape Item.
11+ (LP: #1239317)
12+
13+ [ Omer Akram ]
14+ * test: make sure the search indicator hides when an app has focus.
15+
16+ [ Nick Dedekind ]
17+ * Fixed indicator slider menu item alignment to label field and icon.
18+ (LP: #1240756)
19+
20+ [ chris.gagnon ]
21+ * Update to autopilot 1.4.
22+
23+ [ Ubuntu daily release ]
24+ * Automatic snapshot from revision 500
25+
26+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Wed, 06 Nov 2013 03:37:02 +0000
27+
28+unity8 (7.83+14.04.20131105.1-0ubuntu1) trusty; urgency=low
29+
30+ [ Michał Sawicz ]
31+ * Implement switching between previews by swiping. (LP: #1220651,
32+ #1088572)
33+
34+ [ Nick Dedekind ]
35+ * Faster loading of indicator menus. (LP: #1226650)
36+
37+ [ Albert Astals ]
38+ * Make sure we have ssh started when we need it .
39+ * Fix a few warnings in DashContent.qml on shutdown
40+ Dash/DashContent.qml:119: TypeError: Cannot read property
41+ 'previewShown' of null Dash/DashContent.qml:120: TypeError: Cannot
42+ read property 'moving' of null .
43+ * Don't use deprecated Panel methods.
44+
45+ [ Christopher Lee ]
46+ * Adds an easy to consume function that attempts to unlock the unity
47+ greeter. (LP: #1240261)
48+
49+ [ Lars Uebernickel ]
50+ * Indicators: add TimeFormatter and use it in the messaging menu This
51+ component can be used to turn a timestamp and a format string into a
52+ string with the corresponding time and format. The string will
53+ change whenever the timezone changes. (LP: #1236413)
54+
55+ [ Andrea Cimitan ]
56+ * Allow drag over bounds, but not overshoot. (LP: #1204300)
57+ * Threshold to activate the left edge swipe to reveal dash is now 26
58+ GU. (LP: #1236286)
59+
60+ [ Michael Zanetti ]
61+ * replace the launcher quicklist's Popover with an own quicklist
62+ implementation The Popover probably won't ever support what the
63+ launcher needs.
64+ * Implement switching between previews by swiping. (LP: #1220651,
65+ #1088572)
66+ * don't trigger the greeter teasing during a movement of the greeter.
67+
68+ [ Ubuntu daily release ]
69+ * Automatic snapshot from revision 495
70+
71+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Tue, 05 Nov 2013 12:22:04 +0000
72+
173unity8 (7.83+14.04.20131031-0ubuntu1) trusty; urgency=low
274
375 [ Michał Sawicz ]
debian/control+4−5
@@ -17,10 +17,7 @@ Build-Depends: cmake,
1717 libpulse-dev,
1818 libqmenumodel-dev (>= 0.2.7),
1919 libqt5v8-5-private-dev,
20− libsigc++-2.0-dev,
21− libunity-api-dev (>= 7.80.3),
22− libunity-core-6.0-dev (>= 7.1.1),
23− libunity-dev (>= 7.0.12),
20+ libunity-api-dev (>= 7.80.4),
2421 libunity-mir-dev,
2522 libunity-scopes-json-def-phone,
2623 libupstart-dev,
@@ -78,6 +75,8 @@ Depends: gsettings-desktop-schemas,
7875 unity8-fake-env | qtubuntu-shell,
7976 unity8-private (= ${binary:Version}),
8077 unity8-private | unity-launcher-impl,
78+ unity-plugin-scopes | unity-scopes-impl,
79+ unity-scopes-impl-0,
8180# for setcap:
8281 libcap2-bin,
8382 ${misc:Depends},
@@ -91,7 +90,7 @@ Description: Unity 8 shell
9190Package: unity8-autopilot
9291Architecture: all
9392Depends: gir1.2-glib-2.0,
94− libautopilot-qt,
93+ libautopilot-qt (>= 1.4),
9594 libqt5test5,
9695 libqt5widgets5,
9796 python-evdev,
paths.h.in+4−2
@@ -58,9 +58,11 @@ inline QStringList overrideImportPaths() {
5858inline QStringList fallbackImportPaths() {
5959 QStringList paths;
6060 if (isRunningInstalled()) {
61− paths << QString("@CMAKE_INSTALL_PREFIX@/@SHELL_PRIVATE_LIBDIR@/qml");
62− paths << QString("@CMAKE_INSTALL_PREFIX@/@SHELL_PRIVATE_LIBDIR@/qml/mocks");
61+ paths << QString("@CMAKE_INSTALL_PREFIX@/@SHELL_INSTALL_QML@");
62+ paths << QString("@SHELL_PLUGINDIR@");
63+ paths << QString("@CMAKE_INSTALL_PREFIX@/@SHELL_INSTALL_QML@/mocks");
6364 } else {
65+ paths << QString("@SHELL_PLUGINDIR@");
6466 paths << QString("@CMAKE_BINARY_DIR@/tests/mocks");
6567 }
6668 return paths;
plugins/AccountsService/plugin.cpp+1−1
@@ -20,7 +20,7 @@
2020#include "AccountsService.h"
2121
2222#include <QDBusMetaType>
23−#include <QtQml>
23+#include <QtQml/qqml.h>
2424
2525static QObject *service_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
2626{
plugins/ListViewWithPageHeader/listviewwithpageheader.cpp+32−6
@@ -155,6 +155,7 @@ ListViewWithPageHeader::ListViewWithPageHeader()
155155 , m_topSectionItem(nullptr)
156156 , m_forceNoClip(false)
157157 , m_inLayout(false)
158+ , m_inContentHeightKeepHeaderShown(false)
158159{
159160 m_clipItem = new QQuickItem(contentItem());
160161// m_clipItem = new QQuickRectangle(contentItem());
@@ -286,10 +287,12 @@ void ListViewWithPageHeader::setSectionDelegate(QQmlComponent *delegate)
286287 m_topSectionItem = getSectionItem(QString());
287288 m_topSectionItem->setZ(3);
288289 QQuickItemPrivate::get(m_topSectionItem)->setCulled(true);
290+ connect(m_topSectionItem, SIGNAL(heightChanged()), SIGNAL(stickyHeaderHeightChanged()));
289291
290292 // TODO create sections for existing items
291293
292294 Q_EMIT sectionDelegateChanged();
295+ Q_EMIT stickyHeaderHeightChanged();
293296 }
294297}
295298
@@ -325,6 +328,11 @@ void ListViewWithPageHeader::setForceNoClip(bool noClip)
325328 }
326329}
327330
331+int ListViewWithPageHeader::stickyHeaderHeight() const
332+{
333+ return m_topSectionItem ? m_topSectionItem->height() : 0;
334+}
335+
328336void ListViewWithPageHeader::positionAtBeginning()
329337{
330338 if (m_delegateModel->count() <= 0)
@@ -471,12 +479,18 @@ void ListViewWithPageHeader::componentComplete()
471479
472480void ListViewWithPageHeader::viewportMoved(Qt::Orientations orient)
473481{
482+ // Check we are not being taken down and don't paint anything
483+ // TODO Check if we still need this in 5.2
484+ // For reproduction just inifnite loop testDash or testDashContent
485+ if (!QQmlEngine::contextForObject(this)->parentContext())
486+ return;
487+
474488 QQuickFlickable::viewportMoved(orient);
475489// qDebug() << "ListViewWithPageHeader::viewportMoved" << contentY();
476490 qreal diff = m_previousContentY - contentY();
477491 const bool showHeaderAnimationRunning = m_contentYAnimation->isRunning() && contentYAnimationType == ContentYAnimationShowHeader;
478492 if (m_headerItem) {
479− auto oldHeaderItemShownHeight = m_headerItemShownHeight;
493+ const auto oldHeaderItemShownHeight = m_headerItemShownHeight;
480494 if (contentY() < -m_minYExtent) {
481495 // Stick the header item to the top when dragging down
482496 m_headerItem->setY(contentY());
@@ -491,10 +505,10 @@ void ListViewWithPageHeader::viewportMoved(Qt::Orientations orient)
491505 const bool notShownByItsOwn = contentY() + diff >= m_headerItem->y() + m_headerItem->height();
492506 const bool maximizeVisibleAreaRunning = m_contentYAnimation->isRunning() && contentYAnimationType == ContentYAnimationMaximizeVisibleArea;
493507
494− if (!scrolledUp && contentY() == -m_minYExtent) {
508+ if (!scrolledUp && (contentY() == -m_minYExtent || (m_headerItemShownHeight == 0 && m_previousContentY == m_headerItem->y()))) {
495509 m_headerItemShownHeight = 0;
496− m_headerItem->setY(contentY());
497− } else if ((scrolledUp && notRebounding && notShownByItsOwn && !maximizeVisibleAreaRunning) || (m_headerItemShownHeight > 0)) {
510+ m_headerItem->setY(-m_minYExtent);
511+ } else if ((scrolledUp && notRebounding && notShownByItsOwn && !maximizeVisibleAreaRunning) || (m_headerItemShownHeight > 0) || m_inContentHeightKeepHeaderShown) {
498512 if (maximizeVisibleAreaRunning && diff > 0) // If we are maximizing and the header was shown, make sure we hide it
499513 m_headerItemShownHeight -= diff;
500514 else
@@ -847,6 +861,11 @@ void ListViewWithPageHeader::itemCreated(int modelIndex, QObject *object)
847861 }
848862#endif
849863// qDebug() << "ListViewWithPageHeader::itemCreated" << modelIndex << item;
864+ // Check we are not being taken down and don't paint anything
865+ // TODO Check if we still need this in 5.2
866+ // For reproduction just inifnite loop testDash or testDashContent
867+ if (!QQmlEngine::contextForObject(this)->parentContext())
868+ return;
850869
851870 item->setParentItem(m_clipItem);
852871 QQmlContext *context = QQmlEngine::contextForObject(item)->parentContext();
@@ -980,7 +999,6 @@ void ListViewWithPageHeader::onModelUpdated(const QQmlChangeSet &changeSet, bool
980999 if (growUp) {
9811000 ListItem *firstItem = m_visibleItems.first();
9821001 firstItem->setY(firstItem->y() - item->height());
983− adjustMinYExtent();
9841002 }
9851003 // Adding an item may break a "same section" chain, so check
9861004 // if we need adding a new section item
@@ -991,7 +1009,6 @@ void ListViewWithPageHeader::onModelUpdated(const QQmlChangeSet &changeSet, bool
9911009 if (growUp && nextItem->m_sectionItem) {
9921010 ListItem *firstItem = m_visibleItems.first();
9931011 firstItem->setY(firstItem->y() - nextItem->m_sectionItem->height());
994− adjustMinYExtent();
9951012 }
9961013 }
9971014 }
@@ -1000,6 +1017,7 @@ void ListViewWithPageHeader::onModelUpdated(const QQmlChangeSet &changeSet, bool
10001017 ListItem *firstItem = m_visibleItems.first();
10011018 firstItem->setY(oldFirstValidIndexPos);
10021019 }
1020+ adjustMinYExtent();
10031021 } else if (insert.index <= m_firstVisibleIndex) {
10041022 m_firstVisibleIndex += insert.count;
10051023 }
@@ -1228,6 +1246,12 @@ void ListViewWithPageHeader::layout()
12281246
12291247void ListViewWithPageHeader::updatePolish()
12301248{
1249+ // Check we are not being taken down and don't paint anything
1250+ // TODO Check if we still need this in 5.2
1251+ // For reproduction just inifnite loop testDash or testDashContent
1252+ if (!QQmlEngine::contextForObject(this)->parentContext())
1253+ return;
1254+
12311255 Q_FOREACH(ListItem *item, m_itemsToRelease)
12321256 reallyReleaseItem(item);
12331257 m_itemsToRelease.clear();
@@ -1267,7 +1291,9 @@ void ListViewWithPageHeader::updatePolish()
12671291
12681292 m_contentHeightDirty = false;
12691293 adjustMinYExtent();
1294+ m_inContentHeightKeepHeaderShown = m_headerItem && m_headerItem->y() == contentY();
12701295 setContentHeight(contentHeight);
1296+ m_inContentHeightKeepHeaderShown = false;
12711297 }
12721298}
12731299
plugins/ListViewWithPageHeader/listviewwithpageheader.h+5
@@ -60,6 +60,7 @@ class ListViewWithPageHeader : public QQuickFlickable, public QQuickItemChangeLi
6060 Q_PROPERTY(QQmlComponent *sectionDelegate READ sectionDelegate WRITE setSectionDelegate NOTIFY sectionDelegateChanged)
6161 Q_PROPERTY(QString sectionProperty READ sectionProperty WRITE setSectionProperty NOTIFY sectionPropertyChanged)
6262 Q_PROPERTY(bool forceNoClip READ forceNoClip WRITE setForceNoClip NOTIFY forceNoClipChanged)
63+ Q_PROPERTY(int stickyHeaderHeight READ stickyHeaderHeight NOTIFY stickyHeaderHeightChanged)
6364
6465 friend class ListViewWithPageHeaderTest;
6566 friend class ListViewWithPageHeaderTestSection;
@@ -87,6 +88,8 @@ public:
8788 bool forceNoClip() const;
8889 void setForceNoClip(bool noClip);
8990
91+ int stickyHeaderHeight() const;
92+
9093 Q_INVOKABLE void positionAtBeginning();
9194 Q_INVOKABLE void showHeader();
9295 Q_INVOKABLE QQuickItem *item(int modelIndex) const;
@@ -104,6 +107,7 @@ Q_SIGNALS:
104107 void sectionDelegateChanged();
105108 void sectionPropertyChanged();
106109 void forceNoClipChanged();
110+ void stickyHeaderHeightChanged();
107111
108112protected:
109113 void componentComplete();
@@ -202,6 +206,7 @@ private:
202206
203207 bool m_forceNoClip;
204208 bool m_inLayout;
209+ bool m_inContentHeightKeepHeaderShown;
205210
206211 // Qt 5.0 doesn't like releasing the items just after itemCreated
207212 // so we delay the releasing until the next updatePolish
plugins/SessionBroadcast/plugin.cpp+1−1
@@ -19,7 +19,7 @@
1919#include "plugin.h"
2020#include "SessionBroadcast.h"
2121
22−#include <QtQml>
22+#include <QtQml/qqml.h>
2323
2424static QObject *broadcast_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
2525{
plugins/Ubuntu/Gestures/AxisVelocityCalculator.cpp+9−18
@@ -21,25 +21,19 @@
2121#include "AxisVelocityCalculator.h"
2222#include <QtCore/QElapsedTimer>
2323
24−class RealTimeSource : public UbuntuGestures::TimeSource {
25−public:
26− RealTimeSource()
27− : UbuntuGestures::TimeSource() {
28− m_timer.start();
29− }
30− virtual qint64 msecsSinceReference() {
31− return m_timer.elapsed();
32− }
33−private:
34− QElapsedTimer m_timer;
35−};
24+using namespace UbuntuGestures;
3625
3726AxisVelocityCalculator::AxisVelocityCalculator(QObject *parent)
27+ : AxisVelocityCalculator(SharedTimeSource(new RealTimeSource), parent)
28+{
29+}
30+
31+AxisVelocityCalculator::AxisVelocityCalculator(const SharedTimeSource &timeSource,
32+ QObject *parent)
3833 : QObject(parent)
39− , m_timeSource(new RealTimeSource)
34+ , m_timeSource(timeSource)
4035 , m_trackedPosition(0.0)
4136{
42− m_timeSource->setParent(this);
4337 reset();
4438}
4539
@@ -142,11 +136,8 @@ int AxisVelocityCalculator::numSamples() const
142136 }
143137}
144138
145−void AxisVelocityCalculator::setTimeSource(UbuntuGestures::TimeSource *timeSource)
139+void AxisVelocityCalculator::setTimeSource(const SharedTimeSource &timeSource)
146140{
147− if (m_timeSource && m_timeSource->parent() == this)
148− delete m_timeSource;
149−
150141 m_timeSource = timeSource;
151142
152143 if (numSamples() > 0) {
plugins/Ubuntu/Gestures/AxisVelocityCalculator.h+9−16
@@ -24,19 +24,7 @@
2424#include "UbuntuGesturesGlobal.h"
2525#include <stdint.h>
2626#include <QtCore/QObject>
27−
28−namespace UbuntuGestures {
29−/*
30− Interface for a time source.
31− */
32−class UBUNTUGESTURES_EXPORT TimeSource : public QObject {
33− Q_OBJECT
34−public:
35− virtual ~TimeSource() {}
36− /* Returns the current time in milliseconds since some reference time in the past. */
37− virtual qint64 msecsSinceReference() = 0;
38−};
39−}
27+#include "TimeSource.h"
4028
4129/*
4230 Estimates the current velocity of a finger based on recent movement along an axis
@@ -73,10 +61,15 @@ class UBUNTUGESTURES_EXPORT AxisVelocityCalculator : public QObject
7361public:
7462
7563 /*
76− Regular constructor
64+ Regular, simple, constructor
7765 */
7866 AxisVelocityCalculator(QObject *parent = 0);
7967
68+ /*
69+ Constructor that takes a TimeSource
70+ */
71+ AxisVelocityCalculator(const UbuntuGestures::SharedTimeSource &timeSource, QObject *parent = 0);
72+
8073 virtual ~AxisVelocityCalculator();
8174
8275 qreal trackedPosition() const;
@@ -97,7 +90,7 @@ public:
9790 /*
9891 Replaces the TimeSource with the given one. Useful for testing purposes.
9992 */
100− void setTimeSource(UbuntuGestures::TimeSource *timeSource);
93+ void setTimeSource(const UbuntuGestures::SharedTimeSource &timeSource);
10194
10295 /*
10396 The minimum amount of samples needed for a velocity calculation.
@@ -145,7 +138,7 @@ private:
145138 int m_samplesRead; /* index of the oldest sample available. -1 if buffer is empty */
146139 int m_samplesWrite; /* index where the next sample will be written */
147140
148− UbuntuGestures::TimeSource *m_timeSource;
141+ UbuntuGestures::SharedTimeSource m_timeSource;
149142
150143 qreal m_trackedPosition;
151144};
plugins/Ubuntu/Gestures/CMakeLists.txt+1
@@ -6,6 +6,7 @@ set(UbuntuGestureQml_SOURCES
66 AxisVelocityCalculator.cpp
77 Direction.cpp
88 DirectionalDragArea.cpp
9+ TimeSource.cpp
910)
1011
1112add_definitions(-DUBUNTUGESTURES_LIBRARY)
plugins/Ubuntu/Gestures/DirectionalDragArea.cpp+307−71
@@ -18,6 +18,75 @@
1818
1919#include <QtCore/qmath.h>
2020#include <QtCore/QTimer>
21+#include <QDebug>
22+
23+using namespace UbuntuGestures;
24+
25+#define DIRECTIONALDRAGAREA_DEBUG 0
26+
27+#if DIRECTIONALDRAGAREA_DEBUG
28+#define DDA_DEBUG(msg) qDebug("[DDA] " msg)
29+namespace {
30+QString touchPointStateToString(Qt::TouchPointState state) {
31+ switch (state) {
32+ case Qt::TouchPointPressed:
33+ return QString("pressed");
34+ case Qt::TouchPointMoved:
35+ return QString("moved");
36+ case Qt::TouchPointStationary:
37+ return QString("stationary");
38+ default: // Qt::TouchPointReleased:
39+ return QString("released");
40+ }
41+}
42+QString touchEventToString(QTouchEvent *ev)
43+{
44+ QString message;
45+
46+ switch (ev->type()) {
47+ case QEvent::TouchBegin:
48+ message.append("TouchBegin ");
49+ break;
50+ case QEvent::TouchUpdate:
51+ message.append("TouchUpdate ");
52+ break;
53+ case QEvent::TouchEnd:
54+ message.append("TouchEnd ");
55+ break;
56+ default: //QEvent::TouchCancel
57+ message.append("TouchCancel ");
58+ }
59+
60+ for (int i=0; i < ev->touchPoints().size(); ++i) {
61+
62+ const QTouchEvent::TouchPoint& touchPoint = ev->touchPoints().at(i);
63+ message.append(
64+ QString("(id:%1, state:%2, scenePos:(%3,%4)) ")
65+ .arg(touchPoint.id())
66+ .arg(touchPointStateToString(touchPoint.state()))
67+ .arg(touchPoint.scenePos().x())
68+ .arg(touchPoint.scenePos().y())
69+ );
70+ }
71+
72+ return message;
73+}
74+
75+const char *statusToString(DirectionalDragArea::Status status)
76+{
77+ if (status == DirectionalDragArea::WaitingForTouch) {
78+ return "WaitingForTouch";
79+ } else if (status == DirectionalDragArea::Undecided) {
80+ return "Undecided";
81+ } else {
82+ return "Recognized";
83+ }
84+}
85+
86+} // namespace {
87+#else // DIRECTIONALDRAGAREA_DEBUG
88+#define DDA_DEBUG(msg) do{}while(0)
89+#endif // DIRECTIONALDRAGAREA_DEBUG
2190
2291// Essentially a QTimer wrapper
2392class RecognitionTimer : public UbuntuGestures::AbstractTimer
@@ -48,9 +117,12 @@ DirectionalDragArea::DirectionalDragArea(QQuickItem *parent)
48117 , m_minSpeed(0)
49118 , m_maxSilenceTime(200)
50119 , m_silenceTime(0)
120+ , m_compositionTime(60)
51121 , m_numSamplesOnLastSpeedCheck(0)
52122 , m_recognitionTimer(0)
53123 , m_velocityCalculator(0)
124+ , m_timeSource(new RealTimeSource)
125+ , m_activeTouches(m_timeSource)
54126{
55127 setRecognitionTimer(new RecognitionTimer(this));
56128 m_recognitionTimer->setInterval(60);
@@ -73,8 +145,8 @@ void DirectionalDragArea::setDirection(Direction::Type direction)
73145
74146void DirectionalDragArea::setMaxDeviation(qreal value)
75147{
76− if (m_dampedPos.maxDelta() != value) {
77− m_dampedPos.setMaxDelta(value);
148+ if (m_dampedScenePos.maxDelta() != value) {
149+ m_dampedScenePos.setMaxDelta(value);
78150 Q_EMIT maxDeviationChanged(value);
79151 }
80152}
@@ -118,6 +190,14 @@ void DirectionalDragArea::setMaxSilenceTime(int value)
118190 }
119191}
120192
193+void DirectionalDragArea::setCompositionTime(int value)
194+{
195+ if (m_compositionTime != value) {
196+ m_compositionTime = value;
197+ Q_EMIT compositionTimeChanged(value);
198+ }
199+}
200+
121201void DirectionalDragArea::setRecognitionTimer(UbuntuGestures::AbstractTimer *timer)
122202{
123203 int interval = 0;
@@ -141,9 +221,11 @@ void DirectionalDragArea::setRecognitionTimer(UbuntuGestures::AbstractTimer *tim
141221 }
142222}
143223
144−void DirectionalDragArea::setTimeSource(UbuntuGestures::TimeSource *timeSource)
224+void DirectionalDragArea::setTimeSource(const SharedTimeSource &timeSource)
145225{
226+ m_timeSource = timeSource;
146227 m_velocityCalculator->setTimeSource(timeSource);
228+ m_activeTouches.m_timeSource = timeSource;
147229}
148230
149231qreal DirectionalDragArea::distance() const
@@ -186,6 +268,12 @@ qreal DirectionalDragArea::touchSceneY() const
186268
187269void DirectionalDragArea::touchEvent(QTouchEvent *event)
188270{
271+ #if DIRECTIONALDRAGAREA_DEBUG
272+ // TODO Consider using qCDebug() when available (Qt 5.2)
273+ qDebug() << "[DDA]" << m_timeSource->msecsSinceReference()
274+ << qPrintable(touchEventToString(event));
275+ #endif
276+
189277 if (!isEnabled() || !isVisible()) {
190278 QQuickItem::touchEvent(event);
191279 return;
@@ -198,76 +286,124 @@ void DirectionalDragArea::touchEvent(QTouchEvent *event)
198286 case Undecided:
199287 touchEvent_undecided(event);
200288 break;
201− case Recognized:
289+ default: // Recognized:
202290 touchEvent_recognized(event);
203291 break;
204− default: // Rejected
205− touchEvent_rejected(event);
206− break;
207292 }
293+
294+ m_activeTouches.update(event);
208295}
209296
210297void DirectionalDragArea::touchEvent_absent(QTouchEvent *event)
211298{
212− if ((event->touchPointStates() && (Qt::TouchPointPressed || Qt::TouchPointMoved))
213− && event->touchPoints().count() == 1) {
214− const QTouchEvent::TouchPoint &touchPoint = event->touchPoints()[0];
215− m_startPos = touchPoint.pos();
216− m_startScenePos = touchPoint.scenePos();
217− m_touchId = touchPoint.id();
218− m_dampedPos.reset(m_startPos);
219− updateVelocityCalculator(m_startPos);
220− m_velocityCalculator->reset();
221− m_numSamplesOnLastSpeedCheck = 0;
222− m_silenceTime = 0;
223− setPreviousPos(m_startPos);
224− setPreviousScenePos(m_startScenePos);
299+ if (!event->touchPointStates().testFlag(Qt::TouchPointPressed)) {
300+ // Nothing to see here. No touch starting in this event.
301+ return;
302+ }
225303
226− if (m_distanceThreshold > 0)
227− setStatus(Undecided);
228− else
229− setStatus(Recognized);
304+ if (isWithinTouchCompositionWindow()) {
305+ // too close to the last touch start. So we consider them as starting roughly at the same time.
306+ // Can't be a single-touch gesture.
307+ #if DIRECTIONALDRAGAREA_DEBUG
308+ qDebug("[DDA] A new touch point came in but we're still within time composition window. Ignoring it.");
309+ #endif
310+ return;
230311 }
312+
313+ const QList<QTouchEvent::TouchPoint> &touchPoints = event->touchPoints();
314+
315+ const QTouchEvent::TouchPoint *newTouchPoint = nullptr;
316+ for (int i = 0; i < touchPoints.count(); ++i) {
317+ const QTouchEvent::TouchPoint &touchPoint = touchPoints.at(i);
318+ if (touchPoint.state() == Qt::TouchPointPressed) {
319+ if (newTouchPoint) {
320+ // more than one touch starting in this QTouchEvent. Can't be a single-touch gesture
321+ return;
322+ } else {
323+ // that's our candidate
324+ m_touchId = touchPoint.id();
325+ newTouchPoint = &touchPoint;
326+ }
327+ }
328+ }
329+
330+ Q_ASSERT(newTouchPoint);
331+
332+ // If we have made this far, we are good to go to the next status.
333+
334+ m_startPos = newTouchPoint->pos();
335+ m_startScenePos = newTouchPoint->scenePos();
336+ m_touchId = newTouchPoint->id();
337+ m_dampedScenePos.reset(m_startScenePos);
338+ updateVelocityCalculator(m_startScenePos);
339+ m_velocityCalculator->reset();
340+ m_numSamplesOnLastSpeedCheck = 0;
341+ m_silenceTime = 0;
342+ setPreviousPos(m_startPos);
343+ setPreviousScenePos(m_startScenePos);
344+
345+ setStatus(Undecided);
231346}
232347
233348void DirectionalDragArea::touchEvent_undecided(QTouchEvent *event)
234349{
235350 const QTouchEvent::TouchPoint *touchPoint = fetchTargetTouchPoint(event);
236− const QPointF &touchPos = touchPoint->pos();
351+
352+ if (!touchPoint) {
353+ qCritical() << "DirectionalDragArea[status=Undecided]: touch " << m_touchId
354+ << "missing from QTouchEvent without first reaching state Qt::TouchPointReleased. "
355+ "Considering it as released.";
356+ setStatus(WaitingForTouch);
357+ return;
358+ }
359+
360+ const QPointF &touchScenePos = touchPoint->scenePos();
237361
238362 if (touchPoint->state() == Qt::TouchPointReleased) {
239363 // touch has ended before recognition concluded
364+ DDA_DEBUG("Touch has ended before recognition concluded");
240365 setStatus(WaitingForTouch);
241366 return;
242367 }
243368
244− if (event->touchPointStates().testFlag(Qt::TouchPointPressed)
245− || event->touchPoints().count() > 1) {
369+ if (event->touchPointStates().testFlag(Qt::TouchPointPressed) && isWithinTouchCompositionWindow()) {
246370 // multi-finger drags are not accepted
247− setStatus(Rejected);
371+ DDA_DEBUG("Multi-finger drags are not accepted");
372+ setStatus(WaitingForTouch);
248373 return;
249374 }
250375
251− m_previousDampedPos.setX(m_dampedPos.x());
252− m_previousDampedPos.setY(m_dampedPos.y());
253− m_dampedPos.update(touchPos);
254− updateVelocityCalculator(touchPos);
376+ m_previousDampedScenePos.setX(m_dampedScenePos.x());
377+ m_previousDampedScenePos.setY(m_dampedScenePos.y());
378+ m_dampedScenePos.update(touchScenePos);
379+ updateVelocityCalculator(touchScenePos);
255380
256381 if (!pointInsideAllowedArea()) {
257− setStatus(Rejected);
382+ DDA_DEBUG("Rejecting gesture because touch point is outside allowed area.");
383+ setStatus(WaitingForTouch);
258384 return;
259385 }
260386
261387 if (!movingInRightDirection()) {
262− setStatus(Rejected);
388+ DDA_DEBUG("Rejecting gesture becauuse touch point is moving in the wrong direction.");
389+ setStatus(WaitingForTouch);
263390 return;
264391 }
265392
266− setPreviousPos(touchPos);
267− setPreviousScenePos(touchPoint->scenePos());
393+ setPreviousPos(touchPoint->pos());
394+ setPreviousScenePos(touchScenePos);
268395
269− if (movedFarEnough(touchPos)) {
396+ if (isWithinTouchCompositionWindow()) {
397+ // There's still time for some new touch to appear and ruin our party as it would be combined
398+ // with our m_touchId one and therefore deny the possibility of a single-finger gesture.
399+ DDA_DEBUG("Sill within composition window. Let's wait more.");
400+ return;
401+ }
402+
403+ if (movedFarEnough(touchScenePos)) {
270404 setStatus(Recognized);
405+ } else {
406+ DDA_DEBUG("Didn't move far enough yet. Let's wait more.");
271407 }
272408}
273409
@@ -275,20 +411,18 @@ void DirectionalDragArea::touchEvent_recognized(QTouchEvent *event)
275411{
276412 const QTouchEvent::TouchPoint *touchPoint = fetchTargetTouchPoint(event);
277413
278− setPreviousPos(touchPoint->pos());
279− setPreviousScenePos(touchPoint->scenePos());
280−
281− if (touchPoint->state() == Qt::TouchPointReleased) {
414+ if (!touchPoint) {
415+ qCritical() << "DirectionalDragArea[status=Recognized]: touch " << m_touchId
416+ << "missing from QTouchEvent without first reaching state Qt::TouchPointReleased. "
417+ "Considering it as released.";
282418 setStatus(WaitingForTouch);
283− }
284−}
285−
286−void DirectionalDragArea::touchEvent_rejected(QTouchEvent *event)
287−{
288− const QTouchEvent::TouchPoint *touchPoint = fetchTargetTouchPoint(event);
419+ } else {
420+ setPreviousPos(touchPoint->pos());
421+ setPreviousScenePos(touchPoint->scenePos());
289422
290− if (!touchPoint || touchPoint->state() == Qt::TouchPointReleased) {
291− setStatus(WaitingForTouch);
423+ if (touchPoint->state() == Qt::TouchPointReleased) {
424+ setStatus(WaitingForTouch);
425+ }
292426 }
293427}
294428
@@ -307,8 +441,8 @@ const QTouchEvent::TouchPoint *DirectionalDragArea::fetchTargetTouchPoint(QTouch
307441
308442bool DirectionalDragArea::pointInsideAllowedArea() const
309443{
310− qreal dX = m_dampedPos.x() - m_startPos.x();
311− qreal dY = m_dampedPos.y() - m_startPos.y();
444+ qreal dX = m_dampedScenePos.x() - m_startScenePos.x();
445+ qreal dY = m_dampedScenePos.y() - m_startScenePos.y();
312446
313447 switch (m_direction) {
314448 case Direction::Upwards:
@@ -326,22 +460,26 @@ bool DirectionalDragArea::movingInRightDirection() const
326460{
327461 switch (m_direction) {
328462 case Direction::Upwards:
329− return m_dampedPos.y() <= m_previousDampedPos.y();
463+ return m_dampedScenePos.y() <= m_previousDampedScenePos.y();
330464 case Direction::Downwards:
331− return m_dampedPos.y() >= m_previousDampedPos.y();
465+ return m_dampedScenePos.y() >= m_previousDampedScenePos.y();
332466 case Direction::Leftwards:
333− return m_dampedPos.x() <= m_previousDampedPos.x();
467+ return m_dampedScenePos.x() <= m_previousDampedScenePos.x();
334468 default: // Direction::Rightwards:
335− return m_dampedPos.x() >= m_previousDampedPos.x();
469+ return m_dampedScenePos.x() >= m_previousDampedScenePos.x();
336470 }
337471}
338472
339473bool DirectionalDragArea::movedFarEnough(const QPointF &point) const
340474{
341− if (Direction::isHorizontal(m_direction))
342− return qFabs(point.x() - m_startPos.x()) > m_distanceThreshold;
343− else
344− return qFabs(point.y() - m_startPos.y()) > m_distanceThreshold;
475+ if (m_distanceThreshold > 0) {
476+ if (Direction::isHorizontal(m_direction))
477+ return qFabs(point.x() - m_startScenePos.x()) > m_distanceThreshold;
478+ else
479+ return qFabs(point.y() - m_startScenePos.y()) > m_distanceThreshold;
480+ } else {
481+ return true;
482+ }
345483}
346484
347485void DirectionalDragArea::checkSpeed()
@@ -351,7 +489,8 @@ void DirectionalDragArea::checkSpeed()
351489 qreal minSpeedMsecs = m_minSpeed / 1000.0;
352490
353491 if (speed < minSpeedMsecs) {
354− setStatus(Rejected);
492+ DDA_DEBUG("Rejecting gesture because it's below minimum speed.");
493+ setStatus(WaitingForTouch);
355494 }
356495 }
357496
@@ -359,7 +498,8 @@ void DirectionalDragArea::checkSpeed()
359498 m_silenceTime += m_recognitionTimer->interval();
360499
361500 if (m_silenceTime > m_maxSilenceTime) {
362− setStatus(Rejected);
501+ DDA_DEBUG("Rejecting gesture because it's silence time has been exceeded.");
502+ setStatus(WaitingForTouch);
363503 }
364504 } else {
365505 m_silenceTime = 0;
@@ -381,11 +521,13 @@ void DirectionalDragArea::setStatus(DirectionalDragArea::Status newStatus)
381521 m_status = newStatus;
382522 Q_EMIT statusChanged(m_status);
383523
524+ #if DIRECTIONALDRAGAREA_DEBUG
525+ qDebug() << "[DDA]" << statusToString(oldStatus) << "->" << statusToString(newStatus);
526+ #endif
527+
384528 switch (newStatus) {
385529 case WaitingForTouch:
386− if (oldStatus != DirectionalDragArea::Rejected) {
387− Q_EMIT draggingChanged(false);
388− }
530+ Q_EMIT draggingChanged(false);
389531 break;
390532 case Undecided:
391533 m_recognitionTimer->start();
@@ -395,9 +537,6 @@ void DirectionalDragArea::setStatus(DirectionalDragArea::Status newStatus)
395537 if (oldStatus == WaitingForTouch)
396538 Q_EMIT draggingChanged(true);
397539 break;
398− case Rejected:
399− Q_EMIT draggingChanged(false);
400− break;
401540 default:
402541 // no-op
403542 break;
@@ -406,8 +545,6 @@ void DirectionalDragArea::setStatus(DirectionalDragArea::Status newStatus)
406545
407546void DirectionalDragArea::setPreviousPos(const QPointF &point)
408547{
409− Q_ASSERT(m_status != Rejected);
410−
411548 bool xChanged = m_previousPos.x() != point.x();
412549 bool yChanged = m_previousPos.y() != point.y();
413550
@@ -428,8 +565,6 @@ void DirectionalDragArea::setPreviousPos(const QPointF &point)
428565
429566void DirectionalDragArea::setPreviousScenePos(const QPointF &point)
430567{
431− Q_ASSERT(m_status != Rejected);
432−
433568 bool xChanged = m_previousScenePos.x() != point.x();
434569 bool yChanged = m_previousScenePos.y() != point.y();
435570
@@ -457,5 +592,106 @@ void DirectionalDragArea::updateVelocityCalculator(const QPointF &point)
457592 }
458593}
459594
595+bool DirectionalDragArea::isWithinTouchCompositionWindow()
596+{
597+ return !m_activeTouches.isEmpty() &&
598+ m_timeSource->msecsSinceReference() <=
599+ m_activeTouches.mostRecentStartTime() + (qint64)compositionTime();
600+}
601+
602+//************************** ActiveTouchesInfo **************************
603+
604+DirectionalDragArea::ActiveTouchesInfo::ActiveTouchesInfo(const SharedTimeSource &timeSource)
605+ : m_timeSource(timeSource), m_lastUsedIndex(-1)
606+{
607+ // Estimate of the maximum number of active touches we might reach.
608+ // Not a problem if it ends up being an underestimate as this is just
609+ // an optimization.
610+ m_vector.resize(3);
611+}
612+
613+void DirectionalDragArea::ActiveTouchesInfo::update(QTouchEvent *event)
614+{
615+ if (!(event->touchPointStates() & (Qt::TouchPointPressed | Qt::TouchPointReleased))) {
616+ // nothing to update
617+ return;
618+ }
619+
620+ const QList<QTouchEvent::TouchPoint> &touchPoints = event->touchPoints();
621+ for (int i = 0; i < touchPoints.count(); ++i) {
622+ const QTouchEvent::TouchPoint &touchPoint = touchPoints.at(i);
623+ if (touchPoint.state() == Qt::TouchPointPressed) {
624+ addTouchPoint(touchPoint);
625+ } else if (touchPoint.state() == Qt::TouchPointReleased) {
626+ removeTouchPoint(touchPoint);
627+ }
628+ }
629+}
630+
631+void DirectionalDragArea::ActiveTouchesInfo::addTouchPoint(const QTouchEvent::TouchPoint &touchPoint)
632+{
633+ ActiveTouchInfo &activeTouchInfo = getEmptySlot();
634+ activeTouchInfo.id = touchPoint.id();
635+ activeTouchInfo.startTime = m_timeSource->msecsSinceReference();
636+}
637+
638+void DirectionalDragArea::ActiveTouchesInfo::removeTouchPoint(const QTouchEvent::TouchPoint &touchPoint)
639+{
640+ for (int i = 0; i <= m_lastUsedIndex; ++i) {
641+ if (touchPoint.id() == m_vector.at(i).id) {
642+ freeSlot(i);
643+ return;
644+ }
645+ }
646+ Q_ASSERT(false); // shouldn't reach this point
647+}
648+
649+DirectionalDragArea::ActiveTouchInfo &DirectionalDragArea::ActiveTouchesInfo::getEmptySlot()
650+{
651+ Q_ASSERT(m_lastUsedIndex < m_vector.size());
652+
653+ // Look for an in-between vacancy first
654+ for (int i = 0; i < m_lastUsedIndex; ++i) {
655+ ActiveTouchInfo &activeTouchInfo = m_vector[i];
656+ if (!activeTouchInfo.isValid()) {
657+ return activeTouchInfo;
658+ }
659+ }
660+
661+ ++m_lastUsedIndex;
662+ if (m_lastUsedIndex >= m_vector.size()) {
663+ m_vector.resize(m_lastUsedIndex + 1);
664+ }
665+
666+ return m_vector[m_lastUsedIndex];
667+}
668+
669+void DirectionalDragArea::ActiveTouchesInfo::freeSlot(int index)
670+{
671+ m_vector[index].reset();
672+ if (index == m_lastUsedIndex) {
673+ do {
674+ --m_lastUsedIndex;
675+ } while (m_lastUsedIndex >= 0 && !m_vector.at(m_lastUsedIndex).isValid());
676+ }
677+}
678+
679+qint64 DirectionalDragArea::ActiveTouchesInfo::mostRecentStartTime()
680+{
681+ Q_ASSERT(m_lastUsedIndex >= 0);
682+
683+ qint64 highestStartTime = m_vector.at(0).startTime;
684+ int i = 1;
685+ do {
686+ const ActiveTouchInfo &activeTouchInfo = m_vector.at(i);
687+ if (activeTouchInfo.isValid() && activeTouchInfo.startTime > highestStartTime) {
688+ highestStartTime = activeTouchInfo.startTime;
689+ }
690+ ++i;
691+ } while (i < m_lastUsedIndex);
692+
693+ return highestStartTime;
694+}
695+
460696// Because we are defining a new QObject-based class (RecognitionTimer) here.
461697#include "DirectionalDragArea.moc"
plugins/Ubuntu/Gestures/DirectionalDragArea.h+50−13
@@ -117,9 +117,17 @@ class UBUNTUGESTURES_EXPORT DirectionalDragArea : public QQuickItem {
117117 Q_PROPERTY(int maxSilenceTime READ maxSilenceTime
118118 WRITE setMaxSilenceTime
119119 NOTIFY maxSilenceTimeChanged)
120+
120121 //
121122 /////
122123
124+ // Maximum time (in milliseconds) after the start of a given touch point where
125+ // subsequent touch starts are grouped with the first one into an N-touches gesture
126+ // (e.g. a two-fingers tap or drag).
127+ Q_PROPERTY(int compositionTime READ compositionTime
128+ WRITE setCompositionTime
129+ NOTIFY compositionTimeChanged)
130+
123131 Q_ENUMS(Direction)
124132 Q_ENUMS(Status)
125133public:
@@ -130,26 +138,23 @@ public:
130138
131139 // Describes the state of the directional drag gesture.
132140 enum Status {
133− // There's no touch point over this area.
141+ // Waiting for a new touch point to land on this area. No gesture is being processed
142+ // or tracked.
134143 WaitingForTouch,
135144
136145 // A touch point has landed on this area but it's not know yet whether it is
137146 // performing a drag in the correct direction.
147+ // If it's decided that the touch point is not performing a directional drag gesture,
148+ // it will be rejected/ignored and status will return to WaitingForTouch.
138149 Undecided, //Recognizing,
139150
140151 // There's a touch point in this area and it performed a drag in the correct
141152 // direction.
142153 //
143− // Once recognized, the gesture state will move back to Absent only once
154+ // Once recognized, the gesture state will move back to WaitingForTouch only once
144155 // that touch point ends. The gesture will remain in the Recognized state even if
145156 // the touch point starts moving in other directions or halts.
146157 Recognized,
147−
148− // A gesture was performed but it wasn't a single-touch drag in the correct
149− // direction.
150− // It will remain in this state until there are no more touch points over this
151− // area, at which point it will move to Absent state.
152− Rejected
153158 };
154159 Status status() const { return m_status; }
155160
@@ -164,7 +169,7 @@ public:
164169
165170 bool dragging() const { return (m_status == Undecided) || (m_status == Recognized); }
166171
167− qreal maxDeviation() const { return m_dampedPos.maxDelta(); }
172+ qreal maxDeviation() const { return m_dampedScenePos.maxDelta(); }
168173 void setMaxDeviation(qreal value);
169174
170175 qreal wideningAngle() const;
@@ -179,13 +184,16 @@ public:
179184 int maxSilenceTime() const { return m_maxSilenceTime; }
180185 void setMaxSilenceTime(int value);
181186
187+ int compositionTime() const { return m_compositionTime; }
188+ void setCompositionTime(int value);
189+
182190 // Replaces the existing Timer with the given one.
183191 //
184192 // Useful for providing a fake timer when testing.
185193 void setRecognitionTimer(UbuntuGestures::AbstractTimer *timer);
186194
187195 // Useful for testing, where a fake time source can be supplied
188− void setTimeSource(UbuntuGestures::TimeSource *timeSource);
196+ void setTimeSource(const UbuntuGestures::SharedTimeSource &timeSource);
189197
190198Q_SIGNALS:
191199 void directionChanged(Direction::Type direction);
@@ -198,6 +206,7 @@ Q_SIGNALS:
198206 void distanceThresholdChanged(qreal value);
199207 void minSpeedChanged(qreal value);
200208 void maxSilenceTimeChanged(int value);
209+ void compositionTimeChanged(int value);
201210 void touchXChanged(qreal value);
202211 void touchYChanged(qreal value);
203212 void touchSceneXChanged(qreal value);
@@ -213,7 +222,6 @@ private:
213222 void touchEvent_absent(QTouchEvent *event);
214223 void touchEvent_undecided(QTouchEvent *event);
215224 void touchEvent_recognized(QTouchEvent *event);
216− void touchEvent_rejected(QTouchEvent *event);
217225 bool pointInsideAllowedArea() const;
218226 bool movingInRightDirection() const;
219227 bool movedFarEnough(const QPointF &point) const;
@@ -222,6 +230,7 @@ private:
222230 void setPreviousPos(const QPointF &point);
223231 void setPreviousScenePos(const QPointF &point);
224232 void updateVelocityCalculator(const QPointF &point);
233+ bool isWithinTouchCompositionWindow();
225234
226235 Status m_status;
227236
@@ -233,8 +242,8 @@ private:
233242
234243 // A movement damper is used in some of the gesture recognition calculations
235244 // to get rid of noise or small oscillations in the touch position.
236− DampedPointF m_dampedPos;
237− QPointF m_previousDampedPos;
245+ DampedPointF m_dampedScenePos;
246+ QPointF m_previousDampedScenePos;
238247
239248 Direction::Type m_direction;
240249 qreal m_wideningAngle; // in degrees
@@ -243,9 +252,37 @@ private:
243252 qreal m_minSpeed;
244253 int m_maxSilenceTime; // in milliseconds
245254 int m_silenceTime; // in milliseconds
255+ int m_compositionTime; // in milliseconds
246256 int m_numSamplesOnLastSpeedCheck;
247257 UbuntuGestures::AbstractTimer *m_recognitionTimer;
248258 AxisVelocityCalculator *m_velocityCalculator;
259+
260+ UbuntuGestures::SharedTimeSource m_timeSource;
261+
262+ // Information about an active touch point
263+ struct ActiveTouchInfo {
264+ ActiveTouchInfo() : id(-1), startTime(-1) {}
265+ bool isValid() const { return id != -1; }
266+ void reset() { id = -1; }
267+ int id;
268+ qint64 startTime;
269+ };
270+ class ActiveTouchesInfo {
271+ public:
272+ ActiveTouchesInfo(const UbuntuGestures::SharedTimeSource &timeSource);
273+ void update(QTouchEvent *event);
274+ ActiveTouchInfo &touchInfo(int id);
275+ qint64 mostRecentStartTime();
276+ UbuntuGestures::SharedTimeSource m_timeSource;
277+ bool isEmpty() const { return m_lastUsedIndex == -1; }
278+ private:
279+ void addTouchPoint(const QTouchEvent::TouchPoint &touchPoint);
280+ ActiveTouchInfo &getEmptySlot();
281+ void freeSlot(int index);
282+ void removeTouchPoint(const QTouchEvent::TouchPoint &touchPoint);
283+ QVector<struct ActiveTouchInfo> m_vector;
284+ int m_lastUsedIndex;
285+ } m_activeTouches;
249286};
250287
251288#endif // DIRECTIONAL_DRAG_AREA_H
plugins/Ubuntu/Gestures/TimeSource.cppnew file+49
@@ -0,0 +1,49 @@
1+/*
2+ * Copyright (C) 2013 - Canonical Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it
5+ * under the terms of the GNU Lesser General Public License, as
6+ * published by the Free Software Foundation; either version 2.1 or 3.0
7+ * of the License.
8+ *
9+ * This program is distributed in the hope that it will be useful, but
10+ * WITHOUT ANY WARRANTY; without even the implied warranties of
11+ * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
12+ * PURPOSE. See the applicable version of the GNU Lesser General Public
13+ * License for more details.
14+ *
15+ * You should have received a copy of both the GNU Lesser General Public
16+ * License along with this program. If not, see <http://www.gnu.org/licenses/>
17+ *
18+ * Authored by: Daniel d'Andrada <daniel.dandrada@canonical.com>
19+ */
20+
21+#include "TimeSource.h"
22+
23+#include <QElapsedTimer>
24+
25+namespace UbuntuGestures {
26+class RealTimeSourcePrivate {
27+public:
28+ QElapsedTimer timer;
29+};
30+}
31+
32+using namespace UbuntuGestures;
33+
34+RealTimeSource::RealTimeSource()
35+ : UbuntuGestures::TimeSource()
36+ , d(new RealTimeSourcePrivate)
37+{
38+ d->timer.start();
39+}
40+
41+RealTimeSource::~RealTimeSource()
42+{
43+ delete d;
44+}
45+
46+qint64 RealTimeSource::msecsSinceReference()
47+{
48+ return d->timer.elapsed();
49+}
plugins/Ubuntu/Gestures/TimeSource.hnew file+54
@@ -0,0 +1,54 @@
1+/*
2+ * Copyright (C) 2013 - Canonical Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it
5+ * under the terms of the GNU Lesser General Public License, as
6+ * published by the Free Software Foundation; either version 2.1 or 3.0
7+ * of the License.
8+ *
9+ * This program is distributed in the hope that it will be useful, but
10+ * WITHOUT ANY WARRANTY; without even the implied warranties of
11+ * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
12+ * PURPOSE. See the applicable version of the GNU Lesser General Public
13+ * License for more details.
14+ *
15+ * You should have received a copy of both the GNU Lesser General Public
16+ * License along with this program. If not, see <http://www.gnu.org/licenses/>
17+ *
18+ * Authored by: Daniel d'Andrada <daniel.dandrada@canonical.com>
19+ */
20+
21+#ifndef UBUNTUGESTURES_TIMESOURCE_H
22+#define UBUNTUGESTURES_TIMESOURCE_H
23+
24+#include "UbuntuGesturesGlobal.h"
25+#include <QSharedPointer>
26+
27+namespace UbuntuGestures {
28+/*
29+ Interface for a time source.
30+ */
31+class UBUNTUGESTURES_EXPORT TimeSource {
32+public:
33+ virtual ~TimeSource() {}
34+ /* Returns the current time in milliseconds since some reference time in the past. */
35+ virtual qint64 msecsSinceReference() = 0;
36+};
37+typedef QSharedPointer<TimeSource> SharedTimeSource;
38+
39+/*
40+ Implementation of a time source
41+ */
42+class RealTimeSourcePrivate;
43+class RealTimeSource : public TimeSource {
44+public:
45+ RealTimeSource();
46+ virtual ~RealTimeSource();
47+ qint64 msecsSinceReference() override;
48+private:
49+ RealTimeSourcePrivate *d;
50+};
51+
52+} // namespace UbuntuGestures
53+
54+#endif // UBUNTUGESTURES_TIMESOURCE_H
plugins/Unity/CMakeLists.txt−69
@@ -1,71 +1,2 @@
1−# export_qmlplugin macro
2−include(Plugins)
3−
41add_subdirectory(Indicators)
5−
6−# Dependencies
7−include(FindPkgConfig)
8−pkg_check_modules(QTDEE REQUIRED libdee-qt5>=3.2)
9−pkg_check_modules(UNITYCORE REQUIRED unity-core-6.0>=7.1.1)
10−
11−include_directories(
12− ${CMAKE_CURRENT_SOURCE_DIR}
13− ${CMAKE_CURRENT_BINARY_DIR}
14− ${QTDEE_INCLUDE_DIRS}
15− ${UNITYCORE_INCLUDE_DIRS}
16− ${Qt5DBus_INCLUDE_DIRS}
17−)
18−
19−set(QMLPLUGIN_SRC
20− abstractfilteroption.cpp
21− scope.cpp
22− scopes.cpp
23− categories.cpp
24− checkoptionfilter.cpp
25− filter.cpp
26− filteroption.cpp
27− filters.cpp
28− genericoptionsmodel.cpp
29− ratingoptionsmodel.cpp
30− unityoptionsmodel.cpp
31− categoryresults.cpp
32− plugin.cpp
33− multirangefilter.cpp
34− radiooptionfilter.cpp
35− ratingsfilter.cpp
36− ratingfilteroption.cpp
37− bottombarvisibilitycommunicatorshell.cpp
38− applicationpreview.cpp
39− genericpreview.cpp
40− moviepreview.cpp
41− musicpreview.cpp
42− preview.cpp
43− previewaction.cpp
44− previewinfohint.cpp
45− result.cpp
46− showallfilteroption.cpp
47− signalslist.cpp
48− socialpreview.cpp
49− socialpreviewcomment.cpp
50− iconutils.cpp
51− variantutils.cpp
52−)
53−
54−add_library(Unity-qml MODULE
55− ${QMLPLUGIN_SRC}
56− )
57−
58−target_link_libraries(Unity-qml
59− ${QTDEE_LDFLAGS}
60− ${UNITYCORE_LDFLAGS}
61− ${Qt5DBus_LIBRARIES}
62− ${Qt5Gui_LIBRARIES}
63− )
64−
65−qt5_use_modules(Unity-qml Qml)
66−
67−# export the qmldir qmltypes and plugin files
68−export_qmlfiles(Unity Unity)
69−export_qmlplugin(Unity 0.1 Unity TARGETS Unity-qml)
70−
712add_subdirectory(Launcher)
plugins/Unity/Indicators/indicator.cpp+8−16
@@ -31,32 +31,24 @@ Indicator::~Indicator()
3131{
3232}
3333
34−void Indicator::init(const QString& busName, const QSettings& settings)
34+void Indicator::init(const QString &profile, const QString& busName, const QSettings& settings)
3535{
3636 setId(settings.value("Indicator Service/Name").toString());
37− setPosition(settings.value("Indicator Service/Position", QVariant::fromValue(0)).toInt());
3837
39− QString actionObjectPath = settings.value("Indicator Service/ObjectPath").toString();
40−
41− QVariantMap mapMenuObjectPaths;
42− Q_FOREACH(const QString& childGroup, settings.childGroups())
43− {
44− if (childGroup == "Indicator Service")
45− continue;
38+ QVariant pos = settings.value(profile + "/Position");
39+ if (!pos.isValid())
40+ pos = settings.value("Indicator Service/Position", QVariant::fromValue(0));
41+ setPosition(pos.toInt());
4642
47− QString menuPath = childGroup+"/ObjectPath";
48− if (settings.contains(menuPath))
49− {
50− mapMenuObjectPaths[childGroup] = settings.value(menuPath).toString();
51− }
52− }
43+ QString actionObjectPath = settings.value("Indicator Service/ObjectPath").toString();
44+ QString menuObjectPath = settings.value(profile + "/ObjectPath").toString();
5345
5446 QVariantMap properties;
5547 properties.clear();
5648 properties.insert("busType", 1);
5749 properties.insert("busName", busName);
5850 properties.insert("actionsObjectPath", actionObjectPath);
59− properties.insert("menuObjectPaths", mapMenuObjectPaths);
51+ properties.insert("menuObjectPath", menuObjectPath);
6052 setIndicatorProperties(properties);
6153}
6254
plugins/Unity/Indicators/indicator.h+1−1
@@ -35,7 +35,7 @@ public:
3535 Indicator(QObject *parent = 0);
3636 virtual ~Indicator();
3737
38− void init(const QString& busName, const QSettings& settings);
38+ void init(const QString &profile, const QString& busName, const QSettings& settings);
3939
4040 QString identifier() const;
4141 int position() const;
plugins/Unity/Indicators/indicatorsmanager.cpp+3−1
@@ -26,6 +26,8 @@
2626
2727#include "paths.h"
2828
29+const QString profile = "phone";
30+
2931
3032class IndicatorsManager::IndicatorData
3133{
@@ -298,7 +300,7 @@ Indicator::Ptr IndicatorsManager::indicator(const QString& indicator_name)
298300 Indicator::Ptr new_indicator(new Indicator(this));
299301 data->m_indicator = new_indicator;
300302 QSettings settings(data->m_fileInfo.absoluteFilePath(), QSettings::IniFormat, this);
301− new_indicator->init(data->m_fileInfo.fileName(), settings);
303+ new_indicator->init(profile, data->m_fileInfo.fileName(), settings);
302304 return new_indicator;
303305}
304306
plugins/Unity/Indicators/qml/IndicatorBase.qml+3−4
@@ -24,16 +24,15 @@ import Unity.Indicators 0.1 as Indicators
2424Item {
2525 id: indicatorItem
2626
27− enabled: menuObjectPaths.hasOwnProperty(device)
27+ enabled: menuObjectPath != ""
2828
2929 //const
3030 property string busName
3131 property string actionsObjectPath
32− property var menuObjectPaths: undefined
33− readonly property string device: "phone"
32+ property string menuObjectPath
3433 property string rootMenuType: "com.canonical.indicator.root"
3534
36− property string deviceMenuObjectPath: menuObjectPaths.hasOwnProperty(device) ? menuObjectPaths[device] : ""
35+ property string deviceMenuObjectPath: menuObjectPath
3736
3837 property alias menuModel: cachedModel.model
3938
plugins/Unity/Indicators/qml/IndicatorWidget.qml+1−1
@@ -24,5 +24,5 @@ IndicatorBase {
2424 id: indicatorWidget
2525
2626 enabled: false
27− property int iconSize: height - units.gu(0.5)
27+ property int iconSize: height
2828}
plugins/Unity/Indicators/unitymenumodelstack.cpp+98−7
@@ -19,6 +19,64 @@
1919
2020#include "unitymenumodelstack.h"
2121
22+#include <QDebug>
23+#include <unitymenumodel.h>
24+
25+class UnityMenuModelEntry : public QObject {
26+ Q_OBJECT
27+public:
28+ UnityMenuModelEntry(UnityMenuModel* model, UnityMenuModel* parentModel, int index)
29+ : m_model(model),
30+ m_parentModel(parentModel),
31+ m_index(index)
32+ {
33+ if (m_parentModel) {
34+ QObject::connect(m_parentModel, SIGNAL(rowsInserted(QModelIndex, int, int)), this, SLOT(onRowsInserted(QModelIndex, int, int)));
35+ QObject::connect(m_parentModel, SIGNAL(rowsRemoved(QModelIndex, int, int)), this, SLOT(onRowsRemoved(QModelIndex, int, int)));
36+ QObject::connect(m_parentModel, SIGNAL(modelReset()), this, SLOT(onModelReset()));
37+ }
38+ }
39+
40+ UnityMenuModel* model() const { return m_model; }
41+
42+private Q_SLOTS:
43+ void onRowsInserted(const QModelIndex&, int start, int end)
44+ {
45+ int delta = end-start + 1;
46+ if (start <= m_index) {
47+ m_index += delta;
48+ }
49+ }
50+
51+ void onRowsRemoved(const QModelIndex&, int start, int end)
52+ {
53+ int delta = end-start + 1;
54+ if (start <= m_index) {
55+ if (start + delta > m_index) {
56+ // in the range removed
57+ Q_EMIT remove();
58+ disconnect(m_parentModel, 0, this, 0);
59+ } else {
60+ m_index -= delta;
61+ }
62+ }
63+ }
64+
65+ void onModelReset()
66+ {
67+ Q_EMIT remove();
68+ disconnect(m_parentModel, 0, this, 0);
69+ }
70+
71+Q_SIGNALS:
72+ void remove();
73+
74+private:
75+ UnityMenuModel* m_model;
76+ UnityMenuModel* m_parentModel;
77+ int m_index;
78+};
79+
2280UnityMenuModelStack::UnityMenuModelStack(QObject* parent)
2381 : QObject(parent)
2482{
@@ -26,31 +84,44 @@ UnityMenuModelStack::UnityMenuModelStack(QObject* parent)
2684
2785UnityMenuModelStack::~UnityMenuModelStack()
2886{
87+ qDeleteAll(m_menuModels);
88+ m_menuModels.clear();
2989}
3090
3191UnityMenuModel* UnityMenuModelStack::head() const
3292{
33− return !m_menuModels.isEmpty() ? m_menuModels.first() : NULL;
93+ return !m_menuModels.isEmpty() ? m_menuModels.first()->model() : NULL;
3494}
3595
3696void UnityMenuModelStack::setHead(UnityMenuModel* model)
3797{
3898 if (head() != model) {
99+ qDeleteAll(m_menuModels);
39100 m_menuModels.clear();
40− push(model);
101+
102+ push(model, 0);
41103 Q_EMIT headChanged(model);
42104 }
43105}
44106
45107UnityMenuModel* UnityMenuModelStack::tail() const
46108{
47− return !m_menuModels.isEmpty() ? m_menuModels.last() : NULL;
109+ return !m_menuModels.isEmpty() ? m_menuModels.last()->model() : NULL;
110+}
111+
112+int UnityMenuModelStack::count() const
113+{
114+ return m_menuModels.count();
48115}
49116
50−void UnityMenuModelStack::push(UnityMenuModel* model)
117+void UnityMenuModelStack::push(UnityMenuModel* model, int index)
51118{
52− m_menuModels << model;
119+ UnityMenuModelEntry* entry = new UnityMenuModelEntry(model, tail(), index);
120+ QObject::connect(entry, SIGNAL(remove()), SLOT(onRemove()));
121+
122+ m_menuModels << entry;
53123 Q_EMIT tailChanged(model);
124+ Q_EMIT countChanged(m_menuModels.count());
54125}
55126
56127UnityMenuModel* UnityMenuModelStack::pop()
@@ -58,12 +129,32 @@ UnityMenuModel* UnityMenuModelStack::pop()
58129 if (m_menuModels.isEmpty()) {
59130 return NULL;
60131 }
61− UnityMenuModel* model = m_menuModels.takeLast();
132+ UnityMenuModelEntry* entry = m_menuModels.takeLast();
133+ UnityMenuModel* model = entry->model();
134+ entry->deleteLater();
62135
63136 Q_EMIT tailChanged(tail());
64137 if (m_menuModels.isEmpty()) {
65138 Q_EMIT headChanged(NULL);
66139 }
140+ Q_EMIT countChanged(m_menuModels.count());
67141
68142 return model;
69−}
143+}
144+
145+void UnityMenuModelStack::onRemove()
146+{
147+ UnityMenuModelEntry* removed = qobject_cast<UnityMenuModelEntry*>(sender());
148+ if (!m_menuModels.contains(removed))
149+ return;
150+
151+ for (int i = m_menuModels.count() -1; i >= 0; i--) {
152+ UnityMenuModelEntry* entry = m_menuModels[i];
153+ pop();
154+ if (entry == removed) {
155+ break;
156+ }
157+ }
158+}
159+
160+#include "unitymenumodelstack.moc"
plugins/Unity/Indicators/unitymenumodelstack.h+10−2
@@ -25,6 +25,7 @@
2525#include <QObject>
2626#include <QList>
2727
28+class UnityMenuModelEntry;
2829class UnityMenuModel;
2930
3031// A LIFO queue for storing the current submenu of a UnityMenuModel.
@@ -37,6 +38,7 @@ class UNITYINDICATORS_EXPORT UnityMenuModelStack : public QObject
3738 Q_OBJECT
3839 Q_PROPERTY(UnityMenuModel* head READ head WRITE setHead NOTIFY headChanged)
3940 Q_PROPERTY(UnityMenuModel* tail READ tail NOTIFY tailChanged)
41+ Q_PROPERTY(int count READ count NOTIFY countChanged)
4042public:
4143 UnityMenuModelStack(QObject*parent=NULL);
4244 ~UnityMenuModelStack();
@@ -46,15 +48,21 @@ public:
4648
4749 UnityMenuModel* tail() const;
4850
49− Q_INVOKABLE void push(UnityMenuModel* model);
51+ int count() const;
52+
53+ Q_INVOKABLE void push(UnityMenuModel* model, int menuIndex);
5054 Q_INVOKABLE UnityMenuModel* pop();
5155
5256Q_SIGNALS:
5357 void headChanged(UnityMenuModel* head);
5458 void tailChanged(UnityMenuModel* tail);
59+ void countChanged(int count);
60+
61+private Q_SLOTS:
62+ void onRemove();
5563
5664private:
57− QList<UnityMenuModel*> m_menuModels;
65+ QList<UnityMenuModelEntry*> m_menuModels;
5866};
5967
6068#endif // UNITYMENUMODELSTACK_H
plugins/Unity/Launcher/launcheritem.cpp+4−2
@@ -20,6 +20,8 @@
2020#include "launcheritem.h"
2121#include "quicklistmodel.h"
2222
23+#include <libintl.h>
24+
2325LauncherItem::LauncherItem(const QString &appId, const QString &name, const QString &icon, QObject *parent) :
2426 LauncherItemInterface(parent),
2527 m_appId(appId),
@@ -38,7 +40,7 @@ LauncherItem::LauncherItem(const QString &appId, const QString &name, const QStr
3840 m_quickList->appendAction(nameAction);
3941 QuickListEntry pinningAction;
4042 pinningAction.setActionId("pin_item");
41− pinningAction.setText("Pin to Launcher");
43+ pinningAction.setText(gettext("Lock to Launcher"));
4244 m_quickList->appendAction(pinningAction);
4345}
4446
@@ -68,7 +70,7 @@ void LauncherItem::setPinned(bool pinned)
6870 m_pinned = pinned;
6971 QuickListEntry entry;
7072 entry.setActionId("pin_item");
71− entry.setText(pinned ? "Remove from Launcher": "Pin to Launcher");
73+ entry.setText(pinned ? gettext("Unlock from Launcher") : gettext("Lock to Launcher"));
7274 m_quickList->updateAction(entry);
7375 Q_EMIT pinnedChanged(pinned);
7476 }
plugins/Unity/abstractfilteroption.hdeleted−58
@@ -1,58 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * Authors:
5− * Pawel Stolowski <pawel.stolowski@canonical.com>
6− *
7− * This program is free software; you can redistribute it and/or modify
8− * it under the terms of the GNU General Public License as published by
9− * the Free Software Foundation; version 3.
10− *
11− * This program is distributed in the hope that it will be useful,
12− * but WITHOUT ANY WARRANTY; without even the implied warranty of
13− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14− * GNU General Public License for more details.
15− *
16− * You should have received a copy of the GNU General Public License
17− * along with this program. If not, see <http://www.gnu.org/licenses/>.
18− */
19−
20−#ifndef ABSTRACTFILTEROPTION_H
21−#define ABSTRACTFILTEROPTION_H
22−
23−// Qt
24−#include <QObject>
25−#include <QMetaType>
26−
27−class Q_DECL_EXPORT AbstractFilterOption : public QObject
28−{
29− Q_OBJECT
30−
31− Q_PROPERTY(QString id READ id NOTIFY idChanged)
32− Q_PROPERTY(QString name READ name NOTIFY nameChanged)
33− Q_PROPERTY(QString iconHint READ iconHint NOTIFY iconHintChanged)
34− Q_PROPERTY(bool active READ active WRITE setActive NOTIFY activeChanged)
35−
36−public:
37− /* getters */
38− virtual QString id() const = 0;
39− virtual QString name() const = 0;
40− virtual QString iconHint() const = 0;
41− virtual bool active() const = 0;
42−
43− /* setters */
44− virtual void setActive(bool active) = 0;
45−
46−protected:
47− AbstractFilterOption(QObject *parent);
48−
49−Q_SIGNALS:
50− void idChanged(const QString &);
51− void nameChanged(const QString &);
52− void iconHintChanged(const QString &);
53− void activeChanged(bool);
54−};
55−
56−Q_DECLARE_METATYPE(AbstractFilterOption*)
57−
58−#endif // ABSTRACTFILTEROPTION_H
plugins/Unity/applicationpreview.cppdeleted−100
@@ -1,100 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * Authors:
5− * Pawel Stolowski <pawel.stolowski@canonical.com>
6− *
7− * This program is free software; you can redistribute it and/or modify
8− * it under the terms of the GNU General Public License as published by
9− * the Free Software Foundation; version 3.
10− *
11− * This program is distributed in the hope that it will be useful,
12− * but WITHOUT ANY WARRANTY; without even the implied warranty of
13− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14− * GNU General Public License for more details.
15− *
16− * You should have received a copy of the GNU General Public License
17− * along with this program. If not, see <http://www.gnu.org/licenses/>.
18− */
19−
20−// local
21−#include "applicationpreview.h"
22−#include "iconutils.h"
23−
24−#include <QDebug>
25−
26−ApplicationPreview::ApplicationPreview(QObject *parent):
27− Preview(parent),
28− m_unityAppPreview(nullptr)
29−{
30−}
31−
32−QString ApplicationPreview::lastUpdate() const
33−{
34− if (m_unityAppPreview) {
35− return QString::fromStdString(m_unityAppPreview->last_update());
36− } else {
37− qWarning() << "Preview not set";
38− }
39− return QString();
40−}
41−
42−QString ApplicationPreview::copyright() const
43−{
44− if (m_unityAppPreview) {
45− return QString::fromStdString(m_unityAppPreview->copyright());
46− } else {
47− qWarning() << "Preview not set";
48− }
49− return QString();
50−}
51−
52−QString ApplicationPreview::license() const
53−{
54− if (m_unityAppPreview) {
55− return QString::fromStdString(m_unityAppPreview->license());
56− } else {
57− qWarning() << "Preview not set";
58− }
59− return QString();
60−}
61−
62−QString ApplicationPreview::appIcon() const
63−{
64− if (m_unityAppPreview) {
65− auto giconString = g_icon_to_string(m_unityAppPreview->app_icon());
66− QString result(gIconToDeclarativeImageProviderString(QString::fromUtf8(giconString)));
67− g_free(giconString);
68− return result;
69− } else {
70− qWarning() << "Preview not set";
71− }
72− return QString();
73−}
74−
75−float ApplicationPreview::rating() const
76−{
77− if (m_unityAppPreview) {
78− return m_unityAppPreview->rating();
79− } else {
80− qWarning() << "Preview not set";
81− }
82− return 0.0f;
83−}
84−
85−unsigned int ApplicationPreview::numRatings() const
86−{
87− if (m_unityAppPreview) {
88− return m_unityAppPreview->num_ratings();
89− } else {
90− qWarning() << "Preview not set";
91− }
92− return 0;
93−}
94−
95−void ApplicationPreview::setUnityPreview(unity::dash::Preview::Ptr unityPreview)
96−{
97− m_unityAppPreview = std::dynamic_pointer_cast<unity::dash::ApplicationPreview>(unityPreview);
98−
99− Q_EMIT previewChanged();
100−}
plugins/Unity/applicationpreview.hdeleted−66
@@ -1,66 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * Authors:
5− * Pawel Stolowski <pawel.stolowski@canonical.com>
6− *
7− * This program is free software; you can redistribute it and/or modify
8− * it under the terms of the GNU General Public License as published by
9− * the Free Software Foundation; version 3.
10− *
11− * This program is distributed in the hope that it will be useful,
12− * but WITHOUT ANY WARRANTY; without even the implied warranty of
13− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14− * GNU General Public License for more details.
15− *
16− * You should have received a copy of the GNU General Public License
17− * along with this program. If not, see <http://www.gnu.org/licenses/>.
18− */
19−
20−#ifndef APPLICATIONPREVIEW_H
21−#define APPLICATIONPREVIEW_H
22−
23−// local
24−#include "preview.h"
25−
26−// Qt
27−#include <QObject>
28−#include <QMetaType>
29−
30−// libunity-core
31−#include <UnityCore/ApplicationPreview.h>
32−
33−class Q_DECL_EXPORT ApplicationPreview: public Preview
34−{
35− Q_OBJECT
36−
37− Q_PROPERTY(QString lastUpdate READ lastUpdate NOTIFY previewChanged)
38− Q_PROPERTY(QString copyright READ copyright NOTIFY previewChanged)
39− Q_PROPERTY(QString license READ license NOTIFY previewChanged)
40− Q_PROPERTY(QString appIcon READ appIcon NOTIFY previewChanged)
41− Q_PROPERTY(float rating READ rating NOTIFY previewChanged)
42− Q_PROPERTY(unsigned int numRatings READ numRatings NOTIFY previewChanged)
43−
44−public:
45− explicit ApplicationPreview(QObject *parent = 0);
46−
47− QString lastUpdate() const;
48− QString copyright() const;
49− QString license() const;
50− QString appIcon() const;
51− float rating() const;
52− unsigned int numRatings() const;
53−
54−Q_SIGNALS:
55− void previewChanged();
56−
57−protected:
58− void setUnityPreview(unity::dash::Preview::Ptr unityPreview) override;
59−
60−private:
61− unity::dash::ApplicationPreview::Ptr m_unityAppPreview;
62−};
63−
64−Q_DECLARE_METATYPE(ApplicationPreview *)
65−
66−#endif
plugins/Unity/categories.cppdeleted−299
@@ -1,299 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * Authors:
5− * Michał Sawicz <michal.sawicz@canonical.com>
6− * Michal Hruby <michal.hruby@canonical.com>
7− *
8− * This program is free software; you can redistribute it and/or modify
9− * it under the terms of the GNU General Public License as published by
10− * the Free Software Foundation; version 3.
11− *
12− * This program is distributed in the hope that it will be useful,
13− * but WITHOUT ANY WARRANTY; without even the implied warranty of
14− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15− * GNU General Public License for more details.
16− *
17− * You should have received a copy of the GNU General Public License
18− * along with this program. If not, see <http://www.gnu.org/licenses/>.
19− */
20−
21−// self
22−#include "categories.h"
23−#include "categoryresults.h"
24−#include <QDebug>
25−
26−// TODO: use something from libunity once it's public
27−enum CategoryColumn {
28− ID,
29− DISPLAY_NAME,
30− ICON_HINT,
31− RENDERER_NAME,
32− HINTS
33−};
34−
35−Categories::Categories(QObject* parent)
36− : DeeListModel(parent)
37−{
38− m_roles[Categories::RoleCategoryId] = "categoryId";
39− m_roles[Categories::RoleName] = "name";
40− m_roles[Categories::RoleIcon] = "icon";
41− m_roles[Categories::RoleRenderer] = "renderer";
42− m_roles[Categories::RoleContentType] = "contentType";
43− m_roles[Categories::RoleRendererHint] = "rendererHint";
44− m_roles[Categories::RoleProgressSource] = "progressSource";
45− m_roles[Categories::RoleHints] = "hints";
46− m_roles[Categories::RoleResults] = "results";
47− m_roles[Categories::RoleCount] = "count";
48−
49− // TODO This should not be needed but accumulatting the count changes
50− // makes the visualization more stable and also makes crashes on fast
51− // change of the search term harder to reproduce
52− m_timer.setSingleShot(true);
53− m_timer.setInterval(50);
54− connect(&m_timer, &QTimer::timeout, this, &Categories::onEmitCountChanged);
55−}
56−
57−DeeListModel*
58−Categories::getResults(int index) const
59−{
60− if (!m_results.contains(index)) {
61− CategoryResults* results = new CategoryResults(const_cast<Categories*>(this));
62− results->setCategoryIndex(index);
63− connect(results, &DeeListModel::countChanged, this, &Categories::onCountChanged);
64−
65− unsigned categoryIndex = static_cast<unsigned>(index);
66− auto unity_results = m_unityScope->GetResultsForCategory(categoryIndex);
67− if (unity_results) {
68− results->setModel(unity_results->model());
69− } else {
70− // No results model returned by unity core; this can be the case when the global
71− // results model of this scope is still not set in unity core. Don't set backend
72− // model in DeeListModel - it will still beahve properly as an empty model. Since
73− // we're connected to the category model change signal, and it is set by unity core
74− // at the same time as results model (on channel opening), we'll reset category
75− // results models with proper models when we're notifed again.
76− qWarning() << "No results model for category" << categoryIndex;
77− }
78−
79− m_results.insert(index, results);
80− }
81−
82− return m_results[index];
83−}
84−
85−void Categories::onCategoriesModelChanged(unity::glib::Object<DeeModel> model)
86−{
87− m_updatedCategories.clear();
88− // FIXME: this might destroy the renderer view and re-create it, optimize?
89− Q_FOREACH(DeeListModel* model, m_results) {
90− delete model;
91− }
92− m_results.clear();
93− m_categoryOrder.clear();
94−
95− setModel(model);
96−}
97−
98−void Categories::onCategoryOrderChanged(const std::vector<unsigned int>& cat_order)
99−{
100− for (unsigned int pos = 0; pos<cat_order.size(); pos++)
101− {
102− unsigned int cat = cat_order[pos];
103− const int old_pos = m_categoryOrder.indexOf(cat);
104−
105− if (old_pos < 0) {
106− qWarning() << "No such category index:" << cat;
107− continue;
108− }
109−
110− if (static_cast<int>(pos) != old_pos) {
111− int target_pos = pos;
112− if (target_pos > old_pos)
113− target_pos++;
114− const bool status = beginMoveRows(QModelIndex(), old_pos, old_pos, QModelIndex(), target_pos);
115− if (status)
116− m_categoryOrder.move(old_pos, pos);
117− else
118− qWarning() << "beginMoveRows failed:" << old_pos << target_pos;
119− endMoveRows();
120− }
121− }
122−}
123−
124−void
125−Categories::setUnityScope(const unity::dash::Scope::Ptr& scope)
126−{
127− m_unityScope = scope;
128−
129− // no need to call this, we'll get notified
130− //setModel(m_unityScope->categories()->model());
131−
132− m_signals.disconnectAll();
133− m_signals << m_unityScope->categories()->model.changed.connect(sigc::mem_fun(this, &Categories::onCategoriesModelChanged));
134−
135− // FIXME: Don't handle category order changes for now as it causes UI issues (https://bugs.launchpad.net/unity8/+bug/1239584).
136− //m_signals << m_unityScope->category_order.changed.connect(sigc::mem_fun(this, &Categories::onCategoryOrderChanged));
137−}
138−
139−void
140−Categories::onCountChanged()
141−{
142− CategoryResults* results = qobject_cast<CategoryResults*>(sender());
143− if (results) {
144− if (!m_updatedCategories.contains(results->categoryIndex())) {
145− m_updatedCategories << results->categoryIndex();
146− }
147− m_timer.start();
148− }
149−}
150−
151−void Categories::onRowCountChanged()
152−{
153− QAbstractItemModel* model = qobject_cast<QAbstractItemModel*>(sender());
154− // find the corresponding category index
155− for (auto iter = m_overriddenCategories.begin(); iter != m_overriddenCategories.end(); ++iter) {
156− if (iter.value() == model) {
157− for (int i = 0; i < rowCount(); i++) {
158− auto id = data(index(i), RoleCategoryId).toString();
159− if (id != iter.key()) continue;
160− QVector<int> roles;
161− roles.append(RoleCount);
162− QModelIndex changedIndex = index(i);
163− Q_EMIT dataChanged(changedIndex, changedIndex, roles);
164− break;
165− }
166− }
167− }
168−}
169−
170−void
171−Categories::onEmitCountChanged()
172−{
173− QVector<int> roles;
174− roles.append(Categories::RoleCount);
175− Q_FOREACH(int categoryIndex, m_updatedCategories) {
176− if (!m_results.contains(categoryIndex)) continue;
177− const int realIndex = m_categoryOrder.indexOf(categoryIndex);
178− const QModelIndex changedIndex = index(realIndex);
179− Q_EMIT dataChanged(changedIndex, changedIndex, roles);
180− }
181− m_updatedCategories.clear();
182−}
183−
184−QHash<int, QByteArray>
185−Categories::roleNames() const
186−{
187− return m_roles;
188−}
189−
190−void Categories::onOverrideModelDestroyed()
191−{
192− QObject* model = sender();
193− auto iter = m_overriddenCategories.begin();
194− while (iter != m_overriddenCategories.end()) {
195− if (iter.value() == model) {
196− iter = m_overriddenCategories.erase(iter);
197− continue;
198− }
199− ++iter;
200− }
201−}
202−
203−void Categories::overrideResults(const QString& categoryId, QAbstractItemModel* model)
204−{
205− m_overriddenCategories[categoryId] = model;
206− // watch the model
207− connect(model, &QObject::destroyed, this, &Categories::onOverrideModelDestroyed);
208− connect(model, &QAbstractItemModel::rowsInserted, this, &Categories::onRowCountChanged);
209− connect(model, &QAbstractItemModel::rowsRemoved, this, &Categories::onRowCountChanged);
210− connect(model, &QAbstractItemModel::modelReset, this, &Categories::onRowCountChanged);
211−
212− // emit the dataChanged signal if the category is already in the model
213− for (int i = 0; i < rowCount(); i++) {
214− auto id = data(index(i), RoleCategoryId).toString();
215− if (id != categoryId) continue;
216− QVector<int> roles;
217− roles.append(RoleCount);
218− roles.append(RoleResults);
219− QModelIndex changedIndex = index(i);
220− Q_EMIT dataChanged(changedIndex, changedIndex, roles);
221− break;
222− }
223−}
224−
225−QVariant
226−Categories::data(const QModelIndex& index, int role) const
227−{
228− if (!index.isValid()) {
229− return QVariant();
230− }
231−
232− if (m_categoryOrder.size() != rowCount())
233− {
234− // populate category order vector with 0..n
235− m_categoryOrder.clear();
236− const unsigned int lim = rowCount();
237− for (unsigned int i = 0; i<lim; i++) {
238− m_categoryOrder.append(i);
239− }
240− }
241−
242− int realRow = index.row();
243− if (index.row() < m_categoryOrder.size()) {
244− realRow = m_categoryOrder[index.row()];
245− } else {
246− qWarning() << "Invalid index" << index.row();
247− return QVariant();
248− }
249−
250− const QModelIndex realIndex = createIndex(realRow, index.column());
251−
252− switch (role) {
253− case RoleCategoryId:
254− return DeeListModel::data(realIndex, CategoryColumn::ID);
255− case RoleName:
256− return DeeListModel::data(realIndex, CategoryColumn::DISPLAY_NAME);
257− case RoleIcon:
258− return DeeListModel::data(realIndex, CategoryColumn::ICON_HINT);
259− case RoleRenderer:
260− return DeeListModel::data(realIndex, CategoryColumn::RENDERER_NAME);
261− case RoleContentType:
262− {
263− auto hints = DeeListModel::data(realIndex, CategoryColumn::HINTS).toHash();
264− return hints.contains("content-type") ? hints["content-type"] : QVariant(QString("default"));
265− }
266− case RoleRendererHint:
267− {
268− auto hints = DeeListModel::data(realIndex, CategoryColumn::HINTS).toHash();
269− return hints.contains("renderer-hint") ? hints["renderer-hint"] : QVariant(QString());
270− }
271− case RoleProgressSource:
272− {
273− auto hints = DeeListModel::data(realIndex, CategoryColumn::HINTS).toHash();
274− return hints.contains("progress-source") ? hints["progress-source"] : QVariant();
275− }
276− case RoleHints:
277− return DeeListModel::data(realIndex, CategoryColumn::HINTS);
278− case RoleResults:
279− if (m_overriddenCategories.size() > 0)
280− {
281− auto id = DeeListModel::data(realIndex, CategoryColumn::ID).toString();
282− if (m_overriddenCategories.find(id) != m_overriddenCategories.end())
283− return QVariant::fromValue(m_overriddenCategories[id]);
284− }
285− return QVariant::fromValue(getResults(realRow));
286− case RoleCount:
287− if (m_overriddenCategories.size() > 0)
288− {
289− auto id = DeeListModel::data(realIndex, CategoryColumn::ID).toString();
290− if (m_overriddenCategories.find(id) != m_overriddenCategories.end())
291− {
292− return QVariant::fromValue(m_overriddenCategories[id]->rowCount());
293− }
294− }
295− return QVariant::fromValue(getResults(realRow)->rowCount());
296− default:
297− return QVariant();
298− }
299−}
plugins/Unity/categories.hdeleted−95
@@ -1,95 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * Authors:
5− * Michał Sawicz <michal.sawicz@canonical.com>
6− * Michal Hruby <michal.hruby@canonical.com>
7− *
8− * This program is free software; you can redistribute it and/or modify
9− * it under the terms of the GNU General Public License as published by
10− * the Free Software Foundation; version 3.
11− *
12− * This program is distributed in the hope that it will be useful,
13− * but WITHOUT ANY WARRANTY; without even the implied warranty of
14− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15− * GNU General Public License for more details.
16− *
17− * You should have received a copy of the GNU General Public License
18− * along with this program. If not, see <http://www.gnu.org/licenses/>.
19− */
20−
21−
22−#ifndef CATEGORIES_H
23−#define CATEGORIES_H
24−
25−// unity-core
26−#include <UnityCore/Scope.h>
27−
28−// dee-qt
29−#include "deelistmodel.h"
30−
31−#include <QPointer>
32−#include <QSet>
33−#include <QTimer>
34−
35−// local
36−#include "signalslist.h"
37−
38−class Categories : public DeeListModel
39−{
40− Q_OBJECT
41−
42− Q_ENUMS(Roles)
43−
44−public:
45− explicit Categories(QObject* parent = 0);
46−
47− enum Roles {
48− RoleCategoryId,
49− RoleName,
50− RoleIcon,
51− RoleRenderer,
52− RoleContentType,
53− RoleRendererHint,
54− RoleProgressSource,
55− RoleHints,
56− RoleResults,
57− RoleCount
58− };
59−
60− Q_INVOKABLE void overrideResults(const QString& categoryId, QAbstractItemModel* model);
61−
62− QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
63−
64− QHash<int, QByteArray> roleNames() const;
65−
66− /* setters */
67− void setUnityScope(const unity::dash::Scope::Ptr& scope);
68−
69−private Q_SLOTS:
70− void onCountChanged();
71− void onRowCountChanged();
72− void onEmitCountChanged();
73− void onOverrideModelDestroyed();
74−
75−private:
76− void onCategoriesModelChanged(unity::glib::Object<DeeModel> model);
77− void onCategoryOrderChanged(const std::vector<unsigned int>& cat_order);
78−
79− DeeListModel* getResults(int index) const;
80−
81− unity::dash::Scope::Ptr m_unityScope;
82− QTimer m_timer;
83− QSet<int> m_updatedCategories;
84− QHash<int, QByteArray> m_roles;
85− QMap<QString, QAbstractItemModel*> m_overriddenCategories;
86− mutable QMap<int, DeeListModel*> m_results;
87− SignalsList m_signals;
88−
89− /* Category order array contains indices of actual categories in the underlying DeeListModel.
90− It's used internally to reflect category order reported by scope.
91− */
92− mutable QList<unsigned int> m_categoryOrder;
93−};
94−
95−#endif // CATEGORIES_H
plugins/Unity/checkoptionfilter.cppdeleted−65
@@ -1,65 +0,0 @@
1−/*
2− * Copyright (C) 2011 Canonical, Ltd.
3− *
4− * Authors:
5− * Florian Boucault <florian.boucault@canonical.com>
6− *
7− * This program is free software; you can redistribute it and/or modify
8− * it under the terms of the GNU General Public License as published by
9− * the Free Software Foundation; version 3.
10− *
11− * This program is distributed in the hope that it will be useful,
12− * but WITHOUT ANY WARRANTY; without even the implied warranty of
13− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14− * GNU General Public License for more details.
15− *
16− * You should have received a copy of the GNU General Public License
17− * along with this program. If not, see <http://www.gnu.org/licenses/>.
18− */
19−
20−// Self
21−#include "checkoptionfilter.h"
22−
23−// local
24−#include "unityoptionsmodel.h"
25−
26−CheckOptionFilter::CheckOptionFilter(QObject *parent) :
27− Filter(parent),
28− m_unityCheckOptionFilter(nullptr),
29− m_options(nullptr)
30−{
31−}
32−
33−GenericOptionsModel* CheckOptionFilter::options() const
34−{
35− return m_options;
36−}
37−
38−void CheckOptionFilter::setUnityFilter(unity::dash::Filter::Ptr filter)
39−{
40− Filter::setUnityFilter(filter);
41− m_unityCheckOptionFilter = std::dynamic_pointer_cast<unity::dash::CheckOptionFilter>(m_unityFilter);
42− onOptionsChanged(m_unityCheckOptionFilter->options);
43−}
44−
45−void CheckOptionFilter::onOptionsChanged(unity::dash::CheckOptionFilter::CheckOptions options)
46−{
47− if (m_options != nullptr) {
48− m_signals.disconnectAll();
49− delete m_options;
50− m_options = nullptr;
51− }
52−
53− m_options = new UnityOptionsModel(this, options,
54− m_unityCheckOptionFilter->option_added,
55− m_unityCheckOptionFilter->option_removed,
56− m_unityCheckOptionFilter->show_all_button);
57−
58− connect(m_options, SIGNAL(activeChanged(AbstractFilterOption *)), m_options, SLOT(ensureTheOnlyActive(AbstractFilterOption *)));
59− connect(m_options, SIGNAL(showAllActivated()), this, SLOT(clear()));
60−
61− /* Property change signals */
62− m_signals << m_unityCheckOptionFilter->options.changed.connect(sigc::mem_fun(this, &CheckOptionFilter::onOptionsChanged));
63−
64− Q_EMIT optionsChanged();
65−}
plugins/Unity/checkoptionfilter.hdeleted−57
@@ -1,57 +0,0 @@
1−/*
2− * Copyright (C) 2011 Canonical, Ltd.
3− *
4− * Authors:
5− * Florian Boucault <florian.boucault@canonical.com>
6− *
7− * This program is free software; you can redistribute it and/or modify
8− * it under the terms of the GNU General Public License as published by
9− * the Free Software Foundation; version 3.
10− *
11− * This program is distributed in the hope that it will be useful,
12− * but WITHOUT ANY WARRANTY; without even the implied warranty of
13− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14− * GNU General Public License for more details.
15− *
16− * You should have received a copy of the GNU General Public License
17− * along with this program. If not, see <http://www.gnu.org/licenses/>.
18− */
19−
20−#ifndef CHECKOPTIONFILTER_H
21−#define CHECKOPTIONFILTER_H
22−
23−// Qt
24−#include <QObject>
25−#include <QMetaType>
26−
27−// libunity-core
28−#include <UnityCore/CheckOptionFilter.h>
29−
30−// Local
31−#include "filter.h"
32−#include "signalslist.h"
33−
34−class Q_DECL_EXPORT CheckOptionFilter : public Filter
35−{
36− Q_OBJECT
37−
38−public:
39− explicit CheckOptionFilter(QObject *parent = nullptr);
40−
41− /* getters */
42− GenericOptionsModel* options() const override;
43−
44−protected:
45− void setUnityFilter(unity::dash::Filter::Ptr filter) override;
46−
47−private:
48− void onOptionsChanged(unity::dash::CheckOptionFilter::CheckOptions filter);
49−
50− unity::dash::CheckOptionFilter::Ptr m_unityCheckOptionFilter;
51− SignalsList m_signals;
52− GenericOptionsModel* m_options;
53−};
54−
55−Q_DECLARE_METATYPE(CheckOptionFilter*)
56−
57−#endif // CHECKOPTIONFILTER_H
plugins/Unity/filter.cppdeleted−129
@@ -1,129 +0,0 @@
1−/*
2− * Copyright (C) 2011, 2013 Canonical, Ltd.
3− *
4− * Authors:
5− * Florian Boucault <florian.boucault@canonical.com>
6− * Pawel Stolowski <pawel.stolowski@canonical.com>
7− *
8− * This program is free software; you can redistribute it and/or modify
9− * it under the terms of the GNU General Public License as published by
10− * the Free Software Foundation; version 3.
11− *
12− * This program is distributed in the hope that it will be useful,
13− * but WITHOUT ANY WARRANTY; without even the implied warranty of
14− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15− * GNU General Public License for more details.
16− *
17− * You should have received a copy of the GNU General Public License
18− * along with this program. If not, see <http://www.gnu.org/licenses/>.
19− */
20−
21−// Self
22−#include "filter.h"
23−
24−// local
25−#include "ratingsfilter.h"
26−#include "radiooptionfilter.h"
27−#include "checkoptionfilter.h"
28−#include "multirangefilter.h"
29−
30−// libunity-core
31−#include <UnityCore/Filter.h>
32−#include <UnityCore/RatingsFilter.h>
33−#include <UnityCore/RadioOptionFilter.h>
34−#include <UnityCore/CheckOptionFilter.h>
35−#include <UnityCore/MultiRangeFilter.h>
36−
37−// Qt
38−#include <QDebug>
39−
40−Filter::Filter(QObject *parent) :
41− QObject(parent)
42−{
43−}
44−
45−QString Filter::id() const
46−{
47− if (!m_unityFilter)
48− return QString::Null();
49− return QString::fromStdString(m_unityFilter->id());
50−}
51−
52−QString Filter::name() const
53−{
54− if (!m_unityFilter)
55− return QString::Null();
56− return QString::fromStdString(m_unityFilter->name());
57−}
58−
59−QString Filter::iconHint() const
60−{
61− if (!m_unityFilter)
62− return QString::Null();
63− return QString::fromStdString(m_unityFilter->icon_hint());
64−}
65−
66−QString Filter::rendererName() const
67−{
68− if (!m_unityFilter)
69− return QString::Null();
70− return QString::fromStdString(m_unityFilter->renderer_name());
71−}
72−
73−bool Filter::visible() const
74−{
75− if (!m_unityFilter)
76− return false;
77− return m_unityFilter->visible();
78−}
79−
80−bool Filter::collapsed() const
81−{
82− if (!m_unityFilter)
83− return false;
84− return m_unityFilter->collapsed();
85−}
86−
87−bool Filter::filtering() const
88−{
89− if (!m_unityFilter)
90− return false;
91− return m_unityFilter->filtering();
92−}
93−
94−void Filter::clear()
95−{
96− if (m_unityFilter)
97− m_unityFilter->Clear();
98−}
99−
100−void Filter::setUnityFilter(unity::dash::Filter::Ptr unityFilter)
101−{
102− m_unityFilter = unityFilter;
103−}
104−
105−Filter* Filter::newFromUnityFilter(unity::dash::Filter::Ptr unityFilter)
106−{
107− Filter* filter;
108−
109− if (typeid(*unityFilter) == typeid(unity::dash::RatingsFilter)) {
110− filter = new RatingsFilter;
111− } else if (typeid(*unityFilter) == typeid(unity::dash::CheckOptionFilter)) {
112− filter = new CheckOptionFilter;
113− } else if (typeid(*unityFilter) == typeid(unity::dash::RadioOptionFilter)) {
114− filter = new RadioOptionFilter;
115− } else if (typeid(*unityFilter) == typeid(unity::dash::MultiRangeFilter)) {
116− filter = new MultiRangeFilter;
117− } else {
118− qWarning() << "Filter of unknown type: " << typeid(*unityFilter).name();
119− return nullptr;
120− }
121−
122− filter->setUnityFilter(unityFilter);
123− return filter;
124−}
125−
126−bool Filter::hasUnityFilter(unity::dash::Filter::Ptr unityFilter) const
127−{
128− return m_unityFilter == unityFilter;
129−}
plugins/Unity/filter.hdeleted−75
@@ -1,75 +0,0 @@
1−/*
2− * Copyright (C) 2011, 2013 Canonical, Ltd.
3− *
4− * Authors:
5− * Florian Boucault <florian.boucault@canonical.com>
6− * Pawel Stolowski <pawel.stolowski@canonical.com>
7− *
8− * This program is free software; you can redistribute it and/or modify
9− * it under the terms of the GNU General Public License as published by
10− * the Free Software Foundation; version 3.
11− *
12− * This program is distributed in the hope that it will be useful,
13− * but WITHOUT ANY WARRANTY; without even the implied warranty of
14− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15− * GNU General Public License for more details.
16− *
17− * You should have received a copy of the GNU General Public License
18− * along with this program. If not, see <http://www.gnu.org/licenses/>.
19− */
20−
21−#ifndef FILTER_H
22−#define FILTER_H
23−
24−// Qt
25−#include <QObject>
26−#include <QMetaType>
27−
28−// libunity-core
29−#include <UnityCore/Filter.h>
30−
31−class GenericOptionsModel;
32−
33−class Q_DECL_EXPORT Filter : public QObject
34−{
35− Q_OBJECT
36−
37− Q_PROPERTY(QString id READ id CONSTANT)
38− Q_PROPERTY(QString name READ name CONSTANT)
39− Q_PROPERTY(QString iconHint READ iconHint CONSTANT)
40− Q_PROPERTY(QString rendererName READ rendererName CONSTANT)
41− Q_PROPERTY(bool visible READ visible CONSTANT)
42− Q_PROPERTY(bool collapsed READ collapsed CONSTANT)
43− Q_PROPERTY(bool filtering READ filtering CONSTANT)
44− Q_PROPERTY(GenericOptionsModel* options READ options NOTIFY optionsChanged)
45−
46−public:
47− explicit Filter(QObject *parent = nullptr);
48−
49− /* getters */
50− QString id() const;
51− QString name() const;
52− QString iconHint() const;
53− QString rendererName() const;
54− bool visible() const;
55− bool collapsed() const;
56− bool filtering() const;
57− virtual GenericOptionsModel* options() const = 0;
58−
59− static Filter* newFromUnityFilter(unity::dash::Filter::Ptr unityFilter);
60− bool hasUnityFilter(unity::dash::Filter::Ptr unityFilter) const;
61−
62−public Q_SLOTS:
63− void clear();
64−
65−Q_SIGNALS:
66− void optionsChanged();
67−
68−protected:
69− unity::dash::Filter::Ptr m_unityFilter;
70− virtual void setUnityFilter(unity::dash::Filter::Ptr unityFilter);
71−};
72−
73−Q_DECLARE_METATYPE(Filter*)
74−
75−#endif // FILTER_H
plugins/Unity/filteroption.cppdeleted−91
@@ -1,91 +0,0 @@
1−/*
2− * Copyright (C) 2011, 2013 Canonical, Ltd.
3− *
4− * Authors:
5− * Florian Boucault <florian.boucault@canonical.com>
6− * Pawel Stolowski <pawel.stolowski@canonical.com>
7− *
8− * This program is free software; you can redistribute it and/or modify
9− * it under the terms of the GNU General Public License as published by
10− * the Free Software Foundation; version 3.
11− *
12− * This program is distributed in the hope that it will be useful,
13− * but WITHOUT ANY WARRANTY; without even the implied warranty of
14− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15− * GNU General Public License for more details.
16− *
17− * You should have received a copy of the GNU General Public License
18− * along with this program. If not, see <http://www.gnu.org/licenses/>.
19− */
20−
21−// Self
22−#include "filteroption.h"
23−
24−// libunity-core
25−#include <UnityCore/Filter.h>
26−
27−FilterOption::FilterOption(unity::dash::FilterOption::Ptr unityFilterOption, QObject *parent) :
28− AbstractFilterOption(parent), m_unityFilterOption(nullptr)
29−{
30− setUnityFilterOption(unityFilterOption);
31−}
32−
33−QString FilterOption::id() const
34−{
35− return QString::fromStdString(m_unityFilterOption->id());
36−}
37−
38−QString FilterOption::name() const
39−{
40− return QString::fromStdString(m_unityFilterOption->name());
41−}
42−
43−QString FilterOption::iconHint() const
44−{
45− return QString::fromStdString(m_unityFilterOption->icon_hint());
46−}
47−
48−bool FilterOption::active() const
49−{
50− return m_unityFilterOption->active();
51−}
52−
53−void FilterOption::setActive(bool active)
54−{
55− m_unityFilterOption->active = active;
56−}
57−
58−void FilterOption::setUnityFilterOption(unity::dash::FilterOption::Ptr unityFilterOption)
59−{
60− if (m_unityFilterOption != nullptr) {
61− m_signals.disconnectAll();
62− }
63−
64− m_unityFilterOption = unityFilterOption;
65−
66− /* Property change signals */
67− m_signals << m_unityFilterOption->id.changed.connect(sigc::mem_fun(this, &FilterOption::onIdChanged))
68− << m_unityFilterOption->name.changed.connect(sigc::mem_fun(this, &FilterOption::onNameChanged))
69− << m_unityFilterOption->icon_hint.changed.connect(sigc::mem_fun(this, &FilterOption::onIconHintChanged))
70− << m_unityFilterOption->active.changed.connect(sigc::mem_fun(this, &FilterOption::onActiveChanged));
71−}
72−
73−void FilterOption::onIdChanged(const std::string &id)
74−{
75− Q_EMIT idChanged(QString::fromStdString(id));
76−}
77−
78−void FilterOption::onNameChanged(const std::string &name)
79−{
80− Q_EMIT nameChanged(QString::fromStdString(name));
81−}
82−
83−void FilterOption::onIconHintChanged(const std::string &iconHint)
84−{
85− Q_EMIT iconHintChanged(QString::fromStdString(iconHint));
86−}
87−
88−void FilterOption::onActiveChanged(bool active)
89−{
90− Q_EMIT activeChanged(active);
91−}
plugins/Unity/filteroption.hdeleted−61
@@ -1,61 +0,0 @@
1−/*
2− * Copyright (C) 2011, 2013 Canonical, Ltd.
3− *
4− * Authors:
5− * Florian Boucault <florian.boucault@canonical.com>
6− * Pawel Stolowski <pawel.stolowski@canonical.com>
7− *
8− * This program is free software; you can redistribute it and/or modify
9− * it under the terms of the GNU General Public License as published by
10− * the Free Software Foundation; version 3.
11− *
12− * This program is distributed in the hope that it will be useful,
13− * but WITHOUT ANY WARRANTY; without even the implied warranty of
14− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15− * GNU General Public License for more details.
16− *
17− * You should have received a copy of the GNU General Public License
18− * along with this program. If not, see <http://www.gnu.org/licenses/>.
19− */
20−
21−#ifndef FILTEROPTION_H
22−#define FILTEROPTION_H
23−
24−// Local
25−#include "abstractfilteroption.h"
26−#include "signalslist.h"
27−
28−// libunity-core
29−#include <UnityCore/Filter.h>
30−
31−class Q_DECL_EXPORT FilterOption : public AbstractFilterOption
32−{
33− Q_OBJECT
34−
35−public:
36− explicit FilterOption(unity::dash::FilterOption::Ptr unityFilterOption, QObject *parent = nullptr);
37−
38− /* getters */
39− QString id() const override;
40− QString name() const override;
41− QString iconHint() const override;
42− bool active() const override;
43−
44− /* setters */
45− void setActive(bool active) override;
46−
47−private:
48− void onIdChanged(const std::string &id);
49− void onNameChanged(const std::string &name);
50− void onIconHintChanged(const std::string &iconHint);
51− void onActiveChanged(bool active);
52−
53− void setUnityFilterOption(unity::dash::FilterOption::Ptr unityFilterOption);
54− SignalsList m_signals;
55−
56− unity::dash::FilterOption::Ptr m_unityFilterOption;
57−};
58−
59−Q_DECLARE_METATYPE(FilterOption*)
60−
61−#endif // FILTEROPTION_H
plugins/Unity/filters.cppdeleted−165
@@ -1,165 +0,0 @@
1−/*
2− * Copyright (C) 2011, 2013 Canonical, Ltd.
3− *
4− * Authors:
5− * Florian Boucault <florian.boucault@canonical.com>
6− * Pawel Stolowski <pawel.stolowski@canonical.com>
7− *
8− * This program is free software; you can redistribute it and/or modify
9− * it under the terms of the GNU General Public License as published by
10− * the Free Software Foundation; version 3.
11− *
12− * This program is distributed in the hope that it will be useful,
13− * but WITHOUT ANY WARRANTY; without even the implied warranty of
14− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15− * GNU General Public License for more details.
16− *
17− * You should have received a copy of the GNU General Public License
18− * along with this program. If not, see <http://www.gnu.org/licenses/>.
19− */
20−
21−// Self
22−#include "filters.h"
23−
24−// Local
25−#include "filter.h"
26−#include "genericoptionsmodel.h"
27−
28−// Qt
29−#include <QDebug>
30−
31−Filters::Filters(unity::dash::Filters::Ptr unityFilters, QObject *parent) :
32− QAbstractListModel(parent), m_unityFilters(unityFilters)
33−{
34− for (unsigned int i=0; i<m_unityFilters->count(); i++) {
35− unity::dash::Filter::Ptr unityFilter = m_unityFilters->FilterAtIndex(i);
36− addFilter(unityFilter, i);
37− }
38− m_unityFilters->filter_added.connect(sigc::mem_fun(this, &Filters::onFilterAdded));
39− m_unityFilters->filter_changed.connect(sigc::mem_fun(this, &Filters::onFilterChanged));
40− m_unityFilters->filter_removed.connect(sigc::mem_fun(this, &Filters::onFilterRemoved));
41−}
42−
43−Filters::~Filters()
44−{
45− while (!m_filters.isEmpty()) {
46− delete m_filters.takeFirst();
47− }
48−}
49−
50−int Filters::rowCount(const QModelIndex& parent) const
51−{
52− Q_UNUSED(parent)
53−
54− return m_unityFilters->count();
55−}
56−
57−QVariant Filters::data(const QModelIndex& index, int role) const
58−{
59− if (!index.isValid()) {
60− return QVariant();
61− }
62−
63− Filter* filter = m_filters.at(index.row());
64− switch (role)
65− {
66− case Filters::RoleId:
67− return filter->id();
68− case Filters::RoleName:
69− case Qt::DisplayRole:
70− return filter->name();
71− case Filters::RoleIconHint:
72− return filter->iconHint();
73− case Filters::RoleRendererName:
74− return filter->rendererName();
75− case Filters::RoleVisible:
76− return filter->visible();
77− case Filters::RoleCollapsed:
78− return filter->collapsed();
79− case Filters::RoleFiltering:
80− return filter->filtering();
81− case Filters::RoleOptions:
82− return QVariant::fromValue(filter->options());
83− default:
84− break;
85− }
86− return QVariant();
87−}
88−
89−QHash<int, QByteArray> Filters::roleNames() const
90−{
91− QHash<int, QByteArray> roles;
92− roles[Filters::RoleId] = "id";
93− roles[Filters::RoleName] = "name";
94− roles[Filters::RoleIconHint] = "iconHint";
95− roles[Filters::RoleRendererName] = "rendererName";
96− roles[Filters::RoleVisible] = "visible";
97− roles[Filters::RoleCollapsed] = "collapsed";
98− roles[Filters::RoleFiltering] = "filtering";
99− roles[Filters::RoleOptions] = "options";
100− return roles;
101−}
102−
103−Filter* Filters::getFilter(const QString& id) const
104−{
105− Q_FOREACH (Filter* filter, m_filters) {
106− if (filter->id() == id) {
107− return filter;
108− }
109− }
110− return nullptr;
111−}
112−
113−void Filters::onFilterAdded(unity::dash::Filter::Ptr unityFilter)
114−{
115− if (unityFilter == nullptr) {
116− return;
117− }
118−
119− int index = m_filters.count();
120− addFilter(unityFilter, index);
121−}
122−
123−void Filters::onFilterChanged(unity::dash::Filter::Ptr unityFilter)
124−{
125− if (unityFilter == nullptr) {
126− return;
127− }
128−
129− QModelIndex filterIndex = index(indexForFilter(unityFilter));
130− Q_EMIT dataChanged(filterIndex, filterIndex);
131−}
132−
133−void Filters::onFilterRemoved(unity::dash::Filter::Ptr unityFilter)
134−{
135− removeFilter(indexForFilter(unityFilter));
136−}
137−
138−void Filters::addFilter(unity::dash::Filter::Ptr unityFilter, int index)
139−{
140− beginInsertRows(QModelIndex(), index, index);
141− Filter* filter = Filter::newFromUnityFilter(unityFilter);
142− if (filter != nullptr) {
143− m_filters.insert(index, filter);
144− }
145− endInsertRows();
146−}
147−
148−void Filters::removeFilter(int index)
149−{
150− beginRemoveRows(QModelIndex(), index, index);
151− Filter* filter = m_filters.takeAt(index);
152− delete filter;
153− endRemoveRows();
154−}
155−
156−int Filters::indexForFilter(unity::dash::Filter::Ptr unityFilter)
157−{
158− for (int index=0; index<m_filters.count(); index++) {
159− if (m_filters[index]->hasUnityFilter(unityFilter)) {
160− return index;
161− }
162− }
163− qWarning() << "Filter" << QString::fromStdString(unityFilter->name()) << "not found in local cache.";
164− return -1;
165−}
plugins/Unity/filters.hdeleted−77
@@ -1,77 +0,0 @@
1−/*
2− * Copyright (C) 2011, 2013 Canonical, Ltd.
3− *
4− * Authors:
5− * Florian Boucault <florian.boucault@canonical.com>
6− * Pawel Stolowski <pawel.stolowski@canonical.com>
7− *
8− * This program is free software; you can redistribute it and/or modify
9− * it under the terms of the GNU General Public License as published by
10− * the Free Software Foundation; version 3.
11− *
12− * This program is distributed in the hope that it will be useful,
13− * but WITHOUT ANY WARRANTY; without even the implied warranty of
14− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15− * GNU General Public License for more details.
16− *
17− * You should have received a copy of the GNU General Public License
18− * along with this program. If not, see <http://www.gnu.org/licenses/>.
19− */
20−
21−#ifndef FILTERS_H
22−#define FILTERS_H
23−
24−// Qt
25−#include <QAbstractListModel>
26−#include <QList>
27−
28−// libunity-core
29−#include <UnityCore/Filters.h>
30−#include <UnityCore/Filter.h>
31−
32−class Filter;
33−
34−class Filters : public QAbstractListModel
35−{
36− Q_OBJECT
37−
38− Q_ENUMS(Roles)
39−
40−public:
41− explicit Filters(unity::dash::Filters::Ptr unityFilters, QObject *parent = nullptr);
42− ~Filters();
43−
44− enum Roles {
45− RoleId = Qt::UserRole,
46− RoleName,
47− RoleIconHint,
48− RoleRendererName,
49− RoleVisible,
50− RoleCollapsed,
51− RoleFiltering,
52− RoleOptions
53− };
54−
55− QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
56− int rowCount(const QModelIndex& parent = QModelIndex()) const override;
57− QHash<int, QByteArray> roleNames() const override;
58−
59− Filter* getFilter(const QString& id) const;
60−
61−private:
62− void onFilterAdded(unity::dash::Filter::Ptr unityFilter);
63− void onFilterChanged(unity::dash::Filter::Ptr unityFilter);
64− void onFilterRemoved(unity::dash::Filter::Ptr unityFilter);
65−
66− void addFilter(unity::dash::Filter::Ptr unityFilter, int index);
67− void removeFilter(int index);
68−
69− int indexForFilter(unity::dash::Filter::Ptr unityFilter);
70−
71− unity::dash::Filters::Ptr m_unityFilters;
72− QList<Filter*> m_filters;
73−};
74−
75−Q_DECLARE_METATYPE(Filters*)
76−
77−#endif // FILTERS_H
plugins/Unity/genericoptionsmodel.cppdeleted−187
@@ -1,187 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * Authors:
5− * Pawel Stolowski <pawel.stolowski@canonical.com>
6− *
7− * This program is free software; you can redistribute it and/or modify
8− * it under the terms of the GNU General Public License as published by
9− * the Free Software Foundation; version 3.
10− *
11− * This program is distributed in the hope that it will be useful,
12− * but WITHOUT ANY WARRANTY; without even the implied warranty of
13− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14− * GNU General Public License for more details.
15− *
16− * You should have received a copy of the GNU General Public License
17− * along with this program. If not, see <http://www.gnu.org/licenses/>.
18− */
19−
20−// self
21−#include "genericoptionsmodel.h"
22−
23−// local
24−#include "abstractfilteroption.h"
25−#include "showallfilteroption.h"
26−
27−GenericOptionsModel::GenericOptionsModel(bool showAllOption, QObject *parent)
28− : QAbstractListModel(parent)
29−{
30− if (showAllOption)
31− {
32− auto showAll = new ShowAllFilterOption(this);
33− connect(showAll, SIGNAL(activeChanged(bool)), this, SLOT(onOptionChanged()));
34− connect(showAll, SIGNAL(activeChanged(bool)), this, SLOT(onShowAllClicked(bool)));
35− addOption(showAll);
36− }
37−}
38−
39−GenericOptionsModel::~GenericOptionsModel()
40−{
41− Q_FOREACH(auto opt, m_options)
42− {
43− opt->deleteLater();
44− }
45−}
46−
47−QHash<int, QByteArray> GenericOptionsModel::roleNames() const
48−{
49− QHash<int, QByteArray> roles;
50− roles[GenericOptionsModel::RoleId] = "id";
51− roles[GenericOptionsModel::RoleName] = "name";
52− roles[GenericOptionsModel::RoleIconHint] = "iconHint";
53− roles[GenericOptionsModel::RoleActive] = "active";
54− return roles;
55−}
56−
57−QVariant GenericOptionsModel::data(const QModelIndex& index, int role) const
58−{
59− if (!index.isValid()) {
60− return QVariant();
61− }
62−
63− auto filterOption = m_options[index.row()];
64− switch (role)
65− {
66− case GenericOptionsModel::RoleId:
67− return filterOption->id();
68− case GenericOptionsModel::RoleName:
69− case Qt::DisplayRole:
70− return filterOption->name();
71− case GenericOptionsModel::RoleIconHint:
72− return filterOption->iconHint();
73− case GenericOptionsModel::RoleActive:
74− return filterOption->active();
75− default:
76− break;
77− }
78−
79− return QVariant();
80−}
81−
82−int GenericOptionsModel::rowCount(const QModelIndex& /* parent */) const
83−{
84− return m_options.size();
85−}
86−
87−void GenericOptionsModel::setActive(int idx, bool value)
88−{
89− if (idx >= 0 && idx < m_options.size())
90− {
91− m_options[idx]->setActive(value);
92− }
93−}
94−
95−void GenericOptionsModel::setActive(const QString &id, bool value)
96−{
97− Q_FOREACH(auto opt, m_options) {
98− if (opt->id() == id) {
99− opt->setActive(value);
100− break;
101− }
102− }
103−}
104−
105−AbstractFilterOption* GenericOptionsModel::getRawOption(QVector<AbstractFilterOption *>::size_type idx) const
106−{
107− if (idx < m_options.size())
108− {
109− return m_options[idx];
110− }
111− return nullptr;
112−}
113−
114−void GenericOptionsModel::ensureTheOnlyActive(AbstractFilterOption *activeOption)
115−{
116− if (activeOption->active()) {
117− // disable all other options
118− Q_FOREACH(auto opt, m_options) {
119− if (opt != activeOption && opt->active()) {
120− opt->setActive(false);
121− }
122− }
123− }
124−}
125−
126−void GenericOptionsModel::addOption(AbstractFilterOption *option, int index)
127−{
128− if (index >= 0)
129− m_options.insert(index, option);
130− else
131− m_options.append(option);
132−
133− connect(option, SIGNAL(idChanged(const QString &)), this, SLOT(onOptionChanged()));
134− connect(option, SIGNAL(nameChanged(const QString &)), this, SLOT(onOptionChanged()));
135− connect(option, SIGNAL(iconHintChanged(const QString &)), this, SLOT(onOptionChanged()));
136− connect(option, SIGNAL(activeChanged(bool)), this, SLOT(onOptionChanged()));
137− connect(option, SIGNAL(activeChanged(bool)), this, SLOT(onActiveChanged()));
138−}
139−
140−void GenericOptionsModel::removeOption(int index)
141−{
142− m_options[index]->deleteLater();
143− m_options.remove(index);
144−}
145−
146−int GenericOptionsModel::indexOf(const QString &option_id)
147−{
148− int row = 0;
149− Q_FOREACH(auto opt, m_options)
150− {
151− if (opt->id() == option_id)
152− {
153− return row;
154− }
155− ++row;
156− }
157− return -1;
158−}
159−
160−void GenericOptionsModel::onOptionChanged()
161−{
162− AbstractFilterOption *option = dynamic_cast<AbstractFilterOption*>(QObject::sender());
163− if (option)
164− {
165− int idx = indexOf(option->id());
166− if (idx >= 0)
167− {
168− QModelIndex optionIndex = index(idx);
169− Q_EMIT dataChanged(optionIndex, optionIndex);
170− }
171− }
172−}
173−
174−void GenericOptionsModel::onActiveChanged()
175−{
176− AbstractFilterOption *option = dynamic_cast<AbstractFilterOption*>(QObject::sender());
177− if (option)
178− {
179− Q_EMIT activeChanged(option);
180− }
181−}
182−
183−void GenericOptionsModel::onShowAllClicked(bool active)
184−{
185− if (active)
186− Q_EMIT showAllActivated();
187−}
plugins/Unity/genericoptionsmodel.hdeleted−79
@@ -1,79 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * Authors:
5− * Pawel Stolowski <pawel.stolowski@canonical.com>
6− *
7− * This program is free software; you can redistribute it and/or modify
8− * it under the terms of the GNU General Public License as published by
9− * the Free Software Foundation; version 3.
10− *
11− * This program is distributed in the hope that it will be useful,
12− * but WITHOUT ANY WARRANTY; without even the implied warranty of
13− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14− * GNU General Public License for more details.
15− *
16− * You should have received a copy of the GNU General Public License
17− * along with this program. If not, see <http://www.gnu.org/licenses/>.
18− */
19−
20−#ifndef GENERICOPTIONSMODEL_H
21−#define GENERICOPTIONSMODEL_H
22−
23−// Qt
24−#include <QObject>
25−#include <QAbstractListModel>
26−#include <QHash>
27−#include <QVector>
28−
29−class AbstractFilterOption;
30−
31−class Q_DECL_EXPORT GenericOptionsModel : public QAbstractListModel
32−{
33− Q_OBJECT
34−
35− Q_ENUMS(Roles)
36−
37−public:
38− GenericOptionsModel(bool showAllOption = false, QObject *parent = nullptr);
39− ~GenericOptionsModel();
40−
41− enum Roles {
42− RoleId = Qt::UserRole,
43− RoleName,
44− RoleIconHint,
45− RoleActive
46− };
47−
48− QHash<int, QByteArray> roleNames() const override;
49− QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
50− int rowCount(const QModelIndex& parent = QModelIndex()) const override;
51−
52− Q_INVOKABLE void setActive(int idx, bool value);
53− Q_INVOKABLE void setActive(const QString &id, bool value);
54−
55− AbstractFilterOption* getRawOption(QVector<AbstractFilterOption *>::size_type idx) const;
56−
57−public Q_SLOTS:
58− virtual void ensureTheOnlyActive(AbstractFilterOption *activeOption);
59−
60−Q_SIGNALS:
61− void activeChanged(AbstractFilterOption *option);
62− void showAllActivated();
63−
64−protected Q_SLOTS:
65− void onOptionChanged();
66− void onActiveChanged();
67− void onShowAllClicked(bool active);
68−
69−protected:
70− void addOption(AbstractFilterOption *option, int index = -1);
71− void removeOption(int index);
72− int indexOf(const QString &option_id);
73−
74− QVector<AbstractFilterOption *> m_options;
75−};
76−
77−Q_DECLARE_METATYPE(GenericOptionsModel*)
78−
79−#endif // GENERICOPTIONSMODEL_H
plugins/Unity/moviepreview.cppdeleted−67
@@ -1,67 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * Authors:
5− * Pawel Stolowski <pawel.stolowski@canonical.com>
6− *
7− * This program is free software; you can redistribute it and/or modify
8− * it under the terms of the GNU General Public License as published by
9− * the Free Software Foundation; version 3.
10− *
11− * This program is distributed in the hope that it will be useful,
12− * but WITHOUT ANY WARRANTY; without even the implied warranty of
13− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14− * GNU General Public License for more details.
15− *
16− * You should have received a copy of the GNU General Public License
17− * along with this program. If not, see <http://www.gnu.org/licenses/>.
18− */
19−
20−// local
21−#include "moviepreview.h"
22−
23−// Qt
24−#include <QDebug>
25−
26−MoviePreview::MoviePreview(QObject *parent):
27− Preview(parent),
28− m_unityMoviePreview(nullptr)
29−{
30−}
31−
32−QString MoviePreview::year() const
33−{
34− if (m_unityMoviePreview) {
35− return QString::fromStdString(m_unityMoviePreview->year());
36− } else {
37− qWarning() << "Preview not set";
38− }
39− return QString();
40−}
41−
42−float MoviePreview::rating() const
43−{
44− if (m_unityMoviePreview) {
45− return m_unityMoviePreview->rating();
46− } else {
47− qWarning() << "Preview not set";
48− }
49− return 0.0f;
50−}
51−
52−unsigned int MoviePreview::numRatings() const
53−{
54− if (m_unityMoviePreview) {
55− return m_unityMoviePreview->num_ratings();
56− } else {
57− qWarning() << "Preview not set";
58− }
59− return 0;
60−}
61−
62−void MoviePreview::setUnityPreview(unity::dash::Preview::Ptr unityPreview)
63−{
64− m_unityMoviePreview = std::dynamic_pointer_cast<unity::dash::MoviePreview>(unityPreview);
65−
66− Q_EMIT previewChanged();
67−}
plugins/Unity/moviepreview.hdeleted−60
@@ -1,60 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * Authors:
5− * Pawel Stolowski <pawel.stolowski@canonical.com>
6− *
7− * This program is free software; you can redistribute it and/or modify
8− * it under the terms of the GNU General Public License as published by
9− * the Free Software Foundation; version 3.
10− *
11− * This program is distributed in the hope that it will be useful,
12− * but WITHOUT ANY WARRANTY; without even the implied warranty of
13− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14− * GNU General Public License for more details.
15− *
16− * You should have received a copy of the GNU General Public License
17− * along with this program. If not, see <http://www.gnu.org/licenses/>.
18− */
19−
20−#ifndef MOVIEPREVIEW_H
21−#define MOVIEPREVIEW_H
22−
23−// local
24−#include "preview.h"
25−
26−// Qt
27−#include <QObject>
28−#include <QMetaType>
29−
30−// libunity-core
31−#include <UnityCore/MoviePreview.h>
32−
33−class Q_DECL_EXPORT MoviePreview: public Preview
34−{
35− Q_OBJECT
36−
37− Q_PROPERTY(QString year READ year NOTIFY previewChanged)
38− Q_PROPERTY(float rating READ rating NOTIFY previewChanged)
39− Q_PROPERTY(unsigned int numRatings READ numRatings NOTIFY previewChanged)
40−
41−public:
42− explicit MoviePreview(QObject *parent = 0);
43−
44− QString year() const;
45− float rating() const;
46− unsigned int numRatings() const;
47−
48−Q_SIGNALS:
49− void previewChanged();
50−
51−protected:
52− void setUnityPreview(unity::dash::Preview::Ptr unityPreview) override;
53−
54−private:
55− unity::dash::MoviePreview::Ptr m_unityMoviePreview;
56−};
57−
58−Q_DECLARE_METATYPE(MoviePreview *)
59−
60−#endif
plugins/Unity/multirangefilter.cppdeleted−65
@@ -1,65 +0,0 @@
1−/*
2− * Copyright (C) 2011, 2013 Canonical, Ltd.
3− *
4− * Authors:
5− * Florian Boucault <florian.boucault@canonical.com>
6− * Pawel Stolowski <pawel.stolowski@canonical.com>
7− *
8− * This program is free software; you can redistribute it and/or modify
9− * it under the terms of the GNU General Public License as published by
10− * the Free Software Foundation; version 3.
11− *
12− * This program is distributed in the hope that it will be useful,
13− * but WITHOUT ANY WARRANTY; without even the implied warranty of
14− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15− * GNU General Public License for more details.
16− *
17− * You should have received a copy of the GNU General Public License
18− * along with this program. If not, see <http://www.gnu.org/licenses/>.
19− */
20−
21−// Self
22−#include "multirangefilter.h"
23−
24−// local
25−#include "unityoptionsmodel.h"
26−
27−MultiRangeFilter::MultiRangeFilter(QObject *parent) :
28− Filter(parent), m_unityMultiRangeFilter(nullptr), m_options(nullptr)
29−{
30−}
31−
32−GenericOptionsModel* MultiRangeFilter::options() const
33−{
34− return m_options;
35−}
36−
37−void MultiRangeFilter::setUnityFilter(unity::dash::Filter::Ptr filter)
38−{
39− Filter::setUnityFilter(filter);
40− m_unityMultiRangeFilter = std::dynamic_pointer_cast<unity::dash::MultiRangeFilter>(m_unityFilter);
41−
42− onOptionsChanged(m_unityMultiRangeFilter->options);
43−}
44−
45−void MultiRangeFilter::onOptionsChanged(unity::dash::MultiRangeFilter::Options options)
46−{
47− if (m_options != nullptr) {
48− m_signals.disconnectAll();
49− delete m_options;
50− m_options = nullptr;
51− }
52−
53− m_options = new UnityOptionsModel(this, options,
54− m_unityMultiRangeFilter->option_added,
55− m_unityMultiRangeFilter->option_removed,
56− m_unityMultiRangeFilter->show_all_button);
57−
58− connect(m_options, SIGNAL(activeChanged(AbstractFilterOption *)), m_options, SLOT(ensureTheOnlyActive(AbstractFilterOption *)));
59− connect(m_options, SIGNAL(showAllActivated()), this, SLOT(clear()));
60−
61− /* Property change signals */
62− m_signals << m_unityMultiRangeFilter->options.changed.connect(sigc::mem_fun(this, &MultiRangeFilter::onOptionsChanged));
63−
64− Q_EMIT optionsChanged();
65−}
plugins/Unity/multirangefilter.hdeleted−60
@@ -1,60 +0,0 @@
1−/*
2− * Copyright (C) 2011, 2013 Canonical, Ltd.
3− *
4− * Authors:
5− * Florian Boucault <florian.boucault@canonical.com>
6− * Pawel Stolowski <pawel.stolowski@canonical.com>
7− *
8− * This program is free software; you can redistribute it and/or modify
9− * it under the terms of the GNU General Public License as published by
10− * the Free Software Foundation; version 3.
11− *
12− * This program is distributed in the hope that it will be useful,
13− * but WITHOUT ANY WARRANTY; without even the implied warranty of
14− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15− * GNU General Public License for more details.
16− *
17− * You should have received a copy of the GNU General Public License
18− * along with this program. If not, see <http://www.gnu.org/licenses/>.
19− */
20−
21−#ifndef MULTIRANGEFILTER_H
22−#define MULTIRANGEFILTER_H
23−
24−// Qt
25−#include <QObject>
26−#include <QMetaType>
27−
28−// libunity-core
29−#include <UnityCore/MultiRangeFilter.h>
30−
31−// Local
32−#include "filter.h"
33−#include "signalslist.h"
34−
35−class GenericOptionsModel;
36−
37−class Q_DECL_EXPORT MultiRangeFilter : public Filter
38−{
39− Q_OBJECT
40−
41−public:
42− explicit MultiRangeFilter(QObject *parent = nullptr);
43−
44− /* getters */
45− GenericOptionsModel* options() const override;
46−
47−protected:
48− void setUnityFilter(unity::dash::Filter::Ptr filter) override;
49−
50−private:
51− unity::dash::MultiRangeFilter::Ptr m_unityMultiRangeFilter;
52− SignalsList m_signals;
53− GenericOptionsModel* m_options;
54−
55− void onOptionsChanged(unity::dash::MultiRangeFilter::Options);
56−};
57−
58−Q_DECLARE_METATYPE(MultiRangeFilter*)
59−
60−#endif // MULTIRANGEFILTER_H
plugins/Unity/musicpreview.cppdeleted−54
@@ -1,54 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * Authors:
5− * Pawel Stolowski <pawel.stolowski@canonical.com>
6− *
7− * This program is free software; you can redistribute it and/or modify
8− * it under the terms of the GNU General Public License as published by
9− * the Free Software Foundation; version 3.
10− *
11− * This program is distributed in the hope that it will be useful,
12− * but WITHOUT ANY WARRANTY; without even the implied warranty of
13− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14− * GNU General Public License for more details.
15− *
16− * You should have received a copy of the GNU General Public License
17− * along with this program. If not, see <http://www.gnu.org/licenses/>.
18− */
19−
20−#include "musicpreview.h"
21−#include <QDebug>
22−
23−// dee-qt
24−#include "deelistmodel.h"
25−
26−MusicPreview::MusicPreview(QObject *parent):
27− Preview(parent),
28− m_unityMusicPreview(nullptr)
29−{
30− m_tracks = new DeeListModel(this);
31−}
32−
33−void MusicPreview::setUnityPreview(unity::dash::Preview::Ptr unityPreview)
34−{
35− m_unityMusicPreview = std::dynamic_pointer_cast<unity::dash::MusicPreview>(unityPreview);
36− m_tracks->setModel(m_unityMusicPreview->GetTracksModel()->model());
37− m_unityMusicPreview->GetTracksModel()->model.changed.connect(sigc::mem_fun(this, &MusicPreview::onTracksModelChanged));
38−
39− Q_EMIT previewChanged();
40− Q_EMIT tracksChanged();
41−}
42−
43−DeeListModel* MusicPreview::tracks() const
44−{
45− if (m_unityMusicPreview == nullptr) {
46− qWarning() << "Preview not set";
47− }
48− return m_tracks;
49−}
50−
51−void MusicPreview::onTracksModelChanged(unity::glib::Object<DeeModel> /* model */)
52−{
53− m_tracks->setModel(m_unityMusicPreview->GetTracksModel()->model());
54−}
plugins/Unity/musicpreview.hdeleted−62
@@ -1,62 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * Authors:
5− * Pawel Stolowski <pawel.stolowski@canonical.com>
6− *
7− * This program is free software; you can redistribute it and/or modify
8− * it under the terms of the GNU General Public License as published by
9− * the Free Software Foundation; version 3.
10− *
11− * This program is distributed in the hope that it will be useful,
12− * but WITHOUT ANY WARRANTY; without even the implied warranty of
13− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14− * GNU General Public License for more details.
15− *
16− * You should have received a copy of the GNU General Public License
17− * along with this program. If not, see <http://www.gnu.org/licenses/>.
18− */
19−
20−#ifndef MUSICPREVIEW_H
21−#define MUSICPREVIEW_H
22−
23−// local
24−#include "preview.h"
25−
26−// Qt
27−#include <QObject>
28−#include <QMetaType>
29−
30−// libunity-core
31−#include <UnityCore/MusicPreview.h>
32−
33−class DeeListModel;
34−
35−class Q_DECL_EXPORT MusicPreview: public Preview
36−{
37− Q_OBJECT
38−
39− Q_PROPERTY(DeeListModel* tracks READ tracks NOTIFY tracksChanged)
40−
41−public:
42− explicit MusicPreview(QObject *parent = 0);
43−
44− DeeListModel* tracks() const;
45−
46−Q_SIGNALS:
47− void tracksChanged();
48−
49−protected:
50− void setUnityPreview(unity::dash::Preview::Ptr unityPreview) override;
51−
52−private Q_SLOTS:
53− void onTracksModelChanged(unity::glib::Object<DeeModel> model);
54−
55−private:
56− unity::dash::MusicPreview::Ptr m_unityMusicPreview;
57− DeeListModel *m_tracks;
58−};
59−
60−Q_DECLARE_METATYPE(MusicPreview *)
61−
62−#endif
plugins/Unity/plugin.cppdeleted−74
@@ -1,74 +0,0 @@
1−/*
2− * Copyright (C) 2012 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU 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− * Author: Michał Sawicz <michal.sawicz@canonical.com>
17− */
18−
19−// Qt
20−#include <QDBusConnection>
21−#include <QQmlContext>
22−#include <qqml.h>
23−
24−// self
25−#include "plugin.h"
26−
27−// local
28−#include "preview.h"
29−#include "previewaction.h"
30−#include "previewinfohint.h"
31−#include "socialpreviewcomment.h"
32−#include "scope.h"
33−#include "scopes.h"
34−#include "categories.h"
35−#include "categoryresults.h"
36−#include "bottombarvisibilitycommunicatorshell.h"
37−#include "genericoptionsmodel.h"
38−#include "result.h"
39−
40−// libqtdee
41−#include "deelistmodel.h"
42−
43−static const char* BOTTOM_BAR_VISIBILITY_COMMUNICATOR_DBUS_PATH = "/BottomBarVisibilityCommunicator";
44−static const char* DBUS_SERVICE = "com.canonical.Shell.BottomBarVisibilityCommunicator";
45−
46−void UnityPlugin::registerTypes(const char *uri)
47−{
48− Q_ASSERT(uri == QLatin1String("Unity"));
49− qmlRegisterUncreatableType<Preview>(uri, 0, 1, "Preview", "Can't create Preview object in QML.");
50− qmlRegisterUncreatableType<PreviewAction>(uri, 0, 1, "PreviewAction", "Can't create PreviewAction object in QML.");
51− qmlRegisterUncreatableType<PreviewInfoHint>(uri, 0, 1, "PreviewInfoHint", "Can't create PreviewInfoHint object in QML.");
52− qmlRegisterUncreatableType<SocialPreviewComment>(uri, 0, 1, "SocialPreviewComment", "Can't create SocialPreviewComment object in QML.");
53− qmlRegisterUncreatableType<GenericOptionsModel>(uri, 0, 1, "GenericOptionsModel", "Can't create options model in QML.");
54− qmlRegisterUncreatableType<Result>(uri, 0, 1, "Result", "Can't create result object in QML.");
55− qmlRegisterType<Scope>(uri, 0, 1, "Scope");
56− qmlRegisterType<Scopes>(uri, 0, 1, "Scopes");
57− qmlRegisterType<Categories>(uri, 0, 1, "Categories");
58− qmlRegisterUncreatableType<CategoryResults>(uri, 0, 1, "CategoryResults", "Can't create new Category Results in QML. Get them from Categories instance.");
59− qmlRegisterType<DeeListModel>(uri, 0, 1, "DeeListModel");
60− qmlRegisterUncreatableType<BottomBarVisibilityCommunicatorShell>(uri, 0, 1, "BottomBarVisibilityCommunicatorShell", "Can't create BottomBarVisibilityCommunicatorShell");
61−}
62−
63−void UnityPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
64−{
65− QQmlExtensionPlugin::initializeEngine(engine, uri);
66−#ifndef GLIB_VERSION_2_36
67− g_type_init();
68−#endif
69−
70− QDBusConnection::sessionBus().registerService(DBUS_SERVICE);
71− BottomBarVisibilityCommunicatorShell *bottomBarVisibilityCommunicator = &BottomBarVisibilityCommunicatorShell::instance();
72− QDBusConnection::sessionBus().registerObject(BOTTOM_BAR_VISIBILITY_COMMUNICATOR_DBUS_PATH, bottomBarVisibilityCommunicator, QDBusConnection::ExportAllContents);
73− engine->rootContext()->setContextProperty("bottomBarVisibilityCommunicatorShell", bottomBarVisibilityCommunicator);
74−}
plugins/Unity/preview.cppdeleted−199
@@ -1,199 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * Authors:
5− * Pawel Stolowski <pawel.stolowski@canonical.com>
6− *
7− * This program is free software; you can redistribute it and/or modify
8− * it under the terms of the GNU General Public License as published by
9− * the Free Software Foundation; version 3.
10− *
11− * This program is distributed in the hope that it will be useful,
12− * but WITHOUT ANY WARRANTY; without even the implied warranty of
13− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14− * GNU General Public License for more details.
15− *
16− * You should have received a copy of the GNU General Public License
17− * along with this program. If not, see <http://www.gnu.org/licenses/>.
18− */
19−
20−// local
21−#include "preview.h"
22−#include "previewaction.h"
23−#include "previewinfohint.h"
24−#include "genericpreview.h"
25−#include "applicationpreview.h"
26−#include "moviepreview.h"
27−#include "musicpreview.h"
28−#include "socialpreview.h"
29−#include "iconutils.h"
30−#include "variantutils.h"
31−
32−// Qt
33−#include <QDebug>
34−#include <QtAlgorithms>
35−
36−#include <UnityCore/GenericPreview.h>
37−#include <UnityCore/ApplicationPreview.h>
38−#include <UnityCore/MoviePreview.h>
39−#include <UnityCore/MusicPreview.h>
40−#include <UnityCore/SocialPreview.h>
41−
42−#include <UnityCore/GLibWrapper.h>
43−
44−Preview::Preview(QObject *parent):
45− QObject(parent),
46− m_unityPreview(nullptr),
47− m_result(new Result(this))
48−{
49−}
50−
51−QString Preview::rendererName() const
52−{
53− if (m_unityPreview) {
54− return QString::fromStdString(m_unityPreview->renderer_name());
55− } else {
56− qWarning() << "Preview not set";
57− }
58− return QString();
59−}
60−
61−QString Preview::title() const
62−{
63− if (m_unityPreview) {
64− return QString::fromStdString(m_unityPreview->title());
65− } else {
66− qWarning() << "Preview not set";
67− }
68− return QString();
69−}
70−
71−QString Preview::subtitle () const
72−{
73− if (m_unityPreview) {
74− return QString::fromStdString(m_unityPreview->subtitle());
75− } else {
76− qWarning() << "Preview not set";
77− }
78− return QString();
79−}
80−
81−QString Preview::description() const
82−{
83− if (m_unityPreview) {
84− return QString::fromStdString(m_unityPreview->description());
85− } else {
86− qWarning() << "Preview not set";
87− }
88− return QString();
89−}
90−
91−QVariant Preview::actions()
92−{
93− return QVariant::fromValue(m_actions);
94−}
95−
96−QVariant Preview::infoHints()
97−{
98− return QVariant::fromValue(m_infoHints);
99−}
100−
101−QVariantMap Preview::infoHintsHash() const
102−{
103− return m_infoHintsHash;
104−}
105−
106−QString Preview::image() const
107−{
108− if (m_unityPreview) {
109− if (m_unityPreview->image() != nullptr) {
110− auto giconString = g_icon_to_string(m_unityPreview->image());
111− QString result(gIconToDeclarativeImageProviderString(QString::fromUtf8(giconString)));
112− g_free(giconString);
113− return result;
114− } else {
115− QString sourceMedia(QString::fromStdString(m_unityPreview->image_source_uri()));
116− QString thumbnailUri(uriToThumbnailerProviderString(sourceMedia, m_result->mimeType(), m_result->metadata().toHash()));
117− if (!thumbnailUri.isNull()) return thumbnailUri;
118− }
119− } else {
120− qWarning() << "Preview not set";
121− }
122− return QString::null;
123−}
124−
125−QVariant Preview::result() const
126−{
127− return QVariant::fromValue(m_result);
128−}
129−
130−Preview* Preview::newFromUnityPreview(unity::dash::Preview::Ptr unityPreview)
131−{
132− Preview* preview = nullptr;
133−
134− if (dynamic_cast<unity::dash::GenericPreview *>(unityPreview.get()) != nullptr) {
135− preview = new GenericPreview();
136− } else if (dynamic_cast<unity::dash::MusicPreview *>(unityPreview.get()) != nullptr) {
137− preview = new MusicPreview();
138− } else if (dynamic_cast<unity::dash::MoviePreview *>(unityPreview.get()) != nullptr) {
139− preview = new MoviePreview();
140− } else if (dynamic_cast<unity::dash::ApplicationPreview *>(unityPreview.get()) != nullptr) {
141− preview = new ApplicationPreview();
142− } else if (dynamic_cast<unity::dash::SocialPreview *>(unityPreview.get()) != nullptr) {
143− preview = new SocialPreview();
144− } else {
145− qWarning() << "Unknown preview type: " << typeid(*unityPreview).name();
146− preview = new GenericPreview();
147− }
148−
149− preview->setUnityPreviewBase(unityPreview);
150− preview->setUnityPreview(unityPreview);
151−
152− return preview;
153−}
154−
155−void Preview::setUnityPreviewBase(unity::dash::Preview::Ptr unityPreview)
156−{
157− m_unityPreview = unityPreview;
158− m_result->setPreview(unityPreview);
159−
160− qDeleteAll(m_infoHints);
161− m_infoHints.clear();
162− m_infoHintsHash.clear();
163− qDeleteAll(m_actions);
164− m_actions.clear();
165−
166− for (auto unityInfoHint: m_unityPreview->GetInfoHints()) {
167− auto hint = new PreviewInfoHint(this);
168− hint->setUnityInfoHint(unityInfoHint);
169− m_infoHints.append(hint);
170− m_infoHintsHash[hint->id()] = QVariant::fromValue(hint);
171− }
172−
173− for (auto unityAction: m_unityPreview->GetActions()) {
174− auto action = new PreviewAction(this);
175− action->setUnityAction(unityAction);
176− m_actions.append(action);
177− }
178−}
179−
180−void Preview::setUnityPreview(unity::dash::Preview::Ptr /* unityPreview */)
181−{
182− // default implementation does nothing
183−}
184−
185−void Preview::execute(const QString& actionId, const QHash<QString, QVariant>& hints)
186−{
187− if (m_unityPreview) {
188− auto unityHints = convertToHintsMap(hints);
189− m_actionCancellable.Renew();
190− m_unityPreview->PerformAction(actionId.toStdString(), unityHints, nullptr, m_actionCancellable);
191− } else {
192− qWarning() << "Preview not set";
193− }
194−}
195−
196−void Preview::cancelAction()
197−{
198− m_actionCancellable.Cancel();
199−}
plugins/Unity/preview.hdeleted−89
@@ -1,89 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * Authors:
5− * Pawel Stolowski <pawel.stolowski@canonical.com>
6− *
7− * This program is free software; you can redistribute it and/or modify
8− * it under the terms of the GNU General Public License as published by
9− * the Free Software Foundation; version 3.
10− *
11− * This program is distributed in the hope that it will be useful,
12− * but WITHOUT ANY WARRANTY; without even the implied warranty of
13− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14− * GNU General Public License for more details.
15− *
16− * You should have received a copy of the GNU General Public License
17− * along with this program. If not, see <http://www.gnu.org/licenses/>.
18− */
19−
20−#ifndef PREVIEW_H
21−#define PREVIEW_H
22−
23−// Qt
24−#include <QObject>
25−#include <QString>
26−#include <QMetaType>
27−#include <QList>
28−#include <QVariantMap>
29−
30−// libunity-core
31−#include <UnityCore/Preview.h>
32−
33−// local
34−#include "result.h"
35−#include "previewaction.h"
36−#include <UnityCore/GLibWrapper.h>
37−
38−class Q_DECL_EXPORT Preview : public QObject
39−{
40− Q_OBJECT
41−
42− Q_PROPERTY(QString rendererName READ rendererName NOTIFY previewChanged)
43− Q_PROPERTY(QString title READ title NOTIFY previewChanged)
44− Q_PROPERTY(QString subtitle READ subtitle NOTIFY previewChanged)
45− Q_PROPERTY(QString description READ description NOTIFY previewChanged)
46− Q_PROPERTY(QVariant actions READ actions NOTIFY previewChanged)
47− Q_PROPERTY(QVariant infoHints READ infoHints NOTIFY previewChanged)
48− Q_PROPERTY(QVariantMap infoMap READ infoHintsHash NOTIFY previewChanged)
49− Q_PROPERTY(QString image READ image NOTIFY previewChanged)
50− Q_PROPERTY(QVariant result READ result NOTIFY previewChanged)
51−
52−public:
53− explicit Preview(QObject *parent = 0);
54− static Preview* newFromUnityPreview(unity::dash::Preview::Ptr unityPreview);
55−
56− QString rendererName() const;
57− QString title() const;
58− QString subtitle() const;
59− QString description() const;
60− QVariant actions();
61− QVariant infoHints();
62− QVariantMap infoHintsHash() const;
63− QString image() const;
64− QVariant result() const;
65−
66− Q_INVOKABLE void execute(const QString& actionId, const QHash<QString, QVariant>& hints);
67− Q_INVOKABLE void cancelAction();
68−
69−Q_SIGNALS:
70− void previewChanged();
71−
72−protected:
73− virtual void setUnityPreview(unity::dash::Preview::Ptr unityPreview);
74−
75− unity::dash::Preview::Ptr m_unityPreview;
76− Result* m_result;
77−
78−private:
79− void setUnityPreviewBase(unity::dash::Preview::Ptr unityPreview);
80−
81− QList<QObject *> m_actions;
82− QList<QObject *> m_infoHints;
83− QVariantMap m_infoHintsHash;
84− unity::glib::Cancellable m_actionCancellable;
85−};
86−
87−Q_DECLARE_METATYPE(Preview *)
88−
89−#endif
plugins/Unity/previewaction.cppdeleted−75
@@ -1,75 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * Authors:
5− * Pawel Stolowski <pawel.stolowski@canonical.com>
6− *
7− * This program is free software; you can redistribute it and/or modify
8− * it under the terms of the GNU General Public License as published by
9− * the Free Software Foundation; version 3.
10− *
11− * This program is distributed in the hope that it will be useful,
12− * but WITHOUT ANY WARRANTY; without even the implied warranty of
13− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14− * GNU General Public License for more details.
15− *
16− * You should have received a copy of the GNU General Public License
17− * along with this program. If not, see <http://www.gnu.org/licenses/>.
18− */
19−
20−#include "previewaction.h"
21−
22−PreviewAction::PreviewAction(QObject *parent)
23− : QObject(parent),
24− m_unityAction(nullptr)
25−{
26−}
27−
28−void PreviewAction::setUnityAction(unity::dash::Preview::ActionPtr unityAction)
29−{
30− m_unityAction = unityAction;
31−
32− Q_EMIT previewActionChanged();
33−}
34−
35−QString PreviewAction::id() const
36−{
37− if (m_unityAction)
38− return QString::fromStdString(m_unityAction->id);
39− return QString();
40−}
41−
42−QString PreviewAction::displayName() const
43−{
44− if (m_unityAction)
45− return QString::fromStdString(m_unityAction->display_name);
46− return QString();
47−}
48−
49−QString PreviewAction::iconHint() const
50−{
51− if (m_unityAction)
52− return QString::fromStdString(m_unityAction->icon_hint);
53− return QString();
54−}
55−
56−QString PreviewAction::extraText() const
57−{
58− if (m_unityAction)
59− return QString::fromStdString(m_unityAction->extra_text);
60− return QString();
61−}
62−
63−QString PreviewAction::activationUri() const
64−{
65− if (m_unityAction)
66− return QString::fromStdString(m_unityAction->activation_uri);
67− return QString();
68−}
69−
70−LayoutHint PreviewAction::layoutHint() const
71−{
72− if (m_unityAction)
73− return static_cast<LayoutHint>(m_unityAction->layout_hint);
74− return LayoutHint::None;
75−}
plugins/Unity/previewaction.hdeleted−71
@@ -1,71 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * Authors:
5− * Pawel Stolowski <pawel.stolowski@canonical.com>
6− *
7− * This program is free software; you can redistribute it and/or modify
8− * it under the terms of the GNU General Public License as published by
9− * the Free Software Foundation; version 3.
10− *
11− * This program is distributed in the hope that it will be useful,
12− * but WITHOUT ANY WARRANTY; without even the implied warranty of
13− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14− * GNU General Public License for more details.
15− *
16− * You should have received a copy of the GNU General Public License
17− * along with this program. If not, see <http://www.gnu.org/licenses/>.
18− */
19−
20−#ifndef PREVIEWACTION_H
21−#define PREVIEWACTION_H
22−
23−// Qt
24−#include <QObject>
25−#include <QList>
26−
27−// libuinity-core
28−#include <UnityCore/Preview.h>
29−
30−enum LayoutHint // keep in sync with unty::dash::LayoutHint
31−{
32− None,
33− Left,
34− Right,
35− Top,
36− Bottom
37−};
38−
39−class Q_DECL_EXPORT PreviewAction : public QObject
40−{
41− Q_OBJECT
42−
43− Q_PROPERTY(QString id READ id NOTIFY previewActionChanged)
44− Q_PROPERTY(QString displayName READ displayName NOTIFY previewActionChanged)
45− Q_PROPERTY(QString iconHint READ iconHint NOTIFY previewActionChanged)
46− Q_PROPERTY(QString extraText READ extraText NOTIFY previewActionChanged)
47− Q_PROPERTY(QString activationUri READ activationUri NOTIFY previewActionChanged)
48− Q_PROPERTY(LayoutHint layoutHint READ layoutHint NOTIFY previewActionChanged)
49−
50−public:
51− explicit PreviewAction(QObject *parent = 0);
52− void setUnityAction(unity::dash::Preview::ActionPtr unityAction);
53−
54− QString id() const;
55− QString displayName() const;
56− QString iconHint() const;
57− QString extraText() const;
58− QString activationUri() const;
59− LayoutHint layoutHint() const;
60−
61−Q_SIGNALS:
62− void previewActionChanged();
63−
64−private:
65− unity::dash::Preview::ActionPtr m_unityAction;
66−};
67−
68−Q_DECLARE_METATYPE(PreviewAction *)
69−Q_DECLARE_METATYPE(LayoutHint)
70−
71−#endif
plugins/Unity/previewinfohint.cppdeleted−67
@@ -1,67 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * Authors:
5− * Pawel Stolowski <pawel.stolowski@canonical.com>
6− *
7− * This program is free software; you can redistribute it and/or modify
8− * it under the terms of the GNU General Public License as published by
9− * the Free Software Foundation; version 3.
10− *
11− * This program is distributed in the hope that it will be useful,
12− * but WITHOUT ANY WARRANTY; without even the implied warranty of
13− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14− * GNU General Public License for more details.
15− *
16− * You should have received a copy of the GNU General Public License
17− * along with this program. If not, see <http://www.gnu.org/licenses/>.
18− */
19−
20−#include <deelistmodel.h>
21−// local
22−#include "previewinfohint.h"
23−
24−PreviewInfoHint::PreviewInfoHint(QObject *parent):
25− QObject(parent),
26− m_unityInfoHint(nullptr)
27−{
28−}
29−
30−void PreviewInfoHint::setUnityInfoHint(unity::dash::Preview::InfoHintPtr unityInfoHint)
31−{
32− m_unityInfoHint = unityInfoHint;
33−
34− Q_EMIT previewInfoHintChanged();
35−}
36−
37−QString PreviewInfoHint::id() const
38−{
39− if (m_unityInfoHint) {
40− return QString::fromStdString(m_unityInfoHint->id);
41− }
42− return QString();
43−}
44−
45−QString PreviewInfoHint::displayName() const
46−{
47− if (m_unityInfoHint) {
48− return QString::fromStdString(m_unityInfoHint->display_name);
49− }
50− return QString();
51−}
52−
53−QString PreviewInfoHint::iconHint() const
54−{
55− if (m_unityInfoHint) {
56− return QString::fromStdString(m_unityInfoHint->icon_hint);
57− }
58− return QString();
59−}
60−
61−QVariant PreviewInfoHint::value() const
62−{
63− if (m_unityInfoHint) {
64− return DeeListModel::VariantForData(m_unityInfoHint->value);
65− }
66− return QVariant();
67−}
plugins/Unity/previewinfohint.hdeleted−58
@@ -1,58 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * Authors:
5− * Pawel Stolowski <pawel.stolowski@canonical.com>
6− *
7− * This program is free software; you can redistribute it and/or modify
8− * it under the terms of the GNU General Public License as published by
9− * the Free Software Foundation; version 3.
10− *
11− * This program is distributed in the hope that it will be useful,
12− * but WITHOUT ANY WARRANTY; without even the implied warranty of
13− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14− * GNU General Public License for more details.
15− *
16− * You should have received a copy of the GNU General Public License
17− * along with this program. If not, see <http://www.gnu.org/licenses/>.
18− */
19−
20−#ifndef PREVIEWINFOHINT_H
21−#define PREVIEWINFOHINT_H
22−
23−// Qt
24−#include <QObject>
25−#include <QString>
26−#include <QVariant>
27−
28−// libunity-core
29−#include <UnityCore/Preview.h>
30−
31−class PreviewInfoHint : public QObject
32−{
33− Q_OBJECT
34−
35− Q_PROPERTY(QString id READ id NOTIFY previewInfoHintChanged)
36− Q_PROPERTY(QString displayName READ displayName NOTIFY previewInfoHintChanged)
37− Q_PROPERTY(QString iconHint READ iconHint NOTIFY previewInfoHintChanged)
38− Q_PROPERTY(QVariant value READ value NOTIFY previewInfoHintChanged)
39−
40−public:
41− explicit PreviewInfoHint(QObject *parent = 0);
42− void setUnityInfoHint(unity::dash::Preview::InfoHintPtr unityInfoHint);
43−
44− QString id() const;
45− QString displayName() const;
46− QString iconHint() const;
47− QVariant value() const;
48−
49−Q_SIGNALS:
50− void previewInfoHintChanged();
51−
52−private:
53− unity::dash::Preview::InfoHintPtr m_unityInfoHint;
54−};
55−
56−Q_DECLARE_METATYPE(PreviewInfoHint *)
57−
58−#endif
plugins/Unity/qmldirdeleted−3
@@ -1,3 +0,0 @@
1−module Unity
2−plugin Unity-qml
3−typeinfo plugin.qmltypes
plugins/Unity/radiooptionfilter.cppdeleted−61
@@ -1,61 +0,0 @@
1−/*
2− * Copyright (C) 2011, 2013 Canonical, Ltd.
3− *
4− * Authors:
5− * Florian Boucault <florian.boucault@canonical.com>
6− * Pawel Stolowski <pawel.stolowski@canonical.com>
7− *
8− * This program is free software; you can redistribute it and/or modify
9− * it under the terms of the GNU General Public License as published by
10− * the Free Software Foundation; version 3.
11− *
12− * This program is distributed in the hope that it will be useful,
13− * but WITHOUT ANY WARRANTY; without even the implied warranty of
14− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15− * GNU General Public License for more details.
16− *
17− * You should have received a copy of the GNU General Public License
18− * along with this program. If not, see <http://www.gnu.org/licenses/>.
19− */
20−
21−// Self
22−#include "radiooptionfilter.h"
23−
24−// local
25−#include "unityoptionsmodel.h"
26−
27−RadioOptionFilter::RadioOptionFilter(QObject *parent) :
28− Filter(parent), m_unityRadioOptionFilter(nullptr), m_options(nullptr)
29−{
30−}
31−
32−GenericOptionsModel* RadioOptionFilter::options() const
33−{
34− return m_options;
35−}
36−
37−void RadioOptionFilter::setUnityFilter(unity::dash::Filter::Ptr filter)
38−{
39− Filter::setUnityFilter(filter);
40− m_unityRadioOptionFilter = std::dynamic_pointer_cast<unity::dash::RadioOptionFilter>(m_unityFilter);
41−
42− onOptionsChanged(m_unityRadioOptionFilter->options);
43−}
44−
45−void RadioOptionFilter::onOptionsChanged(unity::dash::RadioOptionFilter::RadioOptions)
46−{
47− if (m_options != nullptr) {
48− m_signals.disconnectAll();
49− delete m_options;
50− m_options = nullptr;
51− }
52− m_options = new UnityOptionsModel(this, m_unityRadioOptionFilter->options,
53− m_unityRadioOptionFilter->option_added,
54− m_unityRadioOptionFilter->option_removed,
55− m_unityRadioOptionFilter->show_all_button);
56− connect(m_options, SIGNAL(showAllActivated()), this, SLOT(clear()));
57−
58− m_signals << m_unityRadioOptionFilter->options.changed.connect(sigc::mem_fun(this, &RadioOptionFilter::onOptionsChanged));
59−
60− Q_EMIT optionsChanged();
61−}
plugins/Unity/radiooptionfilter.hdeleted−59
@@ -1,59 +0,0 @@
1−/*
2− * Copyright (C) 2011, 2013 Canonical, Ltd.
3− *
4− * Authors:
5− * Florian Boucault <florian.boucault@canonical.com>
6− * Pawel Stolowski <pawel.stolowski@canonical.com>
7− *
8− * This program is free software; you can redistribute it and/or modify
9− * it under the terms of the GNU General Public License as published by
10− * the Free Software Foundation; version 3.
11− *
12− * This program is distributed in the hope that it will be useful,
13− * but WITHOUT ANY WARRANTY; without even the implied warranty of
14− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15− * GNU General Public License for more details.
16− *
17− * You should have received a copy of the GNU General Public License
18− * along with this program. If not, see <http://www.gnu.org/licenses/>.
19− */
20−
21−#ifndef RADIOOPTIONFILTER_H
22−#define RADIOOPTIONFILTER_H
23−
24−// Qt
25−#include <QObject>
26−#include <QMetaType>
27−
28−// libunity-core
29−#include <UnityCore/RadioOptionFilter.h>
30−
31−// Local
32−#include "filter.h"
33−#include "filteroption.h"
34−#include "signalslist.h"
35−
36−class Q_DECL_EXPORT RadioOptionFilter : public Filter
37−{
38− Q_OBJECT
39−
40−public:
41− explicit RadioOptionFilter(QObject *parent = nullptr);
42−
43− /* getters */
44− GenericOptionsModel* options() const override;
45−
46−protected:
47− void setUnityFilter(unity::dash::Filter::Ptr filter) override;
48−
49−private:
50− unity::dash::RadioOptionFilter::Ptr m_unityRadioOptionFilter;
51− GenericOptionsModel* m_options;
52− SignalsList m_signals;
53−
54− void onOptionsChanged(unity::dash::RadioOptionFilter::RadioOptions);
55−};
56−
57−Q_DECLARE_METATYPE(RadioOptionFilter*)
58−
59−#endif // RADIOOPTIONFILTER_H
plugins/Unity/ratingfilteroption.cppdeleted−62
@@ -1,62 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * Authors:
5− * Pawel Stolowski <pawel.stolowski@canonical.com>
6− *
7− * This program is free software; you can redistribute it and/or modify
8− * it under the terms of the GNU General Public License as published by
9− * the Free Software Foundation; version 3.
10− *
11− * This program is distributed in the hope that it will be useful,
12− * but WITHOUT ANY WARRANTY; without even the implied warranty of
13− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14− * GNU General Public License for more details.
15− *
16− * You should have received a copy of the GNU General Public License
17− * along with this program. If not, see <http://www.gnu.org/licenses/>.
18− */
19−
20−// self
21−#include "ratingfilteroption.h"
22−
23−RatingFilterOption::RatingFilterOption(const QString &id, float value, QObject *parent) :
24− AbstractFilterOption(parent),
25− m_active(false),
26− m_id(id),
27− m_value(value)
28−{
29−}
30−
31−QString RatingFilterOption::id() const
32−{
33− return m_id;
34−}
35−
36−QString RatingFilterOption::name() const
37−{
38− return QString::Null();
39−}
40−
41−QString RatingFilterOption::iconHint() const
42−{
43− return QString::Null();
44−}
45−
46−float RatingFilterOption::value() const
47−{
48− return m_value;
49−}
50−
51−bool RatingFilterOption::active() const
52−{
53− return m_active;
54−}
55−
56−void RatingFilterOption::setActive(bool active)
57−{
58− if (active != m_active) {
59− m_active = active;
60− Q_EMIT activeChanged(m_active);
61− }
62−}
plugins/Unity/ratingfilteroption.hdeleted−53
@@ -1,53 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * Authors:
5− * Pawel Stolowski <pawel.stolowski@canonical.com>
6− *
7− * This program is free software; you can redistribute it and/or modify
8− * it under the terms of the GNU General Public License as published by
9− * the Free Software Foundation; version 3.
10− *
11− * This program is distributed in the hope that it will be useful,
12− * but WITHOUT ANY WARRANTY; without even the implied warranty of
13− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14− * GNU General Public License for more details.
15− *
16− * You should have received a copy of the GNU General Public License
17− * along with this program. If not, see <http://www.gnu.org/licenses/>.
18− */
19−
20−#ifndef RATINGFILTEROPTION_H
21−#define RATINGFILTEROPTION_H
22−
23−// local
24−#include "abstractfilteroption.h"
25−
26−class Q_DECL_EXPORT RatingFilterOption : public AbstractFilterOption
27−{
28− Q_OBJECT
29−
30− Q_PROPERTY(float value READ value CONSTANT)
31−
32−public:
33− explicit RatingFilterOption(const QString &id, float ratingValue, QObject *parent = nullptr);
34−
35− /* getters */
36− QString id() const override;
37− QString name() const override;
38− QString iconHint() const override;
39− bool active() const override;
40− float value() const;
41−
42− /* setters */
43− void setActive(bool active) override;
44−
45−private:
46− bool m_active;
47− QString m_id;
48− float m_value;
49−};
50−
51−Q_DECLARE_METATYPE(RatingFilterOption*)
52−
53−#endif // RATINGFILTEROPTION_H
plugins/Unity/ratingsfilter.cppdeleted−73
@@ -1,73 +0,0 @@
1−/*
2− * Copyright (C) 2011, 2013 Canonical, Ltd.
3− *
4− * Authors:
5− * Florian Boucault <florian.boucault@canonical.com>
6− * Pawel Stolowski <pawel.stolowski@canonical.com>
7− *
8− * This program is free software; you can redistribute it and/or modify
9− * it under the terms of the GNU General Public License as published by
10− * the Free Software Foundation; version 3.
11− *
12− * This program is distributed in the hope that it will be useful,
13− * but WITHOUT ANY WARRANTY; without even the implied warranty of
14− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15− * GNU General Public License for more details.
16− *
17− * You should have received a copy of the GNU General Public License
18− * along with this program. If not, see <http://www.gnu.org/licenses/>.
19− */
20−
21−// Self
22−#include "ratingsfilter.h"
23−
24−// local
25−#include "ratingfilteroption.h"
26−#include "ratingoptionsmodel.h"
27−
28−RatingsFilter::RatingsFilter(QObject *parent) :
29− Filter(parent),
30− m_unityRatingsFilter(nullptr),
31− m_options(nullptr)
32−{
33−}
34−
35−GenericOptionsModel* RatingsFilter::options() const
36−{
37− return m_options;
38−}
39−
40−float RatingsFilter::rating() const
41−{
42− if (m_unityRatingsFilter)
43− {
44− return m_unityRatingsFilter->rating;
45− }
46− return 0.0f;
47−}
48−
49−void RatingsFilter::setUnityFilter(unity::dash::Filter::Ptr filter)
50−{
51− Filter::setUnityFilter(filter);
52− m_unityRatingsFilter = std::dynamic_pointer_cast<unity::dash::RatingsFilter>(m_unityFilter);
53−
54− delete m_options;
55−
56− m_options = new RatingOptionsModel(m_unityRatingsFilter->show_all_button, this);
57− connect(m_options, SIGNAL(activeChanged(AbstractFilterOption *)), m_options, SLOT(ensureTheOnlyActive(AbstractFilterOption *)));
58− connect(m_options, SIGNAL(activeChanged(AbstractFilterOption *)), this, SLOT(onActiveChanged(AbstractFilterOption *)));
59− connect(m_options, SIGNAL(showAllActivated()), this, SLOT(clear()));
60−
61− Q_EMIT optionsChanged();
62−}
63−
64−void RatingsFilter::onActiveChanged(AbstractFilterOption *option)
65−{
66− RatingFilterOption *ratingOption = dynamic_cast<RatingFilterOption*>(option);
67− if (ratingOption != nullptr)
68− {
69− const float val = ratingOption->active() ? ratingOption->value() : 0.0f;
70− m_unityRatingsFilter->rating = val;
71− Q_EMIT ratingChanged(val);
72− }
73−}
plugins/Unity/ratingsfilter.hdeleted−66
@@ -1,66 +0,0 @@
1−/*
2− * Copyright (C) 2011, 2013 Canonical, Ltd.
3− *
4− * Authors:
5− * Florian Boucault <florian.boucault@canonical.com>
6− * Pawel Stolowski <pawel.stolowski@canonical.com>
7− *
8− * This program is free software; you can redistribute it and/or modify
9− * it under the terms of the GNU General Public License as published by
10− * the Free Software Foundation; version 3.
11− *
12− * This program is distributed in the hope that it will be useful,
13− * but WITHOUT ANY WARRANTY; without even the implied warranty of
14− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15− * GNU General Public License for more details.
16− *
17− * You should have received a copy of the GNU General Public License
18− * along with this program. If not, see <http://www.gnu.org/licenses/>.
19− */
20−
21−#ifndef RATINGSFILTER_H
22−#define RATINGSFILTER_H
23−
24−// Qt
25−#include <QObject>
26−#include <QMetaType>
27−
28−// libunity-core
29−#include <UnityCore/RatingsFilter.h>
30−
31−// Local
32−#include "filter.h"
33−
34−class GenericOptionsModel;
35−class AbstractFilterOption;
36−
37−class Q_DECL_EXPORT RatingsFilter : public Filter
38−{
39− Q_OBJECT
40−
41− Q_PROPERTY(float rating READ rating NOTIFY ratingChanged)
42−
43−public:
44− explicit RatingsFilter(QObject *parent = nullptr);
45−
46− /* getters */
47− GenericOptionsModel* options() const override;
48− float rating() const;
49−
50−Q_SIGNALS:
51− void ratingChanged(float);
52−
53−protected:
54− void setUnityFilter(unity::dash::Filter::Ptr filter) override;
55−
56−protected Q_SLOTS:
57− void onActiveChanged(AbstractFilterOption *option);
58−
59−private:
60− unity::dash::RatingsFilter::Ptr m_unityRatingsFilter;
61− GenericOptionsModel *m_options;
62−};
63−
64−Q_DECLARE_METATYPE(RatingsFilter*)
65−
66−#endif // RATINGSFILTER_H
plugins/Unity/result.cppdeleted−82
@@ -1,82 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * Authors:
5− * Pawel Stolowski <pawel.stolowski@canonical.com>
6− *
7− * This program is free software; you can redistribute it and/or modify
8− * it under the terms of the GNU General Public License as published by
9− * the Free Software Foundation; version 3.
10− *
11− * This program is distributed in the hope that it will be useful,
12− * but WITHOUT ANY WARRANTY; without even the implied warranty of
13− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14− * GNU General Public License for more details.
15− *
16− * You should have received a copy of the GNU General Public License
17− * along with this program. If not, see <http://www.gnu.org/licenses/>.
18− */
19−
20−#include "result.h"
21−#include "variantutils.h"
22−
23−Result::Result(QObject *parent) :
24− QObject(parent)
25−{
26−}
27−
28−Result::Result(unity::dash::Preview::Ptr preview, QObject *parent) :
29− QObject(parent),
30− m_preview(preview)
31−{
32−}
33−
34−void Result::setPreview(unity::dash::Preview::Ptr preview)
35−{
36− m_preview = preview;
37−}
38−
39−QString Result::uri() const
40−{
41− return m_preview != nullptr ? QString::fromStdString(m_preview->preview_result.uri) : QString::null;
42−}
43−
44−QString Result::iconHint() const
45−{
46− return m_preview != nullptr ? QString::fromStdString(m_preview->preview_result.icon_hint) : QString::null;
47−}
48−
49−unsigned Result::categoryIndex() const
50−{
51− return m_preview != nullptr ? m_preview->preview_result.category_index : 0;
52−}
53−
54−unsigned Result::resultType() const
55−{
56− return m_preview != nullptr ? m_preview->preview_result.result_type : 0;
57−}
58−
59−QString Result::mimeType() const
60−{
61− return m_preview != nullptr ? QString::fromStdString(m_preview->preview_result.mimetype) : QString::null;
62−}
63−
64−QString Result::title() const
65−{
66− return m_preview != nullptr ? QString::fromStdString(m_preview->preview_result.name) : QString::null;
67−}
68−
69−QString Result::comment() const
70−{
71− return m_preview != nullptr ? QString::fromStdString(m_preview->preview_result.comment) : QString::null;
72−}
73−
74−QString Result::dndUri() const
75−{
76− return m_preview != nullptr ? QString::fromStdString(m_preview->preview_result.dnd_uri) : QString::null;
77−}
78−
79−QVariant Result::metadata() const
80−{
81− return m_preview != nullptr ? convertToQVariantHash(m_preview->preview_result.hints) : QVariant();
82−}
plugins/Unity/result.hdeleted−69
@@ -1,69 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * Authors:
5− * Pawel Stolowski <pawel.stolowski@canonical.com>
6− *
7− * This program is free software; you can redistribute it and/or modify
8− * it under the terms of the GNU General Public License as published by
9− * the Free Software Foundation; version 3.
10− *
11− * This program is distributed in the hope that it will be useful,
12− * but WITHOUT ANY WARRANTY; without even the implied warranty of
13− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14− * GNU General Public License for more details.
15− *
16− * You should have received a copy of the GNU General Public License
17− * along with this program. If not, see <http://www.gnu.org/licenses/>.
18− */
19−
20−#ifndef RESULT_H
21−#define RESULT_H
22−
23−// Qt
24−#include <QObject>
25−#include <QVariant>
26−
27−// libunity-core
28−#include <UnityCore/Preview.h>
29−
30−class Q_DECL_EXPORT Result : public QObject
31−{
32− Q_OBJECT
33−
34− Q_PROPERTY(QString uri READ uri CONSTANT)
35− Q_PROPERTY(QString iconHint READ iconHint CONSTANT)
36− Q_PROPERTY(unsigned categoryIndex READ categoryIndex CONSTANT)
37− Q_PROPERTY(unsigned resultType READ resultType CONSTANT)
38− Q_PROPERTY(QString mimeType READ mimeType CONSTANT)
39− Q_PROPERTY(QString title READ title CONSTANT)
40− Q_PROPERTY(QString comment READ comment CONSTANT)
41− Q_PROPERTY(QString dndUri READ dndUri CONSTANT)
42− Q_PROPERTY(QVariant metadata READ metadata CONSTANT)
43−
44−public:
45− Result(QObject *parent = nullptr);
46− Result(unity::dash::Preview::Ptr preview, QObject *parent = nullptr);
47−
48− void setPreview(unity::dash::Preview::Ptr preview);
49−
50− QString uri() const;
51− QString iconHint() const;
52− unsigned categoryIndex() const;
53− unsigned resultType() const;
54− QString mimeType() const;
55− QString title() const;
56− QString comment() const;
57− QString dndUri() const;
58− QVariant metadata() const;
59−
60−private:
61− /* Keep reference to the original preview to access result attributes via it, rather than keeping copies of them;
62− this will save us a bit on copying, especially as UI is mostly interested in just uri.
63− */
64− unity::dash::Preview::Ptr m_preview;
65−};
66−
67−Q_DECLARE_METATYPE(Result *)
68−
69−#endif
plugins/Unity/scope.cppdeleted−413
@@ -1,413 +0,0 @@
1−/*
2− * Copyright (C) 2011 Canonical, Ltd.
3− *
4− * Authors:
5− * Florian Boucault <florian.boucault@canonical.com>
6− * Michal Hruby <michal.hruby@canonical.com>
7− *
8− * This program is free software; you can redistribute it and/or modify
9− * it under the terms of the GNU General Public License as published by
10− * the Free Software Foundation; version 3.
11− *
12− * This program is distributed in the hope that it will be useful,
13− * but WITHOUT ANY WARRANTY; without even the implied warranty of
14− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15− * GNU General Public License for more details.
16− *
17− * You should have received a copy of the GNU General Public License
18− * along with this program. If not, see <http://www.gnu.org/licenses/>.
19− */
20−
21−// Self
22−#include "scope.h"
23−
24−// local
25−#include "categories.h"
26−#include "preview.h"
27−#include "variantutils.h"
28−
29−// Qt
30−#include <QUrl>
31−#include <QUrlQuery>
32−#include <QDebug>
33−#include <QtGui/QDesktopServices>
34−#include <QQmlEngine>
35−
36−#include <UnityCore/Variant.h>
37−#include <UnityCore/GLibWrapper.h>
38−
39−#include <libintl.h>
40−#include <glib.h>
41−
42−Scope::Scope(QObject *parent) : QObject(parent)
43− , m_formFactor("phone")
44− , m_isActive(false)
45− , m_searchInProgress(false)
46−{
47− m_categories.reset(new Categories(this));
48−
49− connect(this, &Scope::isActiveChanged, this, &Scope::scopeIsActiveChanged);
50−}
51−
52−QString Scope::id() const
53−{
54− return QString::fromStdString(m_unityScope->id());
55−}
56−
57−QString Scope::name() const
58−{
59− return QString::fromStdString(m_unityScope->name());
60−}
61−
62−QString Scope::iconHint() const
63−{
64− return QString::fromStdString(m_unityScope->icon_hint());
65−}
66−
67−QString Scope::description() const
68−{
69− return QString::fromStdString(m_unityScope->description());
70−}
71−
72−QString Scope::searchHint() const
73−{
74− return QString::fromStdString(m_unityScope->search_hint());
75−}
76−
77−bool Scope::searchInProgress() const
78−{
79− return m_searchInProgress;
80−}
81−
82−bool Scope::visible() const
83−{
84− return m_unityScope->visible();
85−}
86−
87−QString Scope::shortcut() const
88−{
89− return QString::fromStdString(m_unityScope->shortcut());
90−}
91−
92−bool Scope::connected() const
93−{
94− return m_unityScope->connected();
95−}
96−
97−Categories* Scope::categories() const
98−{
99− return m_categories.get();
100−}
101−
102−QString Scope::searchQuery() const
103−{
104− return m_searchQuery;
105−}
106−
107−QString Scope::noResultsHint() const
108−{
109− return m_noResultsHint;
110−}
111−
112−QString Scope::formFactor() const
113−{
114− return m_formFactor;
115−}
116−
117−bool Scope::isActive() const
118−{
119− return m_isActive;
120−}
121−
122−Filters* Scope::filters() const
123−{
124− return m_filters.get();
125−}
126−
127−void Scope::setSearchQuery(const QString& search_query)
128−{
129− /* Checking for m_searchQuery.isNull() which returns true only when the string
130− has never been set is necessary because when search_query is the empty
131− string ("") and m_searchQuery is the null string,
132− search_query != m_searchQuery is still true.
133− */
134− using namespace std::placeholders;
135−
136− if (m_searchQuery.isNull() || search_query != m_searchQuery) {
137− m_searchQuery = search_query;
138− m_cancellable.Renew();
139− m_unityScope->Search(search_query.toStdString(), std::bind(&Scope::onSearchFinished, this, _1, _2, _3), m_cancellable);
140− Q_EMIT searchQueryChanged();
141− if (!m_searchInProgress) {
142− m_searchInProgress = true;
143− Q_EMIT searchInProgressChanged();
144− }
145− }
146−}
147−
148−void Scope::setNoResultsHint(const QString& hint) {
149− if (hint != m_noResultsHint) {
150− m_noResultsHint = hint;
151− Q_EMIT noResultsHintChanged();
152− }
153−}
154−
155−void Scope::setFormFactor(const QString& form_factor) {
156− if (form_factor != m_formFactor) {
157− m_formFactor = form_factor;
158− if (m_unityScope) {
159− m_unityScope->form_factor = m_formFactor.toStdString();
160− synchronizeStates(); // will trigger a re-search
161− }
162− Q_EMIT formFactorChanged();
163− }
164−}
165−
166−void Scope::setActive(const bool active) {
167− if (active != m_isActive) {
168− m_isActive = active;
169− Q_EMIT isActiveChanged(m_isActive);
170− }
171−}
172−
173−unity::dash::LocalResult Scope::createLocalResult(const QVariant &uri, const QVariant &icon_hint,
174− const QVariant &category, const QVariant &result_type,
175− const QVariant &mimetype, const QVariant &title,
176− const QVariant &comment, const QVariant &dnd_uri,
177− const QVariant &metadata)
178−{
179− unity::dash::LocalResult res;
180− res.uri = uri.toString().toStdString();
181− res.icon_hint = icon_hint.toString().toStdString();
182− res.category_index = category.toUInt();
183− res.result_type = result_type.toUInt();
184− res.mimetype = mimetype.toString().toStdString();
185− res.name = title.toString().toStdString();
186− res.comment = comment.toString().toStdString();
187− res.dnd_uri = dnd_uri.toString().toStdString();
188− res.hints = convertToHintsMap(metadata);
189−
190− return res;
191−}
192−
193−// FIXME: Change to use row index.
194−void Scope::activate(const QVariant &uri, const QVariant &icon_hint, const QVariant &category,
195− const QVariant &result_type, const QVariant &mimetype, const QVariant &title,
196− const QVariant &comment, const QVariant &dnd_uri, const QVariant &metadata)
197−{
198− auto res = createLocalResult(uri, icon_hint, category, result_type, mimetype, title, comment, dnd_uri, metadata);
199− m_unityScope->Activate(res);
200−}
201−
202−// FIXME: Change to use row index.
203−void Scope::preview(const QVariant &uri, const QVariant &icon_hint, const QVariant &category,
204− const QVariant &result_type, const QVariant &mimetype, const QVariant &title,
205− const QVariant &comment, const QVariant &dnd_uri, const QVariant &metadata)
206−{
207− QVariant real_metadata(metadata);
208− // handle overridden results, since QML doesn't support defining maps
209− if (metadata.type() == QVariant::String) {
210− real_metadata = QVariant::fromValue(subscopeUriToMetadataHash(metadata.toString()));
211− }
212−
213− auto res = createLocalResult(uri, icon_hint, category, result_type, mimetype, title, comment, dnd_uri, real_metadata);
214− m_previewCancellable.Renew();
215−
216− // canned queries don't have previews, must be activated
217− if (uri.toString().startsWith("x-unity-no-preview-scopes-query://")) {
218− m_unityScope->Activate(res);
219− } else {
220− m_unityScope->Preview(res, nullptr, m_previewCancellable);
221− }
222−}
223−
224−void Scope::cancelActivation()
225−{
226− m_previewCancellable.Cancel();
227−}
228−
229−void Scope::onActivated(unity::dash::LocalResult const& result, unity::dash::ScopeHandledType type, unity::glib::HintsMap const& hints)
230−{
231− Q_EMIT activated();
232− // note: we will not get called on SHOW_PREVIEW, instead UnityCore will signal preview_ready.
233− switch (type)
234− {
235− case unity::dash::NOT_HANDLED:
236− fallbackActivate(QString::fromStdString(result.uri));
237− break;
238− case unity::dash::SHOW_DASH:
239− Q_EMIT showDash();
240− break;
241− case unity::dash::HIDE_DASH:
242− Q_EMIT hideDash();
243− break;
244− case unity::dash::GOTO_DASH_URI:
245− if (hints.find("goto-uri") != hints.end()) {
246− Q_EMIT gotoUri(QString::fromStdString(g_variant_get_string(hints.at("goto-uri"), nullptr)));
247− } else {
248− qWarning() << "Missing goto-uri hint for GOTO_DASH_URI activation reply";
249− }
250− break;
251− case unity::dash::PERFORM_SEARCH:
252− if (hints.find("query") != hints.end()) {
253− // note: this will emit searchQueryChanged, and shell will call setSearchQuery back with a new query,
254− // but it will get ignored.
255− setSearchQuery(QString::fromStdString(g_variant_get_string(hints.at("query"), nullptr)));
256− }
257− break;
258− default:
259− qWarning() << "Unhandled activation response:" << type;
260− }
261−}
262−
263−void Scope::onPreviewReady(unity::dash::LocalResult const& /* result */, unity::dash::Preview::Ptr const& preview)
264−{
265− Q_EMIT activated();
266− auto prv = Preview::newFromUnityPreview(preview);
267− // is this the best solution? QML may need to keep more than one preview instance around, so we can't own it.
268− // passing it by value is not possible.
269− QQmlEngine::setObjectOwnership(prv, QQmlEngine::JavaScriptOwnership);
270− Q_EMIT previewReady(prv);
271−}
272−
273−void Scope::fallbackActivate(const QString& uri)
274−{
275− /* Tries various methods to trigger a sensible action for the given 'uri'.
276− If it has no understanding of the given scheme it falls back on asking
277− Qt to open the uri.
278− */
279− QUrl url(uri);
280− if (url.scheme() == "file") {
281− /* Override the files place's default URI handler: we want the file
282− manager to handle opening folders, not the dash.
283−
284− Ref: https://bugs.launchpad.net/upicek/+bug/689667
285− */
286− QDesktopServices::openUrl(url);
287− return;
288− }
289− if (url.scheme() == "application") {
290− // get the full path to the desktop file
291− QString path(url.path().isEmpty() ? url.authority() : url.path());
292− if (path.startsWith("/")) {
293− Q_EMIT activateApplication(path);
294− } else {
295− // TODO: use the new desktop file finder/parser when it's ready
296− gchar* full_path = nullptr;
297− GKeyFile* key_file = g_key_file_new();
298− QString apps_path = "applications/" + path;
299− if (g_key_file_load_from_data_dirs(key_file, apps_path.toLocal8Bit().constData(), &full_path,
300− G_KEY_FILE_NONE, nullptr)) {
301− path = full_path;
302− Q_EMIT activateApplication(path);
303− } else {
304− qWarning() << "Unable to activate " << path;
305− }
306− g_key_file_free(key_file);
307− g_free(full_path);
308− }
309− return;
310− }
311−
312− qDebug() << "Trying to open" << uri;
313−
314− /* Try our luck */
315− QDesktopServices::openUrl(uri); //url?
316−}
317−
318−void Scope::setUnityScope(const unity::dash::Scope::Ptr& scope)
319−{
320− m_unityScope = scope;
321−
322− m_categories->setUnityScope(m_unityScope);
323− m_filters.reset(new Filters(m_unityScope->filters, this));
324−
325− m_unityScope->form_factor = m_formFactor.toStdString();
326− /* Property change signals */
327− m_unityScope->id.changed.connect(sigc::mem_fun(this, &Scope::idChanged));
328− m_unityScope->name.changed.connect(sigc::mem_fun(this, &Scope::nameChanged));
329− m_unityScope->icon_hint.changed.connect(sigc::mem_fun(this, &Scope::iconHintChanged));
330− m_unityScope->description.changed.connect(sigc::mem_fun(this, &Scope::descriptionChanged));
331− m_unityScope->search_hint.changed.connect(sigc::mem_fun(this, &Scope::searchHintChanged));
332− m_unityScope->visible.changed.connect(sigc::mem_fun(this, &Scope::visibleChanged));
333− m_unityScope->shortcut.changed.connect(sigc::mem_fun(this, &Scope::shortcutChanged));
334− m_unityScope->connected.changed.connect(sigc::mem_fun(this, &Scope::connectedChanged));
335− m_unityScope->results_dirty.changed.connect(sigc::mem_fun(this, &Scope::resultsDirtyToggled));
336−
337− /* FIXME: signal should be forwarded instead of calling the handler directly */
338− m_unityScope->activated.connect(sigc::mem_fun(this, &Scope::onActivated));
339−
340− m_unityScope->preview_ready.connect(sigc::mem_fun(this, &Scope::onPreviewReady));
341−
342− /* Synchronize local states with m_unityScope right now and whenever
343− m_unityScope becomes connected */
344− /* FIXME: should emit change notification signals for all properties */
345− connect(this, SIGNAL(connectedChanged(bool)), SLOT(synchronizeStates()));
346− synchronizeStates();
347−}
348−
349−unity::dash::Scope::Ptr Scope::unityScope() const
350−{
351− return m_unityScope;
352−}
353−
354−void Scope::synchronizeStates()
355−{
356− using namespace std::placeholders;
357−
358− if (connected()) {
359− /* Forward local states to m_unityScope */
360− if (!m_searchQuery.isNull()) {
361− m_cancellable.Renew();
362− m_unityScope->Search(m_searchQuery.toStdString(), std::bind(&Scope::onSearchFinished, this, _1, _2, _3), m_cancellable);
363− if (!m_searchInProgress) {
364− m_searchInProgress = true;
365− Q_EMIT searchInProgressChanged();
366− }
367− }
368− }
369−}
370−
371−void Scope::scopeIsActiveChanged()
372−{
373− if (!isActive() || !m_unityScope || !m_unityScope->results_dirty()) return;
374−
375− // force new search
376− synchronizeStates();
377−}
378−
379−void Scope::resultsDirtyToggled(bool results_dirty)
380−{
381− if (!results_dirty || !isActive()) return;
382−
383− // force new search
384− synchronizeStates();
385−}
386−
387−void Scope::onSearchFinished(std::string const& /* query */, unity::glib::HintsMap const& hints, unity::glib::Error const& err)
388−{
389− QString hint;
390−
391− GError* error = const_cast<unity::glib::Error&>(err);
392−
393− if (!err || !g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
394− if (m_searchInProgress) {
395− m_searchInProgress = false;
396− Q_EMIT searchInProgressChanged();
397− }
398− } else {
399− // no need to check the results hint, we're still searching
400− return;
401− }
402−
403− if (!m_unityScope->results()->count()) {
404− unity::glib::HintsMap::const_iterator it = hints.find("no-results-hint");
405− if (it != hints.end()) {
406− hint = QString::fromStdString(it->second.GetString());
407− } else {
408− hint = QString::fromUtf8(dgettext("unity", "Sorry, there is nothing that matches your search."));
409− }
410− }
411−
412− setNoResultsHint(hint);
413−}
plugins/Unity/scope.hdeleted−154
@@ -1,154 +0,0 @@
1−/*
2− * Copyright (C) 2011 Canonical, Ltd.
3− *
4− * Authors:
5− * Florian Boucault <florian.boucault@canonical.com>
6− *
7− * This program is free software; you can redistribute it and/or modify
8− * it under the terms of the GNU General Public License as published by
9− * the Free Software Foundation; version 3.
10− *
11− * This program is distributed in the hope that it will be useful,
12− * but WITHOUT ANY WARRANTY; without even the implied warranty of
13− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14− * GNU General Public License for more details.
15− *
16− * You should have received a copy of the GNU General Public License
17− * along with this program. If not, see <http://www.gnu.org/licenses/>.
18− */
19−
20−#ifndef SCOPE_H
21−#define SCOPE_H
22−
23−// Qt
24−#include <QObject>
25−#include <QString>
26−#include <QMetaType>
27−
28−// libunity-core
29−#include <UnityCore/Scope.h>
30−#include <UnityCore/Results.h>
31−#include <UnityCore/GLibWrapper.h>
32−
33−#include "categories.h"
34−#include "filters.h"
35−
36−class Preview;
37−
38−class Scope : public QObject
39−{
40− Q_OBJECT
41−
42− Q_PROPERTY(QString id READ id NOTIFY idChanged)
43− Q_PROPERTY(QString name READ name NOTIFY nameChanged)
44− Q_PROPERTY(QString iconHint READ iconHint NOTIFY iconHintChanged)
45− Q_PROPERTY(QString description READ description NOTIFY descriptionChanged)
46− Q_PROPERTY(QString searchHint READ searchHint NOTIFY searchHintChanged)
47− Q_PROPERTY(bool searchInProgress READ searchInProgress NOTIFY searchInProgressChanged)
48− Q_PROPERTY(bool visible READ visible NOTIFY visibleChanged)
49− Q_PROPERTY(QString shortcut READ shortcut NOTIFY shortcutChanged)
50− Q_PROPERTY(bool connected READ connected NOTIFY connectedChanged)
51− Q_PROPERTY(Categories* categories READ categories NOTIFY categoriesChanged)
52− Q_PROPERTY(Filters* filters READ filters NOTIFY filtersChanged)
53−
54− Q_PROPERTY(QString searchQuery READ searchQuery WRITE setSearchQuery NOTIFY searchQueryChanged)
55− Q_PROPERTY(QString noResultsHint READ noResultsHint WRITE setNoResultsHint NOTIFY noResultsHintChanged)
56− Q_PROPERTY(QString formFactor READ formFactor WRITE setFormFactor NOTIFY formFactorChanged)
57− Q_PROPERTY(bool isActive READ isActive WRITE setActive NOTIFY isActiveChanged)
58−
59−public:
60− explicit Scope(QObject *parent = 0);
61−
62− /* getters */
63− QString id() const;
64− QString name() const;
65− QString iconHint() const;
66− QString description() const;
67− QString searchHint() const;
68− bool visible() const;
69− QString shortcut() const;
70− bool connected() const;
71− bool searchInProgress() const;
72− Categories* categories() const;
73− Filters* filters() const;
74− QString searchQuery() const;
75− QString noResultsHint() const;
76− QString formFactor() const;
77− bool isActive() const;
78−
79− /* setters */
80− void setSearchQuery(const QString& search_query);
81− void setNoResultsHint(const QString& hint);
82− void setFormFactor(const QString& form_factor);
83− void setActive(const bool);
84−
85− Q_INVOKABLE void activate(const QVariant &uri, const QVariant &icon_hint, const QVariant &category,
86− const QVariant &result_type, const QVariant &mimetype, const QVariant &title,
87− const QVariant &comment, const QVariant &dnd_uri, const QVariant &metadata);
88− Q_INVOKABLE void preview(const QVariant &uri, const QVariant &icon_hint, const QVariant &category,
89− const QVariant &result_type, const QVariant &mimetype, const QVariant &title,
90− const QVariant &comment, const QVariant &dnd_uri, const QVariant &metadata);
91− Q_INVOKABLE void cancelActivation();
92−
93− void setUnityScope(const unity::dash::Scope::Ptr& scope);
94− unity::dash::Scope::Ptr unityScope() const;
95−
96−Q_SIGNALS:
97− void idChanged(const std::string&);
98− void dbusNameChanged(const std::string&);
99− void dbusPathChanged(const std::string&);
100− void nameChanged(const std::string&);
101− void iconHintChanged(const std::string&);
102− void descriptionChanged(const std::string&);
103− void searchHintChanged(const std::string&);
104− void searchInProgressChanged();
105− void visibleChanged(bool);
106− void shortcutChanged(const std::string&);
107− void connectedChanged(bool);
108− void categoriesChanged();
109− void searchQueryChanged();
110− void noResultsHintChanged();
111− void formFactorChanged();
112− void isActiveChanged(bool);
113− void filtersChanged();
114−
115− // signals triggered by activate(..) or preview(..) requests.
116− void previewReady(Preview *preview);
117− void showDash();
118− void hideDash();
119− void gotoUri(const QString &uri);
120− void activated();
121−
122− void activateApplication(const QString &desktop);
123−
124−private Q_SLOTS:
125− void synchronizeStates();
126− void scopeIsActiveChanged();
127− void onSearchFinished(std::string const &, unity::glib::HintsMap const &, unity::glib::Error const&);
128−
129−private:
130− unity::dash::LocalResult createLocalResult(const QVariant &uri, const QVariant &icon_hint,
131− const QVariant &category, const QVariant &result_type,
132− const QVariant &mimetype, const QVariant &title,
133− const QVariant &comment, const QVariant &dnd_uri,
134− const QVariant &metadata);
135− void onActivated(unity::dash::LocalResult const& result, unity::dash::ScopeHandledType type, unity::glib::HintsMap const& hints);
136− void onPreviewReady(unity::dash::LocalResult const& result, unity::dash::Preview::Ptr const& preview);
137− void fallbackActivate(const QString& uri);
138− void resultsDirtyToggled(bool);
139−
140− unity::dash::Scope::Ptr m_unityScope;
141− std::unique_ptr<Categories> m_categories;
142− std::unique_ptr<Filters> m_filters;
143− QString m_searchQuery;
144− QString m_noResultsHint;
145− QString m_formFactor;
146− bool m_isActive;
147− bool m_searchInProgress;
148− unity::glib::Cancellable m_cancellable;
149− unity::glib::Cancellable m_previewCancellable;
150−};
151−
152−Q_DECLARE_METATYPE(Scope*)
153−
154−#endif // SCOPE_H
plugins/Unity/scopes.cppdeleted−176
@@ -1,176 +0,0 @@
1−/*
2− * Copyright (C) 2011 Canonical, Ltd.
3− *
4− * Authors:
5− * Florian Boucault <florian.boucault@canonical.com>
6− *
7− * This program is free software; you can redistribute it and/or modify
8− * it under the terms of the GNU General Public License as published by
9− * the Free Software Foundation; version 3.
10− *
11− * This program is distributed in the hope that it will be useful,
12− * but WITHOUT ANY WARRANTY; without even the implied warranty of
13− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14− * GNU General Public License for more details.
15− *
16− * You should have received a copy of the GNU General Public License
17− * along with this program. If not, see <http://www.gnu.org/licenses/>.
18− */
19−
20−// Self
21−#include "scopes.h"
22−
23−// Local
24−#include "scope.h"
25−
26−// Qt
27−#include <QDebug>
28−#include <QtCore/QStringList>
29−#include <QtGui/QKeySequence>
30−
31−Scopes::Scopes(QObject *parent)
32− : QAbstractListModel(parent)
33− , m_unityScopes(std::make_shared<unity::dash::GSettingsScopes>())
34− , m_loaded(false)
35−{
36− m_roles[Scopes::RoleScope] = "scope";
37− m_roles[Scopes::RoleId] = "id";
38− m_roles[Scopes::RoleVisible] = "visible";
39−
40− m_unityScopes->scope_added.connect(sigc::mem_fun(this, &Scopes::onScopeAdded));
41− m_unityScopes->scope_removed.connect(sigc::mem_fun(this, &Scopes::onScopeRemoved));
42− m_unityScopes->scopes_reordered.connect(sigc::mem_fun(this, &Scopes::onScopesReordered));
43− m_unityScopes->LoadScopes();
44−}
45−
46−QHash<int, QByteArray> Scopes::roleNames() const
47−{
48− return m_roles;
49−}
50−
51−int Scopes::rowCount(const QModelIndex& parent) const
52−{
53− Q_UNUSED(parent)
54−
55− return m_scopes.count();
56−}
57−
58−QVariant Scopes::data(const QModelIndex& index, int role) const
59−{
60− Q_UNUSED(role)
61−
62− if (!index.isValid()) {
63− return QVariant();
64− }
65−
66− Scope* scope = m_scopes.at(index.row());
67−
68− if (role == Scopes::RoleScope) {
69− return QVariant::fromValue(scope);
70− } else if (role == Scopes::RoleId) {
71− return QVariant::fromValue(scope->id());
72− } else if (role == Scopes::RoleVisible) {
73− return QVariant::fromValue(scope->visible());
74− } else {
75− return QVariant();
76− }
77−}
78−
79−QVariant Scopes::get(int row) const
80−{
81− return data(QAbstractListModel::index(row), 0);
82−}
83−
84−QVariant Scopes::get(const QString& scope_id) const
85−{
86− Q_FOREACH(Scope* scope, m_scopes) {
87− if (scope->id() == scope_id) {
88− return QVariant::fromValue(scope);
89− }
90− }
91−
92− return QVariant();
93−}
94−
95−bool Scopes::loaded() const
96−{
97− return m_loaded;
98−}
99−
100−void Scopes::onScopeAdded(const unity::dash::Scope::Ptr& scope, int /*position*/)
101−{
102− int index = m_scopes.count();
103− beginInsertRows(QModelIndex(), index, index);
104− addUnityScope(scope);
105− endInsertRows();
106−
107− // FIXME: do only once after all loaded?
108− m_loaded = true;
109− Q_EMIT loadedChanged(m_loaded);
110−}
111−
112−void Scopes::onScopesLoaded()
113−{
114−}
115−
116−void Scopes::onScopeRemoved(const unity::dash::Scope::Ptr& scope)
117−{
118− auto id = QString::fromStdString(scope->id);
119− auto index = findScopeById(id);
120− if (index >= 0) {
121− beginRemoveRows(QModelIndex(), index, index);
122− removeUnityScope(index);
123− endRemoveRows();
124−
125− Q_EMIT scopeRemoved(id, index);
126− }
127−}
128−
129−void Scopes::onScopesReordered(const unity::dash::Scopes::ScopeList& scopes)
130−{
131− // FIXME Should use beginMoveRows()/endMoveRows() to not recreate the UI for every scope.
132− beginResetModel();
133−
134− // remove existing scopes
135− for (auto i=m_scopes.count()-1; i>=0; i--) {
136− removeUnityScope(i);
137− }
138−
139− // re-create scopes
140− for (uint i=0; i<scopes.size(); i++) {
141− addUnityScope(scopes[i]);
142− }
143− endResetModel();
144−}
145−
146−void Scopes::onScopePropertyChanged()
147−{
148− QModelIndex scopeIndex = index(m_scopes.indexOf(qobject_cast<Scope*>(sender())));
149− Q_EMIT dataChanged(scopeIndex, scopeIndex);
150−}
151−
152−void Scopes::addUnityScope(const unity::dash::Scope::Ptr& unity_scope)
153−{
154− Scope* scope = new Scope(this);
155− scope->setUnityScope(unity_scope);
156− /* DOCME */
157− QObject::connect(scope, SIGNAL(visibleChanged(bool)), this, SLOT(onScopePropertyChanged()));
158− m_scopes.append(scope);
159−}
160−
161−void Scopes::removeUnityScope(int index)
162−{
163− Scope* scope = m_scopes.takeAt(index);
164−
165− delete scope;
166−}
167−
168−int Scopes::findScopeById(const QString& scope_id)
169−{
170− for (int i=0; i<m_scopes.count(); i++) {
171− if (m_scopes[i]->id() == scope_id) {
172− return i;
173− }
174− }
175− return -1;
176−}
plugins/Unity/scopes.hdeleted−94
@@ -1,94 +0,0 @@
1−/*
2− * Copyright (C) 2011 Canonical, Ltd.
3− *
4− * Authors:
5− * Florian Boucault <florian.boucault@canonical.com>
6− *
7− * This program is free software; you can redistribute it and/or modify
8− * it under the terms of the GNU General Public License as published by
9− * the Free Software Foundation; version 3.
10− *
11− * This program is distributed in the hope that it will be useful,
12− * but WITHOUT ANY WARRANTY; without even the implied warranty of
13− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14− * GNU General Public License for more details.
15− *
16− * You should have received a copy of the GNU General Public License
17− * along with this program. If not, see <http://www.gnu.org/licenses/>.
18− */
19−
20−#ifndef SCOPES_H
21−#define SCOPES_H
22−
23−// Qt
24−#include <QAbstractListModel>
25−#include <QList>
26−
27−// libunity-core
28−#include <UnityCore/Scope.h>
29−#include <UnityCore/GSettingsScopes.h>
30−
31−namespace unity
32−{
33−namespace dash
34−{
35−class Scopes;
36−}
37−}
38−
39−class Hotkey;
40−class Scope;
41−
42−class Scopes : public QAbstractListModel
43−{
44− Q_OBJECT
45−
46− Q_ENUMS(Roles)
47−
48− Q_PROPERTY(bool loaded READ loaded NOTIFY loadedChanged)
49−
50−public:
51− explicit Scopes(QObject *parent = 0);
52− ~Scopes() = default;
53−
54− enum Roles {
55− RoleScope,
56− RoleId,
57− RoleVisible
58− };
59−
60− QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
61− Q_INVOKABLE int rowCount(const QModelIndex& parent = QModelIndex()) const;
62−
63− Q_INVOKABLE QVariant get(int row) const;
64− Q_INVOKABLE QVariant get(const QString& scope_id) const;
65−
66− QHash<int, QByteArray> roleNames() const;
67−
68− bool loaded() const;
69−
70−Q_SIGNALS:
71− void activateScopeRequested(const QString& scope_id);
72− void loadedChanged(bool loaded);
73− void scopeRemoved(const QString& scope_id, int index);
74−
75−private Q_SLOTS:
76− void onScopesLoaded();
77− void onScopeAdded(const unity::dash::Scope::Ptr& scope, int position);
78− void onScopeRemoved(const unity::dash::Scope::Ptr& scope);
79− void onScopesReordered(const unity::dash::Scopes::ScopeList& scopes);
80− void onScopePropertyChanged();
81−
82−private:
83− unity::dash::GSettingsScopesReader::Ptr m_scopesReader;
84− unity::dash::Scopes::Ptr m_unityScopes;
85− QList<Scope*> m_scopes;
86− QHash<int, QByteArray> m_roles;
87− bool m_loaded;
88−
89− void addUnityScope(const unity::dash::Scope::Ptr& unity_scope);
90− void removeUnityScope(int index);
91− int findScopeById(const QString& scope_id);
92−};
93−
94−#endif // SCOPES_H
plugins/Unity/showallfilteroption.cppdeleted−60
@@ -1,60 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * Authors:
5− * Pawel Stolowski <pawel.stolowski@canonical.com>
6− *
7− * This program is free software; you can redistribute it and/or modify
8− * it under the terms of the GNU General Public License as published by
9− * the Free Software Foundation; version 3.
10− *
11− * This program is distributed in the hope that it will be useful,
12− * but WITHOUT ANY WARRANTY; without even the implied warranty of
13− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14− * GNU General Public License for more details.
15− *
16− * You should have received a copy of the GNU General Public License
17− * along with this program. If not, see <http://www.gnu.org/licenses/>.
18− */
19−
20−// self
21−#include "showallfilteroption.h"
22−
23−#include <libintl.h>
24−
25−unsigned int ShowAllFilterOption::m_showAllCount = 0;
26−
27−ShowAllFilterOption::ShowAllFilterOption(QObject *parent) :
28− AbstractFilterOption(parent),
29− m_active(false)
30−{
31− m_id = QString("show_all::%1").arg(m_showAllCount++);
32−}
33−
34−QString ShowAllFilterOption::id() const
35−{
36− return m_id;
37−}
38−
39−QString ShowAllFilterOption::name() const
40−{
41− return QString::fromUtf8(dgettext("unity", "All"));
42−}
43−
44−QString ShowAllFilterOption::iconHint() const
45−{
46− return QString::Null();
47−}
48−
49−bool ShowAllFilterOption::active() const
50−{
51− return m_active;
52−}
53−
54−void ShowAllFilterOption::setActive(bool active)
55−{
56− if (active != m_active) {
57− m_active = active;
58− Q_EMIT activeChanged(m_active);
59− }
60−}
plugins/Unity/showallfilteroption.hdeleted−51
@@ -1,51 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * Authors:
5− * Pawel Stolowski <pawel.stolowski@canonical.com>
6− *
7− * This program is free software; you can redistribute it and/or modify
8− * it under the terms of the GNU General Public License as published by
9− * the Free Software Foundation; version 3.
10− *
11− * This program is distributed in the hope that it will be useful,
12− * but WITHOUT ANY WARRANTY; without even the implied warranty of
13− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14− * GNU General Public License for more details.
15− *
16− * You should have received a copy of the GNU General Public License
17− * along with this program. If not, see <http://www.gnu.org/licenses/>.
18− */
19−
20−#ifndef SHOWALLFILTEROPTION_H
21−#define SHOWALLFILTEROPTION_H
22−
23−// local
24−#include "abstractfilteroption.h"
25−
26−class Q_DECL_EXPORT ShowAllFilterOption : public AbstractFilterOption
27−{
28− Q_OBJECT
29−
30−public:
31− explicit ShowAllFilterOption(QObject *parent = nullptr);
32−
33− /* getters */
34− QString id() const override;
35− QString name() const override;
36− QString iconHint() const override;
37− bool active() const override;
38−
39− /* setters */
40− void setActive(bool active) override;
41−
42−private:
43− bool m_active;
44− QString m_id;
45−
46− static unsigned int m_showAllCount;
47−};
48−
49−Q_DECLARE_METATYPE(ShowAllFilterOption*)
50−
51−#endif // SHOWALLFILTEROPTION_H
plugins/Unity/signalslist.cppdeleted−39
@@ -1,39 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * Authors:
5− * Pawel Stolowski <pawel.stolowski@canonical.com>
6− *
7− * This program is free software; you can redistribute it and/or modify
8− * it under the terms of the GNU General Public License as published by
9− * the Free Software Foundation; version 3.
10− *
11− * This program is distributed in the hope that it will be useful,
12− * but WITHOUT ANY WARRANTY; without even the implied warranty of
13− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14− * GNU General Public License for more details.
15− *
16− * You should have received a copy of the GNU General Public License
17− * along with this program. If not, see <http://www.gnu.org/licenses/>.
18− */
19−
20−#include "signalslist.h"
21−
22−void SignalsList::append(const sigc::connection &c)
23−{
24− m_signals.append(c);
25−}
26−
27−void SignalsList::disconnectAll()
28−{
29− Q_FOREACH(auto sig, m_signals) {
30− sig.disconnect();
31− }
32− m_signals.clear();
33−}
34−
35−SignalsList& SignalsList::operator<<(const sigc::connection &c)
36−{
37− append(c);
38− return *this;
39−}
plugins/Unity/signalslist.hdeleted−38
@@ -1,38 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * Authors:
5− * Pawel Stolowski <pawel.stolowski@canonical.com>
6− *
7− * This program is free software; you can redistribute it and/or modify
8− * it under the terms of the GNU General Public License as published by
9− * the Free Software Foundation; version 3.
10− *
11− * This program is distributed in the hope that it will be useful,
12− * but WITHOUT ANY WARRANTY; without even the implied warranty of
13− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14− * GNU General Public License for more details.
15− *
16− * You should have received a copy of the GNU General Public License
17− * along with this program. If not, see <http://www.gnu.org/licenses/>.
18− */
19−
20−#ifndef SIGNALSLIST_H
21−#define SIGNALSLIST_H
22−
23−#include <QList>
24−#include <sigc++/sigc++.h>
25−
26−class Q_DECL_EXPORT SignalsList
27−{
28−public:
29− void append(const sigc::connection &c);
30− void disconnectAll();
31−
32− SignalsList& operator<<(const sigc::connection &c);
33−
34−private:
35− QList<sigc::connection> m_signals;
36−};
37−
38−#endif // SIGNALSLIST_H
plugins/Unity/socialpreview.cppdeleted−87
@@ -1,87 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * Authors:
5− * Pawel Stolowski <pawel.stolowski@canonical.com>
6− *
7− * This program is free software; you can redistribute it and/or modify
8− * it under the terms of the GNU General Public License as published by
9− * the Free Software Foundation; version 3.
10− *
11− * This program is distributed in the hope that it will be useful,
12− * but WITHOUT ANY WARRANTY; without even the implied warranty of
13− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14− * GNU General Public License for more details.
15− *
16− * You should have received a copy of the GNU General Public License
17− * along with this program. If not, see <http://www.gnu.org/licenses/>.
18− */
19−
20−#include "socialpreview.h"
21−#include "socialpreviewcomment.h"
22−#include "iconutils.h"
23−
24−#include <QDebug>
25−
26−SocialPreview::SocialPreview(QObject *parent):
27− Preview(parent),
28− m_unitySocialPreview(nullptr)
29−{
30−}
31−
32−QString SocialPreview::sender() const
33−{
34− if (m_unitySocialPreview) {
35− return QString::fromStdString(m_unitySocialPreview->sender());
36− } else {
37− qWarning() << "Preview not set";
38− }
39− return QString();
40−}
41−
42−QString SocialPreview::content() const
43−{
44− if (m_unitySocialPreview) {
45− return QString::fromStdString(m_unitySocialPreview->content());
46− } else {
47− qWarning() << "Preview not set";
48− }
49− return QString();
50−}
51−
52−QString SocialPreview::avatar() const
53−{
54− if (m_unitySocialPreview) {
55− auto giconString = g_icon_to_string(m_unitySocialPreview->avatar());
56− QString result(gIconToDeclarativeImageProviderString(QString::fromUtf8(giconString)));
57− g_free(giconString);
58− return result;
59− } else {
60− qWarning() << "Preview not set";
61− }
62− return QString();
63−}
64−
65−QVariant SocialPreview::comments()
66−{
67− return QVariant::fromValue(m_comments);
68−}
69−
70−void SocialPreview::setUnityPreview(unity::dash::Preview::Ptr unityPreview)
71−{
72− m_unitySocialPreview = std::dynamic_pointer_cast<unity::dash::SocialPreview>(unityPreview);
73− qDeleteAll(m_comments);
74− m_comments.clear();
75−
76− if (m_unitySocialPreview) {
77− for (auto unityComment: m_unitySocialPreview->GetComments()) {
78− auto comment = new SocialPreviewComment(this);
79− comment->setUnityComment(unityComment);
80− m_comments.append(comment);
81−
82− Q_EMIT previewChanged();
83− }
84− } else {
85− qWarning() << "Incorrect preview type";
86− }
87−}
plugins/Unity/socialpreview.hdeleted−63
@@ -1,63 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * Authors:
5− * Pawel Stolowski <pawel.stolowski@canonical.com>
6− *
7− * This program is free software; you can redistribute it and/or modify
8− * it under the terms of the GNU General Public License as published by
9− * the Free Software Foundation; version 3.
10− *
11− * This program is distributed in the hope that it will be useful,
12− * but WITHOUT ANY WARRANTY; without even the implied warranty of
13− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14− * GNU General Public License for more details.
15− *
16− * You should have received a copy of the GNU General Public License
17− * along with this program. If not, see <http://www.gnu.org/licenses/>.
18− */
19−
20−#ifndef SOCIALPREVIEW_H
21−#define SOCIALPREVIEW_H
22−
23−// local
24−#include "preview.h"
25−
26−// Qt
27−#include <QObject>
28−#include <QList>
29−#include <QMetaType>
30−
31−// libunity-core
32−#include <UnityCore/SocialPreview.h>
33−
34−class Q_DECL_EXPORT SocialPreview: public Preview
35−{
36− Q_OBJECT
37−
38− Q_PROPERTY(QString sender READ sender NOTIFY previewChanged)
39− Q_PROPERTY(QString content READ content NOTIFY previewChanged)
40− Q_PROPERTY(QString avatar READ avatar NOTIFY previewChanged)
41−
42−public:
43− explicit SocialPreview(QObject *parent = 0);
44−
45− QString sender() const;
46− QString content() const;
47− QString avatar() const;
48− QVariant comments();
49−
50−Q_SIGNALS:
51− void previewChanged();
52−
53−protected:
54− void setUnityPreview(unity::dash::Preview::Ptr unityPreview) override;
55−
56−private:
57− unity::dash::SocialPreview::Ptr m_unitySocialPreview;
58− QList<QObject *> m_comments;
59−};
60−
61−Q_DECLARE_METATYPE(SocialPreview *)
62−
63−#endif
plugins/Unity/socialpreviewcomment.cppdeleted−63
@@ -1,63 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * Authors:
5− * Pawel Stolowski <pawel.stolowski@canonical.com>
6− *
7− * This program is free software; you can redistribute it and/or modify
8− * it under the terms of the GNU General Public License as published by
9− * the Free Software Foundation; version 3.
10− *
11− * This program is distributed in the hope that it will be useful,
12− * but WITHOUT ANY WARRANTY; without even the implied warranty of
13− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14− * GNU General Public License for more details.
15− *
16− * You should have received a copy of the GNU General Public License
17− * along with this program. If not, see <http://www.gnu.org/licenses/>.
18− */
19−
20−// local
21−#include "socialpreviewcomment.h"
22−
23−SocialPreviewComment::SocialPreviewComment(QObject *parent) :
24− QObject(parent)
25−{
26−}
27−
28−void SocialPreviewComment::setUnityComment(unity::dash::SocialPreview::CommentPtr unityComment)
29−{
30− m_unityComment = unityComment;
31−}
32−
33−QString SocialPreviewComment::id() const
34−{
35− if (m_unityComment) {
36− return QString::fromStdString(m_unityComment->id);
37− }
38− return QString();
39−}
40−
41−QString SocialPreviewComment::displayName() const
42−{
43− if (m_unityComment) {
44− return QString::fromStdString(m_unityComment->display_name);
45− }
46− return QString();
47−}
48−
49−QString SocialPreviewComment::content() const
50−{
51− if (m_unityComment) {
52− return QString::fromStdString(m_unityComment->content);
53− }
54− return QString();
55−}
56−
57−QString SocialPreviewComment::time() const
58−{
59− if (m_unityComment) {
60− return QString::fromStdString(m_unityComment->time);
61− }
62− return QString();
63−}
plugins/Unity/socialpreviewcomment.hdeleted−57
@@ -1,57 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * Authors:
5− * Pawel Stolowski <pawel.stolowski@canonical.com>
6− *
7− * This program is free software; you can redistribute it and/or modify
8− * it under the terms of the GNU General Public License as published by
9− * the Free Software Foundation; version 3.
10− *
11− * This program is distributed in the hope that it will be useful,
12− * but WITHOUT ANY WARRANTY; without even the implied warranty of
13− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14− * GNU General Public License for more details.
15− *
16− * You should have received a copy of the GNU General Public License
17− * along with this program. If not, see <http://www.gnu.org/licenses/>.
18− */
19−
20−#ifndef SOCIALPREVIEWCOMMENT_H
21−#define SOCIALPREVIEWCOMMENT_H
22−
23−// Qt
24−#include <QObject>
25−#include <QMetaType>
26−
27−// libunity-core
28−#include <UnityCore/SocialPreview.h>
29−
30−class Q_DECL_EXPORT SocialPreviewComment : public QObject
31−{
32− Q_OBJECT
33−
34− Q_PROPERTY(QString id READ id NOTIFY socialPreviewCommentChanged)
35− Q_PROPERTY(QString displayName READ displayName NOTIFY socialPreviewCommentChanged)
36− Q_PROPERTY(QString content READ content NOTIFY socialPreviewCommentChanged)
37− Q_PROPERTY(QString time READ time NOTIFY socialPreviewCommentChanged)
38−
39−public:
40− explicit SocialPreviewComment(QObject *parent = 0);
41− void setUnityComment(unity::dash::SocialPreview::CommentPtr unityComment);
42−
43− QString id() const;
44− QString displayName() const;
45− QString content() const;
46− QString time() const;
47−
48−Q_SIGNALS:
49− void socialPreviewCommentChanged();
50−
51−private:
52− unity::dash::SocialPreview::CommentPtr m_unityComment;
53−};
54−
55−Q_DECLARE_METATYPE(SocialPreviewComment *)
56−
57−#endif
plugins/Unity/unityoptionsmodel.cppdeleted−68
@@ -1,68 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * Authors:
5− * Pawel Stolowski <pawel.stolowski@canonical.com>
6− *
7− * This program is free software; you can redistribute it and/or modify
8− * it under the terms of the GNU General Public License as published by
9− * the Free Software Foundation; version 3.
10− *
11− * This program is distributed in the hope that it will be useful,
12− * but WITHOUT ANY WARRANTY; without even the implied warranty of
13− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14− * GNU General Public License for more details.
15− *
16− * You should have received a copy of the GNU General Public License
17− * along with this program. If not, see <http://www.gnu.org/licenses/>.
18− */
19−
20−// self
21−#include "unityoptionsmodel.h"
22−
23−// local
24−#include "filteroption.h"
25−
26−UnityOptionsModel::UnityOptionsModel(QObject *parent,
27− const std::vector<unity::dash::FilterOption::Ptr> options,
28− sigc::signal<void, unity::dash::FilterOption::Ptr> optionAdded,
29− sigc::signal<void, unity::dash::FilterOption::Ptr> optionRemoved,
30− bool showAllOption) :
31− GenericOptionsModel(showAllOption, parent)
32−{
33− setOptions(options, optionAdded, optionRemoved);
34−}
35−
36−void UnityOptionsModel::setOptions(const std::vector<unity::dash::FilterOption::Ptr> options,
37− sigc::signal<void, unity::dash::FilterOption::Ptr> optionAdded,
38− sigc::signal<void, unity::dash::FilterOption::Ptr> optionRemoved)
39−{
40− for (unsigned int i=0; i<options.size(); i++)
41− {
42− addOption(new FilterOption(options[i], this));
43− }
44− optionAdded.connect(sigc::mem_fun(this, &UnityOptionsModel::onOptionAdded));
45− optionRemoved.connect(sigc::mem_fun(this, &UnityOptionsModel::onOptionRemoved));
46−}
47−
48−void UnityOptionsModel::onOptionAdded(unity::dash::FilterOption::Ptr option)
49−{
50− int index = m_options.count();
51− if (index >= 0)
52− {
53− beginInsertRows(QModelIndex(), index, index);
54− addOption(new FilterOption(option, this));
55− endInsertRows();
56− }
57−}
58−
59−void UnityOptionsModel::onOptionRemoved(unity::dash::FilterOption::Ptr option)
60−{
61− auto index = indexOf(QString::fromStdString(option->id));
62− if (index >= 0)
63− {
64− beginRemoveRows(QModelIndex(), index, index);
65− removeOption(index);
66− endRemoveRows();
67− }
68−}
plugins/Unity/unityoptionsmodel.hdeleted−50
@@ -1,50 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * Authors:
5− * Pawel Stolowski <pawel.stolowski@canonical.com>
6− *
7− * This program is free software; you can redistribute it and/or modify
8− * it under the terms of the GNU General Public License as published by
9− * the Free Software Foundation; version 3.
10− *
11− * This program is distributed in the hope that it will be useful,
12− * but WITHOUT ANY WARRANTY; without even the implied warranty of
13− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14− * GNU General Public License for more details.
15− *
16− * You should have received a copy of the GNU General Public License
17− * along with this program. If not, see <http://www.gnu.org/licenses/>.
18− */
19−
20−#ifndef UNITYOPTIONSMODEL_H
21−#define UNITYOPTIONSMODEL_H
22−
23−#include "genericoptionsmodel.h"
24−
25−// libunity-core
26−#include <UnityCore/Filter.h>
27−
28−#include <sigc++/signal.h>
29−
30−class UnityOptionsModel : public GenericOptionsModel
31−{
32− Q_OBJECT
33−
34−public:
35− UnityOptionsModel(QObject *parent,
36− const std::vector<unity::dash::FilterOption::Ptr> options,
37− sigc::signal<void, unity::dash::FilterOption::Ptr> optionAdded,
38− sigc::signal<void, unity::dash::FilterOption::Ptr> optionRemoved,
39− bool showAllOption);
40−
41−private:
42− void setOptions(const std::vector<unity::dash::FilterOption::Ptr> options,
43− sigc::signal<void, unity::dash::FilterOption::Ptr> optionAdded,
44− sigc::signal<void, unity::dash::FilterOption::Ptr> optionRemoved);
45−
46− void onOptionAdded(unity::dash::FilterOption::Ptr option);
47− void onOptionRemoved(unity::dash::FilterOption::Ptr option);
48−};
49−
50−#endif // UNITYOPTIONSMODEL_H
plugins/Unity/variantutils.cppdeleted−82
@@ -1,82 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * Authors:
5− * Pawel Stolowski <pawel.stolowski@canonical.com>
6− *
7− * This program is free software; you can redistribute it and/or modify
8− * it under the terms of the GNU General Public License as published by
9− * the Free Software Foundation; version 3.
10− *
11− * This program is distributed in the hope that it will be useful,
12− * but WITHOUT ANY WARRANTY; without even the implied warranty of
13− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14− * GNU General Public License for more details.
15− *
16− * You should have received a copy of the GNU General Public License
17− * along with this program. If not, see <http://www.gnu.org/licenses/>.
18− */
19−
20−#include <QUrl>
21−#include <QUrlQuery>
22−#include <QStringList>
23−
24−#include <deelistmodel.h>
25−#include "variantutils.h"
26−
27−unity::glib::HintsMap convertToHintsMap(const QHash<QString, QVariant> &val)
28−{
29− unity::glib::HintsMap hintsMap;
30− QHash<QString, QVariant>::const_iterator it = val.constBegin();
31− while (it != val.constEnd()) {
32− hintsMap[it.key().toStdString()] = DeeListModel::DataFromVariant(it.value());
33− ++it;
34− }
35− return hintsMap;
36−}
37−
38−unity::glib::HintsMap convertToHintsMap(const QVariant &var)
39−{
40− if (var.type() == QVariant::Hash) {
41− unity::glib::HintsMap hintsMap;
42− const auto hash = var.toHash();
43− return convertToHintsMap(hash);
44− }
45− return unity::glib::HintsMap();
46−}
47−
48−QVariantHash convertToQVariantHash(const unity::glib::HintsMap& var)
49−{
50− QVariantHash hash;
51− for (auto hint: var) {
52− hash.insert(QString::fromStdString(hint.first), DeeListModel::VariantForData(hint.second));
53− }
54− return hash;
55−}
56−
57−/* This will translate uris in the form of:
58− * "subscope:master.scope/sub.scope?foo=bar"
59− * into a QVariantHash that can be passed as a metadata field to scope.
60− */
61−QVariantHash subscopeUriToMetadataHash(const QString &metadata_string)
62−{
63− QUrl metadata_url(metadata_string);
64− if (metadata_url.scheme() == QLatin1String("subscope")) {
65− QString subscope_uri(metadata_url.toString(QUrl::RemoveScheme | QUrl::RemoveQuery));
66− QVariantHash new_metadata;
67− QUrlQuery query(metadata_url.query());
68− QList<QPair<QString,QString>> queryItems(query.queryItems());
69− for (auto it = queryItems.begin(); it != queryItems.end(); ++it) {
70− new_metadata[it->first] = QVariant::fromValue(it->second);
71− }
72− QStringList parts(subscope_uri.split(QChar('/')));
73− for (int i = parts.size() - 1; i >= 0; i--) {
74− QVariantHash inner;
75− inner["scope-id"] = QVariant::fromValue(parts[i]);
76− inner["content"] = QVariant::fromValue(new_metadata);
77− new_metadata = inner;
78− }
79− return new_metadata;
80− }
81− return QVariantHash();
82−}
plugins/Unity/variantutils.hdeleted−35
@@ -1,35 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * Authors:
5− * Pawel Stolowski <pawel.stolowski@canonical.com>
6− *
7− * This program is free software; you can redistribute it and/or modify
8− * it under the terms of the GNU General Public License as published by
9− * the Free Software Foundation; version 3.
10− *
11− * This program is distributed in the hope that it will be useful,
12− * but WITHOUT ANY WARRANTY; without even the implied warranty of
13− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14− * GNU General Public License for more details.
15− *
16− * You should have received a copy of the GNU General Public License
17− * along with this program. If not, see <http://www.gnu.org/licenses/>.
18− */
19−
20−#ifndef VARIANTUTILS_H
21−#define VARIANTUTILS_H
22−
23−#include <glib.h>
24−#include <QVariant>
25−
26−// libunity-core
27−#include <UnityCore/Variant.h>
28−
29−unity::glib::HintsMap convertToHintsMap(const QHash<QString, QVariant> &val);
30−unity::glib::HintsMap convertToHintsMap(const QVariant &var);
31−QVariantHash convertToQVariantHash(const unity::glib::HintsMap &var);
32−/* used in tests, so we have to export it */
33−Q_DECL_EXPORT QVariantHash subscopeUriToMetadataHash(const QString &metadata_string);
34−
35−#endif
plugins/Utils/CMakeLists.txt+1−2
@@ -12,11 +12,10 @@ include_directories(
1212
1313set(QMLPLUGIN_SRC
1414 albumartprovider.cpp
15− applicationpaths.h
15+ bottombarvisibilitycommunicatorshell.cpp
1616 mediaartcache.cpp
1717 qlimitproxymodelqml.cpp
1818 qsortfilterproxymodelqml.cpp
19− ubuntuwindow.cpp
2019 unitymenumodelpaths.cpp
2120 plugin.cpp
2221 )
plugins/Utils/albumartprovider.cpp+10−7
@@ -32,6 +32,7 @@
3232#include <QByteArray>
3333#include <QImage>
3434#include <QUrl>
35+#include <QUrlQuery>
3536
3637using namespace std;
3738
@@ -65,6 +66,9 @@ AlbumArtProvider::~AlbumArtProvider()
6566std::string AlbumArtProvider::get_lastfm_url(const albuminfo &ai) {
6667 QString artist = QString::fromStdString(ai.artist);
6768 QString album = QString::fromStdString(ai.album);
69+ // audioscrobbler wants it without any / (as it would break the URL)
70+ artist.remove('/');
71+ album.remove('/');
6872
6973 /// @todo: this is the old API which will probably get axed at some point in the future
7074 /// The new 2.0 API requires an API key, but supports JSON output, etc, so switching
@@ -200,21 +204,20 @@ std::string AlbumArtProvider::get_image(const std::string &artist, const std::st
200204QImage AlbumArtProvider::requestImage(const QString &id, QSize *realSize, const QSize &requestedSize) {
201205 Q_UNUSED(requestedSize)
202206
203− const QStringList parts = id.split("/");
204− if (parts.size() != 2) {
207+ QUrlQuery query(id);
208+ if (!query.hasQueryItem(QStringLiteral("artist")) || !query.hasQueryItem(QStringLiteral("album"))) {
205209 qWarning() << "Invalid albumart uri:" << id;
206210 return QImage(QString::fromStdString(DEFAULT_ALBUM_ART));
207211 }
208− const std::string artist = QUrl::fromPercentEncoding(parts[0].toUtf8()).toStdString();
209− const std::string album = QUrl::fromPercentEncoding(parts[1].toUtf8()).toStdString();
212+ const QString artist = query.queryItemValue(QStringLiteral("artist"), QUrl::FullyEncoded);
213+ const QString album = query.queryItemValue(QStringLiteral("album"), QUrl::FullyEncoded);
210214
211215 std::string tgt_path;
212216 try {
213− tgt_path = get_image(artist, album);
217+ tgt_path = get_image(artist.toStdString(), album.toStdString());
214218 if(!tgt_path.empty()) {
215− QString tgt(tgt_path.c_str());
216219 QImage image;
217− image.load(tgt);
220+ image.load(QString::fromStdString(tgt_path));
218221 // FIXME: Rescale to requested size preserving aspect.
219222 *realSize = image.size();
220223 return image;
plugins/Utils/applicationpaths.hdeleted−38
@@ -1,38 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− *
16− * Authored by: Nick Dedekind <nick.dedekind@canonical.com>
17− */
18−
19−
20−#ifndef APPLICATION_PATHS_H
21−#define APPLICATION_PATHS_H
22−
23−#include <QObject>
24−#include "paths.h"
25−
26−class ApplicationPaths : public QObject
27−{
28− Q_OBJECT
29−public:
30− Q_INVOKABLE bool isRunningInstalled() const { return ::isRunningInstalled(); }
31− Q_INVOKABLE QString shellAppDirectory() const { return ::shellAppDirectory(); }
32− Q_INVOKABLE QStringList overrideImportPaths() const { return ::overrideImportPaths(); }
33− Q_INVOKABLE QStringList fallbackImportPaths() const { return ::fallbackImportPaths(); }
34− Q_INVOKABLE QStringList shellDataDirs() const { return ::shellDataDirs(); }
35− Q_INVOKABLE QString sourceDirectory() const { return ::sourceDirectory(); }
36−};
37−
38−#endif // APPLICATION_PATHS_H
plugins/Unity/bottombarvisibilitycommunicatorshell.cpp → plugins/Utils/bottombarvisibilitycommunicatorshell.cpprenamed

The content is the same.

plugins/Unity/bottombarvisibilitycommunicatorshell.h → plugins/Utils/bottombarvisibilitycommunicatorshell.hrenamed

The content is the same.

plugins/Utils/plugin.cpp+11−9
@@ -18,6 +18,8 @@
1818
1919// Qt
2020#include <QtQml/qqml.h>
21+#include <QDBusConnection>
22+#include <QQmlContext>
2123#include <QtQuick/QQuickWindow>
2224#include <QDebug>
2325// self
@@ -25,17 +27,13 @@
2527
2628// local
2729#include "albumartprovider.h"
28−#include "applicationpaths.h"
30+#include "bottombarvisibilitycommunicatorshell.h"
2931#include "qlimitproxymodelqml.h"
3032#include "qsortfilterproxymodelqml.h"
31−#include "ubuntuwindow.h"
3233#include "unitymenumodelpaths.h"
3334
34−static QObject* applicationsPathsSingleton(QQmlEngine* engine, QJSEngine* scriptEngine) {
35− Q_UNUSED(engine);
36− Q_UNUSED(scriptEngine);
37− return new ApplicationPaths;
38−}
35+static const char* BOTTOM_BAR_VISIBILITY_COMMUNICATOR_DBUS_PATH = "/BottomBarVisibilityCommunicator";
36+static const char* DBUS_SERVICE = "com.canonical.Shell.BottomBarVisibilityCommunicator";
3937
4038void UtilsPlugin::registerTypes(const char *uri)
4139{
@@ -44,8 +42,7 @@ void UtilsPlugin::registerTypes(const char *uri)
4442 qmlRegisterType<QLimitProxyModelQML>(uri, 0, 1, "LimitProxyModel");
4543 qmlRegisterType<QSortFilterProxyModelQML>(uri, 0, 1, "SortFilterProxyModel");
4644 qmlRegisterType<UnityMenuModelPaths>(uri, 0, 1, "UnityMenuModelPaths");
47− qmlRegisterExtendedType<QQuickWindow, UbuntuWindow>(uri, 0, 1, "Window");
48− qmlRegisterSingletonType<ApplicationPaths>(uri, 0, 1, "ApplicationPaths", applicationsPathsSingleton);
45+ qmlRegisterUncreatableType<BottomBarVisibilityCommunicatorShell>(uri, 0, 1, "BottomBarVisibilityCommunicatorShell", "Can't create BottomBarVisibilityCommunicatorShell");
4946}
5047
5148void UtilsPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
@@ -64,4 +61,9 @@ void UtilsPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
6461 {
6562 qWarning() << "Failed to register image provider for albumart (unknown error)";
6663 }
64+
65+ QDBusConnection::sessionBus().registerService(DBUS_SERVICE);
66+ BottomBarVisibilityCommunicatorShell *bottomBarVisibilityCommunicator = &BottomBarVisibilityCommunicatorShell::instance();
67+ QDBusConnection::sessionBus().registerObject(BOTTOM_BAR_VISIBILITY_COMMUNICATOR_DBUS_PATH, bottomBarVisibilityCommunicator, QDBusConnection::ExportAllContents);
68+ engine->rootContext()->setContextProperty("bottomBarVisibilityCommunicatorShell", bottomBarVisibilityCommunicator);
6769}
plugins/Utils/ubuntuwindow.cppdeleted−36
@@ -1,36 +0,0 @@
1−/*
2− * Copyright (C) 2012 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU 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 "ubuntuwindow.h"
18−#include <QDebug>
19−
20−
21−UbuntuWindow::UbuntuWindow(QObject *parent)
22− : QObject(parent),
23− m_window(static_cast<QQuickWindow*>(parent))
24−{
25−}
26−
27−int UbuntuWindow::ubuntuSurfaceRole() const
28−{
29− return m_window->property("UbuntuSurfaceRole").toInt();
30−}
31−
32−void UbuntuWindow::setUbuntuSurfaceRole(int ubuntuSurfaceRole)
33−{
34− qDebug() << "setUbuntuSurfaceRole" << ubuntuSurfaceRole;
35− m_window->setProperty("UbuntuSurfaceRole", ubuntuSurfaceRole);
36−}
plugins/Utils/ubuntuwindow.hdeleted−42
@@ -1,42 +0,0 @@
1−/*
2− * Copyright (C) 2012 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU 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 UBUNTUWINDOW_H
18−#define UBUNTUWINDOW_H
19−
20−#include <QtCore/QObject>
21−#include <QtQuick/QQuickWindow>
22−
23−class UbuntuWindow : public QObject
24−{
25− Q_OBJECT
26−
27− Q_PROPERTY(int ubuntuSurfaceRole READ ubuntuSurfaceRole WRITE setUbuntuSurfaceRole NOTIFY ubuntuSurfaceRoleChanged)
28−
29−public:
30− explicit UbuntuWindow(QObject *parent = 0);
31−
32− int ubuntuSurfaceRole() const;
33− void setUbuntuSurfaceRole(int ubuntuSurfaceRole);
34−
35−Q_SIGNALS:
36− void ubuntuSurfaceRoleChanged(int);
37−
38−private:
39− QQuickWindow* m_window;
40−};
41−
42−#endif // UBUNTUWINDOW_H
po/ar.po+23−10
@@ -7,8 +7,8 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
11−"PO-Revision-Date: 2013-10-20 19:41+0000\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
11+"PO-Revision-Date: 2013-11-15 12:29+0000\n"
1212"Last-Translator: Ibrahim Saed <ibraheem5000@gmail.com>\n"
1313"Language-Team: Arabic <ar@li.org>\n"
1414"MIME-Version: 1.0\n"
@@ -16,8 +16,8 @@ msgstr ""
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n % 100 >= "
1818"3 && n % 100 <= 10 ? 3 : n % 100 >= 11 && n % 100 <= 99 ? 4 : 5;\n"
19−"X-Launchpad-Export-Date: 2013-10-21 05:04+0000\n"
20−"X-Generator: Launchpad (build 16807)\n"
19+"X-Launchpad-Export-Date: 2013-11-19 05:59+0000\n"
20+"X-Generator: Launchpad (build 16831)\n"
2121
2222#: Applications/applications.js:23
2323msgid "Phone"
@@ -87,7 +87,7 @@ msgstr "ويكيبيديا"
8787msgid "YouTube"
8888msgstr "يوتيوب"
8989
90−#: Components/EdgeDemoOverlay.qml:149
90+#: Components/EdgeDemoOverlay.qml:151
9191msgid "Skip intro"
9292msgstr "تخطي المقدمة"
9393
@@ -136,7 +136,7 @@ msgstr ""
136136"لقد أتقنت الآن إيماءات الحواف ويمكنك البدء باستخدام الهاتف<br><br>انقر في أي "
137137"مكان للبدء"
138138
139−#: Components/PageHeader.qml:341
139+#: Components/PageHeader.qml:345
140140msgid "Recent searches"
141141msgstr "عمليات البحث الأخيرة"
142142
@@ -160,7 +160,7 @@ msgstr[3] "%1 تعليقات"
160160msgstr[4] "%1 تعليقا"
161161msgstr[5] "%1 تعليق"
162162
163−#: Dash/Apps/AppPreview.qml:126
163+#: Dash/Apps/AppPreview.qml:135
164164msgid "Rate this"
165165msgstr "قيّم ذلك"
166166
@@ -180,7 +180,7 @@ msgstr "أرسل"
180180msgid "Comments:"
181181msgstr "التعليقات:"
182182
183−#: Greeter/Lockscreen.qml:142
183+#: Greeter/Lockscreen.qml:146
184184msgid "Emergency Call"
185185msgstr "مكالمة طوارئ"
186186
@@ -213,11 +213,24 @@ msgstr "تكلم الآن..."
213213msgid "Speaking..."
214214msgstr "تتكلم الآن..."
215215
216+#: Notifications/NotificationMenuItemFactory.qml:89
217+msgid "Show password"
218+msgstr "عرض كلمة السر"
219+
216220#: Panel/SearchIndicator.qml:27
217221msgid "Search"
218222msgstr "ابحث"
219223
220−#: plugins/Unity/scope.cpp:398
224+#: plugins/Unity/Launcher/launcheritem.cpp:43
225+#: plugins/Unity/Launcher/launcheritem.cpp:73
226+msgid "Lock to Launcher"
227+msgstr ""
228+
229+#: plugins/Unity/Launcher/launcheritem.cpp:73
230+msgid "Unlock from Launcher"
231+msgstr ""
232+
233+#: plugins/Unity/scope.cpp:408
221234msgid "Sorry, there is nothing that matches your search."
222235msgstr "عذراً، لا يوجد ما يطابق بحثك."
223236
@@ -225,7 +238,7 @@ msgstr "عذراً، لا يوجد ما يطابق بحثك."
225238msgid "All"
226239msgstr "الكل"
227240
228−#: Shell.qml:438
241+#: Shell.qml:441
229242#, qt-format
230243msgid "Please enter %1"
231244msgstr "من فضلك أدخِل %1"
po/ast.po+22−30
@@ -7,7 +7,7 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity8\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
1111"PO-Revision-Date: 2013-10-03 14:02+0000\n"
1212"Last-Translator: ivarela <ivarela@ubuntu.com>\n"
1313"Language-Team: Asturian <ast@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
18+"X-Launchpad-Export-Date: 2013-11-19 05:59+0000\n"
19+"X-Generator: Launchpad (build 16831)\n"
2020
2121#: Applications/applications.js:23
2222msgid "Phone"
@@ -86,7 +86,7 @@ msgstr "Wikipedia"
8686msgid "YouTube"
8787msgstr "YouTube"
8888
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
9090msgid "Skip intro"
9191msgstr "Omitir la intro"
9292
@@ -136,7 +136,7 @@ msgstr ""
136136"Agora domines los xestos de berbesos y pues usar el teléfonu<br><br>Toca la "
137137"pantalla pa entamar"
138138
139−#: Components/PageHeader.qml:341
139+#: Components/PageHeader.qml:345
140140msgid "Recent searches"
141141msgstr "Busques recientes"
142142
@@ -156,7 +156,7 @@ msgid_plural "%1 reviews"
156156msgstr[0] "%1 reseña"
157157msgstr[1] "%1 reseñes"
158158
159−#: Dash/Apps/AppPreview.qml:126
159+#: Dash/Apps/AppPreview.qml:135
160160msgid "Rate this"
161161msgstr "Valorar esto"
162162
@@ -176,7 +176,7 @@ msgstr "Unviar"
176176msgid "Comments:"
177177msgstr "Comentarios:"
178178
179−#: Greeter/Lockscreen.qml:142
179+#: Greeter/Lockscreen.qml:146
180180msgid "Emergency Call"
181181msgstr "Llamada d'emerxencia"
182182
@@ -209,11 +209,24 @@ msgstr "Fala agora…"
209209msgid "Speaking..."
210210msgstr "Falando…"
211211
212+#: Notifications/NotificationMenuItemFactory.qml:89
213+msgid "Show password"
214+msgstr ""
215+
212216#: Panel/SearchIndicator.qml:27
213217msgid "Search"
214218msgstr "Guetar"
215219
216−#: plugins/Unity/scope.cpp:398
220+#: plugins/Unity/Launcher/launcheritem.cpp:43
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Lock to Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/Launcher/launcheritem.cpp:73
226+msgid "Unlock from Launcher"
227+msgstr ""
228+
229+#: plugins/Unity/scope.cpp:408
217230msgid "Sorry, there is nothing that matches your search."
218231msgstr "Sentímoslo, nun hai res que concase cola gueta"
219232
@@ -221,28 +234,7 @@ msgstr "Sentímoslo, nun hai res que concase cola gueta"
221234msgid "All"
222235msgstr "Too"
223236
224−#: Shell.qml:438
237+#: Shell.qml:441
225238#, qt-format
226239msgid "Please enter %1"
227240msgstr "Introduz %1"
228−
229−#~ msgid "New Releases"
230−#~ msgstr "Llanzamientos nuevos"
231−
232−#~ msgid "Featured"
233−#~ msgstr "Destacaos"
234−
235−#~ msgid "Top Charting"
236−#~ msgstr "Meyor posicionaes"
237−
238−#~ msgid "Recent"
239−#~ msgstr "Recientes"
240−
241−#~ msgid "Videos"
242−#~ msgstr "Vídeos"
243−
244−#~ msgid "Music"
245−#~ msgstr "Música"
246−
247−#~ msgid "Popular Online"
248−#~ msgstr "Populares en llinia"
po/az.po+22−15
@@ -7,7 +7,7 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
1111"PO-Revision-Date: 2013-06-26 23:48+0000\n"
1212"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
1313"Language-Team: Azerbaijani <az@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
18+"X-Launchpad-Export-Date: 2013-11-19 05:59+0000\n"
19+"X-Generator: Launchpad (build 16831)\n"
2020
2121#: Applications/applications.js:23
2222msgid "Phone"
@@ -86,7 +86,7 @@ msgstr ""
8686msgid "YouTube"
8787msgstr ""
8888
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
9090msgid "Skip intro"
9191msgstr ""
9292
@@ -132,7 +132,7 @@ msgid ""
132132"phone<br><br>Tap anywhere to start"
133133msgstr ""
134134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136136msgid "Recent searches"
137137msgstr "Son axtarışlar"
138138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152152msgstr[0] ""
153153msgstr[1] ""
154154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156156msgid "Rate this"
157157msgstr ""
158158
@@ -172,7 +172,7 @@ msgstr ""
172172msgid "Comments:"
173173msgstr ""
174174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176176msgid "Emergency Call"
177177msgstr ""
178178
@@ -205,11 +205,24 @@ msgstr "Söyləyin..."
205205msgid "Speaking..."
206206msgstr "Söylənilir..."
207207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208212#: Panel/SearchIndicator.qml:27
209213msgid "Search"
210214msgstr "Axtar"
211215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213226msgid "Sorry, there is nothing that matches your search."
214227msgstr "Bağışlayın, amma axtarışınıza heç bir nəticə uyğun gəlmir."
215228
@@ -217,13 +230,7 @@ msgstr "Bağışlayın, amma axtarışınıza heç bir nəticə uyğun gəlmir."
217230msgid "All"
218231msgstr ""
219232
220−#: Shell.qml:438
233+#: Shell.qml:441
221234#, qt-format
222235msgid "Please enter %1"
223236msgstr ""
224−
225−#~ msgid "Music"
226−#~ msgstr "Musiqi"
227−
228−#~ msgid "Videos"
229−#~ msgstr "Videolar"
po/bg.po+22−21
@@ -7,7 +7,7 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
1111"PO-Revision-Date: 2013-06-27 00:06+0000\n"
1212"Last-Translator: Miroslav E. Hadzhiev (Хаджиев) "
1313"<miroslav.hadzhiev@gmail.com>\n"
@@ -16,8 +16,8 @@ msgstr ""
1616"Content-Type: text/plain; charset=UTF-8\n"
1717"Content-Transfer-Encoding: 8bit\n"
1818"Plural-Forms: nplurals=2; plural=n != 1;\n"
19−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
20−"X-Generator: Launchpad (build 16799)\n"
19+"X-Launchpad-Export-Date: 2013-11-19 05:59+0000\n"
20+"X-Generator: Launchpad (build 16831)\n"
2121
2222#: Applications/applications.js:23
2323msgid "Phone"
@@ -87,7 +87,7 @@ msgstr "Уикипедия"
8787msgid "YouTube"
8888msgstr "YouTube"
8989
90−#: Components/EdgeDemoOverlay.qml:149
90+#: Components/EdgeDemoOverlay.qml:151
9191msgid "Skip intro"
9292msgstr ""
9393
@@ -133,7 +133,7 @@ msgid ""
133133"phone<br><br>Tap anywhere to start"
134134msgstr ""
135135
136−#: Components/PageHeader.qml:341
136+#: Components/PageHeader.qml:345
137137msgid "Recent searches"
138138msgstr "Скорошни търсения"
139139
@@ -153,7 +153,7 @@ msgid_plural "%1 reviews"
153153msgstr[0] ""
154154msgstr[1] ""
155155
156−#: Dash/Apps/AppPreview.qml:126
156+#: Dash/Apps/AppPreview.qml:135
157157msgid "Rate this"
158158msgstr ""
159159
@@ -173,7 +173,7 @@ msgstr ""
173173msgid "Comments:"
174174msgstr ""
175175
176−#: Greeter/Lockscreen.qml:142
176+#: Greeter/Lockscreen.qml:146
177177msgid "Emergency Call"
178178msgstr ""
179179
@@ -206,11 +206,24 @@ msgstr ""
206206msgid "Speaking..."
207207msgstr ""
208208
209+#: Notifications/NotificationMenuItemFactory.qml:89
210+msgid "Show password"
211+msgstr ""
212+
209213#: Panel/SearchIndicator.qml:27
210214msgid "Search"
211215msgstr "Търсене"
212216
213−#: plugins/Unity/scope.cpp:398
217+#: plugins/Unity/Launcher/launcheritem.cpp:43
218+#: plugins/Unity/Launcher/launcheritem.cpp:73
219+msgid "Lock to Launcher"
220+msgstr ""
221+
222+#: plugins/Unity/Launcher/launcheritem.cpp:73
223+msgid "Unlock from Launcher"
224+msgstr ""
225+
226+#: plugins/Unity/scope.cpp:408
214227msgid "Sorry, there is nothing that matches your search."
215228msgstr "Съжаляваме, няма нищо, което да отговаря на вашето търсене."
216229
@@ -218,19 +231,7 @@ msgstr "Съжаляваме, няма нищо, което да отговар
218231msgid "All"
219232msgstr ""
220233
221−#: Shell.qml:438
234+#: Shell.qml:441
222235#, qt-format
223236msgid "Please enter %1"
224237msgstr ""
225−
226−#~ msgid "Featured"
227−#~ msgstr "Най-отличени"
228−
229−#~ msgid "Recent"
230−#~ msgstr "Най-нови"
231−
232−#~ msgid "Music"
233−#~ msgstr "Музика"
234−
235−#~ msgid "Videos"
236−#~ msgstr "Видеоклипове"
po/ca.po+22−30
@@ -7,7 +7,7 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
1111"PO-Revision-Date: 2013-09-28 07:38+0000\n"
1212"Last-Translator: David Planella <david.planella@ubuntu.com>\n"
1313"Language-Team: Catalan <ca@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
18+"X-Launchpad-Export-Date: 2013-11-19 05:59+0000\n"
19+"X-Generator: Launchpad (build 16831)\n"
2020
2121#: Applications/applications.js:23
2222msgid "Phone"
@@ -86,7 +86,7 @@ msgstr "Viquipèdia"
8686msgid "YouTube"
8787msgstr "YouTube"
8888
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
9090msgid "Skip intro"
9191msgstr "Omet la introducció"
9292
@@ -138,7 +138,7 @@ msgid ""
138138"phone<br><br>Tap anywhere to start"
139139msgstr ""
140140
141−#: Components/PageHeader.qml:341
141+#: Components/PageHeader.qml:345
142142msgid "Recent searches"
143143msgstr "Cerques recents"
144144
@@ -158,7 +158,7 @@ msgid_plural "%1 reviews"
158158msgstr[0] "%1 ressenya"
159159msgstr[1] "%1 ressenyes"
160160
161−#: Dash/Apps/AppPreview.qml:126
161+#: Dash/Apps/AppPreview.qml:135
162162msgid "Rate this"
163163msgstr ""
164164
@@ -178,7 +178,7 @@ msgstr "Envia"
178178msgid "Comments:"
179179msgstr "Comentaris:"
180180
181−#: Greeter/Lockscreen.qml:142
181+#: Greeter/Lockscreen.qml:146
182182msgid "Emergency Call"
183183msgstr "Trucada d'emergència"
184184
@@ -211,11 +211,24 @@ msgstr "Parleu..."
211211msgid "Speaking..."
212212msgstr "S'està parlant..."
213213
214+#: Notifications/NotificationMenuItemFactory.qml:89
215+msgid "Show password"
216+msgstr ""
217+
214218#: Panel/SearchIndicator.qml:27
215219msgid "Search"
216220msgstr "Cerca"
217221
218−#: plugins/Unity/scope.cpp:398
222+#: plugins/Unity/Launcher/launcheritem.cpp:43
223+#: plugins/Unity/Launcher/launcheritem.cpp:73
224+msgid "Lock to Launcher"
225+msgstr ""
226+
227+#: plugins/Unity/Launcher/launcheritem.cpp:73
228+msgid "Unlock from Launcher"
229+msgstr ""
230+
231+#: plugins/Unity/scope.cpp:408
219232msgid "Sorry, there is nothing that matches your search."
220233msgstr "No hi ha res que coincideixi amb la cerca"
221234
@@ -223,28 +236,7 @@ msgstr "No hi ha res que coincideixi amb la cerca"
223236msgid "All"
224237msgstr ""
225238
226−#: Shell.qml:438
239+#: Shell.qml:441
227240#, qt-format
228241msgid "Please enter %1"
229242msgstr "Introduïu %1"
230−
231−#~ msgid "Music"
232−#~ msgstr "Música"
233−
234−#~ msgid "Videos"
235−#~ msgstr "Vídeos"
236−
237−#~ msgid "Recent"
238−#~ msgstr "Recents"
239−
240−#~ msgid "Featured"
241−#~ msgstr "Destacats"
242−
243−#~ msgid "New Releases"
244−#~ msgstr "Novetats"
245−
246−#~ msgid "Top Charting"
247−#~ msgstr "El millor de les llistes"
248−
249−#~ msgid "Popular Online"
250−#~ msgstr "Popular a la xarxa"
po/cs.po+22−24
@@ -7,7 +7,7 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity8\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
1111"PO-Revision-Date: 2013-10-08 08:09+0000\n"
1212"Last-Translator: Tadeáš Pařík <tadeas.parik@gmail.com>\n"
1313"Language-Team: Czech <cs@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
18+"X-Launchpad-Export-Date: 2013-11-19 05:59+0000\n"
19+"X-Generator: Launchpad (build 16831)\n"
2020
2121#: Applications/applications.js:23
2222msgid "Phone"
@@ -86,7 +86,7 @@ msgstr "Wikipedie"
8686msgid "YouTube"
8787msgstr "YouTube"
8888
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
9090msgid "Skip intro"
9191msgstr "Přeskočit intro"
9292
@@ -132,7 +132,7 @@ msgid ""
132132"phone<br><br>Tap anywhere to start"
133133msgstr ""
134134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136136msgid "Recent searches"
137137msgstr "Poslední vyhledávání"
138138
@@ -153,7 +153,7 @@ msgstr[0] "%1 recenze"
153153msgstr[1] "%1 recenze"
154154msgstr[2] "%1 recenzí"
155155
156−#: Dash/Apps/AppPreview.qml:126
156+#: Dash/Apps/AppPreview.qml:135
157157msgid "Rate this"
158158msgstr "Ohodnoťte to"
159159
@@ -173,7 +173,7 @@ msgstr "Odeslat"
173173msgid "Comments:"
174174msgstr "Komentáře:"
175175
176−#: Greeter/Lockscreen.qml:142
176+#: Greeter/Lockscreen.qml:146
177177msgid "Emergency Call"
178178msgstr "Tísňové volání"
179179
@@ -206,11 +206,24 @@ msgstr "Mluvte..."
206206msgid "Speaking..."
207207msgstr "Mluvte..."
208208
209+#: Notifications/NotificationMenuItemFactory.qml:89
210+msgid "Show password"
211+msgstr ""
212+
209213#: Panel/SearchIndicator.qml:27
210214msgid "Search"
211215msgstr "Hledat"
212216
213−#: plugins/Unity/scope.cpp:398
217+#: plugins/Unity/Launcher/launcheritem.cpp:43
218+#: plugins/Unity/Launcher/launcheritem.cpp:73
219+msgid "Lock to Launcher"
220+msgstr ""
221+
222+#: plugins/Unity/Launcher/launcheritem.cpp:73
223+msgid "Unlock from Launcher"
224+msgstr ""
225+
226+#: plugins/Unity/scope.cpp:408
214227msgid "Sorry, there is nothing that matches your search."
215228msgstr "Je nám líto, ale nic neodpovídá zadání"
216229
@@ -218,22 +231,7 @@ msgstr "Je nám líto, ale nic neodpovídá zadání"
218231msgid "All"
219232msgstr "Vše"
220233
221−#: Shell.qml:438
234+#: Shell.qml:441
222235#, qt-format
223236msgid "Please enter %1"
224237msgstr "Zadejte prosím %1"
225−
226−#~ msgid "Featured"
227−#~ msgstr "Oblíbené"
228−
229−#~ msgid "Recent"
230−#~ msgstr "Nedávné"
231−
232−#~ msgid "Videos"
233−#~ msgstr "Videa"
234−
235−#~ msgid "Music"
236−#~ msgstr "Hudba"
237−
238−#~ msgid "Popular Online"
239−#~ msgstr "Oblíbené on-line"
po/de.po+22−9
@@ -7,7 +7,7 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
1111"PO-Revision-Date: 2013-10-18 12:26+0000\n"
1212"Last-Translator: Phillip Sz <Unknown>\n"
1313"Language-Team: German <de@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-19 05:30+0000\n"
19−"X-Generator: Launchpad (build 16807)\n"
18+"X-Launchpad-Export-Date: 2013-11-19 05:59+0000\n"
19+"X-Generator: Launchpad (build 16831)\n"
2020
2121#: Applications/applications.js:23
2222msgid "Phone"
@@ -86,7 +86,7 @@ msgstr "Wikipedia"
8686msgid "YouTube"
8787msgstr "YouTube"
8888
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
9090msgid "Skip intro"
9191msgstr "Überspringe Einführung"
9292
@@ -136,7 +136,7 @@ msgstr ""
136136"Sie haben nun die Einführung abgeschlossen und können Ihr Gerät nun "
137137"verwenden<br><br>Antippen um zu starten"
138138
139−#: Components/PageHeader.qml:341
139+#: Components/PageHeader.qml:345
140140msgid "Recent searches"
141141msgstr "Letzte Suchbegriffe"
142142
@@ -156,7 +156,7 @@ msgid_plural "%1 reviews"
156156msgstr[0] "%1 Bewertung"
157157msgstr[1] "%1 Bewertungen"
158158
159−#: Dash/Apps/AppPreview.qml:126
159+#: Dash/Apps/AppPreview.qml:135
160160msgid "Rate this"
161161msgstr "Bewerten"
162162
@@ -176,7 +176,7 @@ msgstr "Senden"
176176msgid "Comments:"
177177msgstr "Kommentare:"
178178
179−#: Greeter/Lockscreen.qml:142
179+#: Greeter/Lockscreen.qml:146
180180msgid "Emergency Call"
181181msgstr "Notruf"
182182
@@ -209,11 +209,24 @@ msgstr "Sprechen Sie jetzt …"
209209msgid "Speaking..."
210210msgstr "Sie sprechen …"
211211
212+#: Notifications/NotificationMenuItemFactory.qml:89
213+msgid "Show password"
214+msgstr ""
215+
212216#: Panel/SearchIndicator.qml:27
213217msgid "Search"
214218msgstr "Suchen"
215219
216−#: plugins/Unity/scope.cpp:398
220+#: plugins/Unity/Launcher/launcheritem.cpp:43
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Lock to Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/Launcher/launcheritem.cpp:73
226+msgid "Unlock from Launcher"
227+msgstr ""
228+
229+#: plugins/Unity/scope.cpp:408
217230msgid "Sorry, there is nothing that matches your search."
218231msgstr "Entschuldigung, es wurden keine Treffer erzielt."
219232
@@ -221,7 +234,7 @@ msgstr "Entschuldigung, es wurden keine Treffer erzielt."
221234msgid "All"
222235msgstr "Alle"
223236
224−#: Shell.qml:438
237+#: Shell.qml:441
225238#, qt-format
226239msgid "Please enter %1"
227240msgstr "Bitte geben Sie %1 ein"
po/el.po+22−15
@@ -7,7 +7,7 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
1111"PO-Revision-Date: 2013-06-27 00:53+0000\n"
1212"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
1313"Language-Team: Greek <el@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
18+"X-Launchpad-Export-Date: 2013-11-19 05:59+0000\n"
19+"X-Generator: Launchpad (build 16831)\n"
2020
2121#: Applications/applications.js:23
2222msgid "Phone"
@@ -86,7 +86,7 @@ msgstr ""
8686msgid "YouTube"
8787msgstr ""
8888
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
9090msgid "Skip intro"
9191msgstr ""
9292
@@ -132,7 +132,7 @@ msgid ""
132132"phone<br><br>Tap anywhere to start"
133133msgstr ""
134134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136136msgid "Recent searches"
137137msgstr "Πρόσφατες αναζητήσεις"
138138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152152msgstr[0] ""
153153msgstr[1] ""
154154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156156msgid "Rate this"
157157msgstr ""
158158
@@ -172,7 +172,7 @@ msgstr ""
172172msgid "Comments:"
173173msgstr ""
174174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176176msgid "Emergency Call"
177177msgstr ""
178178
@@ -205,11 +205,24 @@ msgstr "Μιλήστε τώρα..."
205205msgid "Speaking..."
206206msgstr "Ομιλία..."
207207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208212#: Panel/SearchIndicator.qml:27
209213msgid "Search"
210214msgstr "Αναζήτηση"
211215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213226msgid "Sorry, there is nothing that matches your search."
214227msgstr "Λυπούμαστε, δεν υπάρχει τίποτα που να ταιριάζει στην αναζήτησή σας."
215228
@@ -217,13 +230,7 @@ msgstr "Λυπούμαστε, δεν υπάρχει τίποτα που να τ
217230msgid "All"
218231msgstr ""
219232
220−#: Shell.qml:438
233+#: Shell.qml:441
221234#, qt-format
222235msgid "Please enter %1"
223236msgstr ""
224−
225−#~ msgid "Music"
226−#~ msgstr "Μουσική"
227−
228−#~ msgid "Videos"
229−#~ msgstr "Βίντεο"
po/en_AU.po+22−30
@@ -7,7 +7,7 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
1111"PO-Revision-Date: 2013-09-28 07:46+0000\n"
1212"Last-Translator: Jared Norris <jarednorris@ubuntu.com>\n"
1313"Language-Team: English (Australia) <en_AU@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
18+"X-Launchpad-Export-Date: 2013-11-19 05:59+0000\n"
19+"X-Generator: Launchpad (build 16831)\n"
2020
2121#: Applications/applications.js:23
2222msgid "Phone"
@@ -86,7 +86,7 @@ msgstr "Wikipedia"
8686msgid "YouTube"
8787msgstr "YouTube"
8888
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
9090msgid "Skip intro"
9191msgstr "Skip intro"
9292
@@ -132,7 +132,7 @@ msgid ""
132132"phone<br><br>Tap anywhere to start"
133133msgstr ""
134134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136136msgid "Recent searches"
137137msgstr "Recent searches"
138138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152152msgstr[0] "%1 review"
153153msgstr[1] "%1 reviews"
154154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156156msgid "Rate this"
157157msgstr "Rate this"
158158
@@ -172,7 +172,7 @@ msgstr "Send"
172172msgid "Comments:"
173173msgstr "Comments:"
174174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176176msgid "Emergency Call"
177177msgstr "Emergency Call"
178178
@@ -205,11 +205,24 @@ msgstr "Speak Now..."
205205msgid "Speaking..."
206206msgstr "Speaking..."
207207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208212#: Panel/SearchIndicator.qml:27
209213msgid "Search"
210214msgstr "Search"
211215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213226msgid "Sorry, there is nothing that matches your search."
214227msgstr "Sorry, there is nothing that matches your search."
215228
@@ -217,28 +230,7 @@ msgstr "Sorry, there is nothing that matches your search."
217230msgid "All"
218231msgstr ""
219232
220−#: Shell.qml:438
233+#: Shell.qml:441
221234#, qt-format
222235msgid "Please enter %1"
223236msgstr "Please enter %1"
224−
225−#~ msgid "Featured"
226−#~ msgstr "Featured"
227−
228−#~ msgid "Recent"
229−#~ msgstr "Recent"
230−
231−#~ msgid "New Releases"
232−#~ msgstr "New Releases"
233−
234−#~ msgid "Top Charting"
235−#~ msgstr "Top Charting"
236−
237−#~ msgid "Music"
238−#~ msgstr "Music"
239−
240−#~ msgid "Popular Online"
241−#~ msgstr "Popular Online"
242−
243−#~ msgid "Videos"
244−#~ msgstr "Videos"
po/en_GB.po+22−30
@@ -7,7 +7,7 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
1111"PO-Revision-Date: 2013-06-27 08:53+0000\n"
1212"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
1313"Language-Team: English (United Kingdom) <en_GB@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
18+"X-Launchpad-Export-Date: 2013-11-19 05:59+0000\n"
19+"X-Generator: Launchpad (build 16831)\n"
2020
2121#: Applications/applications.js:23
2222msgid "Phone"
@@ -86,7 +86,7 @@ msgstr "Wikipedia"
8686msgid "YouTube"
8787msgstr "YouTube"
8888
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
9090msgid "Skip intro"
9191msgstr ""
9292
@@ -132,7 +132,7 @@ msgid ""
132132"phone<br><br>Tap anywhere to start"
133133msgstr ""
134134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136136msgid "Recent searches"
137137msgstr "Recent searches"
138138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152152msgstr[0] ""
153153msgstr[1] ""
154154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156156msgid "Rate this"
157157msgstr ""
158158
@@ -172,7 +172,7 @@ msgstr ""
172172msgid "Comments:"
173173msgstr ""
174174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176176msgid "Emergency Call"
177177msgstr ""
178178
@@ -205,11 +205,24 @@ msgstr "Speak Now..."
205205msgid "Speaking..."
206206msgstr "Speaking..."
207207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208212#: Panel/SearchIndicator.qml:27
209213msgid "Search"
210214msgstr "Search"
211215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213226msgid "Sorry, there is nothing that matches your search."
214227msgstr "Sorry, there is nothing that matches your search."
215228
@@ -217,28 +230,7 @@ msgstr "Sorry, there is nothing that matches your search."
217230msgid "All"
218231msgstr ""
219232
220−#: Shell.qml:438
233+#: Shell.qml:441
221234#, qt-format
222235msgid "Please enter %1"
223236msgstr "Please enter %1"
224−
225−#~ msgid "Featured"
226−#~ msgstr "Featured"
227−
228−#~ msgid "Recent"
229−#~ msgstr "Recent"
230−
231−#~ msgid "New Releases"
232−#~ msgstr "New Releases"
233−
234−#~ msgid "Top Charting"
235−#~ msgstr "Top Charting"
236−
237−#~ msgid "Music"
238−#~ msgstr "Music"
239−
240−#~ msgid "Popular Online"
241−#~ msgstr "Popular Online"
242−
243−#~ msgid "Videos"
244−#~ msgstr "Videos"
po/eo.po+22−9
@@ -7,7 +7,7 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
1111"PO-Revision-Date: 2013-06-26 22:35+0000\n"
1212"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1313"Language-Team: Esperanto <eo@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
18+"X-Launchpad-Export-Date: 2013-11-19 05:59+0000\n"
19+"X-Generator: Launchpad (build 16831)\n"
2020
2121#: Applications/applications.js:23
2222msgid "Phone"
@@ -86,7 +86,7 @@ msgstr ""
8686msgid "YouTube"
8787msgstr ""
8888
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
9090msgid "Skip intro"
9191msgstr ""
9292
@@ -132,7 +132,7 @@ msgid ""
132132"phone<br><br>Tap anywhere to start"
133133msgstr ""
134134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136136msgid "Recent searches"
137137msgstr ""
138138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152152msgstr[0] ""
153153msgstr[1] ""
154154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156156msgid "Rate this"
157157msgstr ""
158158
@@ -172,7 +172,7 @@ msgstr ""
172172msgid "Comments:"
173173msgstr ""
174174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176176msgid "Emergency Call"
177177msgstr ""
178178
@@ -205,11 +205,24 @@ msgstr ""
205205msgid "Speaking..."
206206msgstr ""
207207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208212#: Panel/SearchIndicator.qml:27
209213msgid "Search"
210214msgstr ""
211215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213226msgid "Sorry, there is nothing that matches your search."
214227msgstr ""
215228
@@ -217,7 +230,7 @@ msgstr ""
217230msgid "All"
218231msgstr ""
219232
220−#: Shell.qml:438
233+#: Shell.qml:441
221234#, qt-format
222235msgid "Please enter %1"
223236msgstr ""
po/es.po+23−31
@@ -7,16 +7,16 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
11−"PO-Revision-Date: 2013-10-02 04:59+0000\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
11+"PO-Revision-Date: 2013-11-20 08:46+0000\n"
1212"Last-Translator: Adolfo Jayme Barrientos <fitoschido@gmail.com>\n"
1313"Language-Team: Spanish <es@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
18+"X-Launchpad-Export-Date: 2013-11-21 06:43+0000\n"
19+"X-Generator: Launchpad (build 16831)\n"
2020
2121#: Applications/applications.js:23
2222msgid "Phone"
@@ -86,7 +86,7 @@ msgstr "Wikipedia"
8686msgid "YouTube"
8787msgstr "YouTube"
8888
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
9090msgid "Skip intro"
9191msgstr "Omitir la introducción"
9292
@@ -136,7 +136,7 @@ msgstr ""
136136"Ahora domina los gestos de bordes y puede usar el teléfono<br><br>Toque la "
137137"pantalla para comenzar"
138138
139−#: Components/PageHeader.qml:341
139+#: Components/PageHeader.qml:345
140140msgid "Recent searches"
141141msgstr "Búsquedas recientes"
142142
@@ -156,7 +156,7 @@ msgid_plural "%1 reviews"
156156msgstr[0] "%1 reseña"
157157msgstr[1] "%1 reseñas"
158158
159−#: Dash/Apps/AppPreview.qml:126
159+#: Dash/Apps/AppPreview.qml:135
160160msgid "Rate this"
161161msgstr "Valorar esto"
162162
@@ -176,7 +176,7 @@ msgstr "Enviar"
176176msgid "Comments:"
177177msgstr "Comentarios:"
178178
179−#: Greeter/Lockscreen.qml:142
179+#: Greeter/Lockscreen.qml:146
180180msgid "Emergency Call"
181181msgstr "Llamada de emergencia"
182182
@@ -209,11 +209,24 @@ msgstr "Hable ahora…"
209209msgid "Speaking..."
210210msgstr "Hablando…"
211211
212+#: Notifications/NotificationMenuItemFactory.qml:89
213+msgid "Show password"
214+msgstr "Mostrar contraseña"
215+
212216#: Panel/SearchIndicator.qml:27
213217msgid "Search"
214218msgstr "Buscar"
215219
216−#: plugins/Unity/scope.cpp:398
220+#: plugins/Unity/Launcher/launcheritem.cpp:43
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Lock to Launcher"
223+msgstr "Mantener en el lanzador"
224+
225+#: plugins/Unity/Launcher/launcheritem.cpp:73
226+msgid "Unlock from Launcher"
227+msgstr "No mantener en el lanzador"
228+
229+#: plugins/Unity/scope.cpp:408
217230msgid "Sorry, there is nothing that matches your search."
218231msgstr "No hay nada que coincida con su búsqueda."
219232
@@ -221,28 +234,7 @@ msgstr "No hay nada que coincida con su búsqueda."
221234msgid "All"
222235msgstr "Todo"
223236
224−#: Shell.qml:438
237+#: Shell.qml:441
225238#, qt-format
226239msgid "Please enter %1"
227240msgstr "Introduzca %1"
228−
229−#~ msgid "Featured"
230−#~ msgstr "Destacados"
231−
232−#~ msgid "Recent"
233−#~ msgstr "Recientes"
234−
235−#~ msgid "New Releases"
236−#~ msgstr "Lanzamientos nuevos"
237−
238−#~ msgid "Top Charting"
239−#~ msgstr "Mejor posicionadas"
240−
241−#~ msgid "Music"
242−#~ msgstr "Música"
243−
244−#~ msgid "Popular Online"
245−#~ msgstr "Populares en línea"
246−
247−#~ msgid "Videos"
248−#~ msgstr "Vídeos"
po/fa.po+22−9
@@ -7,7 +7,7 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity8\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
1111"PO-Revision-Date: 2013-10-31 19:02+0000\n"
1212"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1313"Language-Team: Persian <fa@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2013-11-01 06:44+0000\n"
19−"X-Generator: Launchpad (build 16820)\n"
18+"X-Launchpad-Export-Date: 2013-11-19 05:59+0000\n"
19+"X-Generator: Launchpad (build 16831)\n"
2020
2121#: Applications/applications.js:23
2222msgid "Phone"
@@ -86,7 +86,7 @@ msgstr ""
8686msgid "YouTube"
8787msgstr ""
8888
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
9090msgid "Skip intro"
9191msgstr ""
9292
@@ -132,7 +132,7 @@ msgid ""
132132"phone<br><br>Tap anywhere to start"
133133msgstr ""
134134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136136msgid "Recent searches"
137137msgstr ""
138138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152152msgstr[0] ""
153153msgstr[1] ""
154154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156156msgid "Rate this"
157157msgstr ""
158158
@@ -172,7 +172,7 @@ msgstr ""
172172msgid "Comments:"
173173msgstr ""
174174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176176msgid "Emergency Call"
177177msgstr ""
178178
@@ -205,11 +205,24 @@ msgstr ""
205205msgid "Speaking..."
206206msgstr ""
207207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208212#: Panel/SearchIndicator.qml:27
209213msgid "Search"
210214msgstr ""
211215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213226msgid "Sorry, there is nothing that matches your search."
214227msgstr ""
215228
@@ -217,7 +230,7 @@ msgstr ""
217230msgid "All"
218231msgstr ""
219232
220−#: Shell.qml:438
233+#: Shell.qml:441
221234#, qt-format
222235msgid "Please enter %1"
223236msgstr ""
po/fi.po+23−31
@@ -7,16 +7,16 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
11−"PO-Revision-Date: 2013-10-03 09:21+0000\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
11+"PO-Revision-Date: 2013-11-20 08:09+0000\n"
1212"Last-Translator: Jiri Grönroos <Unknown>\n"
1313"Language-Team: Finnish <fi@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
18+"X-Launchpad-Export-Date: 2013-11-21 06:43+0000\n"
19+"X-Generator: Launchpad (build 16831)\n"
2020
2121#: Applications/applications.js:23
2222msgid "Phone"
@@ -86,7 +86,7 @@ msgstr "Wikipedia"
8686msgid "YouTube"
8787msgstr "YouTube"
8888
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
9090msgid "Skip intro"
9191msgstr "Ohita esittely"
9292
@@ -134,7 +134,7 @@ msgstr ""
134134"Hallitset nyt reunaeleet, joten voit aloittaa puhelimen "
135135"käytön<br><br>Napauta missä tahansa aloittaaksesi"
136136
137−#: Components/PageHeader.qml:341
137+#: Components/PageHeader.qml:345
138138msgid "Recent searches"
139139msgstr "Viimeisimmät haut"
140140
@@ -154,7 +154,7 @@ msgid_plural "%1 reviews"
154154msgstr[0] "%1 arvostelu"
155155msgstr[1] "%1 arvostelua"
156156
157−#: Dash/Apps/AppPreview.qml:126
157+#: Dash/Apps/AppPreview.qml:135
158158msgid "Rate this"
159159msgstr "Arvioi tämä"
160160
@@ -174,7 +174,7 @@ msgstr "Lähetä"
174174msgid "Comments:"
175175msgstr "Kommentit:"
176176
177−#: Greeter/Lockscreen.qml:142
177+#: Greeter/Lockscreen.qml:146
178178msgid "Emergency Call"
179179msgstr "Hätäpuhelu"
180180
@@ -207,11 +207,24 @@ msgstr "Puhu nyt..."
207207msgid "Speaking..."
208208msgstr "Puhutaan..."
209209
210+#: Notifications/NotificationMenuItemFactory.qml:89
211+msgid "Show password"
212+msgstr "Näytä salasana"
213+
210214#: Panel/SearchIndicator.qml:27
211215msgid "Search"
212216msgstr "Hae"
213217
214−#: plugins/Unity/scope.cpp:398
218+#: plugins/Unity/Launcher/launcheritem.cpp:43
219+#: plugins/Unity/Launcher/launcheritem.cpp:73
220+msgid "Lock to Launcher"
221+msgstr "Kiinnitä käynnistimeen"
222+
223+#: plugins/Unity/Launcher/launcheritem.cpp:73
224+msgid "Unlock from Launcher"
225+msgstr "Poista käynnistimestä"
226+
227+#: plugins/Unity/scope.cpp:408
215228msgid "Sorry, there is nothing that matches your search."
216229msgstr "Hakuun täsmääviä tuloksia ei löydy."
217230
@@ -219,28 +232,7 @@ msgstr "Hakuun täsmääviä tuloksia ei löydy."
219232msgid "All"
220233msgstr "Kaikki"
221234
222−#: Shell.qml:438
235+#: Shell.qml:441
223236#, qt-format
224237msgid "Please enter %1"
225238msgstr "Kirjoita %1"
226−
227−#~ msgid "Featured"
228−#~ msgstr "Suositellut"
229−
230−#~ msgid "Recent"
231−#~ msgstr "Viimeisimmät"
232−
233−#~ msgid "New Releases"
234−#~ msgstr "Uudet julkaisut"
235−
236−#~ msgid "Top Charting"
237−#~ msgstr "Nousukiidossa"
238−
239−#~ msgid "Music"
240−#~ msgstr "Musiikki"
241−
242−#~ msgid "Popular Online"
243−#~ msgstr "Suosittua verkossa"
244−
245−#~ msgid "Videos"
246−#~ msgstr "Videot"
po/fo.po+22−15
@@ -7,7 +7,7 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
1111"PO-Revision-Date: 2013-10-01 15:13+0000\n"
1212"Last-Translator: Jógvan Olsen <jeggy@jebster.net>\n"
1313"Language-Team: Faroese <fo@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
18+"X-Launchpad-Export-Date: 2013-11-19 05:59+0000\n"
19+"X-Generator: Launchpad (build 16831)\n"
2020
2121#: Applications/applications.js:23
2222msgid "Phone"
@@ -86,7 +86,7 @@ msgstr ""
8686msgid "YouTube"
8787msgstr ""
8888
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
9090msgid "Skip intro"
9191msgstr ""
9292
@@ -132,7 +132,7 @@ msgid ""
132132"phone<br><br>Tap anywhere to start"
133133msgstr ""
134134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136136msgid "Recent searches"
137137msgstr ""
138138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152152msgstr[0] ""
153153msgstr[1] ""
154154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156156msgid "Rate this"
157157msgstr ""
158158
@@ -172,7 +172,7 @@ msgstr ""
172172msgid "Comments:"
173173msgstr ""
174174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176176msgid "Emergency Call"
177177msgstr ""
178178
@@ -205,11 +205,24 @@ msgstr "Snakka nú..."
205205msgid "Speaking..."
206206msgstr "Snakkar..."
207207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208212#: Panel/SearchIndicator.qml:27
209213msgid "Search"
210214msgstr "Leita"
211215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213226msgid "Sorry, there is nothing that matches your search."
214227msgstr "Tíanverri er tað einki sum hóskar til tína leiting."
215228
@@ -217,13 +230,7 @@ msgstr "Tíanverri er tað einki sum hóskar til tína leiting."
217230msgid "All"
218231msgstr ""
219232
220−#: Shell.qml:438
233+#: Shell.qml:441
221234#, qt-format
222235msgid "Please enter %1"
223236msgstr ""
224−
225−#~ msgid "Music"
226−#~ msgstr "Tónleikur"
227−
228−#~ msgid "Videos"
229−#~ msgstr "Sjónbond"
po/fr.po+22−15
@@ -7,7 +7,7 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
1111"PO-Revision-Date: 2013-06-27 03:21+0000\n"
1212"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
1313"Language-Team: French <fr@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=2; plural=n > 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
18+"X-Launchpad-Export-Date: 2013-11-19 05:59+0000\n"
19+"X-Generator: Launchpad (build 16831)\n"
2020
2121#: Applications/applications.js:23
2222msgid "Phone"
@@ -86,7 +86,7 @@ msgstr ""
8686msgid "YouTube"
8787msgstr ""
8888
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
9090msgid "Skip intro"
9191msgstr ""
9292
@@ -132,7 +132,7 @@ msgid ""
132132"phone<br><br>Tap anywhere to start"
133133msgstr ""
134134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136136msgid "Recent searches"
137137msgstr ""
138138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152152msgstr[0] ""
153153msgstr[1] ""
154154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156156msgid "Rate this"
157157msgstr ""
158158
@@ -172,7 +172,7 @@ msgstr ""
172172msgid "Comments:"
173173msgstr ""
174174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176176msgid "Emergency Call"
177177msgstr ""
178178
@@ -205,11 +205,24 @@ msgstr ""
205205msgid "Speaking..."
206206msgstr ""
207207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208212#: Panel/SearchIndicator.qml:27
209213msgid "Search"
210214msgstr ""
211215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213226msgid "Sorry, there is nothing that matches your search."
214227msgstr ""
215228
@@ -217,13 +230,7 @@ msgstr ""
217230msgid "All"
218231msgstr ""
219232
220−#: Shell.qml:438
233+#: Shell.qml:441
221234#, qt-format
222235msgid "Please enter %1"
223236msgstr ""
224−
225−#~ msgid "Music"
226−#~ msgstr "Musique"
227−
228−#~ msgid "Videos"
229−#~ msgstr "Vidéos"
po/gd.po+22−30
@@ -7,7 +7,7 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity8\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
1111"PO-Revision-Date: 2013-09-30 10:34+0000\n"
1212"Last-Translator: Akerbeltz <fios@akerbeltz.org>\n"
1313"Language-Team: Gaelic; Scottish <gd@li.org>\n"
@@ -16,8 +16,8 @@ msgstr ""
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=4; plural=(n==1 || n==11) ? 0 : (n==2 || n==12) ? 1 : "
1818"(n > 2 && n < 20) ? 2 : 3;\n"
19−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
20−"X-Generator: Launchpad (build 16799)\n"
19+"X-Launchpad-Export-Date: 2013-11-19 05:59+0000\n"
20+"X-Generator: Launchpad (build 16831)\n"
2121
2222#: Applications/applications.js:23
2323msgid "Phone"
@@ -87,7 +87,7 @@ msgstr "An Uicipeid"
8787msgid "YouTube"
8888msgstr "YouTube"
8989
90−#: Components/EdgeDemoOverlay.qml:149
90+#: Components/EdgeDemoOverlay.qml:151
9191msgid "Skip intro"
9292msgstr "Gearr leum thairis air an ro-ràdh"
9393
@@ -139,7 +139,7 @@ msgid ""
139139"phone<br><br>Tap anywhere to start"
140140msgstr ""
141141
142−#: Components/PageHeader.qml:341
142+#: Components/PageHeader.qml:345
143143msgid "Recent searches"
144144msgstr "Na lorg thu o chionn goirid"
145145
@@ -161,7 +161,7 @@ msgstr[1] "%1 lèirmheas"
161161msgstr[2] "%1 lèirmheasan"
162162msgstr[3] "%1 lèirmheas"
163163
164−#: Dash/Apps/AppPreview.qml:126
164+#: Dash/Apps/AppPreview.qml:135
165165msgid "Rate this"
166166msgstr "Rangaich seo"
167167
@@ -181,7 +181,7 @@ msgstr "Cuir"
181181msgid "Comments:"
182182msgstr "Beachdan"
183183
184−#: Greeter/Lockscreen.qml:142
184+#: Greeter/Lockscreen.qml:146
185185msgid "Emergency Call"
186186msgstr "Gairm èiginn"
187187
@@ -214,11 +214,24 @@ msgstr "Can rud a-nis..."
214214msgid "Speaking..."
215215msgstr "A' bruidhinn..."
216216
217+#: Notifications/NotificationMenuItemFactory.qml:89
218+msgid "Show password"
219+msgstr ""
220+
217221#: Panel/SearchIndicator.qml:27
218222msgid "Search"
219223msgstr "Lorg"
220224
221−#: plugins/Unity/scope.cpp:398
225+#: plugins/Unity/Launcher/launcheritem.cpp:43
226+#: plugins/Unity/Launcher/launcheritem.cpp:73
227+msgid "Lock to Launcher"
228+msgstr ""
229+
230+#: plugins/Unity/Launcher/launcheritem.cpp:73
231+msgid "Unlock from Launcher"
232+msgstr ""
233+
234+#: plugins/Unity/scope.cpp:408
222235msgid "Sorry, there is nothing that matches your search."
223236msgstr "Tha sinn duilich ach chan eil dad a' freagairt ris na lorg thu."
224237
@@ -226,28 +239,7 @@ msgstr "Tha sinn duilich ach chan eil dad a' freagairt ris na lorg thu."
226239msgid "All"
227240msgstr ""
228241
229−#: Shell.qml:438
242+#: Shell.qml:441
230243#, qt-format
231244msgid "Please enter %1"
232245msgstr "Cuir a-steach %1"
233−
234−#~ msgid "Top Charting"
235−#~ msgstr "Gràinnean-mullaich nan cairt"
236−
237−#~ msgid "Featured"
238−#~ msgstr "Brosnaichte"
239−
240−#~ msgid "Recent"
241−#~ msgstr "O chionn goirid"
242−
243−#~ msgid "New Releases"
244−#~ msgstr "Air ùr-sgaoileadh"
245−
246−#~ msgid "Videos"
247−#~ msgstr "Videothan"
248−
249−#~ msgid "Music"
250−#~ msgstr "Ceòl"
251−
252−#~ msgid "Popular Online"
253−#~ msgstr "Fèill mhòr air air loidhne"
po/gl.po+22−27
@@ -7,7 +7,7 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
1111"PO-Revision-Date: 2013-10-03 18:49+0000\n"
1212"Last-Translator: Marcos Lans <Unknown>\n"
1313"Language-Team: Galician <gl@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
18+"X-Launchpad-Export-Date: 2013-11-19 05:59+0000\n"
19+"X-Generator: Launchpad (build 16831)\n"
2020
2121#: Applications/applications.js:23
2222msgid "Phone"
@@ -86,7 +86,7 @@ msgstr "Wikipedia"
8686msgid "YouTube"
8787msgstr "YouTube"
8888
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
9090msgid "Skip intro"
9191msgstr "Saltar introdución"
9292
@@ -134,7 +134,7 @@ msgstr ""
134134"Xa domina os xestos desde os bordos e pode comezar a usar o "
135135"móbil<br><br>Toque en calquera sitio para comezar"
136136
137−#: Components/PageHeader.qml:341
137+#: Components/PageHeader.qml:345
138138msgid "Recent searches"
139139msgstr "Buscas recentes"
140140
@@ -154,7 +154,7 @@ msgid_plural "%1 reviews"
154154msgstr[0] "%1 opinión"
155155msgstr[1] "%1 opinións"
156156
157−#: Dash/Apps/AppPreview.qml:126
157+#: Dash/Apps/AppPreview.qml:135
158158msgid "Rate this"
159159msgstr "Valore isto"
160160
@@ -174,7 +174,7 @@ msgstr "Enviar"
174174msgid "Comments:"
175175msgstr "Comentarios:"
176176
177−#: Greeter/Lockscreen.qml:142
177+#: Greeter/Lockscreen.qml:146
178178msgid "Emergency Call"
179179msgstr "Chamada de emerxencia"
180180
@@ -207,11 +207,24 @@ msgstr "Fale agora…"
207207msgid "Speaking..."
208208msgstr "Falando…"
209209
210+#: Notifications/NotificationMenuItemFactory.qml:89
211+msgid "Show password"
212+msgstr ""
213+
210214#: Panel/SearchIndicator.qml:27
211215msgid "Search"
212216msgstr "Buscar"
213217
214−#: plugins/Unity/scope.cpp:398
218+#: plugins/Unity/Launcher/launcheritem.cpp:43
219+#: plugins/Unity/Launcher/launcheritem.cpp:73
220+msgid "Lock to Launcher"
221+msgstr ""
222+
223+#: plugins/Unity/Launcher/launcheritem.cpp:73
224+msgid "Unlock from Launcher"
225+msgstr ""
226+
227+#: plugins/Unity/scope.cpp:408
215228msgid "Sorry, there is nothing that matches your search."
216229msgstr "Sentímolo, non hai nada que coincida con esta busca."
217230
@@ -219,25 +232,7 @@ msgstr "Sentímolo, non hai nada que coincida con esta busca."
219232msgid "All"
220233msgstr "Todo"
221234
222−#: Shell.qml:438
235+#: Shell.qml:441
223236#, qt-format
224237msgid "Please enter %1"
225238msgstr "Introduza %1"
226−
227−#~ msgid "Music"
228−#~ msgstr "Música"
229−
230−#~ msgid "Videos"
231−#~ msgstr "Vídeos"
232−
233−#~ msgid "Featured"
234−#~ msgstr "Destacado"
235−
236−#~ msgid "Recent"
237−#~ msgstr "Recentes"
238−
239−#~ msgid "New Releases"
240−#~ msgstr "Novas versións"
241−
242−#~ msgid "Popular Online"
243−#~ msgstr "Populares en liña"
po/he.po+26−32
@@ -7,16 +7,16 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
11−"PO-Revision-Date: 2013-10-01 09:19+0000\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
11+"PO-Revision-Date: 2013-11-20 08:30+0000\n"
1212"Last-Translator: Yaron <sh.yaron@gmail.com>\n"
1313"Language-Team: Hebrew <he@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
18+"X-Launchpad-Export-Date: 2013-11-21 06:43+0000\n"
19+"X-Generator: Launchpad (build 16831)\n"
2020
2121#: Applications/applications.js:23
2222msgid "Phone"
@@ -86,7 +86,7 @@ msgstr "ויקיפדיה"
8686msgid "YouTube"
8787msgstr "YouTube"
8888
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
9090msgid "Skip intro"
9191msgstr "לדלג על הפתיחה"
9292
@@ -131,8 +131,10 @@ msgid ""
131131"You have now mastered the edge gestures and can start using the "
132132"phone<br><br>Tap anywhere to start"
133133msgstr ""
134+"עתה מכשסיימת את ההשתלמות לשימוש במחוות קצה יש לך את הכלים להשתמש "
135+"בטלפון<br><br>ניתן לגעת במקום כלשהו במסך כדי להתחיל"
134136
135−#: Components/PageHeader.qml:341
137+#: Components/PageHeader.qml:345
136138msgid "Recent searches"
137139msgstr "חיפושים אחרונים"
138140
@@ -152,7 +154,7 @@ msgid_plural "%1 reviews"
152154msgstr[0] "סקירה %1"
153155msgstr[1] "%1 סקירות"
154156
155−#: Dash/Apps/AppPreview.qml:126
157+#: Dash/Apps/AppPreview.qml:135
156158msgid "Rate this"
157159msgstr "דירוג היישום"
158160
@@ -172,7 +174,7 @@ msgstr "שליחה"
172174msgid "Comments:"
173175msgstr "הערות:"
174176
175−#: Greeter/Lockscreen.qml:142
177+#: Greeter/Lockscreen.qml:146
176178msgid "Emergency Call"
177179msgstr "שיחת חירום"
178180
@@ -205,40 +207,32 @@ msgstr "יש לדבר כעת..."
205207msgid "Speaking..."
206208msgstr "הדיבור מושמע…"
207209
210+#: Notifications/NotificationMenuItemFactory.qml:89
211+msgid "Show password"
212+msgstr "הצגת הססמה"
213+
208214#: Panel/SearchIndicator.qml:27
209215msgid "Search"
210216msgstr "חיפוש"
211217
212−#: plugins/Unity/scope.cpp:398
218+#: plugins/Unity/Launcher/launcheritem.cpp:43
219+#: plugins/Unity/Launcher/launcheritem.cpp:73
220+msgid "Lock to Launcher"
221+msgstr "נעילה למשגר"
222+
223+#: plugins/Unity/Launcher/launcheritem.cpp:73
224+msgid "Unlock from Launcher"
225+msgstr "הפרדה מהמשגר"
226+
227+#: plugins/Unity/scope.cpp:408
213228msgid "Sorry, there is nothing that matches your search."
214229msgstr "שום דבר אינו תואם לחיפוש שלך, עמך הסליחה."
215230
216231#: plugins/Unity/showallfilteroption.cpp:41
217232msgid "All"
218−msgstr ""
233+msgstr "הכול"
219234
220−#: Shell.qml:438
235+#: Shell.qml:441
221236#, qt-format
222237msgid "Please enter %1"
223238msgstr "נא להזין %1"
224−
225−#~ msgid "Music"
226−#~ msgstr "מוזיקה"
227−
228−#~ msgid "Videos"
229−#~ msgstr "סרטונים"
230−
231−#~ msgid "Top Charting"
232−#~ msgstr "בראש הטבלה"
233−
234−#~ msgid "Featured"
235−#~ msgstr "מומלצים"
236−
237−#~ msgid "Recent"
238−#~ msgstr "אחרונים"
239−
240−#~ msgid "New Releases"
241−#~ msgstr "מהדורות חדשות"
242−
243−#~ msgid "Popular Online"
244−#~ msgstr "פופולריים ברחבי הרשת"
po/hr.po+22−15
@@ -7,7 +7,7 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
1111"PO-Revision-Date: 2013-06-27 04:14+0000\n"
1212"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
1313"Language-Team: Croatian <hr@li.org>\n"
@@ -16,8 +16,8 @@ msgstr ""
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
1818"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
19−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
20−"X-Generator: Launchpad (build 16799)\n"
19+"X-Launchpad-Export-Date: 2013-11-19 05:59+0000\n"
20+"X-Generator: Launchpad (build 16831)\n"
2121
2222#: Applications/applications.js:23
2323msgid "Phone"
@@ -87,7 +87,7 @@ msgstr ""
8787msgid "YouTube"
8888msgstr ""
8989
90−#: Components/EdgeDemoOverlay.qml:149
90+#: Components/EdgeDemoOverlay.qml:151
9191msgid "Skip intro"
9292msgstr ""
9393
@@ -133,7 +133,7 @@ msgid ""
133133"phone<br><br>Tap anywhere to start"
134134msgstr ""
135135
136−#: Components/PageHeader.qml:341
136+#: Components/PageHeader.qml:345
137137msgid "Recent searches"
138138msgstr "Nedavne pretrage"
139139
@@ -153,7 +153,7 @@ msgid_plural "%1 reviews"
153153msgstr[0] ""
154154msgstr[1] ""
155155
156−#: Dash/Apps/AppPreview.qml:126
156+#: Dash/Apps/AppPreview.qml:135
157157msgid "Rate this"
158158msgstr ""
159159
@@ -173,7 +173,7 @@ msgstr ""
173173msgid "Comments:"
174174msgstr ""
175175
176−#: Greeter/Lockscreen.qml:142
176+#: Greeter/Lockscreen.qml:146
177177msgid "Emergency Call"
178178msgstr ""
179179
@@ -206,11 +206,24 @@ msgstr "Recite..."
206206msgid "Speaking..."
207207msgstr "Govor..."
208208
209+#: Notifications/NotificationMenuItemFactory.qml:89
210+msgid "Show password"
211+msgstr ""
212+
209213#: Panel/SearchIndicator.qml:27
210214msgid "Search"
211215msgstr "Pretraživanje"
212216
213−#: plugins/Unity/scope.cpp:398
217+#: plugins/Unity/Launcher/launcheritem.cpp:43
218+#: plugins/Unity/Launcher/launcheritem.cpp:73
219+msgid "Lock to Launcher"
220+msgstr ""
221+
222+#: plugins/Unity/Launcher/launcheritem.cpp:73
223+msgid "Unlock from Launcher"
224+msgstr ""
225+
226+#: plugins/Unity/scope.cpp:408
214227msgid "Sorry, there is nothing that matches your search."
215228msgstr "Nažalost, ne postoji ništa što odgovara vašoj pretrazi."
216229
@@ -218,13 +231,7 @@ msgstr "Nažalost, ne postoji ništa što odgovara vašoj pretrazi."
218231msgid "All"
219232msgstr ""
220233
221−#: Shell.qml:438
234+#: Shell.qml:441
222235#, qt-format
223236msgid "Please enter %1"
224237msgstr ""
225−
226−#~ msgid "Music"
227−#~ msgstr "Glazba"
228−
229−#~ msgid "Videos"
230−#~ msgstr "Video"
po/hu.po+22−15
@@ -7,7 +7,7 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
1111"PO-Revision-Date: 2013-06-27 04:28+0000\n"
1212"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
1313"Language-Team: Hungarian <hu@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
18+"X-Launchpad-Export-Date: 2013-11-19 05:59+0000\n"
19+"X-Generator: Launchpad (build 16831)\n"
2020
2121#: Applications/applications.js:23
2222msgid "Phone"
@@ -86,7 +86,7 @@ msgstr ""
8686msgid "YouTube"
8787msgstr ""
8888
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
9090msgid "Skip intro"
9191msgstr ""
9292
@@ -132,7 +132,7 @@ msgid ""
132132"phone<br><br>Tap anywhere to start"
133133msgstr ""
134134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136136msgid "Recent searches"
137137msgstr "Legutóbbi keresések"
138138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152152msgstr[0] ""
153153msgstr[1] ""
154154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156156msgid "Rate this"
157157msgstr ""
158158
@@ -172,7 +172,7 @@ msgstr ""
172172msgid "Comments:"
173173msgstr ""
174174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176176msgid "Emergency Call"
177177msgstr ""
178178
@@ -205,11 +205,24 @@ msgstr "Beszéljen most…"
205205msgid "Speaking..."
206206msgstr "Beszéd…"
207207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208212#: Panel/SearchIndicator.qml:27
209213msgid "Search"
210214msgstr "Keresés"
211215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213226msgid "Sorry, there is nothing that matches your search."
214227msgstr "Elnézést, nincs találat a keresésre."
215228
@@ -217,13 +230,7 @@ msgstr "Elnézést, nincs találat a keresésre."
217230msgid "All"
218231msgstr ""
219232
220−#: Shell.qml:438
233+#: Shell.qml:441
221234#, qt-format
222235msgid "Please enter %1"
223236msgstr ""
224−
225−#~ msgid "Music"
226−#~ msgstr "Zene"
227−
228−#~ msgid "Videos"
229−#~ msgstr "Videók"
po/hy.po+22−15
@@ -7,7 +7,7 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
1111"PO-Revision-Date: 2013-06-27 04:43+0000\n"
1212"Last-Translator: iAbaS <sosabazyan@yandex.ru>\n"
1313"Language-Team: Armenian <hy@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
18+"X-Launchpad-Export-Date: 2013-11-19 05:59+0000\n"
19+"X-Generator: Launchpad (build 16831)\n"
2020
2121#: Applications/applications.js:23
2222msgid "Phone"
@@ -86,7 +86,7 @@ msgstr ""
8686msgid "YouTube"
8787msgstr ""
8888
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
9090msgid "Skip intro"
9191msgstr ""
9292
@@ -132,7 +132,7 @@ msgid ""
132132"phone<br><br>Tap anywhere to start"
133133msgstr ""
134134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136136msgid "Recent searches"
137137msgstr "Վերջին որոնումներ"
138138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152152msgstr[0] ""
153153msgstr[1] ""
154154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156156msgid "Rate this"
157157msgstr ""
158158
@@ -172,7 +172,7 @@ msgstr ""
172172msgid "Comments:"
173173msgstr ""
174174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176176msgid "Emergency Call"
177177msgstr ""
178178
@@ -205,11 +205,24 @@ msgstr "Խոսի՛ր"
205205msgid "Speaking..."
206206msgstr "Խոսում եմ..."
207207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208212#: Panel/SearchIndicator.qml:27
209213msgid "Search"
210214msgstr "Որոնում"
211215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213226msgid "Sorry, there is nothing that matches your search."
214227msgstr "Կներերք, բայց Ձեր հարցումով ոչինչ չկար"
215228
@@ -217,13 +230,7 @@ msgstr "Կներերք, բայց Ձեր հարցումով ոչինչ չկար"
217230msgid "All"
218231msgstr ""
219232
220−#: Shell.qml:438
233+#: Shell.qml:441
221234#, qt-format
222235msgid "Please enter %1"
223236msgstr ""
224−
225−#~ msgid "Music"
226−#~ msgstr "Երգեր"
227−
228−#~ msgid "Videos"
229−#~ msgstr "Վիդեոներ"
po/id.po+22−9
@@ -7,7 +7,7 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
1111"PO-Revision-Date: 2013-06-26 22:35+0000\n"
1212"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1313"Language-Team: Indonesian <id@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
18+"X-Launchpad-Export-Date: 2013-11-19 05:59+0000\n"
19+"X-Generator: Launchpad (build 16831)\n"
2020
2121#: Applications/applications.js:23
2222msgid "Phone"
@@ -86,7 +86,7 @@ msgstr ""
8686msgid "YouTube"
8787msgstr ""
8888
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
9090msgid "Skip intro"
9191msgstr ""
9292
@@ -132,7 +132,7 @@ msgid ""
132132"phone<br><br>Tap anywhere to start"
133133msgstr ""
134134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136136msgid "Recent searches"
137137msgstr ""
138138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152152msgstr[0] ""
153153msgstr[1] ""
154154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156156msgid "Rate this"
157157msgstr ""
158158
@@ -172,7 +172,7 @@ msgstr ""
172172msgid "Comments:"
173173msgstr ""
174174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176176msgid "Emergency Call"
177177msgstr ""
178178
@@ -205,11 +205,24 @@ msgstr ""
205205msgid "Speaking..."
206206msgstr ""
207207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208212#: Panel/SearchIndicator.qml:27
209213msgid "Search"
210214msgstr ""
211215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213226msgid "Sorry, there is nothing that matches your search."
214227msgstr ""
215228
@@ -217,7 +230,7 @@ msgstr ""
217230msgid "All"
218231msgstr ""
219232
220−#: Shell.qml:438
233+#: Shell.qml:441
221234#, qt-format
222235msgid "Please enter %1"
223236msgstr ""
po/is.po+22−30
@@ -7,7 +7,7 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity8\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
1111"PO-Revision-Date: 2013-09-18 16:22+0000\n"
1212"Last-Translator: Andri Thorlacius <Unknown>\n"
1313"Language-Team: Icelandic <is@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
18+"X-Launchpad-Export-Date: 2013-11-19 05:59+0000\n"
19+"X-Generator: Launchpad (build 16831)\n"
2020
2121#: Applications/applications.js:23
2222msgid "Phone"
@@ -86,7 +86,7 @@ msgstr "Wikipedia"
8686msgid "YouTube"
8787msgstr "YouTube"
8888
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
9090msgid "Skip intro"
9191msgstr "Hoppa yfir kynningu"
9292
@@ -133,7 +133,7 @@ msgid ""
133133"phone<br><br>Tap anywhere to start"
134134msgstr ""
135135
136−#: Components/PageHeader.qml:341
136+#: Components/PageHeader.qml:345
137137msgid "Recent searches"
138138msgstr "Nýlegar leitir"
139139
@@ -153,7 +153,7 @@ msgid_plural "%1 reviews"
153153msgstr[0] "%1 ummæli"
154154msgstr[1] "%1 ummæli"
155155
156−#: Dash/Apps/AppPreview.qml:126
156+#: Dash/Apps/AppPreview.qml:135
157157msgid "Rate this"
158158msgstr "Gefa þessu einkunn"
159159
@@ -173,7 +173,7 @@ msgstr "Senda"
173173msgid "Comments:"
174174msgstr "Athugasemdir:"
175175
176−#: Greeter/Lockscreen.qml:142
176+#: Greeter/Lockscreen.qml:146
177177msgid "Emergency Call"
178178msgstr "Neyðarsímtal"
179179
@@ -206,11 +206,24 @@ msgstr "Talaðu Núna..."
206206msgid "Speaking..."
207207msgstr "Tala..."
208208
209+#: Notifications/NotificationMenuItemFactory.qml:89
210+msgid "Show password"
211+msgstr ""
212+
209213#: Panel/SearchIndicator.qml:27
210214msgid "Search"
211215msgstr "Leita"
212216
213−#: plugins/Unity/scope.cpp:398
217+#: plugins/Unity/Launcher/launcheritem.cpp:43
218+#: plugins/Unity/Launcher/launcheritem.cpp:73
219+msgid "Lock to Launcher"
220+msgstr ""
221+
222+#: plugins/Unity/Launcher/launcheritem.cpp:73
223+msgid "Unlock from Launcher"
224+msgstr ""
225+
226+#: plugins/Unity/scope.cpp:408
214227msgid "Sorry, there is nothing that matches your search."
215228msgstr "Því miður, það var ekkert sem passaði við leitarorðið þitt."
216229
@@ -218,28 +231,7 @@ msgstr "Því miður, það var ekkert sem passaði við leitarorðið þitt."
218231msgid "All"
219232msgstr ""
220233
221−#: Shell.qml:438
234+#: Shell.qml:441
222235#, qt-format
223236msgid "Please enter %1"
224237msgstr ""
225−
226−#~ msgid "Top Charting"
227−#~ msgstr "Topp Listi"
228−
229−#~ msgid "Featured"
230−#~ msgstr "Efst á baugi"
231−
232−#~ msgid "Recent"
233−#~ msgstr "Nýlegt"
234−
235−#~ msgid "New Releases"
236−#~ msgstr "Nýjar Útgáfur"
237−
238−#~ msgid "Videos"
239−#~ msgstr "Myndbönd"
240−
241−#~ msgid "Music"
242−#~ msgstr "Tónlist"
243−
244−#~ msgid "Popular Online"
245−#~ msgstr "Vinsælt á Netinu"
po/it.po+22−30
@@ -7,7 +7,7 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
1111"PO-Revision-Date: 2013-10-07 09:34+0000\n"
1212"Last-Translator: Claudio Arseni <claudio.arseni@gmail.com>\n"
1313"Language-Team: Italian <it@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
18+"X-Launchpad-Export-Date: 2013-11-19 05:59+0000\n"
19+"X-Generator: Launchpad (build 16831)\n"
2020
2121#: Applications/applications.js:23
2222msgid "Phone"
@@ -86,7 +86,7 @@ msgstr "Wikipedia"
8686msgid "YouTube"
8787msgstr "YouTube"
8888
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
9090msgid "Skip intro"
9191msgstr "Salta introduzione"
9292
@@ -139,7 +139,7 @@ msgstr ""
139139"I gesti sui bordi sono stati configurati ed è possibile iniziare a usare il "
140140"telefono<br><br>Toccare in un punto qualunque per iniziare"
141141
142−#: Components/PageHeader.qml:341
142+#: Components/PageHeader.qml:345
143143msgid "Recent searches"
144144msgstr "Ricerche recenti"
145145
@@ -159,7 +159,7 @@ msgid_plural "%1 reviews"
159159msgstr[0] "%1 recensione"
160160msgstr[1] "%1 recensioni"
161161
162−#: Dash/Apps/AppPreview.qml:126
162+#: Dash/Apps/AppPreview.qml:135
163163msgid "Rate this"
164164msgstr "Valuta"
165165
@@ -179,7 +179,7 @@ msgstr "Invia"
179179msgid "Comments:"
180180msgstr "Commenti:"
181181
182−#: Greeter/Lockscreen.qml:142
182+#: Greeter/Lockscreen.qml:146
183183msgid "Emergency Call"
184184msgstr "Chiamata di emergenza"
185185
@@ -212,11 +212,24 @@ msgstr "Parla ora..."
212212msgid "Speaking..."
213213msgstr "Sto parlando..."
214214
215+#: Notifications/NotificationMenuItemFactory.qml:89
216+msgid "Show password"
217+msgstr ""
218+
215219#: Panel/SearchIndicator.qml:27
216220msgid "Search"
217221msgstr "Cerca"
218222
219−#: plugins/Unity/scope.cpp:398
223+#: plugins/Unity/Launcher/launcheritem.cpp:43
224+#: plugins/Unity/Launcher/launcheritem.cpp:73
225+msgid "Lock to Launcher"
226+msgstr ""
227+
228+#: plugins/Unity/Launcher/launcheritem.cpp:73
229+msgid "Unlock from Launcher"
230+msgstr ""
231+
232+#: plugins/Unity/scope.cpp:408
220233msgid "Sorry, there is nothing that matches your search."
221234msgstr "Nessun risultato corrispondente alla ricerca."
222235
@@ -224,28 +237,7 @@ msgstr "Nessun risultato corrispondente alla ricerca."
224237msgid "All"
225238msgstr "Tutto"
226239
227−#: Shell.qml:438
240+#: Shell.qml:441
228241#, qt-format
229242msgid "Please enter %1"
230243msgstr "Inserire %1"
231−
232−#~ msgid "Music"
233−#~ msgstr "Musica"
234−
235−#~ msgid "Videos"
236−#~ msgstr "Video"
237−
238−#~ msgid "Recent"
239−#~ msgstr "Recenti"
240−
241−#~ msgid "New Releases"
242−#~ msgstr "Nuovi rilasci"
243−
244−#~ msgid "Featured"
245−#~ msgstr "In evidenza"
246−
247−#~ msgid "Popular Online"
248−#~ msgstr "Popolari online"
249−
250−#~ msgid "Top Charting"
251−#~ msgstr "Più votate"
po/ja.po+22−9
@@ -7,7 +7,7 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
1111"PO-Revision-Date: 2013-06-26 22:36+0000\n"
1212"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1313"Language-Team: Japanese <ja@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
18+"X-Launchpad-Export-Date: 2013-11-19 05:59+0000\n"
19+"X-Generator: Launchpad (build 16831)\n"
2020
2121#: Applications/applications.js:23
2222msgid "Phone"
@@ -86,7 +86,7 @@ msgstr ""
8686msgid "YouTube"
8787msgstr ""
8888
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
9090msgid "Skip intro"
9191msgstr ""
9292
@@ -132,7 +132,7 @@ msgid ""
132132"phone<br><br>Tap anywhere to start"
133133msgstr ""
134134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136136msgid "Recent searches"
137137msgstr ""
138138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152152msgstr[0] ""
153153msgstr[1] ""
154154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156156msgid "Rate this"
157157msgstr ""
158158
@@ -172,7 +172,7 @@ msgstr ""
172172msgid "Comments:"
173173msgstr ""
174174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176176msgid "Emergency Call"
177177msgstr ""
178178
@@ -205,11 +205,24 @@ msgstr ""
205205msgid "Speaking..."
206206msgstr ""
207207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208212#: Panel/SearchIndicator.qml:27
209213msgid "Search"
210214msgstr ""
211215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213226msgid "Sorry, there is nothing that matches your search."
214227msgstr ""
215228
@@ -217,7 +230,7 @@ msgstr ""
217230msgid "All"
218231msgstr ""
219232
220−#: Shell.qml:438
233+#: Shell.qml:441
221234#, qt-format
222235msgid "Please enter %1"
223236msgstr ""
po/km.po+23−31
@@ -7,16 +7,16 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity8\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
11−"PO-Revision-Date: 2013-10-11 08:49+0000\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
11+"PO-Revision-Date: 2013-11-20 07:34+0000\n"
1212"Last-Translator: Khoem Sokhem <khoemsokhem@khmeros.info>\n"
1313"Language-Team: Khmer <km@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
18+"X-Launchpad-Export-Date: 2013-11-21 06:43+0000\n"
19+"X-Generator: Launchpad (build 16831)\n"
2020
2121#: Applications/applications.js:23
2222msgid "Phone"
@@ -86,7 +86,7 @@ msgstr "វីគីភីឌៀ"
8686msgid "YouTube"
8787msgstr "YouTube"
8888
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
9090msgid "Skip intro"
9191msgstr "រំលង​ការ​ណែនាំ"
9292
@@ -137,7 +137,7 @@ msgstr ""
137137"និង​អាច​ចាប់ផ្ដើម​ប្រើ​ទូរស័ព្ទ​បាន<br><br>ប៉ះ​កន្លែង​ណា​មួយ​ "
138138"ដើម្បី​ចាប់ផ្ដើម"
139139
140−#: Components/PageHeader.qml:341
140+#: Components/PageHeader.qml:345
141141msgid "Recent searches"
142142msgstr "ការ​ស្វែងរក​ថ្មី"
143143
@@ -156,7 +156,7 @@ msgid "%1 review"
156156msgid_plural "%1 reviews"
157157msgstr[0] "ពិនិត្យ​មើល %1"
158158
159−#: Dash/Apps/AppPreview.qml:126
159+#: Dash/Apps/AppPreview.qml:135
160160msgid "Rate this"
161161msgstr "វាយតម្លៃ​វា"
162162
@@ -176,7 +176,7 @@ msgstr "ផ្ញើ"
176176msgid "Comments:"
177177msgstr "មតិយោបល់៖"
178178
179−#: Greeter/Lockscreen.qml:142
179+#: Greeter/Lockscreen.qml:146
180180msgid "Emergency Call"
181181msgstr "ការ​ហៅ​ពេល​អាសន្ន"
182182
@@ -209,11 +209,24 @@ msgstr "និយាយ​ឥឡូវ..."
209209msgid "Speaking..."
210210msgstr "កំពុង​និយាយ..."
211211
212+#: Notifications/NotificationMenuItemFactory.qml:89
213+msgid "Show password"
214+msgstr "បង្ហាញ​ពាក្យ​សម្ងាត់"
215+
212216#: Panel/SearchIndicator.qml:27
213217msgid "Search"
214218msgstr "ស្វែង​រក"
215219
216−#: plugins/Unity/scope.cpp:398
220+#: plugins/Unity/Launcher/launcheritem.cpp:43
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Lock to Launcher"
223+msgstr "ចាក់​សោ​​ទៅ​កម្មវិធី​ចាប់ផ្ដើម"
224+
225+#: plugins/Unity/Launcher/launcheritem.cpp:73
226+msgid "Unlock from Launcher"
227+msgstr "ដោះសោ​ពី​កម្មវិធី​ចាប់ផ្ដើម"
228+
229+#: plugins/Unity/scope.cpp:408
217230msgid "Sorry, there is nothing that matches your search."
218231msgstr "សូម​ទោស មិនមាន​ពាក្យ​ដែល​អ្នក​ស្វែងរក​ទេ​។"
219232
@@ -221,28 +234,7 @@ msgstr "សូម​ទោស មិនមាន​ពាក្យ​ដែល
221234msgid "All"
222235msgstr "ទាំង​អស់"
223236
224−#: Shell.qml:438
237+#: Shell.qml:441
225238#, qt-format
226239msgid "Please enter %1"
227240msgstr "សូម​បញ្ចូល %1"
228−
229−#~ msgid "Popular Online"
230−#~ msgstr "លើ​បណ្ដាញ​ប្រជាប្រិយ"
231−
232−#~ msgid "Music"
233−#~ msgstr "តន្ត្រី"
234−
235−#~ msgid "New Releases"
236−#~ msgstr "ការ​ចេញ​ផ្សាយ​ថ្មី"
237−
238−#~ msgid "Top Charting"
239−#~ msgstr "តារាង​ខាង​លើ"
240−
241−#~ msgid "Featured"
242−#~ msgstr "ដែល​ល្បី"
243−
244−#~ msgid "Recent"
245−#~ msgstr "ថ្មីៗ"
246−
247−#~ msgid "Videos"
248−#~ msgstr "វីដេអូ"
po/kn.po+22−15
@@ -7,7 +7,7 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
1111"PO-Revision-Date: 2013-06-27 05:43+0000\n"
1212"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
1313"Language-Team: Kannada <kn@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
18+"X-Launchpad-Export-Date: 2013-11-19 05:59+0000\n"
19+"X-Generator: Launchpad (build 16831)\n"
2020
2121#: Applications/applications.js:23
2222msgid "Phone"
@@ -86,7 +86,7 @@ msgstr ""
8686msgid "YouTube"
8787msgstr ""
8888
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
9090msgid "Skip intro"
9191msgstr ""
9292
@@ -132,7 +132,7 @@ msgid ""
132132"phone<br><br>Tap anywhere to start"
133133msgstr ""
134134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136136msgid "Recent searches"
137137msgstr "ಇತ್ತೀಚಿನ ಹುಡುಕಾಟಗಳು"
138138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152152msgstr[0] ""
153153msgstr[1] ""
154154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156156msgid "Rate this"
157157msgstr ""
158158
@@ -172,7 +172,7 @@ msgstr ""
172172msgid "Comments:"
173173msgstr ""
174174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176176msgid "Emergency Call"
177177msgstr ""
178178
@@ -205,11 +205,24 @@ msgstr "ಈಗ ಮಾತನಾಡಿ ..."
205205msgid "Speaking..."
206206msgstr "ಮಾತನಾಡುತಿದ್ದೀರಿ"
207207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208212#: Panel/SearchIndicator.qml:27
209213msgid "Search"
210214msgstr "ಹುಡುಕು"
211215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213226msgid "Sorry, there is nothing that matches your search."
214227msgstr "ಕ್ಷಮಿಸಿ ನಿಮ್ಮ ಶೋಧನೆಗೆ ಸರಿಯಾದ ಹೊಂದಾಣಿಕೆಗಳು ದೊರಕುತ್ತಿಲ್ಲ"
215228
@@ -217,13 +230,7 @@ msgstr "ಕ್ಷಮಿಸಿ ನಿಮ್ಮ ಶೋಧನೆಗೆ ಸರಿಯ
217230msgid "All"
218231msgstr ""
219232
220−#: Shell.qml:438
233+#: Shell.qml:441
221234#, qt-format
222235msgid "Please enter %1"
223236msgstr ""
224−
225−#~ msgid "Music"
226−#~ msgstr "ಸಂಗೀತ"
227−
228−#~ msgid "Videos"
229−#~ msgstr "ವೀಡಿಯೋಗಳು"
po/ko.po+22−12
@@ -7,7 +7,7 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
1111"PO-Revision-Date: 2013-10-10 07:04+0000\n"
1212"Last-Translator: Kim Boram <boramism@gmail.com>\n"
1313"Language-Team: Korean <ko@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
18+"X-Launchpad-Export-Date: 2013-11-19 05:59+0000\n"
19+"X-Generator: Launchpad (build 16831)\n"
2020
2121#: Applications/applications.js:23
2222msgid "Phone"
@@ -86,7 +86,7 @@ msgstr "위키백과"
8686msgid "YouTube"
8787msgstr "유튜브"
8888
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
9090msgid "Skip intro"
9191msgstr "도입부 건너뛰기"
9292
@@ -132,7 +132,7 @@ msgid ""
132132"phone<br><br>Tap anywhere to start"
133133msgstr ""
134134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136136msgid "Recent searches"
137137msgstr "최근 검색"
138138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152152msgstr[0] ""
153153msgstr[1] ""
154154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156156msgid "Rate this"
157157msgstr ""
158158
@@ -172,7 +172,7 @@ msgstr ""
172172msgid "Comments:"
173173msgstr ""
174174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176176msgid "Emergency Call"
177177msgstr ""
178178
@@ -205,11 +205,24 @@ msgstr ""
205205msgid "Speaking..."
206206msgstr ""
207207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208212#: Panel/SearchIndicator.qml:27
209213msgid "Search"
210214msgstr "검색"
211215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213226msgid "Sorry, there is nothing that matches your search."
214227msgstr ""
215228
@@ -217,10 +230,7 @@ msgstr ""
217230msgid "All"
218231msgstr ""
219232
220−#: Shell.qml:438
233+#: Shell.qml:441
221234#, qt-format
222235msgid "Please enter %1"
223236msgstr ""
224−
225−#~ msgid "Music"
226−#~ msgstr "음악"
po/ky.po+22−15
@@ -7,7 +7,7 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
1111"PO-Revision-Date: 2013-06-27 06:17+0000\n"
1212"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
1313"Language-Team: Kirghiz <ky@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
18+"X-Launchpad-Export-Date: 2013-11-19 05:59+0000\n"
19+"X-Generator: Launchpad (build 16831)\n"
2020
2121#: Applications/applications.js:23
2222msgid "Phone"
@@ -86,7 +86,7 @@ msgstr ""
8686msgid "YouTube"
8787msgstr ""
8888
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
9090msgid "Skip intro"
9191msgstr ""
9292
@@ -132,7 +132,7 @@ msgid ""
132132"phone<br><br>Tap anywhere to start"
133133msgstr ""
134134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136136msgid "Recent searches"
137137msgstr "Соңку издөөлөр"
138138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152152msgstr[0] ""
153153msgstr[1] ""
154154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156156msgid "Rate this"
157157msgstr ""
158158
@@ -172,7 +172,7 @@ msgstr ""
172172msgid "Comments:"
173173msgstr ""
174174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176176msgid "Emergency Call"
177177msgstr ""
178178
@@ -205,11 +205,24 @@ msgstr "Азыр сүйлөңүз..."
205205msgid "Speaking..."
206206msgstr "Сүйлөнүүдө..."
207207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208212#: Panel/SearchIndicator.qml:27
209213msgid "Search"
210214msgstr "Издөө"
211215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213226msgid "Sorry, there is nothing that matches your search."
214227msgstr "Тилекке каршы, сиздин издөөңүзгө эч нерсе дал келген жок."
215228
@@ -217,13 +230,7 @@ msgstr "Тилекке каршы, сиздин издөөңүзгө эч нер
217230msgid "All"
218231msgstr ""
219232
220−#: Shell.qml:438
233+#: Shell.qml:441
221234#, qt-format
222235msgid "Please enter %1"
223236msgstr ""
224−
225−#~ msgid "Music"
226−#~ msgstr "Музыка"
227−
228−#~ msgid "Videos"
229−#~ msgstr "Видеолор"
po/lo.po+22−15
@@ -7,7 +7,7 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity8\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
1111"PO-Revision-Date: 2013-10-02 10:00+0000\n"
1212"Last-Translator: Anousak <anousak@gmail.com>\n"
1313"Language-Team: Lao <lo@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
18+"X-Launchpad-Export-Date: 2013-11-19 05:59+0000\n"
19+"X-Generator: Launchpad (build 16831)\n"
2020
2121#: Applications/applications.js:23
2222msgid "Phone"
@@ -86,7 +86,7 @@ msgstr ""
8686msgid "YouTube"
8787msgstr "ິYouTube"
8888
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
9090msgid "Skip intro"
9191msgstr ""
9292
@@ -132,7 +132,7 @@ msgid ""
132132"phone<br><br>Tap anywhere to start"
133133msgstr ""
134134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136136msgid "Recent searches"
137137msgstr ""
138138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152152msgstr[0] ""
153153msgstr[1] ""
154154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156156msgid "Rate this"
157157msgstr ""
158158
@@ -172,7 +172,7 @@ msgstr "ສົ່ງ"
172172msgid "Comments:"
173173msgstr "ຄໍ່ເຫັນ"
174174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176176msgid "Emergency Call"
177177msgstr ""
178178
@@ -205,11 +205,24 @@ msgstr "ເວົ້າໂລດ"
205205msgid "Speaking..."
206206msgstr "ກໍາລັງເວົ້າ"
207207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208212#: Panel/SearchIndicator.qml:27
209213msgid "Search"
210214msgstr "ຊອກຫາ"
211215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213226msgid "Sorry, there is nothing that matches your search."
214227msgstr ""
215228
@@ -217,13 +230,7 @@ msgstr ""
217230msgid "All"
218231msgstr "ທັງໝົດ"
219232
220−#: Shell.qml:438
233+#: Shell.qml:441
221234#, qt-format
222235msgid "Please enter %1"
223236msgstr "ກະລູນາປ້ອນ %1"
224−
225−#~ msgid "Videos"
226−#~ msgstr "ວິດີໂອ"
227−
228−#~ msgid "Music"
229−#~ msgstr "ດົນຕີ"
po/lv.po+22−15
@@ -7,7 +7,7 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
1111"PO-Revision-Date: 2013-09-28 16:29+0000\n"
1212"Last-Translator: Jānis-Marks Gailis <jeanmarc.gailis@gmail.com>\n"
1313"Language-Team: Latvian <lv@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
18+"X-Launchpad-Export-Date: 2013-11-19 05:59+0000\n"
19+"X-Generator: Launchpad (build 16831)\n"
2020
2121#: Applications/applications.js:23
2222msgid "Phone"
@@ -86,7 +86,7 @@ msgstr "Vikipēdija"
8686msgid "YouTube"
8787msgstr "YouTube"
8888
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
9090msgid "Skip intro"
9191msgstr ""
9292
@@ -132,7 +132,7 @@ msgid ""
132132"phone<br><br>Tap anywhere to start"
133133msgstr ""
134134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136136msgid "Recent searches"
137137msgstr "Nesen veiktās meklēšanas"
138138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152152msgstr[0] ""
153153msgstr[1] ""
154154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156156msgid "Rate this"
157157msgstr ""
158158
@@ -172,7 +172,7 @@ msgstr ""
172172msgid "Comments:"
173173msgstr ""
174174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176176msgid "Emergency Call"
177177msgstr ""
178178
@@ -205,11 +205,24 @@ msgstr "Runajiet Tagad"
205205msgid "Speaking..."
206206msgstr "Runa..."
207207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208212#: Panel/SearchIndicator.qml:27
209213msgid "Search"
210214msgstr "Meklēt"
211215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213226msgid "Sorry, there is nothing that matches your search."
214227msgstr "Diemžēl nekas neatbilst jūsu meklētajam."
215228
@@ -217,13 +230,7 @@ msgstr "Diemžēl nekas neatbilst jūsu meklētajam."
217230msgid "All"
218231msgstr ""
219232
220−#: Shell.qml:438
233+#: Shell.qml:441
221234#, qt-format
222235msgid "Please enter %1"
223236msgstr ""
224−
225−#~ msgid "Music"
226−#~ msgstr "Mūzika"
227−
228−#~ msgid "Videos"
229−#~ msgstr "Video"
po/ml.ponew file+240
@@ -0,0 +1,240 @@
1+# Malayalam translation for unity8
2+# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013
3+# This file is distributed under the same license as the unity8 package.
4+# FIRST AUTHOR <EMAIL@ADDRESS>, 2013.
5+#
6+msgid ""
7+msgstr ""
8+"Project-Id-Version: unity8\n"
9+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
11+"PO-Revision-Date: 2013-11-23 11:44+0000\n"
12+"Last-Translator: STyM Alfazz <Unknown>\n"
13+"Language-Team: Malayalam <ml@li.org>\n"
14+"MIME-Version: 1.0\n"
15+"Content-Type: text/plain; charset=UTF-8\n"
16+"Content-Transfer-Encoding: 8bit\n"
17+"Plural-Forms: nplurals=2; plural=n != 1;\n"
18+"X-Launchpad-Export-Date: 2013-11-24 05:50+0000\n"
19+"X-Generator: Launchpad (build 16831)\n"
20+
21+#: Applications/applications.js:23
22+msgid "Phone"
23+msgstr "ഫോണ്‍"
24+
25+#: Applications/applications.js:29
26+msgid "Camera"
27+msgstr "ക്യാമറ"
28+
29+#: Applications/applications.js:35
30+msgid "Gallery"
31+msgstr "ഗ്യാലറി"
32+
33+#: Applications/applications.js:40
34+msgid "Facebook"
35+msgstr "ഫേസ്ബുക്ക്"
36+
37+#: Applications/applications.js:46
38+msgid "Browser"
39+msgstr "ബ്രൗസര്‍"
40+
41+#: Applications/applications.js:51
42+msgid "Twitter"
43+msgstr "ട്വിറ്റര്‍"
44+
45+#: Applications/applications.js:57
46+msgid "GMail"
47+msgstr "ജിമെയില്‍"
48+
49+#: Applications/applications.js:62
50+msgid "Weather"
51+msgstr "കാലാവസ്ഥ"
52+
53+#: Applications/applications.js:68
54+msgid "Notepad"
55+msgstr "നോട്പാഡ്"
56+
57+#: Applications/applications.js:74
58+msgid "Calendar"
59+msgstr "കലണ്ടര്‍"
60+
61+#: Applications/applications.js:80
62+msgid "Media Player"
63+msgstr "മീഡിയ പ്ലെയര്‍"
64+
65+#: Applications/applications.js:86
66+msgid "Evernote"
67+msgstr "എവര്‍നോട്ട്"
68+
69+#: Applications/applications.js:91
70+msgid "Map"
71+msgstr "ഭുപടം"
72+
73+#: Applications/applications.js:96
74+msgid "Pinterest"
75+msgstr "പിന്‍ട്രസ്റ്റ്"
76+
77+#: Applications/applications.js:101
78+msgid "SoundCloud"
79+msgstr "സൗണ്ട്ക്ലൗഡ്"
80+
81+#: Applications/applications.js:106
82+msgid "Wikipedia"
83+msgstr "വിക്കിപീഡിയ"
84+
85+#: Applications/applications.js:111
86+msgid "YouTube"
87+msgstr "യുട്യൂബ്"
88+
89+#: Components/EdgeDemoOverlay.qml:151
90+msgid "Skip intro"
91+msgstr "ആമുഖം ഒഴിവാക്കുക"
92+
93+#: Components/EdgeDemo.qml:112
94+msgid "Right edge"
95+msgstr "വലത് മൂല"
96+
97+#: Components/EdgeDemo.qml:113
98+msgid "Try swiping from the right edge to unlock the phone"
99+msgstr "ഫോണ്‍ അണ്‍ലോക്ക് ചെയ്യാന്‍ വലതു വശത്തുനിന്ന് സ്വൈപ് ചെയ്ത് നോക്കുക"
100+
101+#: Components/EdgeDemo.qml:144
102+msgid "Top edge"
103+msgstr "മുകള്‍ വശം"
104+
105+#: Components/EdgeDemo.qml:145
106+msgid "Try swiping from the top edge to access the indicators"
107+msgstr "സൂചകങ്ങള്‍ ലഭ്യമാക്കാന്‍ മുകള്‍ വശത്തുനിന്നും സ്വൈപ് ചെയ്യുക"
108+
109+#: Components/EdgeDemo.qml:170
110+msgid "Close"
111+msgstr "അടക്കുക"
112+
113+#: Components/EdgeDemo.qml:171
114+msgid "Swipe up again to close the settings screen"
115+msgstr "ക്രമീകരണങ്ങളുടെ സ്ക്രീന്‍ അടക്കാന്‍ മുകളിലേക്ക് സ്വൈപ് ചെയ്യുക"
116+
117+#: Components/EdgeDemo.qml:198
118+msgid "Left edge"
119+msgstr "ഇടത് വശം"
120+
121+#: Components/EdgeDemo.qml:199
122+msgid "Swipe from the left to reveal the launcher for quick access to apps"
123+msgstr ""
124+"പ്രയോഗങ്ങള്‍ പെട്ടെന്ന് ലഭ്യമാക്കുന്ന വിക്ഷേപിക ലഭ്യമാക്കാന്‍ ഇടതു വശത്ത് "
125+"നിന്നും സ്വൈപ് ചെയ്യുക"
126+
127+#: Components/EdgeDemo.qml:226
128+msgid "Well done"
129+msgstr "നന്നായി ചെയ്തിരിക്കുന്നു"
130+
131+#: Components/EdgeDemo.qml:227
132+msgid ""
133+"You have now mastered the edge gestures and can start using the "
134+"phone<br><br>Tap anywhere to start"
135+msgstr ""
136+"നിങ്ങളിപ്പോള്‍ സ്വൈപുകളും മറ്റും പഠിച്ചിരിക്കുന്നു<br><br>തുടങ്ങാന്‍ "
137+"എവിടെയെങ്കിലും ടാപ് ചെയ്യുക"
138+
139+#: Components/PageHeader.qml:345
140+msgid "Recent searches"
141+msgstr "സമീപകാല തിരയലുകള്‍"
142+
143+#. TRANSLATORS: Number of persons who rated this app
144+#. TRANSLATORS: Number of persons who rated this app/video/whatever
145+#: Dash/Apps/AppInfo.qml:73 Dash/Previews/Header.qml:93
146+#, qt-format
147+msgid "(%1)"
148+msgstr "(%1)"
149+
150+#. TRANSLATORS: Number of persons who wrote reviews for this app
151+#. TRANSLATORS: Number of persons who wrote reviews for this app/video/whatever
152+#: Dash/Apps/AppInfo.qml:85 Dash/Previews/Header.qml:105
153+#, qt-format
154+msgid "%1 review"
155+msgid_plural "%1 reviews"
156+msgstr[0] "%1 അവലോകനം"
157+msgstr[1] "%1 അവലോകനങ്ങള്‍"
158+
159+#: Dash/Apps/AppPreview.qml:135
160+msgid "Rate this"
161+msgstr "ഇത് അവലോകനം ചെയ്യുക"
162+
163+#: Dash/Previews/Reviews.qml:74
164+msgid "Add a review"
165+msgstr "ഒരു അവലോകനം ചേര്‍ക്കുക"
166+
167+#: Dash/Previews/Reviews.qml:86
168+msgid "Review"
169+msgstr "അവലോകനം"
170+
171+#: Dash/Previews/Reviews.qml:121
172+msgid "Send"
173+msgstr "അയയ്‌ക്കുക"
174+
175+#: Dash/Previews/Reviews.qml:139
176+msgid "Comments:"
177+msgstr "അഭിപ്രായങ്ങള്‍:"
178+
179+#: Greeter/Lockscreen.qml:146
180+msgid "Emergency Call"
181+msgstr "അടിയന്തിര വിളി"
182+
183+#: Greeter/PassphraseLockscreen.qml:59
184+#, qt-format
185+msgid "Hello %1"
186+msgstr "ഹലോ %1"
187+
188+#: Greeter/PassphraseLockscreen.qml:59
189+msgid "Hello"
190+msgstr "ഹലോ"
191+
192+#: Hud/HudParametrizedActionsPage.qml:132
193+msgid "Confirm"
194+msgstr "സ്ഥിരീകരിക്കുക"
195+
196+#: Hud/Hud.qml:61 Hud/Hud.qml:99 Hud/Hud.qml:372
197+msgid "Type or say a command"
198+msgstr "ഒരു ആജ്ഞ പറയുകയോ ടൈപ്പുകയോ ചെയ്യുക"
199+
200+#: Hud/Hud.qml:84
201+msgid "Loading. Please Wait..."
202+msgstr "വരുന്നു. ദയവായി കാത്തിരിക്കുക..."
203+
204+#: Hud/Hud.qml:89
205+msgid "Speak Now..."
206+msgstr "ഇപ്പോള്‍ സംസാരിക്കുക..."
207+
208+#: Hud/Hud.qml:94
209+msgid "Speaking..."
210+msgstr "സംസാരിക്കുന്നു..."
211+
212+#: Notifications/NotificationMenuItemFactory.qml:89
213+msgid "Show password"
214+msgstr "രഹസ്യവാക്ക് കാണിക്കുക"
215+
216+#: Panel/SearchIndicator.qml:27
217+msgid "Search"
218+msgstr "തിരയുക"
219+
220+#: plugins/Unity/Launcher/launcheritem.cpp:43
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Lock to Launcher"
223+msgstr "വിക്ഷേപികയില്‍ സ്ഥിരപ്പെടുത്തുക"
224+
225+#: plugins/Unity/Launcher/launcheritem.cpp:73
226+msgid "Unlock from Launcher"
227+msgstr "വിക്ഷേപികാ സ്ഥിരപ്പെടുത്തല്‍ ഒഴിവാക്കുക"
228+
229+#: plugins/Unity/scope.cpp:408
230+msgid "Sorry, there is nothing that matches your search."
231+msgstr "ക്ഷമിക്കണം, താങ്കളുടെ തിരച്ചിലുമായി ഒത്തുപോകുന്ന ഒന്നും തന്നെയില്ല"
232+
233+#: plugins/Unity/showallfilteroption.cpp:41
234+msgid "All"
235+msgstr "എല്ലാം"
236+
237+#: Shell.qml:441
238+#, qt-format
239+msgid "Please enter %1"
240+msgstr "ദയവായി %1 നല്‍കുക"
po/my.po+22−24
@@ -7,7 +7,7 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
1111"PO-Revision-Date: 2013-10-09 11:35+0000\n"
1212"Last-Translator: Pyae Sone <Unknown>\n"
1313"Language-Team: Burmese <my@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
18+"X-Launchpad-Export-Date: 2013-11-19 05:59+0000\n"
19+"X-Generator: Launchpad (build 16831)\n"
2020
2121#: Applications/applications.js:23
2222msgid "Phone"
@@ -86,7 +86,7 @@ msgstr "ဝီကီပီဒီးယား"
8686msgid "YouTube"
8787msgstr "YouTube"
8888
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
9090msgid "Skip intro"
9191msgstr "မိတ်ဆက်ကိုကျော်မည်"
9292
@@ -132,7 +132,7 @@ msgid ""
132132"phone<br><br>Tap anywhere to start"
133133msgstr ""
134134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136136msgid "Recent searches"
137137msgstr "မကြာသေးခင်က ရှာဖွေခြင်း"
138138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152152msgstr[0] ""
153153msgstr[1] ""
154154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156156msgid "Rate this"
157157msgstr "ဒီဟာကိုအမှတ်ပေးမည်"
158158
@@ -172,7 +172,7 @@ msgstr "ပို့မည်"
172172msgid "Comments:"
173173msgstr "မှတ်ချက်များ-"
174174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176176msgid "Emergency Call"
177177msgstr ""
178178
@@ -205,11 +205,24 @@ msgstr "ယခုပြောပါ"
205205msgid "Speaking..."
206206msgstr "ပြောနေသည်"
207207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208212#: Panel/SearchIndicator.qml:27
209213msgid "Search"
210214msgstr "ရှာဖွေ"
211215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213226msgid "Sorry, there is nothing that matches your search."
214227msgstr "ဆောရီး၊ သင်၏ရှာဖွေမူနှင့်တူညီတာဘာမှမရှိပါ။"
215228
@@ -217,22 +230,7 @@ msgstr "ဆောရီး၊ သင်၏ရှာဖွေမူနှင့
217230msgid "All"
218231msgstr ""
219232
220−#: Shell.qml:438
233+#: Shell.qml:441
221234#, qt-format
222235msgid "Please enter %1"
223236msgstr ""
224−
225−#~ msgid "Music"
226−#~ msgstr "တေးဂီတ"
227−
228−#~ msgid "Videos"
229−#~ msgstr "ဗီဒီယိုများ"
230−
231−#~ msgid "New Releases"
232−#~ msgstr "အသစ်ထွက်ရှိသော"
233−
234−#~ msgid "Recent"
235−#~ msgstr "မကြာသေးခင်က"
236−
237−#~ msgid "Popular Online"
238−#~ msgstr "အွန်လိုင်းတွင်ပေါ်ပြူလာဖြစ်သော"
po/nb.po+22−15
@@ -7,7 +7,7 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
1111"PO-Revision-Date: 2013-06-27 07:02+0000\n"
1212"Last-Translator: Joakim Langvand <jlangvand@gmail.com>\n"
1313"Language-Team: Norwegian Bokmal <nb@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
18+"X-Launchpad-Export-Date: 2013-11-19 05:59+0000\n"
19+"X-Generator: Launchpad (build 16831)\n"
2020
2121#: Applications/applications.js:23
2222msgid "Phone"
@@ -86,7 +86,7 @@ msgstr ""
8686msgid "YouTube"
8787msgstr ""
8888
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
9090msgid "Skip intro"
9191msgstr ""
9292
@@ -132,7 +132,7 @@ msgid ""
132132"phone<br><br>Tap anywhere to start"
133133msgstr ""
134134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136136msgid "Recent searches"
137137msgstr "Siste søk"
138138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152152msgstr[0] ""
153153msgstr[1] ""
154154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156156msgid "Rate this"
157157msgstr ""
158158
@@ -172,7 +172,7 @@ msgstr ""
172172msgid "Comments:"
173173msgstr ""
174174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176176msgid "Emergency Call"
177177msgstr ""
178178
@@ -205,11 +205,24 @@ msgstr "Snakk nå …"
205205msgid "Speaking..."
206206msgstr "Snakker …"
207207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208212#: Panel/SearchIndicator.qml:27
209213msgid "Search"
210214msgstr "Søk"
211215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213226msgid "Sorry, there is nothing that matches your search."
214227msgstr "Søket ga ingen treff."
215228
@@ -217,13 +230,7 @@ msgstr "Søket ga ingen treff."
217230msgid "All"
218231msgstr ""
219232
220−#: Shell.qml:438
233+#: Shell.qml:441
221234#, qt-format
222235msgid "Please enter %1"
223236msgstr ""
224−
225−#~ msgid "Music"
226−#~ msgstr "Musikk"
227−
228−#~ msgid "Videos"
229−#~ msgstr "Videoer"
po/nl.po+22−15
@@ -7,7 +7,7 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
1111"PO-Revision-Date: 2013-06-27 07:19+0000\n"
1212"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
1313"Language-Team: Dutch <nl@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
18+"X-Launchpad-Export-Date: 2013-11-19 05:59+0000\n"
19+"X-Generator: Launchpad (build 16831)\n"
2020
2121#: Applications/applications.js:23
2222msgid "Phone"
@@ -86,7 +86,7 @@ msgstr ""
8686msgid "YouTube"
8787msgstr ""
8888
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
9090msgid "Skip intro"
9191msgstr ""
9292
@@ -132,7 +132,7 @@ msgid ""
132132"phone<br><br>Tap anywhere to start"
133133msgstr ""
134134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136136msgid "Recent searches"
137137msgstr "Recente zoekopdrachten"
138138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152152msgstr[0] ""
153153msgstr[1] ""
154154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156156msgid "Rate this"
157157msgstr ""
158158
@@ -172,7 +172,7 @@ msgstr ""
172172msgid "Comments:"
173173msgstr ""
174174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176176msgid "Emergency Call"
177177msgstr ""
178178
@@ -205,11 +205,24 @@ msgstr "Nu inspreken…"
205205msgid "Speaking..."
206206msgstr "Inspreken…"
207207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208212#: Panel/SearchIndicator.qml:27
209213msgid "Search"
210214msgstr "Zoeken"
211215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213226msgid "Sorry, there is nothing that matches your search."
214227msgstr "Er is helaas niets dat met uw zoekopdracht overeenkomt."
215228
@@ -217,13 +230,7 @@ msgstr "Er is helaas niets dat met uw zoekopdracht overeenkomt."
217230msgid "All"
218231msgstr ""
219232
220−#: Shell.qml:438
233+#: Shell.qml:441
221234#, qt-format
222235msgid "Please enter %1"
223236msgstr ""
224−
225−#~ msgid "Music"
226−#~ msgstr "Muziek"
227−
228−#~ msgid "Videos"
229−#~ msgstr "Video's"
po/pl.po+22−9
@@ -7,7 +7,7 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
1111"PO-Revision-Date: 2013-10-13 13:44+0000\n"
1212"Last-Translator: GTriderXC <gtriderxc@yahoo.com>\n"
1313"Language-Team: Polish <pl@li.org>\n"
@@ -16,8 +16,8 @@ msgstr ""
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
1818"|| n%100>=20) ? 1 : 2;\n"
19−"X-Launchpad-Export-Date: 2013-10-14 05:47+0000\n"
20−"X-Generator: Launchpad (build 16799)\n"
19+"X-Launchpad-Export-Date: 2013-11-19 05:59+0000\n"
20+"X-Generator: Launchpad (build 16831)\n"
2121
2222#: Applications/applications.js:23
2323msgid "Phone"
@@ -87,7 +87,7 @@ msgstr "Wikipedia"
8787msgid "YouTube"
8888msgstr "YouTube"
8989
90−#: Components/EdgeDemoOverlay.qml:149
90+#: Components/EdgeDemoOverlay.qml:151
9191msgid "Skip intro"
9292msgstr "Pomiń intro"
9393
@@ -137,7 +137,7 @@ msgstr ""
137137"Polecenia aktywatorów krawędzi ekranu zostały opanowane<br><br>Dotknij "
138138"gdziekolwiek aby kontynuować"
139139
140−#: Components/PageHeader.qml:341
140+#: Components/PageHeader.qml:345
141141msgid "Recent searches"
142142msgstr "Ostatnie wyszukiwania"
143143
@@ -158,7 +158,7 @@ msgstr[0] "%1 opinia"
158158msgstr[1] "%1 opinie"
159159msgstr[2] "%1 opinii"
160160
161−#: Dash/Apps/AppPreview.qml:126
161+#: Dash/Apps/AppPreview.qml:135
162162msgid "Rate this"
163163msgstr "Oceń to"
164164
@@ -178,7 +178,7 @@ msgstr "Wyślij"
178178msgid "Comments:"
179179msgstr "Komentarze:"
180180
181−#: Greeter/Lockscreen.qml:142
181+#: Greeter/Lockscreen.qml:146
182182msgid "Emergency Call"
183183msgstr "Telefon ratunkowy"
184184
@@ -211,11 +211,24 @@ msgstr "Mów teraz..."
211211msgid "Speaking..."
212212msgstr "Rozpoznanie..."
213213
214+#: Notifications/NotificationMenuItemFactory.qml:89
215+msgid "Show password"
216+msgstr ""
217+
214218#: Panel/SearchIndicator.qml:27
215219msgid "Search"
216220msgstr "Szukaj"
217221
218−#: plugins/Unity/scope.cpp:398
222+#: plugins/Unity/Launcher/launcheritem.cpp:43
223+#: plugins/Unity/Launcher/launcheritem.cpp:73
224+msgid "Lock to Launcher"
225+msgstr ""
226+
227+#: plugins/Unity/Launcher/launcheritem.cpp:73
228+msgid "Unlock from Launcher"
229+msgstr ""
230+
231+#: plugins/Unity/scope.cpp:408
219232msgid "Sorry, there is nothing that matches your search."
220233msgstr "Nie znaleziono pasujących wyników."
221234
@@ -223,7 +236,7 @@ msgstr "Nie znaleziono pasujących wyników."
223236msgid "All"
224237msgstr "Wszystko"
225238
226−#: Shell.qml:438
239+#: Shell.qml:441
227240#, qt-format
228241msgid "Please enter %1"
229242msgstr "Wprowadź %1"
po/pt_BR.po+22−30
@@ -7,7 +7,7 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
1111"PO-Revision-Date: 2013-10-01 13:05+0000\n"
1212"Last-Translator: Rafael Neri <Unknown>\n"
1313"Language-Team: Brazilian Portuguese <pt_BR@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=2; plural=n > 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
18+"X-Launchpad-Export-Date: 2013-11-19 05:59+0000\n"
19+"X-Generator: Launchpad (build 16831)\n"
2020
2121#: Applications/applications.js:23
2222msgid "Phone"
@@ -86,7 +86,7 @@ msgstr "Wikipédia"
8686msgid "YouTube"
8787msgstr "YouTube"
8888
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
9090msgid "Skip intro"
9191msgstr "Pular introdução"
9292
@@ -134,7 +134,7 @@ msgid ""
134134"phone<br><br>Tap anywhere to start"
135135msgstr ""
136136
137−#: Components/PageHeader.qml:341
137+#: Components/PageHeader.qml:345
138138msgid "Recent searches"
139139msgstr "Pesquisas recentes"
140140
@@ -154,7 +154,7 @@ msgid_plural "%1 reviews"
154154msgstr[0] "%1 análise"
155155msgstr[1] "%1 análises"
156156
157−#: Dash/Apps/AppPreview.qml:126
157+#: Dash/Apps/AppPreview.qml:135
158158msgid "Rate this"
159159msgstr "Avaliar isto"
160160
@@ -174,7 +174,7 @@ msgstr "Enviar"
174174msgid "Comments:"
175175msgstr "Comentários:"
176176
177−#: Greeter/Lockscreen.qml:142
177+#: Greeter/Lockscreen.qml:146
178178msgid "Emergency Call"
179179msgstr "Chamada de emergência"
180180
@@ -207,11 +207,24 @@ msgstr "Fale agora..."
207207msgid "Speaking..."
208208msgstr "Falando..."
209209
210+#: Notifications/NotificationMenuItemFactory.qml:89
211+msgid "Show password"
212+msgstr ""
213+
210214#: Panel/SearchIndicator.qml:27
211215msgid "Search"
212216msgstr "Pesquisar"
213217
214−#: plugins/Unity/scope.cpp:398
218+#: plugins/Unity/Launcher/launcheritem.cpp:43
219+#: plugins/Unity/Launcher/launcheritem.cpp:73
220+msgid "Lock to Launcher"
221+msgstr ""
222+
223+#: plugins/Unity/Launcher/launcheritem.cpp:73
224+msgid "Unlock from Launcher"
225+msgstr ""
226+
227+#: plugins/Unity/scope.cpp:408
215228msgid "Sorry, there is nothing that matches your search."
216229msgstr "Desculpe, não há nada que corresponda à sua pesquisa."
217230
@@ -219,28 +232,7 @@ msgstr "Desculpe, não há nada que corresponda à sua pesquisa."
219232msgid "All"
220233msgstr ""
221234
222−#: Shell.qml:438
235+#: Shell.qml:441
223236#, qt-format
224237msgid "Please enter %1"
225238msgstr "Por favor, digite %1"
226−
227−#~ msgid "Music"
228−#~ msgstr "Músicas"
229−
230−#~ msgid "Videos"
231−#~ msgstr "Vídeos"
232−
233−#~ msgid "New Releases"
234−#~ msgstr "Lançamentos"
235−
236−#~ msgid "Recent"
237−#~ msgstr "Recente"
238−
239−#~ msgid "Featured"
240−#~ msgstr "Em destaque"
241−
242−#~ msgid "Top Charting"
243−#~ msgstr "Top gráficos"
244−
245−#~ msgid "Popular Online"
246−#~ msgstr "Popular Online"
po/ro.po+22−15
@@ -7,7 +7,7 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
1111"PO-Revision-Date: 2013-06-27 07:53+0000\n"
1212"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
1313"Language-Team: Romanian <ro@li.org>\n"
@@ -16,8 +16,8 @@ msgstr ""
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=3; plural=(n == 1 ? 0: (((n % 100 > 19) || ((n % 100 "
1818"== 0) && (n != 0))) ? 2: 1));\n"
19−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
20−"X-Generator: Launchpad (build 16799)\n"
19+"X-Launchpad-Export-Date: 2013-11-19 05:59+0000\n"
20+"X-Generator: Launchpad (build 16831)\n"
2121
2222#: Applications/applications.js:23
2323msgid "Phone"
@@ -87,7 +87,7 @@ msgstr ""
8787msgid "YouTube"
8888msgstr ""
8989
90−#: Components/EdgeDemoOverlay.qml:149
90+#: Components/EdgeDemoOverlay.qml:151
9191msgid "Skip intro"
9292msgstr ""
9393
@@ -133,7 +133,7 @@ msgid ""
133133"phone<br><br>Tap anywhere to start"
134134msgstr ""
135135
136−#: Components/PageHeader.qml:341
136+#: Components/PageHeader.qml:345
137137msgid "Recent searches"
138138msgstr "Căutări recente"
139139
@@ -153,7 +153,7 @@ msgid_plural "%1 reviews"
153153msgstr[0] ""
154154msgstr[1] ""
155155
156−#: Dash/Apps/AppPreview.qml:126
156+#: Dash/Apps/AppPreview.qml:135
157157msgid "Rate this"
158158msgstr ""
159159
@@ -173,7 +173,7 @@ msgstr ""
173173msgid "Comments:"
174174msgstr ""
175175
176−#: Greeter/Lockscreen.qml:142
176+#: Greeter/Lockscreen.qml:146
177177msgid "Emergency Call"
178178msgstr ""
179179
@@ -206,11 +206,24 @@ msgstr "Vorbiți acum..."
206206msgid "Speaking..."
207207msgstr "Vorbire..."
208208
209+#: Notifications/NotificationMenuItemFactory.qml:89
210+msgid "Show password"
211+msgstr ""
212+
209213#: Panel/SearchIndicator.qml:27
210214msgid "Search"
211215msgstr "Căutare"
212216
213−#: plugins/Unity/scope.cpp:398
217+#: plugins/Unity/Launcher/launcheritem.cpp:43
218+#: plugins/Unity/Launcher/launcheritem.cpp:73
219+msgid "Lock to Launcher"
220+msgstr ""
221+
222+#: plugins/Unity/Launcher/launcheritem.cpp:73
223+msgid "Unlock from Launcher"
224+msgstr ""
225+
226+#: plugins/Unity/scope.cpp:408
214227msgid "Sorry, there is nothing that matches your search."
215228msgstr ""
216229"Ne pare rău, nu este nimic care se potrivește căutării dumneavoastră."
@@ -219,13 +232,7 @@ msgstr ""
219232msgid "All"
220233msgstr ""
221234
222−#: Shell.qml:438
235+#: Shell.qml:441
223236#, qt-format
224237msgid "Please enter %1"
225238msgstr ""
226−
227−#~ msgid "Music"
228−#~ msgstr "Muzică"
229−
230−#~ msgid "Videos"
231−#~ msgstr "Video"
po/ru.po+22−30
@@ -7,7 +7,7 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
1111"PO-Revision-Date: 2013-10-01 05:55+0000\n"
1212"Last-Translator: Zonov Roman <Unknown>\n"
1313"Language-Team: Russian <ru@li.org>\n"
@@ -16,8 +16,8 @@ msgstr ""
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
1818"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
19−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
20−"X-Generator: Launchpad (build 16799)\n"
19+"X-Launchpad-Export-Date: 2013-11-19 05:59+0000\n"
20+"X-Generator: Launchpad (build 16831)\n"
2121
2222#: Applications/applications.js:23
2323msgid "Phone"
@@ -87,7 +87,7 @@ msgstr "Википедия"
8787msgid "YouTube"
8888msgstr "YouTube"
8989
90−#: Components/EdgeDemoOverlay.qml:149
90+#: Components/EdgeDemoOverlay.qml:151
9191msgid "Skip intro"
9292msgstr "Пропустить обучение"
9393
@@ -138,7 +138,7 @@ msgid ""
138138"phone<br><br>Tap anywhere to start"
139139msgstr ""
140140
141−#: Components/PageHeader.qml:341
141+#: Components/PageHeader.qml:345
142142msgid "Recent searches"
143143msgstr "Последние поисковые запросы"
144144
@@ -157,7 +157,7 @@ msgid "%1 review"
157157msgid_plural "%1 reviews"
158158msgstr[0] "%1 отзыв"
159159
160−#: Dash/Apps/AppPreview.qml:126
160+#: Dash/Apps/AppPreview.qml:135
161161msgid "Rate this"
162162msgstr "Оцените это"
163163
@@ -177,7 +177,7 @@ msgstr "Отправить"
177177msgid "Comments:"
178178msgstr "Комментарии:"
179179
180−#: Greeter/Lockscreen.qml:142
180+#: Greeter/Lockscreen.qml:146
181181msgid "Emergency Call"
182182msgstr "Экстренный вызов"
183183
@@ -210,11 +210,24 @@ msgstr "Говорите..."
210210msgid "Speaking..."
211211msgstr "Говорите..."
212212
213+#: Notifications/NotificationMenuItemFactory.qml:89
214+msgid "Show password"
215+msgstr ""
216+
213217#: Panel/SearchIndicator.qml:27
214218msgid "Search"
215219msgstr "Поиск"
216220
217−#: plugins/Unity/scope.cpp:398
221+#: plugins/Unity/Launcher/launcheritem.cpp:43
222+#: plugins/Unity/Launcher/launcheritem.cpp:73
223+msgid "Lock to Launcher"
224+msgstr ""
225+
226+#: plugins/Unity/Launcher/launcheritem.cpp:73
227+msgid "Unlock from Launcher"
228+msgstr ""
229+
230+#: plugins/Unity/scope.cpp:408
218231msgid "Sorry, there is nothing that matches your search."
219232msgstr "Извините, поиск не дал результатов."
220233
@@ -222,28 +235,7 @@ msgstr "Извините, поиск не дал результатов."
222235msgid "All"
223236msgstr ""
224237
225−#: Shell.qml:438
238+#: Shell.qml:441
226239#, qt-format
227240msgid "Please enter %1"
228241msgstr "Пожалуйста, введите %1"
229−
230−#~ msgid "New Releases"
231−#~ msgstr "Новые релизы"
232−
233−#~ msgid "Music"
234−#~ msgstr "Музыка"
235−
236−#~ msgid "Videos"
237−#~ msgstr "Видео"
238−
239−#~ msgid "Recent"
240−#~ msgstr "Недавние"
241−
242−#~ msgid "Top Charting"
243−#~ msgstr "Наиболее популярное"
244−
245−#~ msgid "Popular Online"
246−#~ msgstr "Популярное в Интернете"
247−
248−#~ msgid "Featured"
249−#~ msgstr "Рекомендованное"
po/shn.po+22−9
@@ -7,7 +7,7 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity8\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
1111"PO-Revision-Date: 2013-10-07 11:46+0000\n"
1212"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1313"Language-Team: Shan <shn@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=2; plural=(n == 1) ? 0 : 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
18+"X-Launchpad-Export-Date: 2013-11-19 05:59+0000\n"
19+"X-Generator: Launchpad (build 16831)\n"
2020
2121#: Applications/applications.js:23
2222msgid "Phone"
@@ -86,7 +86,7 @@ msgstr ""
8686msgid "YouTube"
8787msgstr ""
8888
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
9090msgid "Skip intro"
9191msgstr ""
9292
@@ -132,7 +132,7 @@ msgid ""
132132"phone<br><br>Tap anywhere to start"
133133msgstr ""
134134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136136msgid "Recent searches"
137137msgstr ""
138138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152152msgstr[0] ""
153153msgstr[1] ""
154154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156156msgid "Rate this"
157157msgstr ""
158158
@@ -172,7 +172,7 @@ msgstr ""
172172msgid "Comments:"
173173msgstr ""
174174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176176msgid "Emergency Call"
177177msgstr ""
178178
@@ -205,11 +205,24 @@ msgstr ""
205205msgid "Speaking..."
206206msgstr ""
207207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208212#: Panel/SearchIndicator.qml:27
209213msgid "Search"
210214msgstr ""
211215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213226msgid "Sorry, there is nothing that matches your search."
214227msgstr ""
215228
@@ -217,7 +230,7 @@ msgstr ""
217230msgid "All"
218231msgstr ""
219232
220−#: Shell.qml:438
233+#: Shell.qml:441
221234#, qt-format
222235msgid "Please enter %1"
223236msgstr ""
po/si.po+22−9
@@ -7,7 +7,7 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
1111"PO-Revision-Date: 2013-06-26 22:36+0000\n"
1212"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1313"Language-Team: Sinhalese <si@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
18+"X-Launchpad-Export-Date: 2013-11-19 05:59+0000\n"
19+"X-Generator: Launchpad (build 16831)\n"
2020
2121#: Applications/applications.js:23
2222msgid "Phone"
@@ -86,7 +86,7 @@ msgstr ""
8686msgid "YouTube"
8787msgstr ""
8888
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
9090msgid "Skip intro"
9191msgstr ""
9292
@@ -132,7 +132,7 @@ msgid ""
132132"phone<br><br>Tap anywhere to start"
133133msgstr ""
134134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136136msgid "Recent searches"
137137msgstr ""
138138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152152msgstr[0] ""
153153msgstr[1] ""
154154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156156msgid "Rate this"
157157msgstr ""
158158
@@ -172,7 +172,7 @@ msgstr ""
172172msgid "Comments:"
173173msgstr ""
174174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176176msgid "Emergency Call"
177177msgstr ""
178178
@@ -205,11 +205,24 @@ msgstr ""
205205msgid "Speaking..."
206206msgstr ""
207207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208212#: Panel/SearchIndicator.qml:27
209213msgid "Search"
210214msgstr ""
211215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213226msgid "Sorry, there is nothing that matches your search."
214227msgstr ""
215228
@@ -217,7 +230,7 @@ msgstr ""
217230msgid "All"
218231msgstr ""
219232
220−#: Shell.qml:438
233+#: Shell.qml:441
221234#, qt-format
222235msgid "Please enter %1"
223236msgstr ""
po/sl.po+22−30
@@ -7,7 +7,7 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
1111"PO-Revision-Date: 2013-10-02 10:55+0000\n"
1212"Last-Translator: Damir Jerovšek <Unknown>\n"
1313"Language-Team: Slovenian <sl@li.org>\n"
@@ -16,8 +16,8 @@ msgstr ""
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=4; plural=(n%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || "
1818"n%100==4 ? 3 : 0);\n"
19−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
20−"X-Generator: Launchpad (build 16799)\n"
19+"X-Launchpad-Export-Date: 2013-11-19 05:59+0000\n"
20+"X-Generator: Launchpad (build 16831)\n"
2121
2222#: Applications/applications.js:23
2323msgid "Phone"
@@ -87,7 +87,7 @@ msgstr "Wikipedija"
8787msgid "YouTube"
8888msgstr "YouTube"
8989
90−#: Components/EdgeDemoOverlay.qml:149
90+#: Components/EdgeDemoOverlay.qml:151
9191msgid "Skip intro"
9292msgstr "Preskoči uvod"
9393
@@ -137,7 +137,7 @@ msgstr ""
137137"Sedaj ste osvojili poteze robov ter lahko začnete uporabljati "
138138"telefon<br><br>Tapnite kjerkoli na začetek"
139139
140−#: Components/PageHeader.qml:341
140+#: Components/PageHeader.qml:345
141141msgid "Recent searches"
142142msgstr "Nedavna iskanja"
143143
@@ -159,7 +159,7 @@ msgstr[1] "%1 ocena"
159159msgstr[2] "%1 oceni"
160160msgstr[3] "%1 ocene"
161161
162−#: Dash/Apps/AppPreview.qml:126
162+#: Dash/Apps/AppPreview.qml:135
163163msgid "Rate this"
164164msgstr "Ocenite"
165165
@@ -179,7 +179,7 @@ msgstr "Pošlji"
179179msgid "Comments:"
180180msgstr "Opombe:"
181181
182−#: Greeter/Lockscreen.qml:142
182+#: Greeter/Lockscreen.qml:146
183183msgid "Emergency Call"
184184msgstr "Klic v sili"
185185
@@ -212,11 +212,24 @@ msgstr "Govorite zdaj ..."
212212msgid "Speaking..."
213213msgstr "Govorjenje ..."
214214
215+#: Notifications/NotificationMenuItemFactory.qml:89
216+msgid "Show password"
217+msgstr ""
218+
215219#: Panel/SearchIndicator.qml:27
216220msgid "Search"
217221msgstr "Iskanje"
218222
219−#: plugins/Unity/scope.cpp:398
223+#: plugins/Unity/Launcher/launcheritem.cpp:43
224+#: plugins/Unity/Launcher/launcheritem.cpp:73
225+msgid "Lock to Launcher"
226+msgstr ""
227+
228+#: plugins/Unity/Launcher/launcheritem.cpp:73
229+msgid "Unlock from Launcher"
230+msgstr ""
231+
232+#: plugins/Unity/scope.cpp:408
220233msgid "Sorry, there is nothing that matches your search."
221234msgstr "Nič se ne ujema z vašim iskalnim nizom."
222235
@@ -224,28 +237,7 @@ msgstr "Nič se ne ujema z vašim iskalnim nizom."
224237msgid "All"
225238msgstr "Vse"
226239
227−#: Shell.qml:438
240+#: Shell.qml:441
228241#, qt-format
229242msgid "Please enter %1"
230243msgstr "Vnesite %1"
231−
232−#~ msgid "Music"
233−#~ msgstr "Glasba"
234−
235−#~ msgid "Videos"
236−#~ msgstr "Videi"
237−
238−#~ msgid "New Releases"
239−#~ msgstr "Nove izdaje"
240−
241−#~ msgid "Top Charting"
242−#~ msgstr "Najvišje na lestvici"
243−
244−#~ msgid "Featured"
245−#~ msgstr "Predstavljeno"
246−
247−#~ msgid "Recent"
248−#~ msgstr "Nedavno"
249−
250−#~ msgid "Popular Online"
251−#~ msgstr "Priljubljeno na spletu"
po/sr.po+22−15
@@ -7,7 +7,7 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
1111"PO-Revision-Date: 2013-06-27 09:19+0000\n"
1212"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
1313"Language-Team: Serbian <sr@li.org>\n"
@@ -16,8 +16,8 @@ msgstr ""
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
1818"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
19−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
20−"X-Generator: Launchpad (build 16799)\n"
19+"X-Launchpad-Export-Date: 2013-11-19 05:59+0000\n"
20+"X-Generator: Launchpad (build 16831)\n"
2121
2222#: Applications/applications.js:23
2323msgid "Phone"
@@ -87,7 +87,7 @@ msgstr ""
8787msgid "YouTube"
8888msgstr ""
8989
90−#: Components/EdgeDemoOverlay.qml:149
90+#: Components/EdgeDemoOverlay.qml:151
9191msgid "Skip intro"
9292msgstr ""
9393
@@ -133,7 +133,7 @@ msgid ""
133133"phone<br><br>Tap anywhere to start"
134134msgstr ""
135135
136−#: Components/PageHeader.qml:341
136+#: Components/PageHeader.qml:345
137137msgid "Recent searches"
138138msgstr "Скорашње претраге"
139139
@@ -153,7 +153,7 @@ msgid_plural "%1 reviews"
153153msgstr[0] ""
154154msgstr[1] ""
155155
156−#: Dash/Apps/AppPreview.qml:126
156+#: Dash/Apps/AppPreview.qml:135
157157msgid "Rate this"
158158msgstr ""
159159
@@ -173,7 +173,7 @@ msgstr ""
173173msgid "Comments:"
174174msgstr ""
175175
176−#: Greeter/Lockscreen.qml:142
176+#: Greeter/Lockscreen.qml:146
177177msgid "Emergency Call"
178178msgstr ""
179179
@@ -206,11 +206,24 @@ msgstr "Изговорите сада..."
206206msgid "Speaking..."
207207msgstr "Говор..."
208208
209+#: Notifications/NotificationMenuItemFactory.qml:89
210+msgid "Show password"
211+msgstr ""
212+
209213#: Panel/SearchIndicator.qml:27
210214msgid "Search"
211215msgstr "Претрага"
212216
213−#: plugins/Unity/scope.cpp:398
217+#: plugins/Unity/Launcher/launcheritem.cpp:43
218+#: plugins/Unity/Launcher/launcheritem.cpp:73
219+msgid "Lock to Launcher"
220+msgstr ""
221+
222+#: plugins/Unity/Launcher/launcheritem.cpp:73
223+msgid "Unlock from Launcher"
224+msgstr ""
225+
226+#: plugins/Unity/scope.cpp:408
214227msgid "Sorry, there is nothing that matches your search."
215228msgstr "Нажалост, претрага није наишла на икакво подударање."
216229
@@ -218,13 +231,7 @@ msgstr "Нажалост, претрага није наишла на икакв
218231msgid "All"
219232msgstr ""
220233
221−#: Shell.qml:438
234+#: Shell.qml:441
222235#, qt-format
223236msgid "Please enter %1"
224237msgstr ""
225−
226−#~ msgid "Music"
227−#~ msgstr "Музика"
228−
229−#~ msgid "Videos"
230−#~ msgstr "Видео"
po/sv.po+22−9
@@ -7,7 +7,7 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
1111"PO-Revision-Date: 2013-06-26 22:36+0000\n"
1212"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1313"Language-Team: Swedish <sv@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
18+"X-Launchpad-Export-Date: 2013-11-19 05:59+0000\n"
19+"X-Generator: Launchpad (build 16831)\n"
2020
2121#: Applications/applications.js:23
2222msgid "Phone"
@@ -86,7 +86,7 @@ msgstr ""
8686msgid "YouTube"
8787msgstr ""
8888
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
9090msgid "Skip intro"
9191msgstr ""
9292
@@ -132,7 +132,7 @@ msgid ""
132132"phone<br><br>Tap anywhere to start"
133133msgstr ""
134134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136136msgid "Recent searches"
137137msgstr ""
138138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152152msgstr[0] ""
153153msgstr[1] ""
154154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156156msgid "Rate this"
157157msgstr ""
158158
@@ -172,7 +172,7 @@ msgstr ""
172172msgid "Comments:"
173173msgstr ""
174174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176176msgid "Emergency Call"
177177msgstr ""
178178
@@ -205,11 +205,24 @@ msgstr ""
205205msgid "Speaking..."
206206msgstr ""
207207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208212#: Panel/SearchIndicator.qml:27
209213msgid "Search"
210214msgstr ""
211215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213226msgid "Sorry, there is nothing that matches your search."
214227msgstr ""
215228
@@ -217,7 +230,7 @@ msgstr ""
217230msgid "All"
218231msgstr ""
219232
220−#: Shell.qml:438
233+#: Shell.qml:441
221234#, qt-format
222235msgid "Please enter %1"
223236msgstr ""
po/ta.po+22−9
@@ -7,7 +7,7 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity8\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
1111"PO-Revision-Date: 2013-10-24 11:36+0000\n"
1212"Last-Translator: Thangamani Arun - தங்கமணி அருண் <thangam.arunx@gmail.com>\n"
1313"Language-Team: Ubuntu Tamil Team/Free Tamil Computing/Thamizha\n"
@@ -15,8 +15,8 @@ msgstr ""
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-25 06:05+0000\n"
19−"X-Generator: Launchpad (build 16810)\n"
18+"X-Launchpad-Export-Date: 2013-11-19 05:59+0000\n"
19+"X-Generator: Launchpad (build 16831)\n"
2020"Language: ta\n"
2121
2222#: Applications/applications.js:23
@@ -87,7 +87,7 @@ msgstr "விக்கிப்பீடியா"
8787msgid "YouTube"
8888msgstr "யூட்யுப்"
8989
90−#: Components/EdgeDemoOverlay.qml:149
90+#: Components/EdgeDemoOverlay.qml:151
9191msgid "Skip intro"
9292msgstr "அறிமுகத்தை தவிர்"
9393
@@ -138,7 +138,7 @@ msgstr ""
138138"பயன்படுத்த தொடங்கவும் <br> <br>தட்டுவதன் மூலம் எங்க வேண்டுமானாலும் "
139139"தொடங்கலாம்."
140140
141−#: Components/PageHeader.qml:341
141+#: Components/PageHeader.qml:345
142142msgid "Recent searches"
143143msgstr "கடையாக தேடப்பட்டவைகள்"
144144
@@ -158,7 +158,7 @@ msgid_plural "%1 reviews"
158158msgstr[0] "%1 பரிசீலனை"
159159msgstr[1] "%1 பரிசீலனைகள்"
160160
161−#: Dash/Apps/AppPreview.qml:126
161+#: Dash/Apps/AppPreview.qml:135
162162msgid "Rate this"
163163msgstr "இதை மதிப்பிடு"
164164
@@ -178,7 +178,7 @@ msgstr "அனுப்பு"
178178msgid "Comments:"
179179msgstr "கருத்துகள்:"
180180
181−#: Greeter/Lockscreen.qml:142
181+#: Greeter/Lockscreen.qml:146
182182msgid "Emergency Call"
183183msgstr "அவசர அழைப்பு"
184184
@@ -211,11 +211,24 @@ msgstr "இப்பொது பேசு..."
211211msgid "Speaking..."
212212msgstr "பேசுகிறது..."
213213
214+#: Notifications/NotificationMenuItemFactory.qml:89
215+msgid "Show password"
216+msgstr ""
217+
214218#: Panel/SearchIndicator.qml:27
215219msgid "Search"
216220msgstr "தெடு"
217221
218−#: plugins/Unity/scope.cpp:398
222+#: plugins/Unity/Launcher/launcheritem.cpp:43
223+#: plugins/Unity/Launcher/launcheritem.cpp:73
224+msgid "Lock to Launcher"
225+msgstr ""
226+
227+#: plugins/Unity/Launcher/launcheritem.cpp:73
228+msgid "Unlock from Launcher"
229+msgstr ""
230+
231+#: plugins/Unity/scope.cpp:408
219232msgid "Sorry, there is nothing that matches your search."
220233msgstr "மன்னிக்கவும், உங்களுடைய தேடலுக்கு தகுந்த பொருத்தம் கிடைக்கவில்லை."
221234
@@ -223,7 +236,7 @@ msgstr "மன்னிக்கவும், உங்களுடைய தே
223236msgid "All"
224237msgstr "அனைத்தும்"
225238
226−#: Shell.qml:438
239+#: Shell.qml:441
227240#, qt-format
228241msgid "Please enter %1"
229242msgstr "தயவுச்செய்து %1 உள்ளிடு"
po/te.po+22−12
@@ -7,7 +7,7 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
1111"PO-Revision-Date: 2013-06-27 09:57+0000\n"
1212"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
1313"Language-Team: Telugu <te@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
18+"X-Launchpad-Export-Date: 2013-11-19 05:59+0000\n"
19+"X-Generator: Launchpad (build 16831)\n"
2020
2121#: Applications/applications.js:23
2222msgid "Phone"
@@ -86,7 +86,7 @@ msgstr ""
8686msgid "YouTube"
8787msgstr ""
8888
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
9090msgid "Skip intro"
9191msgstr ""
9292
@@ -132,7 +132,7 @@ msgid ""
132132"phone<br><br>Tap anywhere to start"
133133msgstr ""
134134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136136msgid "Recent searches"
137137msgstr ""
138138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152152msgstr[0] ""
153153msgstr[1] ""
154154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156156msgid "Rate this"
157157msgstr ""
158158
@@ -172,7 +172,7 @@ msgstr ""
172172msgid "Comments:"
173173msgstr ""
174174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176176msgid "Emergency Call"
177177msgstr ""
178178
@@ -205,11 +205,24 @@ msgstr ""
205205msgid "Speaking..."
206206msgstr ""
207207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208212#: Panel/SearchIndicator.qml:27
209213msgid "Search"
210214msgstr ""
211215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213226msgid "Sorry, there is nothing that matches your search."
214227msgstr ""
215228
@@ -217,10 +230,7 @@ msgstr ""
217230msgid "All"
218231msgstr ""
219232
220−#: Shell.qml:438
233+#: Shell.qml:441
221234#, qt-format
222235msgid "Please enter %1"
223236msgstr ""
224−
225−#~ msgid "Music"
226−#~ msgstr "సంగీతం"
po/tr.po+22−30
@@ -7,7 +7,7 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
1111"PO-Revision-Date: 2013-10-01 13:21+0000\n"
1212"Last-Translator: Volkan Gezer <Unknown>\n"
1313"Language-Team: Turkish <tr@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
18+"X-Launchpad-Export-Date: 2013-11-19 05:59+0000\n"
19+"X-Generator: Launchpad (build 16831)\n"
2020
2121#: Applications/applications.js:23
2222msgid "Phone"
@@ -86,7 +86,7 @@ msgstr "Vikipedi"
8686msgid "YouTube"
8787msgstr "YouTube"
8888
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
9090msgid "Skip intro"
9191msgstr "İntro'yu geç"
9292
@@ -133,7 +133,7 @@ msgid ""
133133"phone<br><br>Tap anywhere to start"
134134msgstr ""
135135
136−#: Components/PageHeader.qml:341
136+#: Components/PageHeader.qml:345
137137msgid "Recent searches"
138138msgstr "Son Arananlar"
139139
@@ -153,7 +153,7 @@ msgid_plural "%1 reviews"
153153msgstr[0] "%1 inceleme"
154154msgstr[1] "%1 inceleme"
155155
156−#: Dash/Apps/AppPreview.qml:126
156+#: Dash/Apps/AppPreview.qml:135
157157msgid "Rate this"
158158msgstr "Oyla"
159159
@@ -173,7 +173,7 @@ msgstr "Gönder"
173173msgid "Comments:"
174174msgstr "Yorumlar:"
175175
176−#: Greeter/Lockscreen.qml:142
176+#: Greeter/Lockscreen.qml:146
177177msgid "Emergency Call"
178178msgstr "Acil Arama"
179179
@@ -206,11 +206,24 @@ msgstr "Şimdi Konuşun..."
206206msgid "Speaking..."
207207msgstr "Konuşuyor..."
208208
209+#: Notifications/NotificationMenuItemFactory.qml:89
210+msgid "Show password"
211+msgstr ""
212+
209213#: Panel/SearchIndicator.qml:27
210214msgid "Search"
211215msgstr "Ara"
212216
213−#: plugins/Unity/scope.cpp:398
217+#: plugins/Unity/Launcher/launcheritem.cpp:43
218+#: plugins/Unity/Launcher/launcheritem.cpp:73
219+msgid "Lock to Launcher"
220+msgstr ""
221+
222+#: plugins/Unity/Launcher/launcheritem.cpp:73
223+msgid "Unlock from Launcher"
224+msgstr ""
225+
226+#: plugins/Unity/scope.cpp:408
214227msgid "Sorry, there is nothing that matches your search."
215228msgstr "Üzgünüz, aramanızla eşleşen hiçbir şey yok."
216229
@@ -218,28 +231,7 @@ msgstr "Üzgünüz, aramanızla eşleşen hiçbir şey yok."
218231msgid "All"
219232msgstr ""
220233
221−#: Shell.qml:438
234+#: Shell.qml:441
222235#, qt-format
223236msgid "Please enter %1"
224237msgstr "Lütfen %1 girin"
225−
226−#~ msgid "Featured"
227−#~ msgstr "Öne Çıkanlar"
228−
229−#~ msgid "Recent"
230−#~ msgstr "En Son"
231−
232−#~ msgid "Music"
233−#~ msgstr "Müzik"
234−
235−#~ msgid "Popular Online"
236−#~ msgstr "Genellikle Çevrimiçi"
237−
238−#~ msgid "Videos"
239−#~ msgstr "Videolar"
240−
241−#~ msgid "Top Charting"
242−#~ msgstr "En Çok Beğenilenler"
243−
244−#~ msgid "New Releases"
245−#~ msgstr "Yeni Sürümler"
po/ug.po+22−24
@@ -7,7 +7,7 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
1111"PO-Revision-Date: 2013-10-09 22:38+0000\n"
1212"Last-Translator: Gheyret T.Kenji <Unknown>\n"
1313"Language-Team: Uyghur <ug@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
18+"X-Launchpad-Export-Date: 2013-11-19 05:59+0000\n"
19+"X-Generator: Launchpad (build 16831)\n"
2020
2121#: Applications/applications.js:23
2222msgid "Phone"
@@ -86,7 +86,7 @@ msgstr "ۋىكىپېدىيە"
8686msgid "YouTube"
8787msgstr "YouTube"
8888
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
9090msgid "Skip intro"
9191msgstr ""
9292
@@ -132,7 +132,7 @@ msgid ""
132132"phone<br><br>Tap anywhere to start"
133133msgstr ""
134134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136136msgid "Recent searches"
137137msgstr "يېقىنقى ئىزدەشلەر"
138138
@@ -151,7 +151,7 @@ msgid "%1 review"
151151msgid_plural "%1 reviews"
152152msgstr[0] "%1 باھا"
153153
154−#: Dash/Apps/AppPreview.qml:126
154+#: Dash/Apps/AppPreview.qml:135
155155msgid "Rate this"
156156msgstr ""
157157
@@ -171,7 +171,7 @@ msgstr "ئەۋەت"
171171msgid "Comments:"
172172msgstr "ئىنكاس:"
173173
174−#: Greeter/Lockscreen.qml:142
174+#: Greeter/Lockscreen.qml:146
175175msgid "Emergency Call"
176176msgstr ""
177177
@@ -204,11 +204,24 @@ msgstr "ئەمدى سۆزلەڭ…"
204204msgid "Speaking..."
205205msgstr "سۆزلەۋاتىسىز…"
206206
207+#: Notifications/NotificationMenuItemFactory.qml:89
208+msgid "Show password"
209+msgstr ""
210+
207211#: Panel/SearchIndicator.qml:27
208212msgid "Search"
209213msgstr "ئىزدە"
210214
211−#: plugins/Unity/scope.cpp:398
215+#: plugins/Unity/Launcher/launcheritem.cpp:43
216+#: plugins/Unity/Launcher/launcheritem.cpp:73
217+msgid "Lock to Launcher"
218+msgstr ""
219+
220+#: plugins/Unity/Launcher/launcheritem.cpp:73
221+msgid "Unlock from Launcher"
222+msgstr ""
223+
224+#: plugins/Unity/scope.cpp:408
212225msgid "Sorry, there is nothing that matches your search."
213226msgstr "كەچۈرۈڭ، ئىزدىگىنىڭىزگە ماس نەتىجە تېپىلمىدى."
214227
@@ -216,22 +229,7 @@ msgstr "كەچۈرۈڭ، ئىزدىگىنىڭىزگە ماس نەتىجە تېپ
216229msgid "All"
217230msgstr "ھەممىسى"
218231
219−#: Shell.qml:438
232+#: Shell.qml:441
220233#, qt-format
221234msgid "Please enter %1"
222235msgstr "%1 نى كىرگۈزۈڭ"
223−
224−#~ msgid "Featured"
225−#~ msgstr "داڭلىق"
226−
227−#~ msgid "Recent"
228−#~ msgstr "يېقىنقى"
229−
230−#~ msgid "New Releases"
231−#~ msgstr "يېڭى ئېلان قىلىنغانلىرى"
232−
233−#~ msgid "Music"
234−#~ msgstr "مۇزىكا"
235−
236−#~ msgid "Videos"
237−#~ msgstr "سىنلار"
po/uk.po+24−11
@@ -7,17 +7,17 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
11−"PO-Revision-Date: 2013-10-19 16:44+0000\n"
12−"Last-Translator: Yuri Chornoivan <yurchor@gmail.com>\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
11+"PO-Revision-Date: 2013-11-23 12:37+0000\n"
12+"Last-Translator: Ignat Kizenko <Unknown>\n"
1313"Language-Team: Ukrainian <uk@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
1818"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
19−"X-Launchpad-Export-Date: 2013-10-20 05:20+0000\n"
20−"X-Generator: Launchpad (build 16807)\n"
19+"X-Launchpad-Export-Date: 2013-11-24 05:50+0000\n"
20+"X-Generator: Launchpad (build 16831)\n"
2121
2222#: Applications/applications.js:23
2323msgid "Phone"
@@ -87,7 +87,7 @@ msgstr "Вікіпедія"
8787msgid "YouTube"
8888msgstr "YouTube"
8989
90−#: Components/EdgeDemoOverlay.qml:149
90+#: Components/EdgeDemoOverlay.qml:151
9191msgid "Skip intro"
9292msgstr "Пропустити вступ"
9393
@@ -138,7 +138,7 @@ msgstr ""
138138"Тепер жести налаштовано, ви можете почати користуватися "
139139"телефоном.<br><br>Натисніть у довільному місці екрана."
140140
141−#: Components/PageHeader.qml:341
141+#: Components/PageHeader.qml:345
142142msgid "Recent searches"
143143msgstr "Нещодавні пошуки"
144144
@@ -159,7 +159,7 @@ msgstr[0] "%1 рецензія"
159159msgstr[1] "%1 рецензії"
160160msgstr[2] "%1 рецензій"
161161
162−#: Dash/Apps/AppPreview.qml:126
162+#: Dash/Apps/AppPreview.qml:135
163163msgid "Rate this"
164164msgstr "Оцінити"
165165
@@ -179,7 +179,7 @@ msgstr "Надіслати"
179179msgid "Comments:"
180180msgstr "Коментарі:"
181181
182−#: Greeter/Lockscreen.qml:142
182+#: Greeter/Lockscreen.qml:146
183183msgid "Emergency Call"
184184msgstr "Терміновий виклик"
185185
@@ -212,11 +212,24 @@ msgstr "Можна говорити…"
212212msgid "Speaking..."
213213msgstr "Мовлення…"
214214
215+#: Notifications/NotificationMenuItemFactory.qml:89
216+msgid "Show password"
217+msgstr "Показати пароль"
218+
215219#: Panel/SearchIndicator.qml:27
216220msgid "Search"
217221msgstr "Пошук"
218222
219−#: plugins/Unity/scope.cpp:398
223+#: plugins/Unity/Launcher/launcheritem.cpp:43
224+#: plugins/Unity/Launcher/launcheritem.cpp:73
225+msgid "Lock to Launcher"
226+msgstr "Зафіксувати на панелі запуску"
227+
228+#: plugins/Unity/Launcher/launcheritem.cpp:73
229+msgid "Unlock from Launcher"
230+msgstr "Від’єднати від панелі запуску"
231+
232+#: plugins/Unity/scope.cpp:408
220233msgid "Sorry, there is nothing that matches your search."
221234msgstr "Вибачте, для вказаних вами ключових слів нічого не знайдено."
222235
@@ -224,7 +237,7 @@ msgstr "Вибачте, для вказаних вами ключових слі
224237msgid "All"
225238msgstr "Усе"
226239
227−#: Shell.qml:438
240+#: Shell.qml:441
228241#, qt-format
229242msgid "Please enter %1"
230243msgstr "Будь ласка, введіть %1"
po/unity8.pot+20−7
@@ -8,7 +8,7 @@ msgid ""
88msgstr ""
99"Project-Id-Version: unity8\n"
1010"Report-Msgid-Bugs-To: \n"
11−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
11+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
1212"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
1313"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1414"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -86,7 +86,7 @@ msgstr ""
8686msgid "YouTube"
8787msgstr ""
8888
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
9090msgid "Skip intro"
9191msgstr ""
9292
@@ -132,7 +132,7 @@ msgid ""
132132"phone<br><br>Tap anywhere to start"
133133msgstr ""
134134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136136msgid "Recent searches"
137137msgstr ""
138138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152152msgstr[0] ""
153153msgstr[1] ""
154154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156156msgid "Rate this"
157157msgstr ""
158158
@@ -172,7 +172,7 @@ msgstr ""
172172msgid "Comments:"
173173msgstr ""
174174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176176msgid "Emergency Call"
177177msgstr ""
178178
@@ -205,11 +205,24 @@ msgstr ""
205205msgid "Speaking..."
206206msgstr ""
207207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208212#: Panel/SearchIndicator.qml:27
209213msgid "Search"
210214msgstr ""
211215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213226msgid "Sorry, there is nothing that matches your search."
214227msgstr ""
215228
@@ -217,7 +230,7 @@ msgstr ""
217230msgid "All"
218231msgstr ""
219232
220−#: Shell.qml:438
233+#: Shell.qml:441
221234#, qt-format
222235msgid "Please enter %1"
223236msgstr ""
po/xh.po+22−9
@@ -7,7 +7,7 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity8\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
1111"PO-Revision-Date: 2013-09-28 13:20+0000\n"
1212"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1313"Language-Team: Xhosa <xh@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
18+"X-Launchpad-Export-Date: 2013-11-19 05:59+0000\n"
19+"X-Generator: Launchpad (build 16831)\n"
2020
2121#: Applications/applications.js:23
2222msgid "Phone"
@@ -86,7 +86,7 @@ msgstr ""
8686msgid "YouTube"
8787msgstr ""
8888
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
9090msgid "Skip intro"
9191msgstr ""
9292
@@ -132,7 +132,7 @@ msgid ""
132132"phone<br><br>Tap anywhere to start"
133133msgstr ""
134134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136136msgid "Recent searches"
137137msgstr ""
138138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152152msgstr[0] ""
153153msgstr[1] ""
154154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156156msgid "Rate this"
157157msgstr ""
158158
@@ -172,7 +172,7 @@ msgstr ""
172172msgid "Comments:"
173173msgstr ""
174174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176176msgid "Emergency Call"
177177msgstr ""
178178
@@ -205,11 +205,24 @@ msgstr ""
205205msgid "Speaking..."
206206msgstr ""
207207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208212#: Panel/SearchIndicator.qml:27
209213msgid "Search"
210214msgstr ""
211215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213226msgid "Sorry, there is nothing that matches your search."
214227msgstr ""
215228
@@ -217,7 +230,7 @@ msgstr ""
217230msgid "All"
218231msgstr ""
219232
220−#: Shell.qml:438
233+#: Shell.qml:441
221234#, qt-format
222235msgid "Please enter %1"
223236msgstr ""
po/zh_CN.po+22−30
@@ -7,7 +7,7 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
1111"PO-Revision-Date: 2013-10-09 13:51+0000\n"
1212"Last-Translator: Aron Xu <Unknown>\n"
1313"Language-Team: Chinese (Simplified) <zh_CN@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
18+"X-Launchpad-Export-Date: 2013-11-19 05:59+0000\n"
19+"X-Generator: Launchpad (build 16831)\n"
2020
2121#: Applications/applications.js:23
2222msgid "Phone"
@@ -86,7 +86,7 @@ msgstr "维基百科"
8686msgid "YouTube"
8787msgstr "YouTube"
8888
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
9090msgid "Skip intro"
9191msgstr ""
9292
@@ -132,7 +132,7 @@ msgid ""
132132"phone<br><br>Tap anywhere to start"
133133msgstr ""
134134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136136msgid "Recent searches"
137137msgstr "近期搜索"
138138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152152msgstr[0] ""
153153msgstr[1] ""
154154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156156msgid "Rate this"
157157msgstr ""
158158
@@ -172,7 +172,7 @@ msgstr ""
172172msgid "Comments:"
173173msgstr ""
174174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176176msgid "Emergency Call"
177177msgstr ""
178178
@@ -205,11 +205,24 @@ msgstr "现在请讲..."
205205msgid "Speaking..."
206206msgstr "讲话中..."
207207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208212#: Panel/SearchIndicator.qml:27
209213msgid "Search"
210214msgstr "搜索"
211215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213226msgid "Sorry, there is nothing that matches your search."
214227msgstr "对不起,没有找到您想要的结果。"
215228
@@ -217,28 +230,7 @@ msgstr "对不起,没有找到您想要的结果。"
217230msgid "All"
218231msgstr ""
219232
220−#: Shell.qml:438
233+#: Shell.qml:441
221234#, qt-format
222235msgid "Please enter %1"
223236msgstr ""
224−
225−#~ msgid "Featured"
226−#~ msgstr "推荐"
227−
228−#~ msgid "New Releases"
229−#~ msgstr "新版本"
230−
231−#~ msgid "Top Charting"
232−#~ msgstr "排行榜图"
233−
234−#~ msgid "Music"
235−#~ msgstr "音乐"
236−
237−#~ msgid "Popular Online"
238−#~ msgstr "经常在线"
239−
240−#~ msgid "Videos"
241−#~ msgstr "视频"
242−
243−#~ msgid "Recent"
244−#~ msgstr "最近使用"
po/zh_TW.po+22−15
@@ -7,7 +7,7 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
1111"PO-Revision-Date: 2013-06-27 10:24+0000\n"
1212"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
1313"Language-Team: Chinese (Traditional) <zh_TW@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
18+"X-Launchpad-Export-Date: 2013-11-19 05:59+0000\n"
19+"X-Generator: Launchpad (build 16831)\n"
2020
2121#: Applications/applications.js:23
2222msgid "Phone"
@@ -86,7 +86,7 @@ msgstr ""
8686msgid "YouTube"
8787msgstr ""
8888
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
9090msgid "Skip intro"
9191msgstr ""
9292
@@ -132,7 +132,7 @@ msgid ""
132132"phone<br><br>Tap anywhere to start"
133133msgstr ""
134134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136136msgid "Recent searches"
137137msgstr "最近搜尋"
138138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152152msgstr[0] ""
153153msgstr[1] ""
154154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156156msgid "Rate this"
157157msgstr ""
158158
@@ -172,7 +172,7 @@ msgstr ""
172172msgid "Comments:"
173173msgstr ""
174174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176176msgid "Emergency Call"
177177msgstr ""
178178
@@ -205,11 +205,24 @@ msgstr "請說..."
205205msgid "Speaking..."
206206msgstr "說話中..."
207207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208212#: Panel/SearchIndicator.qml:27
209213msgid "Search"
210214msgstr "搜尋"
211215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213226msgid "Sorry, there is nothing that matches your search."
214227msgstr "很抱歉,找不到符合您想搜尋的結果。"
215228
@@ -217,13 +230,7 @@ msgstr "很抱歉,找不到符合您想搜尋的結果。"
217230msgid "All"
218231msgstr ""
219232
220−#: Shell.qml:438
233+#: Shell.qml:441
221234#, qt-format
222235msgid "Please enter %1"
223236msgstr ""
224−
225−#~ msgid "Music"
226−#~ msgstr "音樂"
227−
228−#~ msgid "Videos"
229−#~ msgstr "影片"
run+2
@@ -42,6 +42,8 @@ done
4242if $FAKE; then
4343 export QML2_IMPORT_PATH=$PWD/builddir/tests/mocks:$PWD/builddir/plugins:$PWD/builddir/modules
4444 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/builddir/tests/mocks/libusermetrics:$PWD/builddir/tests/mocks/LightDM/single
45+else
46+ export QML2_IMPORT_PATH=`pkg-config --variable=plugindir unity-shell-api`
4547fi
4648
4749if $PINLOCK; then
run_on_device+1−1
@@ -76,7 +76,7 @@ setup_adb_forwarding() {
7676
7777install_dependencies() {
7878 exec_with_adb apt-get update
79− exec_with_ssh $SUDO apt-get -y install build-essential rsync bzr ccache gdb ninja-build devscripts equivs
79+ exec_with_ssh $SUDO apt-get -y install build-essential rsync bzr ccache gdb ninja-build devscripts equivs unity-plugin-scopes
8080}
8181
8282sync_code() {
tests/autopilot/unity8/process_helpers.py+65−38
@@ -21,18 +21,25 @@ from autopilot.introspection import (
2121 get_proxy_object_for_existing_process,
2222 ProcessSearchError,
2323)
24+import logging
2425import subprocess
2526from unity8.shell.emulators import UnityEmulatorBase
2627from unity8.shell.emulators.main_window import MainWindow
2728
29+logger = logging.getLogger(__name__)
30+
2831
2932class CannotAccessUnity(Exception):
3033 pass
3134
3235
33−def unlock_unity():
36+def unlock_unity(unity_proxy_obj=None):
3437 """Helper function that attempts to unlock the unity greeter.
3538
39+ If unity_proxy_object is None create a proxy object by querying for the
40+ running unity process.
41+ Otherwise re-use the passed proxy object.
42+
3643 :raises RuntimeError: if the greeter attempts and fails to be unlocked.
3744
3845 :raises RuntimeWarning: when the greeter cannot be found because it is
@@ -43,30 +50,42 @@ def unlock_unity():
4350 upstart job cannot be found at all.
4451
4552 """
46− pid = _get_unity_pid()
47− try:
48− unity = get_proxy_object_for_existing_process(
49− pid=pid,
50− emulator_base=UnityEmulatorBase,
51− )
52− main_window = MainWindow(unity)
53−
54− greeter = main_window.get_greeter()
55− if greeter is None:
56− raise RuntimeWarning("Greeter appears to be already unlocked.")
57− greeter.swipe()
58− except ProcessSearchError as e:
59− raise CannotAccessUnity(
60− "Cannot introspect unity, make sure that it has been started "
61− "with testability. Perhaps use the function "
62− "'restart_unity_with_testability' this module provides."
63− "(%s)"
64− % str(e)
65− )
53+ if unity_proxy_obj is None:
54+ try:
55+ pid = _get_unity_pid()
56+ unity = _get_unity_proxy_object(pid)
57+ main_window = MainWindow(unity)
58+ except ProcessSearchError as e:
59+ raise CannotAccessUnity(
60+ "Cannot introspect unity, make sure that it has been started "
61+ "with testability. Perhaps use the function "
62+ "'restart_unity_with_testability' this module provides."
63+ "(%s)"
64+ % str(e)
65+ )
66+ else:
67+ main_window = MainWindow(unity_proxy_obj)
68+
69+ greeter = main_window.get_greeter()
70+ if greeter.created == False:
71+ raise RuntimeWarning("Greeter appears to be already unlocked.")
72+ greeter.swipe()
73+
74+
75+def restart_unity_with_testability(*args):
76+ """Restarts (or starts) unity with testability enabled.
77+
78+ Passes *args arguments to the launched process.
79+
80+ """
81+ args += ("QT_LOAD_TESTABILITY=1",)
82+ return restart_unity(*args)
83+
6684
85+def restart_unity(*args):
86+ """Restarts (or starts) unity8 using the provided arguments.
6787
68−def restart_unity_with_testability():
69− """Restarts (or just starts) unity8 with the testability driver loaded
88+ Passes *args arguments to the launched process.
7089
7190 :raises subprocess.CalledProcessError: if unable to stop or start the
7291 unity8 upstart job.
@@ -75,27 +94,28 @@ def restart_unity_with_testability():
7594 status = _get_unity_status()
7695 if "start/" in status:
7796 try:
78− print("Stopping unity.")
79− subprocess.check_call([
80− 'initctl',
81− 'stop',
82− 'unity8',
83− ])
97+ output = subprocess.check_output(['initctl', 'stop', 'unity8'])
98+ logger.info(output)
8499 except subprocess.CalledProcessError as e:
85− e.args += ("Failed to stop running instance of unity8", )
100+ e.args += (
101+ "Failed to stop running instance of unity8: %s" % e.output,
102+ )
86103 raise
87104
88105 try:
89− print("Starting unity with testability.")
90− subprocess.check_call([
91− 'initctl',
92− 'start',
93− 'unity8',
94− 'QT_LOAD_TESTABILITY=1',
95− ])
106+ command = ['initctl', 'start', 'unity8'] + list(args)
107+ output = subprocess.check_output(
108+ command,
109+ stderr=subprocess.STDOUT,
110+ universal_newlines=True,
111+ )
112+ logger.info(output)
113+ pid = _get_unity_pid()
96114 except subprocess.CalledProcessError as e:
97− e.args += ("Failed to start unity8 with testability ", )
115+ e.args += ("Failed to start unity8: %s" % e.output,)
98116 raise
117+ else:
118+ return _get_unity_proxy_object(pid)
99119
100120
101121def _get_unity_status():
@@ -114,3 +134,10 @@ def _get_unity_pid():
114134 if not "start/" in status:
115135 raise CannotAccessUnity("Unity is not in the running state.")
116136 return int(status.split()[-1])
137+
138+
139+def _get_unity_proxy_object(pid):
140+ return get_proxy_object_for_existing_process(
141+ pid=pid,
142+ emulator_base=UnityEmulatorBase,
143+ )
tests/autopilot/unity8/shell/emulators/create_interactive_notification.pymode 100755 → 100644

Only the mode changed.

tests/autopilot/unity8/shell/emulators/dash.py+7−17
@@ -18,42 +18,32 @@
1818#
1919
2020from unity8.shell.emulators import UnityEmulatorBase
21−from time import sleep
21+
2222
2323class Dash(UnityEmulatorBase):
2424
2525 """An emulator that understands the Dash."""
2626
2727 def get_home_applications_grid(self):
28− for i in range(1,10):
29− get_grid = self.get_scope('home').select_single(
30− "GenericFilterGrid",
31− objectName="applications.scope"
32− )
33− if get_grid != None:
34− break
35− sleep(1)
28+ get_grid = self.get_scope('home').wait_select_single(
29+ "GenericFilterGrid",
30+ objectName="applications.scope"
31+ )
3632 return get_grid
3733
3834 def get_application_icon(self, text):
3935 """Returns a 'Tile' icon that has the text 'text' from the application
4036 grid.
4137
42− Will return None if the icon isn't found.
43−
4438 :param text: String containing the text of the icon to search for.
4539
4640 """
4741 app_grid = self.get_home_applications_grid()
48− for i in range(1,10):
49− resp_grid = app_grid.select_single('ResponsiveGridView')
50− if resp_grid != None:
51− break
52− sleep(1)
42+ resp_grid = app_grid.wait_select_single('ResponsiveGridView')
5343 return resp_grid.select_single('Tile', text=text)
5444
5545 def get_scope(self, scope_name='home'):
56− dash_content = self.select_single(
46+ dash_content = self.wait_select_single(
5747 'QQuickListView',
5848 objectName='dashContentList'
5949 )
tests/autopilot/unity8/shell/emulators/hud.py+12−4
@@ -26,6 +26,7 @@ from autopilot.input import Touch
2626
2727SwipeCoords = namedtuple('SwipeCoords', 'start_x end_x start_y end_y')
2828
29+
2930class Hud(UnityEmulatorBase, DragMixin):
3031
3132 """An emulator that understands the Hud."""
@@ -34,13 +35,18 @@ class Hud(UnityEmulatorBase, DragMixin):
3435 """Swipes open the Hud."""
3536 self.touch = Touch.create()
3637
37− window = self.get_root_instance().select_single('QQuickView')
38− hud_show_button = window.select_single("HudButton")
38+ window = self.get_root_instance().wait_select_single('QQuickView')
39+ hud_show_button = window.wait_select_single("HudButton")
3940
4041 swipe_coords = self.get_button_swipe_coords(window, hud_show_button)
4142
4243 self.touch.press(swipe_coords.start_x, swipe_coords.start_y)
43− self._drag(swipe_coords.start_x, swipe_coords.start_y, swipe_coords.start_x, swipe_coords.end_y)
44+ self._drag(
45+ swipe_coords.start_x,
46+ swipe_coords.start_y,
47+ swipe_coords.start_x,
48+ swipe_coords.end_y
49+ )
4450 try:
4551 hud_show_button.opacity.wait_for(1.0)
4652 self.touch.release()
@@ -74,6 +80,8 @@ class Hud(UnityEmulatorBase, DragMixin):
7480 start_x = int(main_view.x + (main_view.width / 2))
7581 end_x = start_x
7682 start_y = main_view.y + (main_view.height - 3)
77− end_y = main_view.y + int(hud_show_button.y + (hud_show_button.height/2))
83+ end_y = main_view.y + int(
84+ hud_show_button.y + (hud_show_button.height/2)
85+ )
7886
7987 return SwipeCoords(start_x, end_x, start_y, end_y)
tests/autopilot/unity8/shell/emulators/main_window.py+7−7
@@ -38,11 +38,14 @@ class MainWindow(object):
3838 return self.app.select_single(Greeter)
3939
4040 def get_greeter_content_loader(self):
41− return self.app.select_single(
41+ return self.app.wait_select_single(
4242 "QQuickLoader",
4343 objectName="greeterContentLoader"
4444 )
4545
46+ def get_greeter_background(self):
47+ return self.app.select_single("CrossFadeImage", objectName="greeterBackground")
48+
4649 def get_login_loader(self):
4750 return self.app.select_single("QQuickLoader", objectName="loginLoader")
4851
@@ -64,12 +67,6 @@ class MainWindow(object):
6467 def get_dash(self):
6568 return self.app.select_single(Dash)
6669
67− def get_dash_home_applications_grid(self):
68− return self.app.select_single(
69− "ApplicationsFilterGrid",
70− objectName="dashHomeApplicationsGrid"
71− )
72−
7370 def get_bottombar(self):
7471 return self.app.select_single("Bottombar")
7572
@@ -99,3 +96,6 @@ class MainWindow(object):
9996 'DefaultIndicatorWidget',
10097 objectName=indicator_name+'-widget'
10198 )
99+
100+ def get_shell_background(self):
101+ return self.app.select_single("CrossFadeImage", objectName="backgroundImage")
tests/autopilot/unity8/shell/tests/__init__.py+54−36
@@ -28,13 +28,12 @@ from autopilot.platform import model
2828from autopilot.testcase import AutopilotTestCase
2929from autopilot.matchers import Eventually
3030from autopilot.input import Touch
31−from autopilot.introspection import get_proxy_object_for_existing_process
3231from autopilot.display import Display
3332import logging
3433import os.path
3534import subprocess
3635import sys
37−from testtools.matchers import Equals, NotEquals
36+from testtools.matchers import Equals
3837
3938from unity8 import (
4039 get_lib_path,
@@ -43,7 +42,7 @@ from unity8 import (
4342 get_default_extra_mock_libraries,
4443 get_data_dirs
4544)
46−from unity8.shell.emulators import UnityEmulatorBase
45+from unity8.process_helpers import restart_unity_with_testability
4746from unity8.shell.emulators.dash import Dash
4847from unity8.shell.emulators.main_window import MainWindow
4948
@@ -53,7 +52,7 @@ logger = logging.getLogger(__name__)
5352UNITYSHELL_GSETTINGS_SCHEMA = "org.compiz.unityshell"
5453UNITYSHELL_GSETTINGS_PATH = "/org/compiz/profiles/unity/plugins/unityshell/"
5554UNITYSHELL_LAUNCHER_KEY = "launcher-hide-mode"
56−UNITYSHELL_LAUNCHER_MODE = 1 # launcher hidden
55+UNITYSHELL_LAUNCHER_MODE = 1 # launcher hidden
5756
5857
5958def _get_device_emulation_scenarios(devices='All'):
@@ -93,17 +92,25 @@ class UnityTestCase(AutopilotTestCase):
9392 ], stderr=subprocess.STDOUT)
9493 except subprocess.CalledProcessError, e:
9594 sys.stderr.write(
96− "Error: `initctl status unity8` failed, most probably the unity8 session could not be found:\n\n"
95+ "Error: `initctl status unity8` failed, most probably the "
96+ "unity8 session could not be found:\n\n"
9797 "{0}\n"
98− "Please install unity8 or copy data/unity8.conf to {1}\n".format(
98+ "Please install unity8 or copy data/unity8.conf to "
99+ "{1}\n".format(
99100 e.output,
100− os.path.join(os.getenv("XDG_CONFIG_HOME", os.path.join(os.getenv("HOME"), ".config")), "upstart")
101− ))
101+ os.path.join(os.getenv("XDG_CONFIG_HOME",
102+ os.path.join(os.getenv("HOME"),
103+ ".config")
104+ ),
105+ "upstart")
106+ )
107+ )
102108 sys.exit(1)
103109
104110 if "start/" in output:
105111 sys.stderr.write(
106− "Error: Unity is currently running, these tests require it to be 'stopped'.\n"
112+ "Error: Unity is currently running, these tests require it to "
113+ "be 'stopped'.\n"
107114 "Please run this command before running these tests: \n"
108115 "initctl stop unity8\n"
109116 )
@@ -111,11 +118,22 @@ class UnityTestCase(AutopilotTestCase):
111118
112119 def setUp(self):
113120 super(UnityTestCase, self).setUp()
114− if Gio is not None and UNITYSHELL_GSETTINGS_SCHEMA in Gio.Settings.list_relocatable_schemas():
121+ if (Gio is not None and
122+ UNITYSHELL_GSETTINGS_SCHEMA in
123+ Gio.Settings.list_relocatable_schemas()):
124+
115125 # Hide Unity launcher
116− self._unityshell_schema = Gio.Settings.new_with_path(UNITYSHELL_GSETTINGS_SCHEMA, UNITYSHELL_GSETTINGS_PATH)
117− self._launcher_hide_mode = self._unityshell_schema.get_int(UNITYSHELL_LAUNCHER_KEY)
118− self._unityshell_schema.set_int(UNITYSHELL_LAUNCHER_KEY, UNITYSHELL_LAUNCHER_MODE)
126+ self._unityshell_schema = Gio.Settings.new_with_path(
127+ UNITYSHELL_GSETTINGS_SCHEMA,
128+ UNITYSHELL_GSETTINGS_PATH,
129+ )
130+ self._launcher_hide_mode = self._unityshell_schema.get_int(
131+ UNITYSHELL_LAUNCHER_KEY,
132+ )
133+ self._unityshell_schema.set_int(
134+ UNITYSHELL_LAUNCHER_KEY,
135+ UNITYSHELL_LAUNCHER_MODE,
136+ )
119137 self.addCleanup(self._reset_launcher)
120138
121139 self._proxy = None
@@ -136,7 +154,10 @@ class UnityTestCase(AutopilotTestCase):
136154
137155 def _reset_launcher(self):
138156 """Reset Unity launcher hide mode"""
139− self._unityshell_schema.set_int(UNITYSHELL_LAUNCHER_KEY, self._launcher_hide_mode)
157+ self._unityshell_schema.set_int(
158+ UNITYSHELL_LAUNCHER_KEY,
159+ self._launcher_hide_mode,
160+ )
140161
141162 def _setup_display_details(self):
142163 scale_divisor = self._determine_geometry()
@@ -217,7 +238,10 @@ class UnityTestCase(AutopilotTestCase):
217238 def _upstart_reset_env(self, key, value):
218239 logger.info("Resetting upstart env %s to %s", key, value)
219240 if value is None:
220− subprocess.call(["/sbin/initctl", "unset-env", key], stderr=subprocess.STDOUT)
241+ subprocess.call(
242+ ["/sbin/initctl", "unset-env", key],
243+ stderr=subprocess.STDOUT,
244+ )
221245 else:
222246 subprocess.call([
223247 "/sbin/initctl",
@@ -244,9 +268,13 @@ class UnityTestCase(AutopilotTestCase):
244268 self._setup_extra_mock_environment_patch()
245269
246270 # FIXME: we shouldn't be doing this
247− # $MIR_SOCKET, fallback to $XDG_RUNTIME_DIR/mir_socket and /tmp/mir_socket as last resort
271+ # $MIR_SOCKET, fallback to $XDG_RUNTIME_DIR/mir_socket and
272+ # /tmp/mir_socket as last resort
248273 try:
249− os.unlink(os.getenv('MIR_SOCKET', os.path.join(os.getenv('XDG_RUNTIME_DIR', "/tmp"), "mir_socket")))
274+ os.unlink(
275+ os.getenv('MIR_SOCKET',
276+ os.path.join(os.getenv('XDG_RUNTIME_DIR', "/tmp"),
277+ "mir_socket")))
250278 except OSError:
251279 pass
252280 try:
@@ -256,7 +284,7 @@ class UnityTestCase(AutopilotTestCase):
256284
257285 app_proxy = self._launch_unity_with_upstart(
258286 binary_path,
259− self.unity_geometry_args
287+ self.unity_geometry_args,
260288 )
261289
262290 self._set_proxy(app_proxy)
@@ -274,29 +302,20 @@ class UnityTestCase(AutopilotTestCase):
274302
275303 binary_arg = "BINARY=%s" % binary_path
276304 extra_args = "ARGS=%s" % " ".join(args)
277−
278− output = subprocess.check_output([
279− "/sbin/initctl",
280− "start",
281− "unity8",
282− binary_arg,
283− extra_args
284− ] + ["%s=%s" % (k,v) for k,v in self._environment.iteritems()],
285− stderr=subprocess.STDOUT)
305+ env_args = ["%s=%s" % (k, v) for k, v in self._environment.iteritems()]
306+ all_args = [binary_arg, extra_args] + env_args
286307
287308 self.addCleanup(self._cleanup_launching_upstart_unity)
288309
289− pid = int(output.split()[-1])
290−
291− return get_proxy_object_for_existing_process(
292− pid=pid,
293− emulator_base=UnityEmulatorBase,
294− )
310+ return restart_unity_with_testability(*all_args)
295311
296312 def _cleanup_launching_upstart_unity(self):
297313 logger.info("Stopping unity")
298314 try:
299− subprocess.check_output(["/sbin/initctl", "stop", "unity8"], stderr=subprocess.STDOUT)
315+ subprocess.check_output(
316+ ["/sbin/initctl", "stop", "unity8"],
317+ stderr=subprocess.STDOUT
318+ )
300319 except subprocess.CalledProcessError:
301320 logger.warning("Appears unity was already stopped!")
302321
@@ -366,8 +385,7 @@ class UnityTestCase(AutopilotTestCase):
366385 self.assertThat(home_scope.isCurrent, Eventually(Equals(True)))
367386
368387 def get_dash(self):
369− dash = self._proxy.select_single(Dash)
370− self.assertThat(dash, NotEquals(None))
388+ dash = self._proxy.wait_select_single(Dash)
371389 return dash
372390
373391 @property
tests/autopilot/unity8/shell/tests/test_greeter.pynew file+38
@@ -0,0 +1,38 @@
1+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
2+#
3+# Unity Autopilot Test Suite
4+# Copyright (C) 2012-2013 Canonical
5+#
6+# This program is free software: you can redistribute it and/or modify
7+# it under the terms of the GNU General Public License as published by
8+# the Free Software Foundation, either version 3 of the License, or
9+# (at your option) any later version.
10+#
11+# This program is distributed in the hope that it will be useful,
12+# but WITHOUT ANY WARRANTY; without even the implied warranty of
13+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+# GNU General Public License for more details.
15+#
16+# You should have received a copy of the GNU General Public License
17+# along with this program. If not, see <http://www.gnu.org/licenses/>.
18+#
19+
20+from unity8.shell.tests import UnityTestCase, _get_device_emulation_scenarios
21+
22+from testtools.matchers import Equals
23+
24+class TestGreeter(UnityTestCase):
25+
26+ """Tests the Shell Greeter."""
27+
28+ scenarios = _get_device_emulation_scenarios()
29+
30+ def test_greeter_background(self):
31+ """Test that the background of the greeter and the background of the shell are placed correctly
32+
33+ """
34+ self.launch_unity()
35+ self.main_window.get_greeter()
36+ greeter_background = self.main_window.get_greeter_background()
37+ shell_background = self.main_window.get_shell_background()
38+ self.assertThat(greeter_background.globalRect, Equals(shell_background.globalRect))
tests/autopilot/unity8/shell/tests/test_hud.py+11−10
@@ -19,6 +19,7 @@
1919
2020from __future__ import absolute_import
2121
22+from unity8.process_helpers import unlock_unity
2223from unity8.shell import with_lightdm_mock, DragMixin
2324from unity8.shell.tests import UnityTestCase, _get_device_emulation_scenarios
2425
@@ -38,8 +39,8 @@ class TestHud(UnityTestCase, DragMixin):
3839 The button must disappear when touching somewhere on the screen except the button itself.
3940
4041 """
41− self.launch_unity()
42− self.main_window.get_greeter().swipe()
42+ unity_proxy = self.launch_unity()
43+ unlock_unity(unity_proxy)
4344 window = self.main_window.get_qml_view()
4445 hud_show_button = self.main_window.get_hud_show_button()
4546 edge_drag_area = self.main_window.get_hud_edge_drag_area()
@@ -80,8 +81,8 @@ class TestHud(UnityTestCase, DragMixin):
8081 Test that the hud button stays on screen and tapping it opens the hud.
8182
8283 """
83− self.launch_unity()
84− self.main_window.get_greeter().swipe()
84+ unity_proxy = self.launch_unity()
85+ unlock_unity(unity_proxy)
8586 window = self.main_window.get_qml_view()
8687 hud_show_button = self.main_window.get_hud_show_button()
8788 hud = self.main_window.get_hud()
@@ -117,8 +118,8 @@ class TestHud(UnityTestCase, DragMixin):
117118
118119 def test_hide_hud_click(self):
119120 """Tapping the close button of the Hud must dismiss it."""
120− self.launch_unity()
121− self.main_window.get_greeter().swipe()
121+ unity_proxy = self.launch_unity()
122+ unlock_unity(unity_proxy)
122123 hud = self.main_window.get_hud()
123124
124125 self._launch_test_app_from_app_screen()
@@ -134,8 +135,8 @@ class TestHud(UnityTestCase, DragMixin):
134135 released downward.
135136
136137 """
137− self.launch_unity()
138− self.main_window.get_greeter().swipe()
138+ unity_proxy = self.launch_unity()
139+ unlock_unity(unity_proxy)
139140 window = self.main_window.get_qml_view()
140141 hud = self.main_window.get_hud()
141142
@@ -152,8 +153,8 @@ class TestHud(UnityTestCase, DragMixin):
152153
153154 def test_launcher_hides_hud(self):
154155 """Opening the Launcher while the Hud is active must close the Hud."""
155− self.launch_unity()
156− self.main_window.get_greeter().swipe()
156+ unity_proxy = self.launch_unity()
157+ unlock_unity(unity_proxy)
157158 hud = self.main_window.get_hud()
158159 launcher = self.main_window.get_launcher()
159160
tests/autopilot/unity8/shell/tests/test_notifications.py+74−72
@@ -21,6 +21,7 @@
2121
2222from __future__ import absolute_import
2323
24+from unity8.process_helpers import unlock_unity
2425from unity8.shell.tests import UnityTestCase, _get_device_emulation_scenarios
2526
2627from testtools.matchers import Equals, NotEquals
@@ -45,7 +46,7 @@ class NotificationsBase(UnityTestCase):
4546 """Given an icons file name returns the full path (either system or
4647 source tree.
4748
48− Consider the graphics directory as root so for example (runnign tests
49+ Consider the graphics directory as root so for example (running tests
4950 from installed unity8-autopilot package):
5051 >>> self.get_icon_path('clock.png')
5152 /usr/share/unity8/graphics/clock.png
@@ -118,9 +119,8 @@ class InteractiveNotificationBase(NotificationsBase):
118119
119120 def test_interactive(self):
120121 """Interactive notification must react upon click on itself."""
121− self.launch_unity()
122− greeter = self.main_window.get_greeter()
123− greeter.swipe()
122+ unity_proxy = self.launch_unity()
123+ unlock_unity(unity_proxy)
124124
125125 notify_list = self._get_notifications_list()
126126
@@ -145,8 +145,8 @@ class InteractiveNotificationBase(NotificationsBase):
145145 hints,
146146 )
147147
148− get_notification = lambda: notify_list.select_single('Notification', objectName='notification1')
149− self.assertThat(get_notification, Eventually(NotEquals(None)))
148+ get_notification = lambda: notify_list.wait_select_single(
149+ 'Notification', objectName='notification1')
150150 notification = get_notification()
151151
152152 self.touch.tap_object(
@@ -156,10 +156,10 @@ class InteractiveNotificationBase(NotificationsBase):
156156 self.assert_notification_action_id_was_called('action_id')
157157
158158 def test_sd_incoming_call(self):
159− """Rejecting a call should make notification expand and offer more options."""
160− self.launch_unity()
161− greeter = self.main_window.get_greeter()
162− greeter.swipe()
159+ """Rejecting a call should make notification expand and
160+ offer more options."""
161+ unity_proxy = self.launch_unity()
162+ unlock_unity(unity_proxy)
163163
164164 notify_list = self._get_notifications_list()
165165
@@ -191,8 +191,8 @@ class InteractiveNotificationBase(NotificationsBase):
191191 hints
192192 )
193193
194− get_notification = lambda: notify_list.select_single('Notification', objectName='notification1')
195− self.assertThat(get_notification, Eventually(NotEquals(None)))
194+ get_notification = lambda: notify_list.wait_select_single(
195+ 'Notification', objectName='notification1')
196196 notification = get_notification()
197197 self._assert_notification(notification, None, None, True, True, 1.0)
198198 initial_height = notification.height
@@ -200,8 +200,10 @@ class InteractiveNotificationBase(NotificationsBase):
200200 self.assertThat(
201201 notification.height,
202202 Eventually(Equals(initial_height +
203− 3 * notification.select_single(objectName="buttonColumn").spacing +
204− 3 * notification.select_single(objectName="button4").height)))
203+ 3 * notification.select_single(
204+ objectName="buttonColumn").spacing +
205+ 3 * notification.select_single(
206+ objectName="button4").height)))
205207 self.touch.tap_object(notification.select_single(objectName="button4"))
206208 self.assert_notification_action_id_was_called("action_decline_4")
207209
@@ -333,9 +335,8 @@ class EphemeralNotificationsTests(NotificationsBase):
333335
334336 def test_icon_summary_body(self):
335337 """Notification must display the expected summary and body text."""
336− self.launch_unity()
337− greeter = self.main_window.get_greeter()
338− greeter.swipe()
338+ unity_proxy = self.launch_unity()
339+ unlock_unity(unity_proxy)
339340
340341 notify_list = self._get_notifications_list()
341342
@@ -360,16 +361,22 @@ class EphemeralNotificationsTests(NotificationsBase):
360361
361362 notification.show()
362363
363− get_notification = lambda: notify_list.select_single('Notification', objectName='notification1')
364− self.assertThat(get_notification, Eventually(NotEquals(None)))
365− notification = get_notification()
366− self._assert_notification(notification, summary, body, True, True, 1.0)
364+ notification = lambda: notify_list.wait_select_single(
365+ 'Notification', objectName='notification1')
366+ self._assert_notification(
367+ notification(),
368+ summary,
369+ body,
370+ True,
371+ True,
372+ 1.0,
373+ )
367374
368375 def test_icon_summary(self):
369− """Notification must display the expected summary and secondary icon."""
370− self.launch_unity()
371− greeter = self.main_window.get_greeter()
372− greeter.swipe()
376+ """Notification must display the expected summary and secondary
377+ icon."""
378+ unity_proxy = self.launch_unity()
379+ unlock_unity(unity_proxy)
373380
374381 notify_list = self._get_notifications_list()
375382
@@ -391,11 +398,11 @@ class EphemeralNotificationsTests(NotificationsBase):
391398
392399 notification.show()
393400
394− get_notification = lambda: notify_list.select_single('Notification', objectName='notification1')
395− self.assertThat(get_notification, Eventually(NotEquals(None)))
396− notification = get_notification()
401+ notification = lambda: notify_list.wait_select_single(
402+ 'Notification', objectName='notification1')
403+
397404 self._assert_notification(
398− notification,
405+ notification(),
399406 summary,
400407 None,
401408 False,
@@ -404,10 +411,10 @@ class EphemeralNotificationsTests(NotificationsBase):
404411 )
405412
406413 def test_urgency_order(self):
407− """Notifications must be displayed in order according to their urgency."""
408− self.launch_unity()
409− greeter = self.main_window.get_greeter()
410− greeter.swipe()
414+ """Notifications must be displayed in order according to their
415+ urgency."""
416+ unity_proxy = self.launch_unity()
417+ unlock_unity(unity_proxy)
411418
412419 notify_list = self._get_notifications_list()
413420
@@ -448,11 +455,10 @@ class EphemeralNotificationsTests(NotificationsBase):
448455 )
449456 notification_critical.show()
450457
451− get_notification = lambda: notify_list.select_single(
458+ get_notification = lambda: notify_list.wait_select_single(
452459 'Notification',
453460 summary=summary_critical
454461 )
455− self.assertThat(get_notification, Eventually(NotEquals(None)))
456462
457463 notification = get_notification()
458464 self._assert_notification(
@@ -464,11 +470,10 @@ class EphemeralNotificationsTests(NotificationsBase):
464470 1.0
465471 )
466472
467− get_normal_notification = lambda: notify_list.select_single(
473+ get_normal_notification = lambda: notify_list.wait_select_single(
468474 'Notification',
469475 summary=summary_normal
470476 )
471− self.assertThat(get_normal_notification, Eventually(NotEquals(None)))
472477 notification = get_normal_notification()
473478 self._assert_notification(
474479 notification,
@@ -479,11 +484,10 @@ class EphemeralNotificationsTests(NotificationsBase):
479484 1.0
480485 )
481486
482− get_low_notification = lambda: notify_list.select_single(
487+ get_low_notification = lambda: notify_list.wait_select_single(
483488 'Notification',
484489 summary=summary_low
485490 )
486− self.assertThat(get_low_notification, Eventually(NotEquals(None)))
487491 notification = get_low_notification()
488492 self._assert_notification(
489493 notification,
@@ -496,9 +500,8 @@ class EphemeralNotificationsTests(NotificationsBase):
496500
497501 def test_summary_and_body(self):
498502 """Notification must display the expected summary- and body-text."""
499− self.launch_unity()
500− greeter = self.main_window.get_greeter()
501− greeter.swipe()
503+ unity_proxy = self.launch_unity()
504+ unlock_unity(unity_proxy)
502505
503506 notify_list = self._get_notifications_list()
504507
@@ -508,9 +511,9 @@ class EphemeralNotificationsTests(NotificationsBase):
508511 notification = self._create_ephemeral_notification(summary, body)
509512 notification.show()
510513
511− get_notification = lambda: notify_list.select_single('Notification', objectName='notification1')
512− self.assertThat(get_notification, Eventually(NotEquals(None)))
513− notification = get_notification()
514+ notification = notify_list.wait_select_single(
515+ 'Notification', objectName='notification1')
516+
514517 self._assert_notification(
515518 notification,
516519 summary,
@@ -522,9 +525,8 @@ class EphemeralNotificationsTests(NotificationsBase):
522525
523526 def test_summary_only(self):
524527 """Notification must display only the expected summary-text."""
525− self.launch_unity()
526− greeter = self.main_window.get_greeter()
527− greeter.swipe()
528+ unity_proxy = self.launch_unity()
529+ unlock_unity(unity_proxy)
528530
529531 notify_list = self._get_notifications_list()
530532
@@ -533,17 +535,16 @@ class EphemeralNotificationsTests(NotificationsBase):
533535 notification = self._create_ephemeral_notification(summary)
534536 notification.show()
535537
536− get_notification = lambda: notify_list.select_single('Notification', objectName='notification1')
537− self.assertThat(get_notification, Eventually(NotEquals(None)))
538− notification = get_notification()
538+ notification = notify_list.wait_select_single(
539+ 'Notification', objectName='notification1')
539540
540541 self._assert_notification(notification, summary, '', False, False, 1.0)
541542
542543 def test_update_notification_same_layout(self):
543− """Notification must allow updating its contents while being displayed."""
544− self.launch_unity()
545− greeter = self.main_window.get_greeter()
546− greeter.swipe()
544+ """Notification must allow updating its contents while being
545+ displayed."""
546+ unity_proxy = self.launch_unity()
547+ unlock_unity(unity_proxy)
547548
548549 notify_list = self._get_notifications_list()
549550
@@ -558,8 +559,8 @@ class EphemeralNotificationsTests(NotificationsBase):
558559 )
559560 notification.show()
560561
561− get_notification = lambda: notify_list.select_single('Notification', summary=summary)
562− self.assertThat(get_notification, Eventually(NotEquals(None)))
562+ get_notification = lambda: notify_list.wait_select_single(
563+ 'Notification', summary=summary)
563564 self._assert_notification(
564565 get_notification(),
565566 summary,
@@ -575,14 +576,13 @@ class EphemeralNotificationsTests(NotificationsBase):
575576 icon_path = self._get_icon_path('avatars/amanda.png')
576577 notification.update(summary, body, icon_path)
577578 notification.show()
578− self.assertThat(get_notification, Eventually(NotEquals(None)))
579579 self._assert_notification(get_notification(), summary, body)
580580
581581 def test_update_notification_layout_change(self):
582− """Notification must allow updating its contents and layout while being displayed."""
583− self.launch_unity()
584− greeter = self.main_window.get_greeter()
585− greeter.swipe()
582+ """Notification must allow updating its contents and layout while
583+ being displayed."""
584+ unity_proxy = self.launch_unity()
585+ unlock_unity(unity_proxy)
586586
587587 notify_list = self._get_notifications_list()
588588
@@ -603,8 +603,9 @@ class EphemeralNotificationsTests(NotificationsBase):
603603 )
604604 notification.show()
605605
606− get_notification = lambda: notify_list.select_single('Notification', objectName='notification1')
607− self.assertThat(get_notification, Eventually(NotEquals(None)))
606+ get_notification = lambda: notify_list.wait_select_single(
607+ 'Notification', objectName='notification1')
608+
608609 self._assert_notification(
609610 get_notification(),
610611 summary,
@@ -626,9 +627,8 @@ class EphemeralNotificationsTests(NotificationsBase):
626627
627628 def test_append_hint(self):
628629 """Notification has to accumulate body-text using append-hint."""
629− self.launch_unity()
630− greeter = self.main_window.get_greeter()
631− greeter.swipe()
630+ unity_proxy = self.launch_unity()
631+ unlock_unity(unity_proxy)
632632
633633 notify_list = self._get_notifications_list()
634634
@@ -645,8 +645,9 @@ class EphemeralNotificationsTests(NotificationsBase):
645645
646646 notification.show()
647647
648− get_notification = lambda: notify_list.select_single('Notification', objectName='notification1')
649− self.assertThat(get_notification, Eventually(NotEquals(None)))
648+ get_notification = lambda: notify_list.wait_select_single(
649+ 'Notification', objectName='notification1')
650+
650651 notification = get_notification()
651652 self._assert_notification(
652653 notification,
@@ -662,7 +663,8 @@ class EphemeralNotificationsTests(NotificationsBase):
662663 'Did you watch the air-race in Oshkosh last week?',
663664 'Phil owned the place like no one before him!',
664665 'Did really everything in the race work according to regulations?',
665− 'Somehow I think to remember Burt Williams did cut corners and was not punished for this.',
666+ 'Somehow I think to remember Burt Williams did cut corners and '
667+ 'was not punished for this.',
666668 'Hopefully the referees will watch the videos of the race.',
667669 'Burt could get fined with US$ 50000 for that rule-violation :)'
668670 ]
@@ -677,11 +679,11 @@ class EphemeralNotificationsTests(NotificationsBase):
677679 hints=[('x-canonical-append', 'true')]
678680 )
679681 notification.show()
680− get_notification = lambda: notify_list.select_single(
682+
683+ get_notification = lambda: notify_list.wait_select_single(
681684 'Notification',
682685 objectName='notification1'
683686 )
684− self.assertThat(get_notification, Eventually(NotEquals(None)))
685687 notification = get_notification()
686688 self._assert_notification(
687689 notification,
tests/mocks/AccountsService/CMakeLists.txt+2−2
@@ -13,9 +13,9 @@ file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/qmldir"
1313 )
1414
1515install(TARGETS MockAccountsService-qml
16− DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/mocks/AccountsService
16+ DESTINATION ${SHELL_INSTALL_QML}/mocks/AccountsService
1717 )
1818
1919install(FILES qmldir
20− DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/mocks/AccountsService
20+ DESTINATION ${SHELL_INSTALL_QML}/mocks/AccountsService
2121 )
tests/mocks/AccountsService/plugin.cpp+1−1
@@ -20,7 +20,7 @@
2020#include "plugin.h"
2121#include "AccountsService.h"
2222
23−#include <QtQml>
23+#include <QtQml/qqml.h>
2424
2525static QObject *service_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
2626{
tests/mocks/LightDM/CMakeLists.txt+2−2
@@ -47,9 +47,9 @@ file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/qmldir"
4747 )
4848
4949install(TARGETS MockLightDM-qml
50− DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/mocks/LightDM
50+ DESTINATION ${SHELL_INSTALL_QML}/mocks/LightDM
5151 )
5252
5353install(FILES qmldir
54− DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/mocks/LightDM
54+ DESTINATION ${SHELL_INSTALL_QML}/mocks/LightDM
5555 )
tests/mocks/LightDM/full/CMakeLists.txt+1−1
@@ -14,5 +14,5 @@ set_target_properties(MockLightDM-full PROPERTIES
1414 OUTPUT_NAME lightdm-qt5-2)
1515
1616install(TARGETS MockLightDM-full
17− DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/mocks/LightDM/full
17+ DESTINATION ${SHELL_INSTALL_QML}/mocks/LightDM/full
1818 )
tests/mocks/LightDM/single-passphrase/CMakeLists.txt+1−1
@@ -15,5 +15,5 @@ set_target_properties(MockLightDM-single-passphrase PROPERTIES
1515 OUTPUT_NAME lightdm-qt5-2)
1616
1717install(TARGETS MockLightDM-single-passphrase
18− DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/mocks/LightDM/single-passphrase
18+ DESTINATION ${SHELL_INSTALL_QML}/mocks/LightDM/single-passphrase
1919 )
tests/mocks/LightDM/single-pin/CMakeLists.txt+1−1
@@ -15,5 +15,5 @@ set_target_properties(MockLightDM-single-pin PROPERTIES
1515 OUTPUT_NAME lightdm-qt5-2)
1616
1717install(TARGETS MockLightDM-single-pin
18− DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/mocks/LightDM/single-pin
18+ DESTINATION ${SHELL_INSTALL_QML}/mocks/LightDM/single-pin
1919 )
tests/mocks/LightDM/single/CMakeLists.txt+1−1
@@ -14,5 +14,5 @@ set_target_properties(MockLightDM-single PROPERTIES
1414 OUTPUT_NAME lightdm-qt5-2)
1515
1616install(TARGETS MockLightDM-single
17− DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/mocks/LightDM/single
17+ DESTINATION ${SHELL_INSTALL_QML}/mocks/LightDM/single
1818 )
tests/mocks/Powerd/CMakeLists.txt+2−2
@@ -13,9 +13,9 @@ file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/qmldir"
1313 )
1414
1515install(TARGETS MockPowerd-qml
16− DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/mocks/Powerd
16+ DESTINATION ${SHELL_INSTALL_QML}/mocks/Powerd
1717 )
1818
1919install(FILES qmldir
20− DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/mocks/Powerd
20+ DESTINATION ${SHELL_INSTALL_QML}/mocks/Powerd
2121 )
tests/mocks/QMenuModel/CMakeLists.txt+23
@@ -9,3 +9,26 @@ add_custom_target(QMenuModelQmlFiles ALL
99 COMMAND cp ${QMLFILES} ${CMAKE_CURRENT_BINARY_DIR}
1010 DEPENDS ${QMLFILES}
1111)
12+
13+include_directories(
14+ ${Qt5Core_INCLUDE_DIRS}
15+ ${Qt5Quick_INCLUDE_DIRS}
16+)
17+
18+set(QMenuModelQml_SOURCES
19+ actionstateparser.cpp
20+ plugin.cpp
21+ unitymenumodel.cpp
22+)
23+
24+add_library(QMenuModelQml SHARED ${QMenuModelQml_SOURCES})
25+target_link_libraries(QMenuModelQml
26+ ${Qt5Core_LIBRARIES}
27+ ${Qt5Quick_LIBRARIES}
28+)
29+
30+qt5_use_modules(QMenuModelQml Core Quick)
31+
32+set_target_properties(QMenuModelQml PROPERTIES
33+ OUTPUT_NAME qmenumodel
34+ VERSION 0)
plugins/Unity/genericpreview.cpp → tests/mocks/QMenuModel/UnityMenuAction.qmlrenamed+11−12
@@ -1,9 +1,6 @@
11/*
22 * Copyright (C) 2013 Canonical, Ltd.
33 *
4− * Authors:
5− * Pawel Stolowski <pawel.stolowski@canonical.com>
6− *
74 * This program is free software; you can redistribute it and/or modify
85 * it under the terms of the GNU General Public License as published by
96 * the Free Software Foundation; version 3.
@@ -15,17 +12,19 @@
1512 *
1613 * You should have received a copy of the GNU General Public License
1714 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors:
17+ * Nick Dedekind <nick.dedekind@canonical.com>
1818 */
1919
20−// local
21−#include "genericpreview.h"
20+import QtQuick 2.0
21+import QMenuModel 0.1
2222
23−GenericPreview::GenericPreview(QObject *parent):
24− Preview(parent)
25−{
26−}
23+QtObject {
24+ property string name
25+ property UnityMenuModel model
26+ property int index
2727
28−void GenericPreview::setUnityPreview(unity::dash::Preview::Ptr /* unityPreview */)
29−{
30− Q_EMIT previewChanged();
28+ readonly property var state: undefined
29+ readonly property bool valid: false
3130}
tests/plugins/Unity/signalslisttest.h → tests/mocks/QMenuModel/actionstateparser.cpprenamed+3−14
@@ -12,19 +12,8 @@
1212 *
1313 * You should have received a copy of the GNU General Public License
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors: Nick Dedekind <nick.dedekind@canonical.com>
1517 */
1618
17−#ifndef SIGNALSLISTTEST_H
18−#define SIGNALSLISTTEST_H
19−
20−#include <QObject>
21−
22−class SignalsListTest : public QObject
23−{
24− Q_OBJECT
25−
26− private Q_SLOTS:
27− void testSignalsList();
28−};
29−
30−#endif // SIGNALSLISTTEST_H
19+#include "actionstateparser.h"
tests/plugins/Unity/resultstest.h → tests/mocks/QMenuModel/actionstateparser.hrenamed+11−15
@@ -13,27 +13,23 @@
1313 * You should have received a copy of the GNU General Public License
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1515 *
16− * Authors:
17− * Michal Hruby <michal.hruby@canonical.com>
16+ * Authors: Nick Dedekind <nick.dedekind@canonical.com>
1817 */
1918
20−#ifndef RESULTSTEST_H
21−#define RESULTSTEST_H
19+#ifndef MOCK_ACTIONSTATEPARSER_H
20+#define MOCK_ACTIONSTATEPARSER_H
2221
2322#include <QObject>
23+#include <QVariant>
2424
25−class ResultsTest : public QObject
25+typedef struct _GVariant GVariant;
26+
27+class Q_DECL_EXPORT ActionStateParser : public QObject
2628{
2729 Q_OBJECT
28−
29− private Q_SLOTS:
30− void testAllColumns();
31− void testIconColumn_data();
32− void testIconColumn();
33− void testSpecialIcons_data();
34− void testSpecialIcons();
35− void testMetadataOverride_data();
36− void testMetadataOverride();
30+public:
31+ ActionStateParser(QObject* parent = 0):QObject(parent) {}
32+ virtual QVariant toQVariant(GVariant*) const { return QVariant(); }
3733};
3834
39−#endif
35+#endif // MOCK_ACTIONSTATEPARSER_H
plugins/Unity/ratingoptionsmodel.h → tests/mocks/QMenuModel/plugin.cpprenamed+12−15
@@ -1,8 +1,5 @@
11/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * Authors:
5− * Pawel Stolowski <pawel.stolowski@canonical.com>
2+ * Copyright (C) 2012,2013 Canonical, Ltd.
63 *
74 * This program is free software; you can redistribute it and/or modify
85 * it under the terms of the GNU General Public License as published by
@@ -15,19 +12,19 @@
1512 *
1613 * You should have received a copy of the GNU General Public License
1714 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors: Nick Dedekind <nick.dedekind@canonical.com>
1817 */
1918
20−#ifndef RATINGOPTIONSMODEL_H
21−#define RATINGOPTIONSMODEL_H
19+#include "plugin.h"
20+#include "unitymenumodel.h"
21+#include "actionstateparser.h"
2222
23−#include "genericoptionsmodel.h"
23+#include <QtQml/qqml.h>
2424
25−class RatingOptionsModel : public GenericOptionsModel
25+void QMenuModelPlugin::registerTypes(const char *uri)
2626{
27− Q_OBJECT
28−
29−public:
30− RatingOptionsModel(bool showAllOption, QObject *parent);
31−};
32−
33−#endif // RATINGOPTIONSMODEL_H
27+ Q_ASSERT(uri == QLatin1String("QMenuModel"));
28+ qmlRegisterType<UnityMenuModel>(uri, 0, 1, "UnityMenuModel");
29+ qmlRegisterType<ActionStateParser>(uri, 0, 1, "ActionStateParser");
30+}
plugins/Unity/plugin.h → tests/mocks/QMenuModel/plugin.hrenamed+7−8
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2012 Canonical, Ltd.
2+ * Copyright (C) 2012,2013 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -13,23 +13,22 @@
1313 * You should have received a copy of the GNU General Public License
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1515 *
16− * Author: Michał Sawicz <michal.sawicz@canonical.com>
16+ * Authors: Nick Dedekind <nick.dedekind@canonical.com>
1717 */
1818
19−#ifndef UNITY_PLUGIN_H
20−#define UNITY_PLUGIN_H
19+#ifndef MOCK_QMENUMODEL_PLUGIN_H
20+#define MOCK_QMENUMODEL_PLUGIN_H
2121
22−#include <QtQml/QQmlEngine>
23−#include <QtQml/QQmlExtensionPlugin>
22+#include <QQmlEngine>
23+#include <QQmlExtensionPlugin>
2424
25−class UnityPlugin : public QQmlExtensionPlugin
25+class QMenuModelPlugin : public QQmlExtensionPlugin
2626{
2727 Q_OBJECT
2828 Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
2929
3030public:
3131 void registerTypes(const char *uri);
32− void initializeEngine(QQmlEngine *engine, const char *uri);
3332};
3433
3534#endif
tests/mocks/QMenuModel/qmldir+3−1
@@ -1,3 +1,5 @@
11module QMenuModel
2+plugin qmenumodel
3+
24QDBusActionGroup 0.1 QDBusActionGroup.qml
3−UnityMenuModel 0.1 UnityMenuModel.qml
5+UnityMenuAction 0.1 UnityMenuAction.qml
tests/mocks/QMenuModel/unitymenumodel.cppnew file+239
@@ -0,0 +1,239 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors: Nick Dedekind <nick.dedekind@canonical.com>
17+ */
18+
19+#include "unitymenumodel.h"
20+#include <QDebug>
21+
22+enum MenuRoles {
23+ LabelRole = Qt::DisplayRole + 1,
24+ SensitiveRole,
25+ IsSeparatorRole,
26+ IconRole,
27+ TypeRole,
28+ ExtendedAttributesRole,
29+ ActionRole,
30+ ActionStateRole,
31+ IsCheckRole,
32+ IsRadioRole,
33+ IsToggledRole
34+};
35+
36+UnityMenuModel::UnityMenuModel(QObject *parent)
37+: QAbstractListModel(parent)
38+{
39+}
40+
41+QVariant UnityMenuModel::modelData() const
42+{
43+ return m_modelData;
44+}
45+
46+void UnityMenuModel::setModelData(const QVariant& data)
47+{
48+ beginResetModel();
49+
50+ m_modelData.clear();
51+ m_modelData = data.toList();
52+
53+ endResetModel();
54+}
55+
56+
57+void UnityMenuModel::insertRow(int row, const QVariant& data)
58+{
59+ row = qMin(row, rowCount());
60+
61+ beginInsertRows(QModelIndex(), row, row);
62+
63+ m_modelData.insert(row, data);
64+
65+ endInsertRows();
66+}
67+
68+void UnityMenuModel::appendRow(const QVariant& data)
69+{
70+ insertRow(rowCount(), data);
71+}
72+
73+void UnityMenuModel::removeRow(int row)
74+{
75+ if (row < 0 || rowCount() <= row) {
76+ return;
77+ }
78+
79+ beginRemoveRows(QModelIndex(), row, row);
80+
81+ m_modelData.removeAt(row);
82+
83+ endRemoveRows();
84+}
85+
86+UnityMenuModel::~UnityMenuModel()
87+{
88+}
89+
90+QByteArray UnityMenuModel::busName() const
91+{
92+ return m_busName;
93+}
94+
95+void UnityMenuModel::setBusName(const QByteArray &busName)
96+{
97+ this->m_busName = busName;
98+}
99+
100+QVariantMap UnityMenuModel::actions() const
101+{
102+ return m_actions;
103+}
104+
105+void UnityMenuModel::setActions(const QVariantMap &actions)
106+{
107+ this->m_actions = actions;
108+}
109+
110+QByteArray UnityMenuModel::menuObjectPath() const
111+{
112+ return m_menuObjectPath;
113+}
114+
115+void UnityMenuModel::setMenuObjectPath(const QByteArray &path)
116+{
117+ this->m_menuObjectPath = path;
118+}
119+
120+ActionStateParser* UnityMenuModel::actionStateParser() const
121+{
122+ return NULL;
123+}
124+
125+void UnityMenuModel::setActionStateParser(ActionStateParser*)
126+{
127+}
128+
129+int UnityMenuModel::rowCount(const QModelIndex&) const
130+{
131+ return m_modelData.count();
132+}
133+
134+int UnityMenuModel::columnCount(const QModelIndex&) const
135+{
136+ return 1;
137+}
138+
139+QVariant UnityMenuModel::data(const QModelIndex &index, int role) const
140+{
141+ return rowData(index.row())[roleNames()[role]];
142+}
143+
144+QVariantMap UnityMenuModel::rowData(int row) const
145+{
146+ return m_modelData[row].toMap()["rowData"].toMap();
147+}
148+
149+QVariant UnityMenuModel::subMenuData(int row) const
150+{
151+ return m_modelData[row].toMap()["submenu"];
152+}
153+
154+QModelIndex UnityMenuModel::index(int row, int column, const QModelIndex&) const
155+{
156+ return createIndex(row, column);
157+}
158+
159+QModelIndex UnityMenuModel::parent(const QModelIndex &) const
160+{
161+ return QModelIndex();
162+}
163+
164+QHash<int, QByteArray> UnityMenuModel::roleNames() const
165+{
166+ QHash<int, QByteArray> names;
167+
168+ names[LabelRole] = "label";
169+ names[SensitiveRole] = "sensitive";
170+ names[IsSeparatorRole] = "isSeparator";
171+ names[IconRole] = "icon";
172+ names[TypeRole] = "type";
173+ names[ExtendedAttributesRole] = "ext";
174+ names[ActionRole] = "action";
175+ names[ActionStateRole] = "actionState";
176+ names[IsCheckRole] = "isCheck";
177+ names[IsRadioRole] = "isRadio";
178+ names[IsToggledRole] = "isToggled";
179+
180+ return names;
181+}
182+
183+QObject * UnityMenuModel::submenu(int position, QQmlComponent*)
184+{
185+ if (position < 0 || m_modelData.count() < position) {
186+ return NULL;
187+ }
188+
189+ while (submenus.count() <= position) {
190+ submenus.append(NULL);
191+ }
192+
193+ QVariant submenuData = subMenuData(position);
194+ if (submenuData.type() == (int)QMetaType::QVariantList) {
195+ UnityMenuModel*& model = submenus[position];
196+ if (!model) {
197+ model = new UnityMenuModel(this);
198+ }
199+ if (model->modelData() != submenuData) {
200+ model->setModelData(submenuData);
201+ }
202+ return model;
203+ }
204+
205+ return NULL;
206+}
207+
208+bool UnityMenuModel::loadExtendedAttributes(int, const QVariantMap &)
209+{
210+ return false;
211+}
212+
213+QVariant UnityMenuModel::get(int row, const QByteArray &role)
214+{
215+ static QHash<QByteArray, int> roles;
216+ if (roles.isEmpty()) {
217+ QHash<int, QByteArray> names = roleNames();
218+ Q_FOREACH (int role, names.keys())
219+ roles.insert(names[role], role);
220+ }
221+
222+ return this->data(this->index(row, 0), roles[role]);
223+}
224+
225+void UnityMenuModel::activate(int, const QVariant&)
226+{
227+}
228+
229+void UnityMenuModel::changeState(int, const QVariant&)
230+{
231+}
232+
233+void UnityMenuModel::registerAction(UnityMenuAction*)
234+{
235+}
236+
237+void UnityMenuModel::unregisterAction(UnityMenuAction*)
238+{
239+}
tests/mocks/QMenuModel/unitymenumodel.hnew file+96
@@ -0,0 +1,96 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors: Nick Dedekind <nick.dedekind@canonical.com>
17+ */
18+
19+#ifndef MOCK_UNITYMENUMODEL_H
20+#define MOCK_UNITYMENUMODEL_H
21+
22+#include <QAbstractListModel>
23+class QQmlComponent;
24+class UnityMenuAction;
25+class ActionStateParser;
26+
27+class Q_DECL_EXPORT UnityMenuModel : public QAbstractListModel
28+{
29+ Q_OBJECT
30+ Q_PROPERTY(QVariant modelData READ modelData WRITE setModelData NOTIFY modelDataChanged)
31+ Q_PROPERTY(QByteArray busName READ busName WRITE setBusName NOTIFY busNameChanged)
32+ Q_PROPERTY(QVariantMap actions READ actions WRITE setActions NOTIFY actionsChanged)
33+ Q_PROPERTY(QByteArray menuObjectPath READ menuObjectPath WRITE setMenuObjectPath NOTIFY menuObjectPathChanged)
34+ Q_PROPERTY(ActionStateParser* actionStateParser READ actionStateParser WRITE setActionStateParser NOTIFY actionStateParserChanged)
35+
36+public:
37+ UnityMenuModel(QObject *parent = NULL);
38+ virtual ~UnityMenuModel();
39+
40+ Q_INVOKABLE void insertRow(int row, const QVariant& data);
41+ Q_INVOKABLE void appendRow(const QVariant& data);
42+ Q_INVOKABLE void removeRow(int row);
43+
44+ QVariant modelData() const;
45+ void setModelData(const QVariant& data);
46+
47+ QByteArray busName() const;
48+ void setBusName(const QByteArray &busName);
49+
50+ QVariantMap actions() const;
51+ void setActions(const QVariantMap &actions);
52+
53+ QByteArray menuObjectPath() const;
54+ void setMenuObjectPath(const QByteArray &path);
55+
56+ ActionStateParser* actionStateParser() const;
57+ void setActionStateParser(ActionStateParser* actionStateParser);
58+
59+ int rowCount(const QModelIndex &parent = QModelIndex()) const;
60+ int columnCount(const QModelIndex &parent = QModelIndex()) const;
61+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
62+ QModelIndex index(int row, int column = 0, const QModelIndex &parent = QModelIndex()) const;
63+ QModelIndex parent(const QModelIndex &index) const;
64+ QHash<int, QByteArray> roleNames() const;
65+
66+ Q_INVOKABLE QObject * submenu(int position, QQmlComponent* actionStateParser = NULL);
67+ Q_INVOKABLE bool loadExtendedAttributes(int position, const QVariantMap &schema);
68+ Q_INVOKABLE QVariant get(int row, const QByteArray &role);
69+
70+ Q_INVOKABLE void activate(int index, const QVariant& parameter = QVariant());
71+ Q_INVOKABLE void changeState(int index, const QVariant& parameter);
72+
73+ void registerAction(UnityMenuAction* action);
74+ void unregisterAction(UnityMenuAction* action);
75+
76+Q_SIGNALS:
77+ void busNameChanged();
78+ void actionsChanged();
79+ void menuObjectPathChanged();
80+ void actionStateParserChanged();
81+ void modelDataChanged();
82+
83+private:
84+ QVariantMap rowData(int row) const;
85+ QVariant subMenuData(int row) const;
86+
87+ class Row;
88+ QVariantList m_modelData;
89+ QList<UnityMenuModel*> submenus;
90+
91+ QByteArray m_busName;
92+ QVariantMap m_actions;
93+ QByteArray m_menuObjectPath;
94+};
95+
96+#endif // MOCK_UNITYMENUMODEL_H
tests/mocks/Ubuntu/DownloadDaemonListener/CMakeLists.txt+1−1
@@ -14,5 +14,5 @@ add_custom_target(UbuntuDownloadQmlDirFile ALL
1414)
1515
1616install(TARGETS FakeUbuntuDownloadDaemonListenerQml
17− DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/mocks/Ubuntu/DownloadDaemonListener
17+ DESTINATION ${SHELL_INSTALL_QML}/mocks/Ubuntu/DownloadDaemonListener
1818 )
tests/mocks/Unity/Application/CMakeLists.txt+2−2
@@ -29,9 +29,9 @@ add_custom_target(OSKControllerQmlFile ALL
2929)
3030
3131install(TARGETS FakeUnityApplicationQml
32− DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/mocks/Unity/Application
32+ DESTINATION ${SHELL_INSTALL_QML}/mocks/Unity/Application
3333 )
3434
3535install(FILES qmldir InputFilterArea.qml OSKController.qml
36− DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/mocks/Unity/Application
36+ DESTINATION ${SHELL_INSTALL_QML}/mocks/Unity/Application
3737 )
tests/mocks/Unity/CMakeLists.txt+2−3
@@ -6,7 +6,6 @@ pkg_search_module(GOBJECT gobject-2.0 REQUIRED)
66pkg_search_module(DEEQT libdee-qt5 REQUIRED)
77
88include_directories(
9− ${CMAKE_SOURCE_DIR}/plugins/Unity
109 ${CMAKE_CURRENT_BINARY_DIR}
1110 ${Qt5Core_INCLUDE_DIRS}
1211 ${Qt5Quick_INCLUDE_DIRS}
@@ -17,8 +16,8 @@ include_directories(
1716add_definitions(-DQT_NO_KEYWORDS)
1817
1918set(UnityQML_SOURCES
20− ${CMAKE_SOURCE_DIR}/plugins/Unity/categoryresults.cpp
21− ${CMAKE_SOURCE_DIR}/plugins/Unity/iconutils.cpp
19+ categoryresults.cpp
20+ iconutils.cpp
2221 fake_applications_scope.cpp
2322 fake_preview.cpp
2423 fake_scope.cpp
tests/mocks/Unity/Indicators/IndicatorBase.qmlnew file+37
@@ -0,0 +1,37 @@
1+/*
2+ * Copyright 2013 Canonical Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU Lesser General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU Lesser General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors:
17+ * Nick Dedekind <nick.dedekind@canonical.com>
18+ */
19+
20+import QtQuick 2.0
21+import QMenuModel 0.1
22+
23+Item {
24+ id: indicatorBase
25+
26+ //const
27+ property string busName
28+ property string actionsObjectPath
29+ property string rootMenuType: "com.canonical.indicator.root"
30+ property string deviceMenuObjectPath
31+
32+ property var menuModel: UnityMenuModel {}
33+
34+ property RootActionState rootActionState: RootActionState {
35+ onUpdated: indicatorBase.rootActionStateChanged()
36+ }
37+}
tests/mocks/Unity/Indicators/IndicatorWidget.qmlnew file+28
@@ -0,0 +1,28 @@
1+/*
2+ * Copyright 2013 Canonical Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU Lesser General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU Lesser General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors:
17+ * Nick Dedekind <nick.dedekind@canonical.com>
18+ */
19+
20+import QtQuick 2.0
21+import Unity.Indicators 0.1 as Indicators
22+
23+IndicatorBase {
24+ id: indicatorWidget
25+
26+ enabled: false
27+ property int iconSize: height
28+}
tests/mocks/Unity/Indicators/RootActionState.qml+17−9
@@ -20,14 +20,22 @@
2020import QtQuick 2.0
2121
2222QtObject {
23− property var menu
24− property bool valid: false
25− property string title
26− property string leftLabel
27− property string rightLabel
28− property var icons
29− property string accessibleName
30− property bool visible: true
23+ property var menu
24+ property bool valid: false
25+ property string title
26+ property string leftLabel
27+ property string rightLabel
28+ property var icons
29+ property string accessibleName
30+ property bool visible: true
3131
32− signal updated
32+ signal updated
33+
34+ onValidChanged: updated()
35+ onTitleChanged: updated()
36+ onLeftLabelChanged: updated()
37+ onRightLabelChanged: updated()
38+ onIconsChanged: updated()
39+ onAccessibleNameChanged: updated()
40+ onVisibleChanged: updated()
3341}
tests/mocks/Unity/Indicators/qmldir+2
@@ -2,6 +2,8 @@ module Unity.Indicators
22plugin IndicatorsFakeQml
33
44CachedUnityMenuModel 0.1 CachedUnityMenuModel.qml
5+IndicatorBase 0.1 IndicatorBase.qml
6+IndicatorWidget 0.1 IndicatorWidget.qml
57IndicatorsModel 0.1 IndicatorsModel.qml
68FakeMenuPage 0.1 FakeMenuPage.qml
79RootActionState 0.1 RootActionState.qml
plugins/Unity/categoryresults.cpp → tests/mocks/Unity/categoryresults.cpprenamed

The content is the same.

plugins/Unity/categoryresults.h → tests/mocks/Unity/categoryresults.hrenamed

The content is the same.

tests/mocks/Unity/fake_scope.cpp+3−20
@@ -25,25 +25,8 @@ static DeeModel* create_results_model(unsigned category_count, unsigned result_c
2525
2626// TODO: Implement remaining pieces
2727
28−Scope::Scope(QObject* parent)
29− : QObject(parent)
30− , m_visible(false)
31− , m_searching(false)
32− , m_isActive(false)
33− , m_categories(new Categories(this))
34− , m_results(new DeeListModel(this))
28+Scope::Scope(QObject* parent) : Scope(QString(), QString(), false, parent)
3529{
36− DeeModel* results_model = create_results_model(4, 30);
37− m_categories->setResultModel(results_model);
38− m_categories->setModel(create_categories_model(4));
39− m_results->setModel(results_model);
40−
41− m_timer.setInterval(1000);
42− m_timer.setSingleShot(true);
43− connect(&m_timer, &QTimer::timeout, [this]() {
44− Preview *p = new Preview(this);
45− Q_EMIT previewReady(p);
46− });
4730}
4831
4932Scope::Scope(QString const& id, QString const& name, bool visible, QObject* parent)
@@ -56,9 +39,9 @@ Scope::Scope(QString const& id, QString const& name, bool visible, QObject* pare
5639 , m_categories(new Categories(this))
5740 , m_results(new DeeListModel(this))
5841{
59− DeeModel* results_model = create_results_model(4, 30);
42+ DeeModel* results_model = create_results_model(20, 300);
6043 m_categories->setResultModel(results_model);
61− m_categories->setModel(create_categories_model(4));
44+ m_categories->setModel(create_categories_model(20));
6245 m_results->setModel(results_model);
6346
6447 m_timer.setInterval(1000);
plugins/Unity/iconutils.cpp → tests/mocks/Unity/iconutils.cpprenamed+10−10
@@ -17,11 +17,13 @@
1717 * Michal Hruby <michal.hruby@canonical.com>
1818 */
1919
20−#include <QStringList>
21−#include <QUrl>
20+#include "iconutils.h"
2221
2322#include <gio/gio.h>
24−#include "iconutils.h"
23+
24+#include <QStringList>
25+#include <QUrl>
26+#include <QUrlQuery>
2527
2628#define BASE_THEME_ICON_URI "image://theme/"
2729#define BASE_THUMBNAILER_URI "image://thumbnailer/"
@@ -104,13 +106,11 @@ QString uriToThumbnailerProviderString(QString const &uri, QString const &mimety
104106 if (contentHash.contains("content")) { // nested content in Home?
105107 contentHash = contentHash["content"].toHash();
106108 }
107− if (contentHash.contains("album") &&
108− contentHash.contains("artist")) {
109− const QString album = contentHash["album"].toString();
110− const QString artist = contentHash["artist"].toString();
111− thumbnailerUri.append(QUrl::toPercentEncoding(artist));
112− thumbnailerUri.append("/");
113− thumbnailerUri.append(QUrl::toPercentEncoding(album));
109+ if (contentHash.contains("album") && contentHash.contains("artist")) {
110+ QUrlQuery query;
111+ query.addQueryItem(QStringLiteral("artist"), contentHash["artist"].toString());
112+ query.addQueryItem(QStringLiteral("album"), contentHash["album"].toString());
113+ thumbnailerUri.append(query.toString());
114114 }
115115 }
116116 } else {
plugins/Unity/iconutils.h → tests/mocks/Unity/iconutils.hrenamed

The content is the same.

tests/mocks/libusermetrics/CMakeLists.txt+1−1
@@ -13,5 +13,5 @@ set_target_properties(MockUserMetrics PROPERTIES
1313 VERSION 1)
1414
1515install(TARGETS MockUserMetrics
16− DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/mocks/libusermetrics
16+ DESTINATION ${SHELL_INSTALL_QML}/mocks/libusermetrics
1717 )
tests/plugins/ListViewWithPageHeader/CMakeLists.txt+7
@@ -1,3 +1,6 @@
1+# add_qml_test macro
2+include(QmlTest)
3+
14# There's no cmake var for v8 include path :-/
25# so create one
36LIST(GET Qt5Core_INCLUDE_DIRS 0 QtCoreDir0)
@@ -37,6 +40,10 @@ qt5_use_modules(listviewwithpageheadertestsectionexternalmodelExec Test Core Qml
3740target_link_libraries(listviewwithpageheadertestsectionexternalmodelExec ${Qt5Gui_LIBRARIES} ${Qt5Quick_LIBRARIES})
3841add_custom_target(testlistviewwithpageheadersectionexternalmodel ${CMAKE_CURRENT_BINARY_DIR}/listviewwithpageheadertestsectionexternalmodelExec -o ${CMAKE_BINARY_DIR}/testlistviewwithpageheadersectionexternalmodel.xml,xunitxml -o -,txt)
3942
43+set(qmltest_DEFAULT_NO_ADD_TEST TRUE)
44+add_qml_test(. listviewwithpageheaderqml IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins)
45+
4046add_dependencies(qmluitests testlistviewwithpageheader)
4147add_dependencies(qmluitests testlistviewwithpageheadersection)
4248add_dependencies(qmluitests testlistviewwithpageheadersectionexternalmodel)
49+add_dependencies(qmluitests testlistviewwithpageheaderqml)
tests/plugins/ListViewWithPageHeader/listviewwithpageheadertest.cpp+42
@@ -1589,6 +1589,28 @@ private Q_SLOTS:
15891589 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
15901590 }
15911591
1592+ void testMaximizeVisibleAreaTopWithHalfPageHeaderUpDown()
1593+ {
1594+ testMaximizeVisibleAreaTopWithHalfPageHeader();
1595+
1596+ changeContentY(-60);
1597+ changeContentY(15);
1598+
1599+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
1600+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1601+ verifyItem(0, -140., 150., false);
1602+ verifyItem(1, 10., 200., false);
1603+ verifyItem(2, 210, 350., false);
1604+ verifyItem(3, 560, 350., true);
1605+ QCOMPARE(lvwph->m_minYExtent, 0.);
1606+ QCOMPARE(lvwph->m_clipItem->y(), 190.);
1607+ QCOMPARE(lvwph->m_clipItem->clip(), true);
1608+ QCOMPARE(lvwph->m_headerItem->y(), 140.);
1609+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1610+ QCOMPARE(lvwph->contentY(), 155.);
1611+ QCOMPARE(lvwph->m_headerItemShownHeight, 35.);
1612+ }
1613+
15921614 void testMaximizeVisibleAreaBottomWithHalfPageHeader()
15931615 {
15941616 changeContentY(430);
@@ -1724,6 +1746,9 @@ private Q_SLOTS:
17241746
17251747 void testMaximizeVisibleAreaMoveUpAndShowHeader()
17261748 {
1749+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
1750+ QSKIP("This test is extremely unstable in 5.0.x");
1751+#endif
17271752 model->setProperty(0, "size", 800);
17281753 verifyItem(0, 50., 800., false);
17291754
@@ -1824,6 +1849,23 @@ private Q_SLOTS:
18241849 lvwph->positionAtBeginning();
18251850 }
18261851
1852+ void testHeaderPositionBug1240118()
1853+ {
1854+ scrollToBottom();
1855+ lvwph->showHeader();
1856+ QTRY_VERIFY(!lvwph->m_contentYAnimation->isRunning());
1857+ QTest::qWait(100); // Make sure stuff is stable
1858+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 0), Q_ARG(QVariant, 100));
1859+ model->setProperty(3, "size", 10);
1860+ model->setProperty(4, "size", 10);
1861+ model->setProperty(5, "size", 10);
1862+ model->setProperty(6, "size", 10);
1863+#if (QT_VERSION > QT_VERSION_CHECK(5, 0, 3))
1864+ QTRY_COMPARE(lvwph->m_minYExtent, 210.);
1865+#endif
1866+ QTRY_COMPARE(lvwph->m_headerItem->y(), -lvwph->m_minYExtent);
1867+ }
1868+
18271869private:
18281870 QQuickView *view;
18291871 ListViewWithPageHeader *lvwph;
tests/plugins/ListViewWithPageHeader/listviewwithpageheadertestsection.cpp+81−1
@@ -1734,7 +1734,25 @@ private Q_SLOTS:
17341734 QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 0), Q_ARG(QVariant, 50), Q_ARG(QVariant, "Agressive"));
17351735 QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 0), Q_ARG(QVariant, 50), Q_ARG(QVariant, "Agressive"));
17361736
1737− changeContentY(140);
1737+ changeContentY(5);
1738+
1739+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 5);
1740+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1741+ verifyItem(0, 45., 90., false, "Agressive", false);
1742+ verifyItem(1, 135., 50., false, QString(), false);
1743+ verifyItem(2, 185., 150., false, QString(), false);
1744+ verifyItem(3, 335., 240., false, "Regular", false);
1745+ verifyItem(4, 575., 390., true, "Mild", true);
1746+ QCOMPARE(lvwph->m_minYExtent, 0.);
1747+ QCOMPARE(lvwph->m_clipItem->y(), 5.);
1748+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1749+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1750+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1751+ QCOMPARE(lvwph->contentY(), 5.);
1752+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1753+ QVERIFY(QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1754+
1755+ changeContentY(135);
17381756
17391757 QTRY_COMPARE(lvwph->m_visibleItems.count(), 5);
17401758 QCOMPARE(lvwph->m_firstVisibleIndex, 0);
@@ -2076,6 +2094,68 @@ private Q_SLOTS:
20762094 QCOMPARE(spy.count(), 0);
20772095 }
20782096
2097+ void testDownAndUp()
2098+ {
2099+ QMetaObject::invokeMethod(model, "removeItems", Q_ARG(QVariant, 1), Q_ARG(QVariant, 5));
2100+
2101+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 1);
2102+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
2103+ verifyItem(0, 50., 190., false, "Agressive", false);
2104+ QCOMPARE(lvwph->m_minYExtent, 0.);
2105+ QCOMPARE(lvwph->m_clipItem->y(), 0.);
2106+ QCOMPARE(lvwph->m_clipItem->clip(), false);
2107+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
2108+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
2109+ QCOMPARE(lvwph->contentY(), 0.);
2110+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
2111+ QVERIFY(QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
2112+
2113+ QTest::qWait(1);
2114+
2115+ changeContentY(-15);
2116+
2117+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 1);
2118+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
2119+ verifyItem(0, 65., 190., false, "Agressive", false);
2120+ QCOMPARE(lvwph->m_minYExtent, 0.);
2121+ QCOMPARE(lvwph->m_clipItem->y(), -15.);
2122+ QCOMPARE(lvwph->m_clipItem->clip(), false);
2123+ QCOMPARE(lvwph->m_headerItem->y(), -15.);
2124+ QCOMPARE(lvwph->m_headerItem->height(), 65.);
2125+ QCOMPARE(lvwph->contentY(), -15.);
2126+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
2127+ QVERIFY(QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
2128+
2129+ changeContentY(25);
2130+
2131+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 1);
2132+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
2133+ verifyItem(0, 40., 190., false, "Agressive", false);
2134+ QCOMPARE(lvwph->m_minYExtent, 0.);
2135+ QCOMPARE(lvwph->m_clipItem->y(), 10.);
2136+ QCOMPARE(lvwph->m_clipItem->clip(), false);
2137+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
2138+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
2139+ QCOMPARE(lvwph->contentY(), 10.);
2140+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
2141+ QVERIFY(QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
2142+
2143+
2144+ QTest::mouseClick(view, Qt::LeftButton, Qt::NoModifier, QPoint(0, 0));
2145+
2146+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 1);
2147+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
2148+ verifyItem(0, 50., 190., false, "Agressive", false);
2149+ QCOMPARE(lvwph->m_minYExtent, 0.);
2150+ QCOMPARE(lvwph->m_clipItem->y(), 0.);
2151+ QCOMPARE(lvwph->m_clipItem->clip(), false);
2152+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
2153+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
2154+ QCOMPARE(lvwph->contentY(), 0.);
2155+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
2156+ QVERIFY(QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
2157+ }
2158+
20792159private:
20802160 QQuickView *view;
20812161 ListViewWithPageHeader *lvwph;
tests/plugins/ListViewWithPageHeader/tst_listviewwithpageheaderqml.qmlnew file+138
@@ -0,0 +1,138 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.0
18+import QtTest 1.0
19+import ListViewWithPageHeader 0.1
20+
21+Rectangle {
22+ width: 300
23+ height: 542
24+ color: "lightblue"
25+
26+ ListModel {
27+ id: model
28+
29+ function insertItem(index, size, type) {
30+ insert(index, { size: size, type: type });
31+ }
32+
33+ function removeItems(index, count) {
34+ remove(index, count);
35+ }
36+
37+ function moveItems(indexFrom, indexTo, count) {
38+ move(indexFrom, indexTo, count);
39+ }
40+
41+ ListElement { type: "Agressive"; size: 150 }
42+ ListElement { type: "Regular"; size: 200 }
43+ ListElement { type: "Mild"; size: 350 }
44+ ListElement { type: "Bold"; size: 350 }
45+ ListElement { type: "Bold"; size: 350 }
46+ ListElement { type: "Lazy"; size: 350 }
47+ }
48+
49+ ListViewWithPageHeader {
50+ id: listView
51+ width: parent.width
52+ anchors.top: parent.top
53+ anchors.bottom: parent.bottom
54+ model: model
55+ delegate: Rectangle {
56+ property bool timerDone: false
57+ width: parent.width - 20
58+ x: 10
59+ color: index % 2 == 0 ? "red" : "blue"
60+ height: size
61+ Text {
62+ text: index
63+ }
64+ }
65+
66+ pageHeader: Rectangle {
67+ color: "transparent"
68+ width: parent.width
69+ height: 50
70+ implicitHeight: 50
71+ Text {
72+ anchors.fill: parent
73+ text: "APPS"
74+ font.pixelSize: 40
75+ }
76+ }
77+
78+ sectionProperty: "type"
79+
80+ property int sectionHeaderHeight: 40
81+ sectionDelegate: Component {
82+ id: sectionHeaderComponent
83+ Rectangle {
84+ color: "green"
85+ height: listView.sectionHeaderHeight
86+ Text { text: section; font.pixelSize: 34 }
87+ anchors { left: parent.left; right: parent.right }
88+ }
89+ }
90+ }
91+
92+ Component {
93+ id: otherSectionHeaderComponent
94+ Rectangle {
95+ color: "green"
96+ height: 50
97+ Text { text: section; font.pixelSize: 34 }
98+ anchors { left: parent.left; right: parent.right }
99+ }
100+ }
101+
102+ SignalSpy {
103+ id: stickyHeaderHeigthSpy
104+ target: listView
105+ signalName: "stickyHeaderHeightChanged"
106+ }
107+
108+ TestCase {
109+ name: "ListViewWithPageHeaderTest"
110+ when: windowShown
111+
112+ function test_stickyHeaderHeightNewHeader() {
113+ stickyHeaderHeigthSpy.clear();
114+ compare(listView.stickyHeaderHeight, 40);
115+
116+ listView.sectionDelegate = otherSectionHeaderComponent;
117+ compare(listView.stickyHeaderHeight, 50);
118+ compare(stickyHeaderHeigthSpy.count, 1);
119+
120+ listView.sectionDelegate = sectionHeaderComponent;
121+ compare(listView.stickyHeaderHeight, 40);
122+ compare(stickyHeaderHeigthSpy.count, 2);
123+ }
124+
125+ function test_stickyHeaderHeightGrowingHeader() {
126+ stickyHeaderHeigthSpy.clear();
127+
128+ compare(listView.stickyHeaderHeight, 40);
129+
130+ listView.sectionHeaderHeight = 60;
131+ compare(listView.stickyHeaderHeight, 60);
132+ compare(stickyHeaderHeigthSpy.count, 1);
133+
134+ // Restore height for other tests
135+ listView.sectionHeaderHeight = 40;
136+ }
137+ }
138+}
tests/plugins/Ubuntu/Gestures/CMakeLists.txt+20−18
@@ -1,33 +1,34 @@
1−########## tst_DirectionalDragArea
1+include(QmlTest)
22
33include_directories(
44 ${CMAKE_SOURCE_DIR}/plugins/Ubuntu/Gestures
55 ${CMAKE_CURRENT_BINARY_DIR}
66 )
77
8−set(testCommand
9− LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/plugins/Ubuntu/Gestures
10− ${CMAKE_CURRENT_BINARY_DIR}/DirectionalDragAreaTestExec
11− -o ${CMAKE_BINARY_DIR}/DirectionalDragAreaTest.xml,xunitxml
12− -o -,txt)
13−
14−add_custom_target(testDirectionalDragArea ${testCommand})
15−add_dependencies(qmluitests testDirectionalDragArea)
16−add_dependencies(testDirectionalDragArea DirectionalDragAreaTestExec UbutunGesturesTestQmlFiles)
17−
18−add_executable(DirectionalDragAreaTestExec tst_DirectionalDragArea.cpp)
19−qt5_use_modules(DirectionalDragAreaTestExec Test Core Qml Gui Quick)
20−target_link_libraries(DirectionalDragAreaTestExec UbuntuGestureQml)
21−
22−add_definitions(-DUBUNTU_GESTURES_PLUGIN_DIR="${CMAKE_BINARY_DIR}/plugins")
23−
248file(GLOB qmlFiles *.qml)
259add_custom_target(UbuntuGesturesTestQmlFiles ALL
2610 COMMAND cp ${qmlFiles} ${CMAKE_CURRENT_BINARY_DIR}
2711 DEPENDS ${qmlFiles}
2812)
2913
30−########## other tests
14+add_definitions(-DUBUNTU_GESTURES_PLUGIN_DIR="${CMAKE_BINARY_DIR}/plugins")
15+
16+macro(add_gesture_ui_test CLASSNAME)
17+ set(testCommand
18+ LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/plugins/Ubuntu/Gestures
19+ ${CMAKE_CURRENT_BINARY_DIR}/${CLASSNAME}TestExec
20+ -o ${CMAKE_BINARY_DIR}/${CLASSNAME}Test.xml,xunitxml
21+ -o -,txt)
22+
23+ add_custom_target(test${CLASSNAME} ${testCommand})
24+ add_dependencies(qmluitests test${CLASSNAME})
25+ add_dependencies(test${CLASSNAME} ${CLASSNAME}TestExec UbuntuGesturesTestQmlFiles)
26+
27+ add_executable(${CLASSNAME}TestExec tst_${CLASSNAME}.cpp GestureTest.cpp)
28+ qt5_use_modules(${CLASSNAME}TestExec Test Core Qml Gui Quick)
29+ target_link_libraries(${CLASSNAME}TestExec UbuntuGestureQml)
30+ add_manual_qml_test(. ${CLASSNAME} IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins)
31+endmacro(add_gesture_ui_test)
3132
3233macro(add_gesture_test CLASSNAME)
3334 set(testCommand
@@ -43,5 +44,6 @@ macro(add_gesture_test CLASSNAME)
4344 target_link_libraries(${CLASSNAME}TestExec UbuntuGestureQml)
4445endmacro(add_gesture_test)
4546
47+add_gesture_ui_test(DirectionalDragArea)
4648add_gesture_test(Damper)
4749add_gesture_test(AxisVelocityCalculator)
tests/plugins/Ubuntu/Gestures/DownwardsLauncher.qml+2−10
@@ -31,10 +31,7 @@ Item {
3131 y: followDragArea()
3232
3333 function followDragArea() {
34− if (dragArea.status === DirectionalDragArea.Rejected)
35− return -height
36− else
37− return dragArea.distance < height ? -height + dragArea.distance : 0
34+ return dragArea.distance < height ? -height + dragArea.distance : 0
3835 }
3936 }
4037
@@ -66,15 +63,10 @@ Item {
6663 dragAreaRect.opacity = 0.3
6764 launcher.y = Qt.binding(launcher.followDragArea)
6865 break;
69− case DirectionalDragArea.Recognized:
66+ defaut: // DirectionalDragArea.Recognized:
7067 dragAreaRect.color = "green"
7168 dragAreaRect.opacity = 0.5
7269 break;
73− default: //case DirectionalDragArea.Rejected:
74− dragAreaRect.color = "red"
75− dragAreaRect.opacity = 0.5
76− launcher.y = -launcher.height
77− break;
7870 }
7971 }
8072
tests/plugins/Ubuntu/Gestures/GestureTest.cppnew file+54
@@ -0,0 +1,54 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include "GestureTest.h"
18+
19+#include <qpa/qwindowsysteminterface.h>
20+#include <QQmlEngine>
21+#include <QQuickView>
22+#include <QtTest>
23+
24+GestureTest::GestureTest(const QString &qmlFilename)
25+ : QObject(), m_device(nullptr), m_view(nullptr), m_qmlFilename(qmlFilename)
26+{
27+}
28+
29+void GestureTest::initTestCase()
30+{
31+ if (!m_device) {
32+ m_device = new QTouchDevice;
33+ m_device->setType(QTouchDevice::TouchScreen);
34+ QWindowSystemInterface::registerTouchDevice(m_device);
35+ }
36+}
37+
38+void GestureTest::init()
39+{
40+ m_view = new QQuickView;
41+ m_view->setResizeMode(QQuickView::SizeViewToRootObject);
42+ m_view->engine()->addImportPath(QStringLiteral(UBUNTU_GESTURES_PLUGIN_DIR));
43+ m_view->setSource(QUrl::fromLocalFile(m_qmlFilename));
44+ m_view->show();
45+ QVERIFY(QTest::qWaitForWindowExposed(m_view));
46+ QVERIFY(m_view->rootObject() != 0);
47+ qApp->processEvents();
48+}
49+
50+void GestureTest::cleanup()
51+{
52+ delete m_view;
53+ m_view = nullptr;
54+}
plugins/Unity/genericpreview.h → tests/plugins/Ubuntu/Gestures/GestureTest.hrenamed+19−19
@@ -1,9 +1,6 @@
11/*
22 * Copyright (C) 2013 Canonical, Ltd.
33 *
4− * Authors:
5− * Pawel Stolowski <pawel.stolowski@canonical.com>
6− *
74 * This program is free software; you can redistribute it and/or modify
85 * it under the terms of the GNU General Public License as published by
96 * the Free Software Foundation; version 3.
@@ -17,30 +14,33 @@
1714 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1815 */
1916
20−#ifndef GENERICPREVIEW_H
21−#define GENERICPREVIEW_H
22−
23−// local
24−#include "preview.h"
17+#ifndef GESTURETEST_H
18+#endif // GESTURETEST_H
2519
26−// Qt
2720#include <QObject>
28−#include <QMetaType>
2921
30−class GenericPreview : public Preview
22+class QQuickView;
23+class QTouchDevice;
24+
25+/*
26+ The common stuff among tests come here
27+ */
28+class GestureTest : public QObject
3129{
3230 Q_OBJECT
33−
3431public:
35− explicit GenericPreview(QObject *parent = 0);
32+ // \param qmlFilename name of the qml file to be loaded by the QQuickView
33+ GestureTest(const QString &qmlFilename);
3634
37−Q_SIGNALS:
38− void previewChanged();
35+protected Q_SLOTS:
36+ void initTestCase(); // will be called before the first test function is executed
37+ virtual void init(); // called right before each and every test function is executed
38+ virtual void cleanup(); // called right after each and every test function is executed
3939
4040protected:
41− void setUnityPreview(unity::dash::Preview::Ptr unityPreview) override;
41+ QTouchDevice *m_device;
42+ QQuickView *m_view;
43+ QString m_qmlFilename;
4244};
4345
44−Q_DECLARE_METATYPE(GenericPreview *)
45−
46−#endif
46+#define GESTURETEST_H
tests/plugins/Ubuntu/Gestures/LeftwardsLauncher.qml+5−13
@@ -32,13 +32,10 @@ Item {
3232 y: 0
3333
3434 function followDragArea() {
35− if (dragArea.status === DirectionalDragArea.Rejected)
36− return root.width
37− else
38− return dragArea.distance > -width ?
39− root.width + dragArea.distance
40− :
41− root.width - width
35+ return dragArea.distance > -width ?
36+ root.width + dragArea.distance
37+ :
38+ root.width - width
4239 }
4340 }
4441
@@ -69,15 +66,10 @@ Item {
6966 dragAreaRect.opacity = 0.3
7067 launcher.x = Qt.binding(launcher.followDragArea)
7168 break;
72− case DirectionalDragArea.Recognized:
69+ default: //case DirectionalDragArea.Recognized:
7370 dragAreaRect.color = "green"
7471 dragAreaRect.opacity = 0.5
7572 break;
76− default: //case DirectionalDragArea.Rejected:
77− dragAreaRect.color = "red"
78− dragAreaRect.opacity = 0.5
79− launcher.x = -launcher.height
80− break;
8173 }
8274 }
8375
tests/plugins/Ubuntu/Gestures/RightwardsLauncher.qml+3−10
@@ -19,6 +19,7 @@ import Ubuntu.Gestures 0.1
1919import Ubuntu.Components 0.1
2020
2121Item {
22+ objectName: "rightwardsLauncher"
2223
2324 function reset() { launcher.x = -launcher.width }
2425
@@ -31,10 +32,7 @@ Item {
3132 y: 0
3233
3334 function followDragArea() {
34− if (dragArea.status === DirectionalDragArea.Rejected)
35− return -width
36− else
37− return dragArea.distance < width ? -width + dragArea.distance : 0
35+ return dragArea.distance < width ? -width + dragArea.distance : 0
3836 }
3937 }
4038
@@ -66,15 +64,10 @@ Item {
6664 dragAreaRect.opacity = 0.3
6765 launcher.x = Qt.binding(launcher.followDragArea)
6866 break;
69− case DirectionalDragArea.Recognized:
67+ default: //case DirectionalDragArea.Recognized:
7068 dragAreaRect.color = "green"
7169 dragAreaRect.opacity = 0.5
7270 break;
73− default: //case DirectionalDragArea.Rejected:
74− dragAreaRect.color = "red"
75− dragAreaRect.opacity = 0.5
76− launcher.x = -launcher.height
77− break;
7871 }
7972 }
8073
tests/plugins/Ubuntu/Gestures/UpwardsLauncher.qml+5−13
@@ -32,13 +32,10 @@ Item {
3232 y: root.height
3333
3434 function followDragArea() {
35− if (dragArea.status === DirectionalDragArea.Rejected)
36− return root.height
37− else
38− return dragArea.distance > -height ?
39− root.height + dragArea.distance
40− :
41− root.height - height
35+ return dragArea.distance > -height ?
36+ root.height + dragArea.distance
37+ :
38+ root.height - height
4239 }
4340 }
4441
@@ -69,15 +66,10 @@ Item {
6966 dragAreaRect.opacity = 0.3
7067 launcher.y = Qt.binding(launcher.followDragArea)
7168 break;
72− case DirectionalDragArea.Recognized:
69+ default: //case DirectionalDragArea.Recognized:
7370 dragAreaRect.color = "green"
7471 dragAreaRect.opacity = 0.5
7572 break;
76− default: //case DirectionalDragArea.Rejected:
77− dragAreaRect.color = "red"
78− dragAreaRect.opacity = 0.5
79− launcher.y = -launcher.height
80− break;
8173 }
8274 }
8375
tests/plugins/Ubuntu/Gestures/tst_AxisVelocityCalculator.cpp+3−3
@@ -54,12 +54,12 @@ private Q_SLOTS:
5454
5555private:
5656 AxisVelocityCalculator *velCalc;
57− FakeTimeSource *fakeTimeSource;
57+ QSharedPointer<FakeTimeSource> fakeTimeSource;
5858};
5959
6060void tst_AxisVelocityCalculator::init()
6161{
62− fakeTimeSource = new FakeTimeSource;
62+ fakeTimeSource.reset(new FakeTimeSource);
6363
6464 velCalc = new AxisVelocityCalculator;
6565 velCalc->setTimeSource(fakeTimeSource);
@@ -68,7 +68,7 @@ void tst_AxisVelocityCalculator::init()
6868void tst_AxisVelocityCalculator::cleanup()
6969{
7070 delete velCalc;
71− delete fakeTimeSource;
71+ fakeTimeSource.reset();
7272}
7373
7474void tst_AxisVelocityCalculator::simpleSamples()
tests/plugins/Ubuntu/Gestures/tst_DirectionalDragArea.cpp+326−168
@@ -16,26 +16,42 @@
1616
1717#include <QtTest/QtTest>
1818#include <QtCore/QObject>
19−#include <qpa/qwindowsysteminterface.h>
2019#include <QtQuick/QQuickView>
2120#include <QtQml/QQmlEngine>
21+#include <QPointer>
2222
2323#include <DirectionalDragArea.h>
2424
25−class FakeTimer : public UbuntuGestures::AbstractTimer
25+#include "GestureTest.h"
26+
27+using namespace UbuntuGestures;
28+
29+class FakeTimer : public AbstractTimer
2630{
2731 Q_OBJECT
2832public:
29− FakeTimer(QObject *parent = 0)
30− : UbuntuGestures::AbstractTimer(parent)
33+ FakeTimer(const SharedTimeSource &timeSource, QObject *parent = 0)
34+ : UbuntuGestures::AbstractTimer(parent),
35+ m_timeSource(timeSource)
3136 {}
3237
33− virtual int interval() const { return m_duration; }
34− virtual void setInterval(int msecs) { m_duration = msecs; }
38+ int interval() const override { return m_interval; }
39+ void setInterval(int msecs) override { m_interval = msecs; }
40+ void start() override {
41+ AbstractTimer::start();
42+ m_nextTimeoutTime = m_timeSource->msecsSinceReference() + (qint64)m_interval;
43+ }
44+
45+ void emitTimeout() {
46+ m_nextTimeoutTime += m_interval;
47+ Q_EMIT timeout();
48+ }
3549
36− void emitTimeout() {Q_EMIT timeout();}
50+ qint64 nextTimeoutTime() const { return m_nextTimeoutTime; }
3751private:
38− int m_duration;
52+ int m_interval;
53+ SharedTimeSource m_timeSource;
54+ qint64 m_nextTimeoutTime;
3955};
4056
4157class FakeTimeSource : public UbuntuGestures::TimeSource
@@ -46,15 +62,12 @@ public:
4662 qint64 m_msecsSinceReference;
4763};
4864
49−class tst_DirectionalDragArea: public QObject
65+class tst_DirectionalDragArea: public GestureTest
5066{
5167 Q_OBJECT
5268public:
53− tst_DirectionalDragArea() : device(0) { }
69+ tst_DirectionalDragArea();
5470private Q_SLOTS:
55− void initTestCase(); // will be called before the first test function is executed
56− void cleanupTestCase(); // will be called after the last test function was executed.
57−
5871 void init(); // called right before each and every test function is executed
5972 void cleanup(); // called right after each and every test function is executed
6073
@@ -67,64 +80,54 @@ private Q_SLOTS:
6780 void maxSilenceTime();
6881 void sceneXAndX();
6982 void sceneYAndY();
70− void emitDraggingChangedOnDirectRecognition();
83+ void twoFingerTap();
84+ void movingDDA();
85+ void ignoreOldFinger();
7186
7287private:
73− QQuickView *createView();
74− QQuickView *view;
75− QTouchDevice *device;
88+ void passTime(qint64 timeSpan);
7689 FakeTimer *fakeTimer;
77− FakeTimeSource *fakeTimeSource;
90+ QSharedPointer<FakeTimeSource> fakeTimeSource;
7891};
7992
80−void tst_DirectionalDragArea::initTestCase()
81−{
82− if (!device) {
83− device = new QTouchDevice;
84− device->setType(QTouchDevice::TouchScreen);
85− QWindowSystemInterface::registerTouchDevice(device);
86− }
87−
88− view = 0;
89−}
90−
91−void tst_DirectionalDragArea::cleanupTestCase()
93+tst_DirectionalDragArea::tst_DirectionalDragArea()
94+ : GestureTest(QStringLiteral("tst_DirectionalDragArea.qml"))
9295{
9396}
9497
9598void tst_DirectionalDragArea::init()
9699{
97− view = createView();
98− view->setSource(QUrl::fromLocalFile("edgeDragExample.qml"));
99− view->show();
100− QVERIFY(QTest::qWaitForWindowExposed(view));
101− QVERIFY(view->rootObject() != 0);
102− qApp->processEvents();
103−
104− fakeTimer = new FakeTimer;
105− fakeTimeSource = new FakeTimeSource;
100+ GestureTest::init();
101+
102+ fakeTimeSource.reset(new FakeTimeSource);
103+ fakeTimer = new FakeTimer(fakeTimeSource);
106104}
107105
108106void tst_DirectionalDragArea::cleanup()
109107{
110− delete view;
111− view = 0;
112−
113108 delete fakeTimer;
114109 fakeTimer = 0;
115110
116− delete fakeTimeSource;
117− fakeTimeSource = 0;
111+ fakeTimeSource.reset();
112+
113+ GestureTest::cleanup();
118114}
119115
120−QQuickView *tst_DirectionalDragArea::createView()
116+void tst_DirectionalDragArea::passTime(qint64 timeSpan)
121117{
122− QQuickView *window = new QQuickView(0);
123− window->setResizeMode(QQuickView::SizeRootObjectToView);
124− window->resize(600, 600);
125− window->engine()->addImportPath(QLatin1String(UBUNTU_GESTURES_PLUGIN_DIR));
118+ qint64 finalTime = fakeTimeSource->m_msecsSinceReference + timeSpan;
119+
120+ if (fakeTimer->isRunning() && finalTime >= fakeTimer->nextTimeoutTime()) {
121+ fakeTimeSource->m_msecsSinceReference = fakeTimer->nextTimeoutTime();
122+ fakeTimer->emitTimeout();
126123
127− return window;
124+ qint64 timeSpanRemainder = finalTime - fakeTimeSource->m_msecsSinceReference;
125+ if (timeSpanRemainder > 0) {
126+ passTime(timeSpanRemainder);
127+ }
128+ } else {
129+ fakeTimeSource->m_msecsSinceReference = finalTime;
130+ }
128131}
129132
130133namespace {
@@ -180,25 +183,28 @@ void tst_DirectionalDragArea::edgeDrag()
180183 QFETCH(QString, dragAreaObjectName);
181184 QFETCH(qreal, wideningAngleMultiplier);
182185 QFETCH(qreal, dragDistanceFactor);
183− QFETCH(int, expectedGestureRecognition);
186+ QFETCH(bool, expectGestureRecognition);
184187
185188 DirectionalDragArea *edgeDragArea =
186− view->rootObject()->findChild<DirectionalDragArea*>(dragAreaObjectName);
189+ m_view->rootObject()->findChild<DirectionalDragArea*>(dragAreaObjectName);
187190 QVERIFY(edgeDragArea != 0);
188191 edgeDragArea->setRecognitionTimer(fakeTimer);
189192 edgeDragArea->setTimeSource(fakeTimeSource);
190193
191194 QSignalSpy draggingSpy(edgeDragArea, SIGNAL(draggingChanged(bool)));
192195
193− QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, view);
196+ QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, m_view);
194197 QPointF touchPoint = initialTouchPos;
195198
196199 qreal desiredDragDistance = edgeDragArea->distanceThreshold()*dragDistanceFactor;
197200 QPointF dragDirectionVector = calculateDirectionVector(edgeDragArea,
198201 wideningAngleMultiplier);
199− QPointF touchMovement = dragDirectionVector * (edgeDragArea->distanceThreshold() * 0.1f);
202+ qreal movementStepDistance = edgeDragArea->distanceThreshold() * 0.1f;
203+ QPointF touchMovement = dragDirectionVector * movementStepDistance;
204+ int totalMovementSteps = qCeil(desiredDragDistance / movementStepDistance);
205+ int movementTimeStepMs = (edgeDragArea->compositionTime() * 1.5f) / totalMovementSteps;
200206
201− QTest::touchEvent(view, device).press(0, touchPoint.toPoint());
207+ QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
202208
203209 QCOMPARE(draggingSpy.count(), 1);
204210 QCOMPARE(edgeDragArea->dragging(), true);
@@ -208,23 +214,24 @@ void tst_DirectionalDragArea::edgeDrag()
208214 // in order to make it easier to leave it by dragging at an angle
209215 // slightly bigger than the widening angle
210216 touchPoint += createTouchDeviation(edgeDragArea);
211− QTest::touchEvent(view, device).move(0, touchPoint.toPoint());
217+ QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
212218 }
213219
214− do {
220+ for (int i = 0; i < totalMovementSteps; ++i) {
215221 touchPoint += touchMovement;
216− QTest::touchEvent(view, device).move(0, touchPoint.toPoint());
217− } while ((touchPoint - initialTouchPos).manhattanLength() < desiredDragDistance);
222+ passTime(movementTimeStepMs);
223+ QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
224+ }
218225
219− if (expectedGestureRecognition)
226+ if (expectGestureRecognition)
220227 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Recognized);
221228
222− if (edgeDragArea->status() == DirectionalDragArea::Rejected) {
229+ if (edgeDragArea->status() == DirectionalDragArea::WaitingForTouch) {
223230 QCOMPARE(edgeDragArea->dragging(), false);
224231 QCOMPARE(draggingSpy.count(), 2);
225232 }
226233
227− QTest::touchEvent(view, device).release(0, touchPoint.toPoint());
234+ QTest::touchEvent(m_view, m_device).release(0, touchPoint.toPoint());
228235
229236 QCOMPARE(draggingSpy.count(), 2);
230237 QCOMPARE(edgeDragArea->dragging(), false);
@@ -235,49 +242,49 @@ void tst_DirectionalDragArea::edgeDrag_data()
235242 QTest::addColumn<QString>("dragAreaObjectName");
236243 QTest::addColumn<qreal>("wideningAngleMultiplier");
237244 QTest::addColumn<qreal>("dragDistanceFactor");
238− QTest::addColumn<int>("expectedGestureRecognition");
245+ QTest::addColumn<bool>("expectGestureRecognition");
239246
240247 QTest::newRow("rightwards, tiny drag")
241− << "hpDragArea" << 0.0 << 0.2 << 0;
248+ << "hpDragArea" << 0.0 << 0.2 << false;
242249
243250 QTest::newRow("rightwards, straight drag")
244− << "hpDragArea" << 0.0 << 3.0 << 1;
251+ << "hpDragArea" << 0.0 << 3.0 << true;
245252
246253 QTest::newRow("rightwards, diagonal drag")
247− << "hpDragArea" << 0.9 << 3.0 << 1;
254+ << "hpDragArea" << 0.9 << 3.0 << true;
248255
249256 QTest::newRow("rightwards, overly diagonal drag")
250− << "hpDragArea" << 2.0 << 3.0 << 0;
257+ << "hpDragArea" << 2.0 << 3.0 << false;
251258
252259 QTest::newRow("leftwards, tiny drag")
253− << "hnDragArea" << 0.0 << 0.2 << 0;
260+ << "hnDragArea" << 0.0 << 0.2 << false;
254261
255262 QTest::newRow("leftwards, straight drag")
256− << "hnDragArea" << 0.0 << 3.0 << 1;
263+ << "hnDragArea" << 0.0 << 3.0 << true;
257264
258265 QTest::newRow("leftwards, diagonal drag")
259− << "hnDragArea" << 0.9 << 3.0 << 1;
266+ << "hnDragArea" << 0.9 << 3.0 << true;
260267
261268 QTest::newRow("downwards, tiny drag")
262− << "vpDragArea" << 0.0 << 0.2 << 0;
269+ << "vpDragArea" << 0.0 << 0.2 << false;
263270
264271 QTest::newRow("downwards, straight drag")
265− << "vpDragArea" << 0.0 << 3.0 << 1;
272+ << "vpDragArea" << 0.0 << 3.0 << true;
266273
267274 QTest::newRow("downwards, diagonal drag")
268− << "vpDragArea" << 0.9 << 3.0 << 1;
275+ << "vpDragArea" << 0.9 << 3.0 << true;
269276
270277 QTest::newRow("upwards, tiny drag")
271− << "vnDragArea" << 0.0 << 0.2 << 0;
278+ << "vnDragArea" << 0.0 << 0.2 << false;
272279
273280 QTest::newRow("upwards, straight drag")
274− << "vnDragArea" << 0.0 << 3.0 << 1;
281+ << "vnDragArea" << 0.0 << 3.0 << true;
275282
276283 QTest::newRow("upwards, diagonal drag")
277− << "vnDragArea" << 0.9 << 3.0 << 1;
284+ << "vnDragArea" << 0.9 << 3.0 << true;
278285
279286 QTest::newRow("upwards, overly diagonal drag")
280− << "vnDragArea" << 2.0 << 3.0 << 0;
287+ << "vnDragArea" << 2.0 << 3.0 << false;
281288}
282289
283290/*
@@ -288,39 +295,47 @@ void tst_DirectionalDragArea::edgeDrag_data()
288295void tst_DirectionalDragArea::dragWithShortDirectionChange()
289296{
290297 DirectionalDragArea *edgeDragArea =
291− view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
298+ m_view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
292299 QVERIFY(edgeDragArea != 0);
293300 edgeDragArea->setRecognitionTimer(fakeTimer);
294301 edgeDragArea->setTimeSource(fakeTimeSource);
295302
296− QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, view);
303+ QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, m_view);
297304 QPointF touchPoint = initialTouchPos;
298305
299306 qreal desiredDragDistance = edgeDragArea->distanceThreshold()*2.0;
300307 QPointF dragDirectionVector(1.0, 0.0);
301− QPointF touchMovement = dragDirectionVector * (edgeDragArea->distanceThreshold() * 0.1f);
308+ qreal touchStepDistance = edgeDragArea->distanceThreshold() * 0.1f;
309+ // make sure we are above minimum speed
310+ int touchStepTimeMs = (touchStepDistance / (edgeDragArea->minSpeed() * 5.0f)) * 1000.0f;
311+ QPointF touchMovement = dragDirectionVector * touchStepDistance;
302312
303− QTest::touchEvent(view, device).press(0, touchPoint.toPoint());
313+ QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
304314
305315 // Move a bit in the proper direction
306316 for (int i=0; i < 3; ++i) {
307317 touchPoint += touchMovement;
308− QTest::touchEvent(view, device).move(0, touchPoint.toPoint());
318+ passTime(touchStepTimeMs);
319+ QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
309320 }
310321
311322 // Then a sudden and small movement to the opposite direction
312− touchPoint -= dragDirectionVector * (edgeDragArea->maxDeviation() * 0.7);
313− QTest::touchEvent(view, device).move(0, touchPoint.toPoint());
323+ touchPoint -= touchMovement*0.2;
324+ passTime(touchStepTimeMs*0.2);
325+ QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
314326
315− // And then resume movment in the correct direction until it crosses the distance threshold.
327+ // And then resume movment in the correct direction until it crosses the distance and time
328+ // thresholds.
316329 do {
317330 touchPoint += touchMovement;
318− QTest::touchEvent(view, device).move(0, touchPoint.toPoint());
319− } while ((touchPoint - initialTouchPos).manhattanLength() < desiredDragDistance);
331+ passTime(touchStepTimeMs);
332+ QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
333+ } while ((touchPoint - initialTouchPos).manhattanLength() < desiredDragDistance
334+ || fakeTimeSource->m_msecsSinceReference < (edgeDragArea->compositionTime() * 1.5f));
320335
321336 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Recognized);
322337
323− QTest::touchEvent(view, device).release(0, touchPoint.toPoint());
338+ QTest::touchEvent(m_view, m_device).release(0, touchPoint.toPoint());
324339}
325340
326341/*
@@ -329,53 +344,50 @@ void tst_DirectionalDragArea::dragWithShortDirectionChange()
329344 */
330345void tst_DirectionalDragArea::minSpeed()
331346{
332− QFETCH(int, minSpeedMsecsDeviation);
347+ QFETCH(qreal, minSpeed);
348+ QFETCH(qreal, speed);
333349 QFETCH(int, expectedStatusAfterSpeedCheck);
334350
335351 DirectionalDragArea *edgeDragArea =
336− view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
352+ m_view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
337353 QVERIFY(edgeDragArea != 0);
338354 edgeDragArea->setRecognitionTimer(fakeTimer);
339355 edgeDragArea->setTimeSource(fakeTimeSource);
340356
341− QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, view);
357+ // A really long, unattainable, number. We don't want it getting recognized before
358+ // the speed checks we want have been performed
359+ edgeDragArea->setDistanceThreshold(500000);
360+
361+ edgeDragArea->setMinSpeed(minSpeed);
362+
363+ QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, m_view);
342364 QPointF touchPoint = initialTouchPos;
343365
344366 QPointF dragDirectionVector(1.0, 0.0);
345− qreal distanceStep = edgeDragArea->distanceThreshold() * 0.1f;
367+ qint64 timeStepMsecs = 10;
368+ qreal distanceStep = (speed / 1000.0f) * timeStepMsecs;
346369 QPointF touchMovement = dragDirectionVector * distanceStep;
347− qreal minSpeedMsecs = edgeDragArea->minSpeed() / 1000.0;
348− qint64 timeStepMsecs = qFloor(distanceStep / minSpeedMsecs) + minSpeedMsecsDeviation;
349370
350− // if it fails it means the params set in the QML file are not in harmony with the values
351− // used in this test
352− Q_ASSERT(timeStepMsecs > 0);
371+ QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
353372
354− fakeTimeSource->m_msecsSinceReference = 0;
355− QTest::touchEvent(view, device).press(0, touchPoint.toPoint());
356−
357− // Move a bit in the proper direction
358− for (int i=0; i < 4; ++i) {
373+ // Move for a while to ensure our speed check is performed a couple of times
374+ for (int i=0; i < 20; ++i) {
359375 touchPoint += touchMovement;
360− fakeTimeSource->m_msecsSinceReference += timeStepMsecs;
361− QTest::touchEvent(view, device).move(0, touchPoint.toPoint());
376+ passTime(timeStepMsecs);
377+ QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
362378 }
363379
364− QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Undecided);
365−
366− // Force the periodic speed check.
367− fakeTimer->emitTimeout();
368−
369380 QCOMPARE((int)edgeDragArea->status(), expectedStatusAfterSpeedCheck);
370381}
371382
372383void tst_DirectionalDragArea::minSpeed_data()
373384{
374− QTest::addColumn<int>("minSpeedMsecsDeviation");
385+ QTest::addColumn<qreal>("minSpeed");
386+ QTest::addColumn<qreal>("speed");
375387 QTest::addColumn<int>("expectedStatusAfterSpeedCheck");
376388
377− QTest::newRow("slower than minSpeed") << 20 << (int)DirectionalDragArea::Rejected;
378− QTest::newRow("faster than minSpeed") << -20 << (int)DirectionalDragArea::Undecided;
389+ QTest::newRow("slower than minSpeed") << 100.0 << 50.0 << (int)DirectionalDragArea::WaitingForTouch;
390+ QTest::newRow("faster than minSpeed") << 100.0 << 150.0 << (int)DirectionalDragArea::Undecided;
379391}
380392
381393/*
@@ -386,37 +398,42 @@ void tst_DirectionalDragArea::minSpeed_data()
386398void tst_DirectionalDragArea::recognitionTimerUsage()
387399{
388400 DirectionalDragArea *edgeDragArea =
389− view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
401+ m_view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
390402 QVERIFY(edgeDragArea != 0);
391403 edgeDragArea->setRecognitionTimer(fakeTimer);
392404 edgeDragArea->setTimeSource(fakeTimeSource);
393405
394− QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, view);
406+ // don't let it interfere with our test
407+ edgeDragArea->setMinSpeed(0.0);
408+
409+ int timeStepMs = 5; // some arbitrary small value.
410+
411+ QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, m_view);
395412 QPointF touchPoint = initialTouchPos;
396413
397414 QPointF dragDirectionVector(1.0, 0.0);
398415 QPointF touchMovement = dragDirectionVector * (edgeDragArea->distanceThreshold() * 0.2f);
399416
417+ QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::WaitingForTouch);
400418 QVERIFY(!fakeTimer->isRunning());
401419
402− QTest::touchEvent(view, device).press(0, touchPoint.toPoint());
420+ QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
403421
422+ QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Undecided);
404423 QVERIFY(fakeTimer->isRunning());
405424
406− // Move a bit in the proper direction
407− for (int i=0; i < 3; ++i) {
408− touchPoint += touchMovement;
409− QTest::touchEvent(view, device).move(0, touchPoint.toPoint());
410− }
425+ // Move beyond distance threshold and composition time to ensure recognition
426+ while (fakeTimeSource->m_msecsSinceReference <= edgeDragArea->compositionTime() ||
427+ (touchPoint - initialTouchPos).manhattanLength() <= edgeDragArea->distanceThreshold()) {
411428
412− QVERIFY(fakeTimer->isRunning());
429+ QCOMPARE(edgeDragArea->status() == DirectionalDragArea::Undecided, fakeTimer->isRunning());
413430
414− // Move beyond distance threshold
415− touchPoint += 3*touchMovement;
416− QTest::touchEvent(view, device).move(0, touchPoint.toPoint());
431+ touchPoint += touchMovement;
432+ passTime(timeStepMs);
433+ QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
434+ }
417435
418436 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Recognized);
419−
420437 QVERIFY(!fakeTimer->isRunning());
421438}
422439
@@ -427,34 +444,28 @@ void tst_DirectionalDragArea::recognitionTimerUsage()
427444void tst_DirectionalDragArea::maxSilenceTime()
428445{
429446 DirectionalDragArea *edgeDragArea =
430− view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
447+ m_view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
431448 QVERIFY(edgeDragArea != 0);
432449 edgeDragArea->setRecognitionTimer(fakeTimer);
433450 edgeDragArea->setTimeSource(fakeTimeSource);
434451
435− QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, view);
452+ // Make sure this property is not disabled
453+ edgeDragArea->setMaxSilenceTime(100);
454+
455+ QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, m_view);
436456 QPointF touchPoint = initialTouchPos;
437457
438− fakeTimeSource->m_msecsSinceReference = 0;
439− QTest::touchEvent(view, device).press(0, touchPoint.toPoint());
458+ QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
440459
441460 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Undecided);
461+ QVERIFY(fakeTimer->isRunning());
442462
443− int neededTimeouts = qCeil((qreal)edgeDragArea->maxSilenceTime() / (qreal)fakeTimer->interval());
444− if ((edgeDragArea->maxSilenceTime() % fakeTimer->interval()) == 0) {
445− ++neededTimeouts;
446− }
447−
448− // Force the periodic speed check.
449− for (int i = 0; i < neededTimeouts; ++i) {
450− fakeTimer->emitTimeout();
451−
452− if (i < neededTimeouts - 1) {
453− QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Undecided);
454− }
463+ // Force timer to timeout until after maxSilenceTime has been reached
464+ while (fakeTimeSource->m_msecsSinceReference < edgeDragArea->maxSilenceTime()) {
465+ passTime(fakeTimer->interval());
455466 }
456467
457− QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Rejected);
468+ QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::WaitingForTouch);
458469}
459470
460471/*
@@ -464,21 +475,20 @@ void tst_DirectionalDragArea::maxSilenceTime()
464475void tst_DirectionalDragArea::sceneXAndX()
465476{
466477 DirectionalDragArea *edgeDragArea =
467− view->rootObject()->findChild<DirectionalDragArea*>("hnDragArea");
478+ m_view->rootObject()->findChild<DirectionalDragArea*>("hnDragArea");
468479 QVERIFY(edgeDragArea != 0);
469480 edgeDragArea->setRecognitionTimer(fakeTimer);
470481 edgeDragArea->setTimeSource(fakeTimeSource);
471482
472− QPointF touchScenePos(view->width() - (edgeDragArea->width()/2.0f), view->height()/2.0f);
483+ QPointF touchScenePos(m_view->width() - (edgeDragArea->width()/2.0f), m_view->height()/2.0f);
473484
474− fakeTimeSource->m_msecsSinceReference = 0;
475− QTest::touchEvent(view, device).press(0, touchScenePos.toPoint());
485+ QTest::touchEvent(m_view, m_device).press(0, touchScenePos.toPoint());
476486
477487 QSignalSpy touchXSpy(edgeDragArea, SIGNAL(touchXChanged(qreal)));
478488 QSignalSpy touchSceneXSpy(edgeDragArea, SIGNAL(touchSceneXChanged(qreal)));
479489
480− touchScenePos.rx() = view->width() / 2;
481− QTest::touchEvent(view, device).move(0, touchScenePos.toPoint());
490+ touchScenePos.rx() = m_view->width() / 2;
491+ QTest::touchEvent(m_view, m_device).move(0, touchScenePos.toPoint());
482492
483493 QCOMPARE(touchXSpy.count(), 1);
484494 QCOMPARE(touchSceneXSpy.count(), 1);
@@ -493,21 +503,20 @@ void tst_DirectionalDragArea::sceneXAndX()
493503void tst_DirectionalDragArea::sceneYAndY()
494504{
495505 DirectionalDragArea *edgeDragArea =
496− view->rootObject()->findChild<DirectionalDragArea*>("vnDragArea");
506+ m_view->rootObject()->findChild<DirectionalDragArea*>("vnDragArea");
497507 QVERIFY(edgeDragArea != 0);
498508 edgeDragArea->setRecognitionTimer(fakeTimer);
499509 edgeDragArea->setTimeSource(fakeTimeSource);
500510
501− QPointF touchScenePos(view->width()/2.0f, view->height() - (edgeDragArea->height()/2.0f));
511+ QPointF touchScenePos(m_view->width()/2.0f, m_view->height() - (edgeDragArea->height()/2.0f));
502512
503− fakeTimeSource->m_msecsSinceReference = 0;
504− QTest::touchEvent(view, device).press(0, touchScenePos.toPoint());
513+ QTest::touchEvent(m_view, m_device).press(0, touchScenePos.toPoint());
505514
506515 QSignalSpy touchYSpy(edgeDragArea, SIGNAL(touchYChanged(qreal)));
507516 QSignalSpy touchSceneYSpy(edgeDragArea, SIGNAL(touchSceneYChanged(qreal)));
508517
509− touchScenePos.ry() = view->height() / 2;
510− QTest::touchEvent(view, device).move(0, touchScenePos.toPoint());
518+ touchScenePos.ry() = m_view->height() / 2;
519+ QTest::touchEvent(m_view, m_device).move(0, touchScenePos.toPoint());
511520
512521 QCOMPARE(touchYSpy.count(), 1);
513522 QCOMPARE(touchSceneYSpy.count(), 1);
@@ -516,34 +525,183 @@ void tst_DirectionalDragArea::sceneYAndY()
516525}
517526
518527/*
519− Emit draggingChanged() when status change from WaitingForTouch directly to Recognized.
520− This happens when the gesture recognition is effectively disabled (e.g. by setting a
521− distanceThreshold of zero)
528+ Regression test for https://bugs.launchpad.net/bugs/1228336
529+
530+ Perform a quick two-finger double-tap and check that DirectionalDragArea properly
531+ rejects those touch points. In the bug above it got confused and crashed.
522532 */
523−void tst_DirectionalDragArea::emitDraggingChangedOnDirectRecognition()
533+void tst_DirectionalDragArea::twoFingerTap()
524534{
525535 DirectionalDragArea *edgeDragArea =
526− view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
536+ m_view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
527537 QVERIFY(edgeDragArea != 0);
528538 edgeDragArea->setRecognitionTimer(fakeTimer);
529539 edgeDragArea->setTimeSource(fakeTimeSource);
530540
531− QPointF touchPos = calculateInitialTouchPos(edgeDragArea, view);
541+ // Make touches evenly spaced along the edgeDragArea
542+ QPoint touchAPos(edgeDragArea->width()/2.0f, m_view->height()*0.33f);
543+ QPoint touchBPos(edgeDragArea->width()/2.0f, m_view->height()*0.66f);
532544
533− QSignalSpy draggingSpy(edgeDragArea, SIGNAL(draggingChanged(bool)));
545+ qint64 timeStepMsecs = 5; // some arbitrary, small value
546+
547+ // Perform the first two-finger tap
548+ // NB: using move() instead of stationary() becasue in the latter you cannot provide
549+ // the touch position and therefore it's left with some garbage numbers.
550+ QTest::touchEvent(m_view, m_device)
551+ .press(0, touchAPos);
552+
553+ QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Undecided);
534554
535− // That will make it completetly skip the recognition phase ("Undecided" status).
536− edgeDragArea->setDistanceThreshold(0.0);
555+ passTime(timeStepMsecs);
556+ QTest::touchEvent(m_view, m_device)
557+ .move(0, touchAPos)
558+ .press(1, touchBPos);
559+
560+ // A second touch point appeared during recognition, reject immediately as this
561+ // can't be a single-touch gesture anymore.
562+ QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::WaitingForTouch);
563+
564+ passTime(timeStepMsecs);
565+ QTest::touchEvent(m_view, m_device)
566+ .release(0, touchAPos)
567+ .move(1, touchBPos);
568+
569+ QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::WaitingForTouch);
570+
571+ passTime(timeStepMsecs);
572+ QTest::touchEvent(m_view, m_device)
573+ .release(1, touchBPos);
537574
538575 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::WaitingForTouch);
539− QCOMPARE(edgeDragArea->dragging(), false);
540576
541− fakeTimeSource->m_msecsSinceReference = 0;
542− QTest::touchEvent(view, device).press(0, touchPos.toPoint());
577+ // Perform the second two-finger tap
578+
579+ passTime(timeStepMsecs);
580+ QTest::touchEvent(m_view, m_device)
581+ .press(0, touchAPos);
582+
583+ QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Undecided);
584+
585+ passTime(timeStepMsecs);
586+ QTest::touchEvent(m_view, m_device)
587+ .move(0, touchAPos)
588+ .press(1, touchBPos);
589+
590+ QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::WaitingForTouch);
591+
592+ passTime(timeStepMsecs);
593+ QTest::touchEvent(m_view, m_device)
594+ .release(0, touchAPos)
595+ .move(1, touchBPos);
596+
597+ QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::WaitingForTouch);
598+
599+ passTime(timeStepMsecs);
600+ QTest::touchEvent(m_view, m_device)
601+ .release(1, touchBPos);
602+
603+ QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::WaitingForTouch);
604+}
605+
606+/*
607+ Tests that gesture recognition works normally even if the DirectionalDragArea moves
608+ during recognition.
609+ This effectively means that we have to do gesture recognition with scene coordinates
610+ instead of local item coordinates.
611+ */
612+void tst_DirectionalDragArea::movingDDA()
613+{
614+ QQuickItem *rightwardsLauncher = m_view->rootObject()->findChild<QQuickItem*>("rightwardsLauncher");
615+ Q_ASSERT(rightwardsLauncher != 0);
616+
617+ DirectionalDragArea *edgeDragArea =
618+ rightwardsLauncher->findChild<DirectionalDragArea*>("hpDragArea");
619+ Q_ASSERT(edgeDragArea != 0);
620+ edgeDragArea->setRecognitionTimer(fakeTimer);
621+ edgeDragArea->setTimeSource(fakeTimeSource);
622+
623+ QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, m_view);
624+ QPointF touchPoint = initialTouchPos;
625+
626+ qreal desiredDragDistance = edgeDragArea->distanceThreshold()*2.0f;
627+ QPointF dragDirectionVector(1.0f, 0.0f);
628+
629+ qreal movementStepDistance = edgeDragArea->distanceThreshold() * 0.1f;
630+ QPointF touchMovement = dragDirectionVector * movementStepDistance;
631+ int totalMovementSteps = qCeil(desiredDragDistance / movementStepDistance);
632+ int movementTimeStepMs = (edgeDragArea->compositionTime() * 1.5f) / totalMovementSteps;
633+
634+ QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
635+
636+ // Move it far ahead along the direction of the gesture
637+ // rightwardsLauncher is a parent of our DirectionalDragArea. So moving it will move our DDA
638+ rightwardsLauncher->setX(rightwardsLauncher->x() + edgeDragArea->distanceThreshold() * 5.0f);
639+
640+ for (int i = 0; i < totalMovementSteps; ++i) {
641+ touchPoint += touchMovement;
642+ passTime(movementTimeStepMs);
643+ QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
644+ }
543645
544646 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Recognized);
545− QCOMPARE(draggingSpy.count(), 1);
546− QCOMPARE(edgeDragArea->dragging(), true);
647+
648+ QTest::touchEvent(m_view, m_device).release(0, touchPoint.toPoint());
649+}
650+
651+/*
652+ The presence of and old, rejected, touch point lying on the DirectionalDragArea
653+ shouldn't impede the recognition of a gesture from a new touch point.
654+ */
655+void tst_DirectionalDragArea::ignoreOldFinger()
656+{
657+ DirectionalDragArea *edgeDragArea =
658+ m_view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
659+ Q_ASSERT(edgeDragArea != 0);
660+ edgeDragArea->setRecognitionTimer(fakeTimer);
661+ edgeDragArea->setTimeSource(fakeTimeSource);
662+
663+ // Make touches evenly spaced along the edgeDragArea
664+ QPoint touch0Pos(edgeDragArea->width()/2.0f, m_view->height()*0.33f);
665+ QPoint touch1Pos(edgeDragArea->width()/2.0f, m_view->height()*0.66f);
666+
667+ QTest::touchEvent(m_view, m_device).press(0, touch0Pos);
668+
669+ QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Undecided);
670+
671+ // leave it lying around for some time
672+ passTime(qMax(edgeDragArea->maxSilenceTime(), edgeDragArea->compositionTime()) * 10);
673+
674+ QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::WaitingForTouch);
675+
676+ qreal desiredDragDistance = edgeDragArea->distanceThreshold()*2.0f;
677+ QPointF dragDirectionVector(1.0f, 0.0f);
678+
679+ qreal movementStepDistance = edgeDragArea->distanceThreshold() * 0.1f;
680+ QPointF touchMovement = dragDirectionVector * movementStepDistance;
681+ int totalMovementSteps = qCeil(desiredDragDistance / movementStepDistance);
682+ int movementTimeStepMs = (edgeDragArea->compositionTime() * 1.5f) / totalMovementSteps;
683+
684+ QTest::touchEvent(m_view, m_device)
685+ .move(0, touch0Pos)
686+ .press(1, touch1Pos);
687+
688+ QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Undecided);
689+
690+ for (int i = 0; i < totalMovementSteps; ++i) {
691+ touch1Pos += touchMovement.toPoint();
692+ passTime(movementTimeStepMs);
693+ QTest::touchEvent(m_view, m_device)
694+ .move(0, touch0Pos)
695+ .move(1, touch1Pos);
696+ }
697+
698+ QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Recognized);
699+
700+ QTest::touchEvent(m_view, m_device)
701+ .move(0, touch0Pos)
702+ .release(1, touch1Pos);
703+
704+ QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::WaitingForTouch);
547705}
548706
549707QTEST_MAIN(tst_DirectionalDragArea)
tests/plugins/Ubuntu/Gestures/edgeDragExample.qml → tests/plugins/Ubuntu/Gestures/tst_DirectionalDragArea.qmlrenamed+9−3
@@ -18,8 +18,8 @@ import QtQuick 2.0
1818import Ubuntu.Components 0.1
1919
2020Rectangle {
21− //width: units.gu(40)
22− //height: units.gu(71)
21+ width: units.gu(40)
22+ height: units.gu(71)
2323 color: "white"
2424
2525 MouseArea {
@@ -33,7 +33,13 @@ Rectangle {
3333 }
3434 }
3535
36− RightwardsLauncher { id: hpLauncher; anchors.fill: parent }
36+ // NB: Do not anchor it as we will move it programmatically from the test
37+ RightwardsLauncher {
38+ id: hpLauncher;
39+ width: parent.width
40+ height: parent.height
41+ }
42+
3743 LeftwardsLauncher { id: hnLauncher; anchors.fill: parent }
3844 DownwardsLauncher { id: vpLauncher; anchors.fill: parent }
3945 UpwardsLauncher { id: vnLauncher; anchors.fill: parent }
tests/plugins/Unity/CMakeLists.txt−51
@@ -1,53 +1,2 @@
11add_subdirectory(Indicators)
22add_subdirectory(Launcher)
3−
4−pkg_check_modules(UNITYCORE REQUIRED unity-core-6.0>=7.1.1)
5−pkg_check_modules(LIBUNITYPROTO REQUIRED unity-protocol-private)
6−pkg_check_modules(LIBUNITY REQUIRED unity)
7−pkg_check_modules(LIBSIGCPP REQUIRED sigc++-2.0)
8−pkg_check_modules(QTDEE REQUIRED libdee-qt5>=3.2)
9−
10−include_directories(
11− ${Unity-qml_SOURCE_DIR}
12− ${CMAKE_CURRENT_SOURCE_DIR}/../../../plugins/Unity
13− ${CMAKE_CURRENT_BINARY_DIR}
14− ${LIBUNITYPROTO_INCLUDE_DIRS}
15− ${LIBUNITY_INCLUDE_DIRS}
16− ${LIBSIGCPP_INCLUDE_DIRS}
17− ${UNITYCORE_INCLUDE_DIRS}
18− ${QTDEE_INCLUDE_DIRS}
19− )
20−
21−macro(run_tests)
22− set(_test_list "")
23− foreach(_test ${ARGN})
24− set(testCommand
25− ${CMAKE_CURRENT_BINARY_DIR}/${_test}Exec
26− -o ${CMAKE_BINARY_DIR}/${_test}.xml,xunitxml
27− -o -,txt)
28− add_test(NAME test${CLASSNAME}${_test} COMMAND ${testCommand})
29− add_custom_target(${_test} ${testCommand})
30− add_executable(${_test}Exec ${_test}.cpp)
31− qt5_use_modules(${_test}Exec Test Core Qml)
32− set_tests_properties(test${CLASSNAME}${_test}
33− PROPERTIES ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/plugins/Unity:${LIBUNITYPROTO_LIBRARY_DIRS}")
34−
35− target_link_libraries(${_test}Exec
36− Unity-qml
37− ${UNITYCORE_LDFLAGS}
38− ${LIBUNITY_LDFLAGS}
39− ${LIBUNITYPROTO_LDFLAGS}
40− ${LIBSIGCPP_LDFLAGS}
41− ${QTDEE_LDFLAGS}
42− )
43−
44− set(_test_list "${_test_list};${_test}")
45− endforeach()
46−endmacro(run_tests)
47−
48−run_tests(
49− signalslisttest
50− previewbindingstest
51− filtersbindingstest
52− resultstest
53− )
tests/plugins/Unity/Indicators/CMakeLists.txt+36−27
@@ -1,34 +1,43 @@
1+pkg_check_modules(GLIB REQUIRED glib-2.0>=2.32)
2+pkg_check_modules(GIO REQUIRED gio-2.0>=2.32)
13pkg_check_modules(QMENUMODEL REQUIRED qmenumodel)
24
5+set(INDICATORS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../../plugins/Unity/Indicators)
6+set(TEST_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../..)
7+
38include_directories(
49 ${CMAKE_CURRENT_BINARY_DIR}
5− ${CMAKE_CURRENT_SOURCE_DIR}/../../../../plugins/Unity/Indicators
6− ${QMENUMODEL_INCLUDE_DIRS}
10+ ${INDICATORS_DIR}
11+ ${TEST_DIR}/mocks/QMenuModel
12+ ${GLIB_INCLUDE_DIRS}
13+ ${GIO_INCLUDE_DIRS}
714 )
815
9−macro(run_tests)
10− set(_test_list "")
11− foreach(_test ${ARGN})
12− set(testCommand ${CMAKE_CURRENT_BINARY_DIR}/${_test}Exec
13− -o ${CMAKE_BINARY_DIR}/${_test}.xml,xunitxml
14− -o -,txt)
15− add_test(NAME ${_test} COMMAND ${testCommand})
16− add_custom_target(${_test} ${testCommand})
17− add_executable(${_test}Exec ${_test}.cpp
18− )
19− qt5_use_modules(${_test}Exec Test Core Qml)
20− target_link_libraries(${_test}Exec
21− IndicatorsQml
22− ${QMENUMODEL_LDFLAGS}
23− )
24− set(_test_list "${_test_list};${_test}")
25− endforeach()
26−endmacro(run_tests)
16+macro(indicator_test TEST)
17+ set(multi_value_keywords ADDITIONAL_CPPS ADDITIONAL_LIBS)
18+ cmake_parse_arguments(test "" "" "${multi_value_keywords}" ${ARGN})
2719
28−run_tests(
29− indicatorsmanagertest
30− indicatorsmodeltest
31− menucontentactivatortest
32− rootactionstatetest
33− timeformattertest
34− )
20+ set(testCommand ${CMAKE_CURRENT_BINARY_DIR}/${TEST}Exec
21+ -o ${CMAKE_BINARY_DIR}/${TEST}.xml,xunitxml
22+ -o -,txt)
23+ add_test(NAME ${TEST} COMMAND ${testCommand})
24+ add_custom_target(${TEST} ${testCommand})
25+ add_executable(${TEST}Exec
26+ ${TEST}.cpp
27+ ${test_ADDITIONAL_CPPS}
28+ )
29+ qt5_use_modules(${TEST}Exec Test Core Qml)
30+ target_link_libraries(${TEST}Exec
31+ ${test_ADDITIONAL_LIBS}
32+ ${GLIB_LIBRARIES}
33+ ${GIO_LIBRARIES}
34+ ${QMENUMODEL_LDFLAGS}
35+ )
36+endmacro(indicator_test)
37+
38+indicator_test(indicatorsmanagertest ADDITIONAL_LIBS IndicatorsQml)
39+indicator_test(indicatorsmodeltest ADDITIONAL_LIBS IndicatorsQml)
40+indicator_test(menucontentactivatortest ADDITIONAL_CPPS ${INDICATORS_DIR}/menucontentactivator.cpp)
41+indicator_test(unitymenumodelstacktest ADDITIONAL_CPPS ${TEST_DIR}/mocks/QMenuModel/unitymenumodel.cpp ${INDICATORS_DIR}/unitymenumodelstack.cpp)
42+indicator_test(rootactionstatetest ADDITIONAL_LIBS IndicatorsQml)
43+indicator_test(timeformattertest ADDITIONAL_LIBS IndicatorsQml)
tests/plugins/Unity/Indicators/indicatorsmanagertest.cpp+1−3
@@ -80,9 +80,7 @@ private Q_SLOTS:
8080 QCOMPARE(props["busName"].toString(), QString("com.canonical.indicator.fake1"));
8181 QCOMPARE(props["actionsObjectPath"].toString(), QString("/com/canonical/indicator/fake1"));
8282
83− QVariantMap objectPaths = props["menuObjectPaths"].toMap();
84− QCOMPARE(objectPaths["phone"].toString(), QString("/com/canonical/indicator/fake1/phone"));
85− QCOMPARE(objectPaths["desktop"].toString(), QString("/com/canonical/indicator/fake1/desktop"));
83+ QCOMPARE(props["menuObjectPath"].toString(), QString("/com/canonical/indicator/fake1/phone"));
8684 }
8785
8886 /*
tests/plugins/Unity/Indicators/unitymenumodelstacktest.cppnew file+206
@@ -0,0 +1,206 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors:
17+ * Nick Dedekind <nick.dedekind@canonical.com>
18+ */
19+
20+#include "indicatorsmanager.h"
21+#include "paths.h"
22+#include "unitymenumodelstack.h"
23+
24+#include <QtTest>
25+#include <QDebug>
26+#include <unitymenumodel.h>
27+
28+class UnityMenuModelStackTest : public QObject
29+{
30+ Q_OBJECT
31+private Q_SLOTS:
32+
33+ void init()
34+ {
35+ m_model = new UnityMenuModel();
36+ m_headChanged = false;
37+ m_tailChanged = false;
38+ }
39+
40+ void cleanup()
41+ {
42+ delete m_model;
43+ m_model = NULL;
44+ }
45+
46+ void testHeadOnSetHead()
47+ {
48+ UnityMenuModelStack stack;
49+ connect(&stack, SIGNAL(headChanged(UnityMenuModel*)), this, SLOT(onHeadChanged()));
50+ stack.setHead(m_model);
51+
52+ QCOMPARE(stack.head(), m_model);
53+ QCOMPARE(m_headChanged, true);
54+ }
55+
56+ void testTailOnSetHead()
57+ {
58+ UnityMenuModelStack stack;
59+ connect(&stack, SIGNAL(tailChanged(UnityMenuModel*)), this, SLOT(onTailChanged()));
60+ stack.setHead(m_model);
61+
62+ QCOMPARE(stack.tail(), m_model);
63+ QCOMPARE(m_tailChanged, true);
64+ }
65+
66+ void testPushPop_data() {
67+ QTest::addColumn<int>("menuDepth");
68+ QTest::addColumn<int>("subMenuCount");
69+ QTest::addColumn<int>("subMenuIndex");
70+
71+ QTest::newRow("depth=0") << 0 << 1 << 0;
72+ QTest::newRow("depth=1") << 1 << 1 << 0;
73+ QTest::newRow("depth=8") << 8 << 2 << 1;
74+ }
75+
76+ void testPushPop()
77+ {
78+ QFETCH(int, menuDepth);
79+ QFETCH(int, subMenuCount);
80+ QFETCH(int, subMenuIndex);
81+
82+ m_model->setModelData(recuseAddMenu(subMenuCount, menuDepth));
83+
84+ UnityMenuModelStack stack;
85+ connect(&stack, SIGNAL(tailChanged(UnityMenuModel*)), this, SLOT(onTailChanged()));
86+
87+ QList<UnityMenuModel*> models;
88+
89+ int count = 0;
90+ auto foreachChild = [&](UnityMenuModel* child, int childIndex) {
91+ stack.push(child, childIndex);
92+ QCOMPARE(stack.count(), count+1);
93+
94+ count++;
95+ models << child;
96+ };
97+ recuseSubmenus(m_model, subMenuIndex, foreachChild);
98+
99+ QCOMPARE(stack.count(), models.count());
100+ QCOMPARE(stack.count(), menuDepth+1);
101+ while(stack.count() > 0) {
102+ m_tailChanged = false;
103+
104+ QCOMPARE(stack.pop(), models.takeLast());
105+
106+ QCOMPARE(m_tailChanged, true);
107+ if (stack.count()) {
108+ QCOMPARE(stack.tail(), models.last());
109+ }
110+ }
111+ QCOMPARE(m_tailChanged, true);
112+ }
113+
114+ void testPopOnRemove_data() {
115+ QTest::addColumn<int>("menuDepth");
116+ QTest::addColumn<int>("subMenuCount");
117+ QTest::addColumn<int>("subMenuIndex");
118+ QTest::addColumn<int>("removeIndex");
119+ QTest::addColumn<int>("resultCount");
120+
121+ QTest::newRow("removeIndexBefore") << 4 << 2 << 1 << 0 << 5;
122+ QTest::newRow("removeCurrentIndex") << 4 << 2 << 0 << 0 << 1;
123+ QTest::newRow("removeIndexAfter") << 4 << 2 << 0 << 1 << 5;
124+ }
125+
126+ void testPopOnRemove()
127+ {
128+ QFETCH(int, menuDepth);
129+ QFETCH(int, subMenuCount);
130+ QFETCH(int, subMenuIndex);
131+ QFETCH(int, removeIndex);
132+ QFETCH(int, resultCount);
133+
134+ m_model->setModelData(recuseAddMenu(subMenuCount, menuDepth));
135+
136+ UnityMenuModelStack stack;
137+
138+ auto foreachChild = [&](UnityMenuModel* child, int childIndex) {
139+ stack.push(child, childIndex);
140+ };
141+ recuseSubmenus(m_model, subMenuIndex, foreachChild);
142+
143+ QCOMPARE(stack.count(), menuDepth+1);
144+
145+ m_model->removeRow(removeIndex);
146+
147+ waitFor([&stack, resultCount]() { return stack.count() == resultCount; }, 1000);
148+ QCOMPARE(stack.count(), resultCount);
149+ }
150+
151+private:
152+ bool waitFor(std::function<bool()> functor, int ms) {
153+
154+ QElapsedTimer timer;
155+ timer.start();
156+ while(!functor() && timer.elapsed() < ms) { QTest::qWait(10); }
157+ return functor();
158+ }
159+
160+ QVariant recuseAddMenu(int subMenuCount, int depth_remaining)
161+ {
162+ QVariantList rows;
163+
164+ for (int i = 0; i < subMenuCount; i ++) {
165+ QVariantMap row;
166+ QVariantMap rowData;
167+
168+ if (depth_remaining > 0) {
169+ row["submenu"] = recuseAddMenu(subMenuCount, depth_remaining-1);
170+ }
171+
172+ row["rowData"] = rowData;
173+
174+ rows << row;
175+ }
176+
177+ return rows;
178+ }
179+
180+ void recuseSubmenus(UnityMenuModel* model, int childIndex, std::function<void(UnityMenuModel*, int)> func) {
181+ UnityMenuModel* parent = model;
182+ UnityMenuModel* child = model;
183+
184+ while(child) {
185+ if (func) {
186+ func(child, childIndex);
187+ }
188+
189+ parent = child;
190+ child = qobject_cast<UnityMenuModel*>(parent->submenu(childIndex));
191+ }
192+
193+ }
194+
195+private Q_SLOTS:
196+ void onHeadChanged() { m_headChanged = true; }
197+ void onTailChanged() { m_tailChanged = true; }
198+
199+public:
200+ UnityMenuModel* m_model;
201+ bool m_headChanged;
202+ bool m_tailChanged;
203+};
204+
205+QTEST_GUILESS_MAIN(UnityMenuModelStackTest)
206+#include "unitymenumodelstacktest.moc"
tests/plugins/Unity/filtersbindingstest.cppdeleted−515
@@ -1,515 +0,0 @@
1−/*
2−* Copyright (C) 2013 Canonical, Ltd.
3−*
4−* Authors:
5−* Pawel Stolowski <pawel.stolowski@canonical.com>
6−*
7−* This program is free software; you can redistribute it and/or modify
8−* it under the terms of the GNU General Public License as published by
9−* the Free Software Foundation; version 3.
10−*
11−* This program is distributed in the hope that it will be useful,
12−* but WITHOUT ANY WARRANTY; without even the implied warranty of
13−* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14−* GNU General Public License for more details.
15−*
16−* You should have received a copy of the GNU General Public License
17−* along with this program. If not, see <http://www.gnu.org/licenses/>.
18−*/
19−
20−#include "filtersbindingstest.h"
21−
22−// libunity-core
23−#include <UnityCore/Filter.h>
24−#include <UnityCore/MultiRangeFilter.h>
25−
26−// Qt
27−#include <QTest>
28−#include <QSignalSpy>
29−
30−// libunity
31−#include <unity.h>
32−
33−// local
34−#include "filter.h"
35−#include "multirangefilter.h"
36−#include "checkoptionfilter.h"
37−#include "radiooptionfilter.h"
38−#include "ratingsfilter.h"
39−#include "ratingfilteroption.h"
40−#include "genericoptionsmodel.h"
41−
42−void FiltersBindingsTest::initTestCase()
43−{
44−}
45−
46−GVariant* FiltersBindingsTest::createOptions(int numOfOptions)
47−{
48− auto vtype = g_variant_type_new("a(sssb)");
49− auto vb = g_variant_builder_new(vtype);
50− for (int i = 0; i<numOfOptions; i++) {
51− const std::string optId = "opt" + std::to_string(i);
52− const std::string optName = "Option " + std::to_string(i);
53− g_variant_builder_add(vb, "(sssb)", optId.c_str(), optName.c_str(), "", false);
54− }
55− return g_variant_builder_end(vb);
56−}
57−
58−DeeModel* FiltersBindingsTest::createFilterModel()
59−{
60− const char* filter_schema[8] = {"s", "s", "s", "s", "a{sv}", "b", "b", "b"};
61− auto model = dee_sequence_model_new();
62− dee_model_set_schema_full (DEE_MODEL(model), filter_schema, 8);
63− return model;
64−}
65−
66−void FiltersBindingsTest::createMultiRangeFilter(DeeModel *model, const std::string &id, const std::string &name, int optionCount)
67−{
68− createFilter(model, "filter-multirange", id, name, optionCount, true);
69−}
70−
71−void FiltersBindingsTest::createRadioOptionFilter(DeeModel *model, const std::string &id, const std::string &name, int optionCount)
72−{
73− createFilter(model, "filter-radiooption", id, name, optionCount, true);
74−}
75−
76−void FiltersBindingsTest::createCheckOptionFilter(DeeModel *model, const std::string &id, const std::string &name, int optionCount)
77−{
78− createFilter(model, "filter-checkoption", id, name, optionCount, true);
79−}
80−
81−void FiltersBindingsTest::createRatingsFilter(DeeModel *model, const std::string &id, const std::string &name)
82−{
83− GVariant* row[8];
84−
85− row[0] = g_variant_new_string(id.c_str());
86− row[1] = g_variant_new_string(name.c_str());
87− row[2] = g_variant_new_string(""); // icon hint
88− row[3] = g_variant_new_string("filter-ratings");
89−
90− GVariant *children[2];
91− GVariant *key1 = g_variant_new_string("show-all-button");
92− GVariant *key2 = g_variant_new_string("rating");
93− children[0] = g_variant_new_dict_entry(key1, g_variant_new_variant(g_variant_new_boolean(true)));
94− children[1] = g_variant_new_dict_entry(key2, g_variant_new_variant(g_variant_new_double(0.0f)));
95− auto fhints = g_variant_new_array(G_VARIANT_TYPE("{sv}"), children, 2);
96−
97− row[4] = fhints;
98− row[5] = g_variant_new_boolean(true); // visible
99− row[6] = g_variant_new_boolean(false); // collapsed
100− row[7] = g_variant_new_boolean(false); // filtering
101−
102− dee_model_append_row(model, row);
103−}
104−
105−void FiltersBindingsTest::createFilter(DeeModel *model, const std::string &renderer, const std::string &id, const std::string &name, int optionCount, bool showAll)
106−{
107− GVariant* row[8];
108−
109− row[0] = g_variant_new_string(id.c_str());
110− row[1] = g_variant_new_string(name.c_str());
111− row[2] = g_variant_new_string(""); // icon hint
112− row[3] = g_variant_new_string(renderer.c_str()); // renderer
113−
114− GVariant *children[2];
115− GVariant *key1 = g_variant_new_string("show-all-button");
116− GVariant *key2 = g_variant_new_string("options");
117− children[0] = g_variant_new_dict_entry(key1, g_variant_new_variant(g_variant_new_boolean(showAll)));
118− children[1] = g_variant_new_dict_entry(key2, g_variant_new_variant(createOptions(optionCount)));
119− auto fhints = g_variant_new_array(G_VARIANT_TYPE("{sv}"), children, 2);
120−
121− row[4] = fhints;
122− row[5] = g_variant_new_boolean(true); // visible
123− row[6] = g_variant_new_boolean(false); // collapsed
124− row[7] = g_variant_new_boolean(false); // filtering
125−
126− dee_model_append_row(model, row);
127−}
128−
129−void FiltersBindingsTest::testMultiRangeFilter()
130−{
131− auto model = createFilterModel();
132−
133− createMultiRangeFilter(model, "f1", "Filter1", 1);
134− createMultiRangeFilter(model, "f2", "Filter2", 2);
135− createMultiRangeFilter(model, "f3", "Filter3", 3);
136−
137− // create filter out of 1st row
138− auto iter = dee_model_get_first_iter(DEE_MODEL(model));
139− {
140− auto core_filter = unity::dash::Filter::FilterFromIter(model, iter);
141− QVERIFY(core_filter != nullptr);
142− auto bind_filter = Filter::newFromUnityFilter(core_filter);
143− auto multi_filter = dynamic_cast<MultiRangeFilter*>(bind_filter);
144− QVERIFY(multi_filter != nullptr);
145− auto options = multi_filter->options();
146− QCOMPARE(options->rowCount(), 2);
147−
148− auto idx = options->index(1);
149− QVariant id_var = options->data(idx, GenericOptionsModel::RoleId);
150− QVariant name_var = options->data(idx, GenericOptionsModel::RoleName);
151− QVariant icon_var = options->data(idx, GenericOptionsModel::RoleIconHint);
152− QVariant active_var = options->data(idx, GenericOptionsModel::RoleActive);
153−
154− QCOMPARE(id_var.toString(), QString("opt0"));
155− QCOMPARE(name_var.toString(), QString("Option 0"));
156− QCOMPARE(icon_var.toString(), QString(""));
157− QCOMPARE(active_var.toBool(), false);
158−
159− delete multi_filter;
160− }
161−
162− // create filter out of 2nd row
163− iter = dee_model_next(DEE_MODEL(model), iter);
164− {
165− auto core_filter = unity::dash::Filter::FilterFromIter(model, iter);
166− QVERIFY(core_filter != nullptr);
167− auto bind_filter = Filter::newFromUnityFilter(core_filter);
168− auto multi_filter = dynamic_cast<MultiRangeFilter*>(bind_filter);
169− QVERIFY(multi_filter != nullptr);
170− auto options = multi_filter->options();
171− QCOMPARE(options->rowCount(), 3);
172−
173− auto idx = options->index(1);
174− QVariant id_var = options->data(idx, GenericOptionsModel::RoleId);
175− QVariant name_var = options->data(idx, GenericOptionsModel::RoleName);
176− QVariant icon_var = options->data(idx, GenericOptionsModel::RoleIconHint);
177− QVariant active_var = options->data(idx, GenericOptionsModel::RoleActive);
178−
179− QCOMPARE(id_var.toString(), QString("opt0"));
180− QCOMPARE(name_var.toString(), QString("Option 0"));
181− QCOMPARE(icon_var.toString(), QString(""));
182− QCOMPARE(active_var.toBool(), false);
183−
184− AbstractFilterOption* opt1 = options->getRawOption(1);
185− QCOMPARE(opt1->id(), QString("opt0"));
186−
187− AbstractFilterOption* opt2 = options->getRawOption(2);
188− QCOMPARE(opt2->id(), QString("opt1"));
189−
190− delete multi_filter;
191− }
192−
193− // create filter out of 3nd row
194− iter = dee_model_next(DEE_MODEL(model), iter);
195− {
196− auto core_filter = unity::dash::Filter::FilterFromIter(model, iter);
197− QVERIFY(core_filter != nullptr);
198− auto bind_filter = Filter::newFromUnityFilter(core_filter);
199− auto multi_filter = dynamic_cast<MultiRangeFilter*>(bind_filter);
200− QVERIFY(multi_filter != nullptr);
201− auto options = multi_filter->options();
202− QCOMPARE(options->rowCount(), 4);
203−
204− AbstractFilterOption* showAll = options->getRawOption(0);
205− QVERIFY(showAll->id().startsWith("show_all::"));
206−
207− AbstractFilterOption* opt0 = options->getRawOption(1);
208− QCOMPARE(opt0->id(), QString("opt0"));
209−
210− AbstractFilterOption* opt1 = options->getRawOption(2);
211− QCOMPARE(opt1->id(), QString("opt1"));
212−
213− AbstractFilterOption* opt2 = options->getRawOption(3);
214− QCOMPARE(opt2->id(), QString("opt2"));
215−
216− // verify filter options are bound to correct underlying unity options
217− auto core_multi_filter = std::dynamic_pointer_cast<unity::dash::MultiRangeFilter>(core_filter);
218− QCOMPARE(QString::fromStdString(core_multi_filter->options()[0]->id()), QString("opt0"));
219− QCOMPARE(QString::fromStdString(core_multi_filter->options()[1]->id()), QString("opt1"));
220− QCOMPARE(QString::fromStdString(core_multi_filter->options()[2]->id()), QString("opt2"));
221−
222− QSignalSpy opt0spy(opt0, SIGNAL(activeChanged(bool)));
223− QSignalSpy opt1spy(opt1, SIGNAL(activeChanged(bool)));
224− QSignalSpy opt2spy(opt2, SIGNAL(activeChanged(bool)));
225−
226− // test active property changes
227− QCOMPARE(opt0->active(), false);
228−
229− opt0->setActive(true); // activate 1st option
230− QCOMPARE(opt0spy.count(), 1);
231− QCOMPARE(opt1spy.count(), 0);
232− QCOMPARE(opt2spy.count(), 0);
233− QCOMPARE(opt0->active(), true);
234− QCOMPARE(opt1->active(), false);
235− QCOMPARE(opt2->active(), false);
236−
237− opt1->setActive(true);
238− QCOMPARE(opt0spy.count(), 2);
239− QCOMPARE(opt1spy.count(), 1);
240− QCOMPARE(opt2spy.count(), 0);
241− QCOMPARE(opt0->active(), false); //1st combined option gets deactivated
242− QCOMPARE(opt1->active(), true);
243− QCOMPARE(opt2->active(), false);
244−
245− opt1->setActive(false); // and de-activate it
246− QCOMPARE(opt0spy.count(), 2);
247− QCOMPARE(opt1spy.count(), 2);
248− QCOMPARE(opt2spy.count(), 0);
249− QCOMPARE(opt0->active(), false);
250− QCOMPARE(opt1->active(), false);
251− QCOMPARE(opt2->active(), false);
252−
253− opt2->setActive(true); // activate another combined option
254− QCOMPARE(opt0spy.count(), 2);
255− QCOMPARE(opt1spy.count(), 2);
256− QCOMPARE(opt2spy.count(), 1);
257− QCOMPARE(opt0->active(), false);
258− QCOMPARE(opt1->active(), false);
259− QCOMPARE(opt2->active(), true);
260−
261− delete multi_filter;
262− }
263−}
264−
265−void FiltersBindingsTest::testCheckOptionFilter()
266−{
267− auto model = createFilterModel();
268−
269− createCheckOptionFilter(model, "f1", "Filter1", 3);
270−
271− // create filter out of 1st row
272− auto iter = dee_model_get_first_iter(DEE_MODEL(model));
273− {
274− auto core_filter = unity::dash::Filter::FilterFromIter(model, iter);
275− QVERIFY(core_filter != nullptr);
276− auto bind_filter = Filter::newFromUnityFilter(core_filter);
277− auto check_filter = dynamic_cast<CheckOptionFilter*>(bind_filter);
278− QVERIFY(check_filter != nullptr);
279− auto options = check_filter->options();
280− QCOMPARE(options->rowCount(), 4);
281−
282− QCOMPARE(check_filter->id(), QString("f1"));
283− QCOMPARE(check_filter->name(), QString("Filter1"));
284− QCOMPARE(check_filter->iconHint(), QString(""));
285− QCOMPARE(check_filter->rendererName(), QString("filter-checkoption"));
286− QCOMPARE(check_filter->visible(), true);
287− QCOMPARE(check_filter->collapsed(), false);
288− QCOMPARE(check_filter->filtering(), false);
289−
290− auto idx = options->index(1);
291− QVariant id_var = options->data(idx, GenericOptionsModel::RoleId);
292− QVariant name_var = options->data(idx, GenericOptionsModel::RoleName);
293− QVariant icon_var = options->data(idx, GenericOptionsModel::RoleIconHint);
294− QVariant active_var = options->data(idx, GenericOptionsModel::RoleActive);
295−
296− QCOMPARE(id_var.toString(), QString("opt0"));
297− QCOMPARE(name_var.toString(), QString("Option 0"));
298− QCOMPARE(icon_var.toString(), QString(""));
299− QCOMPARE(active_var.toBool(), false);
300−
301− idx = options->index(2);
302− id_var = options->data(idx, GenericOptionsModel::RoleId);
303− name_var = options->data(idx, GenericOptionsModel::RoleName);
304− icon_var = options->data(idx, GenericOptionsModel::RoleIconHint);
305− active_var = options->data(idx, GenericOptionsModel::RoleActive);
306−
307− QCOMPARE(id_var.toString(), QString("opt1"));
308− QCOMPARE(name_var.toString(), QString("Option 1"));
309− QCOMPARE(icon_var.toString(), QString(""));
310− QCOMPARE(active_var.toBool(), false);
311−
312− AbstractFilterOption* showAll = options->getRawOption(0);
313− AbstractFilterOption* opt0 = options->getRawOption(1);
314− AbstractFilterOption* opt1 = options->getRawOption(2);
315− AbstractFilterOption* opt2 = options->getRawOption(3);
316−
317− QSignalSpy showAllSpy(showAll, SIGNAL(activeChanged(bool)));
318− QSignalSpy opt0spy(opt0, SIGNAL(activeChanged(bool)));
319− QSignalSpy opt1spy(opt1, SIGNAL(activeChanged(bool)));
320− QSignalSpy opt2spy(opt2, SIGNAL(activeChanged(bool)));
321− QSignalSpy dataChangedSpy(options, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&, const QVector<int>&)));
322−
323− // test active property changes
324− QCOMPARE(showAll->active(), false);
325− QCOMPARE(opt0->active(), false);
326− QCOMPARE(opt1->active(), false);
327− QCOMPARE(opt2->active(), false);
328−
329− opt0->setActive(true);
330− QCOMPARE(showAllSpy.count(), 0);
331− QCOMPARE(opt0spy.count(), 1);
332− QCOMPARE(opt1spy.count(), 0);
333− QCOMPARE(opt2spy.count(), 0);
334− QCOMPARE(showAll->active(), false);
335− QCOMPARE(opt0->active(), true);
336− QCOMPARE(opt1->active(), false);
337− QCOMPARE(opt2->active(), false);
338−
339− opt1->setActive(true);
340− QCOMPARE(showAllSpy.count(), 0);
341− QCOMPARE(opt0spy.count(), 2);
342− QCOMPARE(opt1spy.count(), 1);
343− QCOMPARE(opt2spy.count(), 0);
344− QCOMPARE(showAll->active(), false);
345− QCOMPARE(opt0->active(), false);
346− QCOMPARE(opt1->active(), true);
347− QCOMPARE(opt2->active(), false);
348−
349− QCOMPARE(dataChangedSpy.count(), 3);
350−
351− showAll->setActive(true);
352− QCOMPARE(showAllSpy.count(), 1);
353− QCOMPARE(opt0spy.count(), 2);
354− QCOMPARE(opt1spy.count(), 2);
355− QCOMPARE(opt2spy.count(), 0);
356− QCOMPARE(showAll->active(), true);
357− QCOMPARE(opt0->active(), false);
358− QCOMPARE(opt1->active(), false);
359− QCOMPARE(opt2->active(), false);
360−
361− delete check_filter;
362− }
363−}
364−
365−void FiltersBindingsTest::testRadioOptionFilter()
366−{
367− auto model = createFilterModel();
368−
369− createRadioOptionFilter(model, "f1", "Filter1", 3);
370−
371− // create filter out of 1st row
372− auto iter = dee_model_get_first_iter(DEE_MODEL(model));
373− {
374− auto core_filter = unity::dash::Filter::FilterFromIter(model, iter);
375− QVERIFY(core_filter != nullptr);
376− auto bind_filter = Filter::newFromUnityFilter(core_filter);
377− auto radio_filter = dynamic_cast<RadioOptionFilter*>(bind_filter);
378− QVERIFY(radio_filter != nullptr);
379− auto options = radio_filter->options();
380− QCOMPARE(options->rowCount(), 4);
381−
382− auto idx = options->index(0);
383− QVariant id_var = options->data(idx, GenericOptionsModel::RoleId);
384− QVariant name_var = options->data(idx, GenericOptionsModel::RoleName);
385− QVariant icon_var = options->data(idx, GenericOptionsModel::RoleIconHint);
386− QVariant active_var = options->data(idx, GenericOptionsModel::RoleActive);
387−
388− QVERIFY(id_var.toString().startsWith("show_all::"));
389− QVERIFY(name_var.toString().size() > 0);
390− QCOMPARE(icon_var.toString(), QString(""));
391− QCOMPARE(active_var.toBool(), false);
392−
393− idx = options->index(1);
394− id_var = options->data(idx, GenericOptionsModel::RoleId);
395− name_var = options->data(idx, GenericOptionsModel::RoleName);
396− icon_var = options->data(idx, GenericOptionsModel::RoleIconHint);
397− active_var = options->data(idx, GenericOptionsModel::RoleActive);
398−
399− QCOMPARE(id_var.toString(), QString("opt0"));
400− QCOMPARE(name_var.toString(), QString("Option 0"));
401− QCOMPARE(icon_var.toString(), QString(""));
402− QCOMPARE(active_var.toBool(), false);
403−
404− idx = options->index(2);
405− id_var = options->data(idx, GenericOptionsModel::RoleId);
406− name_var = options->data(idx, GenericOptionsModel::RoleName);
407− icon_var = options->data(idx, GenericOptionsModel::RoleIconHint);
408− active_var = options->data(idx, GenericOptionsModel::RoleActive);
409−
410− QCOMPARE(id_var.toString(), QString("opt1"));
411− QCOMPARE(name_var.toString(), QString("Option 1"));
412− QCOMPARE(icon_var.toString(), QString(""));
413− QCOMPARE(active_var.toBool(), false);
414−
415− AbstractFilterOption* opt0 = options->getRawOption(1);
416− AbstractFilterOption* opt1 = options->getRawOption(2);
417− AbstractFilterOption* opt2 = options->getRawOption(3);
418−
419− QSignalSpy opt0spy(opt0, SIGNAL(activeChanged(bool)));
420− QSignalSpy opt1spy(opt1, SIGNAL(activeChanged(bool)));
421− QSignalSpy opt2spy(opt2, SIGNAL(activeChanged(bool)));
422− QSignalSpy dataChangedSpy(options, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&, const QVector<int>&)));
423−
424− // test active property changes
425− QCOMPARE(opt0->active(), false);
426− QCOMPARE(opt1->active(), false);
427− QCOMPARE(opt2->active(), false);
428−
429− opt0->setActive(true);
430− QCOMPARE(opt0spy.count(), 1);
431− QCOMPARE(opt1spy.count(), 0);
432− QCOMPARE(opt2spy.count(), 0);
433− QCOMPARE(opt0->active(), true);
434− QCOMPARE(opt1->active(), false);
435− QCOMPARE(opt2->active(), false);
436−
437− opt1->setActive(true);
438− QCOMPARE(opt0spy.count(), 2);
439− QCOMPARE(opt1spy.count(), 1);
440− QCOMPARE(opt2spy.count(), 0);
441− QCOMPARE(opt0->active(), false);
442− QCOMPARE(opt1->active(), true);
443− QCOMPARE(opt2->active(), false);
444−
445− QCOMPARE(dataChangedSpy.count(), 3);
446−
447− delete radio_filter;
448− }
449−}
450−
451−void FiltersBindingsTest::testRatingsFilter()
452−{
453− auto model = createFilterModel();
454−
455− createRatingsFilter(model, "f1", "Filter1");
456−
457− // create filter out of 1st row
458− auto iter = dee_model_get_first_iter(DEE_MODEL(model));
459− {
460− auto core_filter = unity::dash::Filter::FilterFromIter(model, iter);
461− QVERIFY(core_filter != nullptr);
462− auto bind_filter = Filter::newFromUnityFilter(core_filter);
463− auto rating_filter = dynamic_cast<RatingsFilter*>(bind_filter);
464− QVERIFY(rating_filter != nullptr);
465− auto options = rating_filter->options();
466− QCOMPARE(options->rowCount(), 6);
467−
468− RatingFilterOption* opt[5];
469− for (int i = 0; i<5; i++) {
470− opt[i] = dynamic_cast<RatingFilterOption *>(options->getRawOption(i+1));
471− }
472−
473− QSignalSpy opt0spy(opt[0], SIGNAL(activeChanged(bool)));
474− QSignalSpy opt4spy(opt[4], SIGNAL(activeChanged(bool)));
475− QSignalSpy dataChangedSpy(options, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&, const QVector<int>&)));
476−
477− QVERIFY(qAbs(opt[0]->value() - 0.2f) <= 0.0001f);
478− QVERIFY(qAbs(opt[1]->value() - 0.4f) <= 0.0001f);
479− QVERIFY(qAbs(opt[2]->value() - 0.6f) <= 0.0001f);
480− QVERIFY(qAbs(opt[3]->value() - 0.8f) <= 0.0001f);
481− QVERIFY(qAbs(opt[4]->value() - 1.0f) <= 0.0001f);
482−
483− QVERIFY(rating_filter->rating() <= 0.0001f); // rating equals zero
484−
485− // all options initially inactive
486− for (int i=0; i<5; i++) {
487− QCOMPARE(opt[i]->active(), false);
488− }
489−
490− // verify activation for all options
491− for (int i=0; i<5; i++) {
492− opt[i]->setActive(true);
493− QCOMPARE(opt[i]->active(), true);
494− QVERIFY(rating_filter->rating() - ((i+1)*0.2f) <= 0.0001f);
495−
496− // verify that all other options are inactive
497− for (int j=0; j<5; j++) {
498− if (i != j) {
499− QCOMPARE(opt[j]->active(), false);
500− }
501− }
502− }
503−
504− QCOMPARE(opt0spy.count(), 2);
505− QCOMPARE(opt4spy.count(), 1);
506−
507− opt[4]->setActive(false);
508− QVERIFY(rating_filter->rating() <= 0.0001f); // rating equals zero
509− QCOMPARE(opt4spy.count(), 2);
510−
511− QCOMPARE(dataChangedSpy.count(), 10);
512− }
513−}
514−
515−QTEST_MAIN(FiltersBindingsTest)
tests/plugins/Unity/filtersbindingstest.hdeleted−47
@@ -1,47 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * Authors:
5− * Pawel Stolowski <pawel.stolowski@canonical.com>
6− *
7− * This program is free software; you can redistribute it and/or modify
8− * it under the terms of the GNU General Public License as published by
9− * the Free Software Foundation; version 3.
10− *
11− * This program is distributed in the hope that it will be useful,
12− * but WITHOUT ANY WARRANTY; without even the implied warranty of
13− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14− * GNU General Public License for more details.
15− *
16− * You should have received a copy of the GNU General Public License
17− * along with this program. If not, see <http://www.gnu.org/licenses/>.
18− */
19−
20−#ifndef FILTERSBINDINGSTEST_H
21−#define FILTERSBINDINGSTEST_H
22−
23−#include <QObject>
24−#include <dee.h>
25−
26−class FiltersBindingsTest : public QObject
27−{
28− Q_OBJECT
29−
30− private Q_SLOTS:
31− void initTestCase();
32− void testMultiRangeFilter();
33− void testCheckOptionFilter();
34− void testRadioOptionFilter();
35− void testRatingsFilter();
36−
37− private:
38− DeeModel* createFilterModel();
39− GVariant* createOptions(int numOfOptions);
40− void createMultiRangeFilter(DeeModel *model, const std::string &id, const std::string &name, int optionCount);
41− void createCheckOptionFilter(DeeModel *model, const std::string &id, const std::string &name, int optionCount);
42− void createRadioOptionFilter(DeeModel *model, const std::string &id, const std::string &name, int optionCount);
43− void createRatingsFilter(DeeModel *model, const std::string &id, const std::string &name);
44− void createFilter(DeeModel *model, const std::string &renderer, const std::string &id, const std::string &name, int optionCount, bool showAll);
45−};
46−
47−#endif // FILTERSBINDINGSTEST_H
tests/plugins/Unity/previewbindingstest.cppdeleted−194
@@ -1,194 +0,0 @@
1−/*
2− * Copyright (C) 2011, 2013 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#include "previewbindingstest.h"
18−#include <QTest>
19−
20−#include <UnityCore/Preview.h>
21−#include <UnityCore/GLibWrapper.h>
22−#include <UnityCore/Variant.h>
23−#include <unity-protocol.h>
24−
25−#include "genericpreview.h"
26−#include "applicationpreview.h"
27−#include "moviepreview.h"
28−#include "musicpreview.h"
29−#include "socialpreview.h"
30−#include "socialpreviewcomment.h"
31−#include "previewaction.h"
32−
33−#include <glib.h>
34−#include <glib-object.h>
35−
36−void PreviewBindingsTest::initTestCase()
37−{
38−}
39−
40−void PreviewBindingsTest::testGenericPreview()
41−{
42− auto rawPreview = (GObject *)unity_protocol_generic_preview_new();
43− unity_protocol_preview_set_title(UNITY_PROTOCOL_PREVIEW(rawPreview), "Metallica");
44− unity_protocol_preview_set_subtitle(UNITY_PROTOCOL_PREVIEW(rawPreview), "Ride The Lightning");
45− unity_protocol_preview_set_description(UNITY_PROTOCOL_PREVIEW(rawPreview), "Lorem ipsum dolor sit amet");
46− GFile *iconFile = g_file_new_for_path("/foo.png");
47− GIcon *icon = g_file_icon_new(iconFile);
48− unity_protocol_preview_add_action(UNITY_PROTOCOL_PREVIEW(rawPreview), "1", "Action1", icon,
49− UNITY_PROTOCOL_LAYOUT_HINT_LEFT);
50− unity::glib::Object<GObject> genPrv(rawPreview);
51−
52− // create local result
53− unity::glib::HintsMap hints;
54− hints["a"] = unity::glib::Variant(g_variant_new_string("b"));
55− unity::dash::LocalResult localResult;
56− localResult.uri = "http://foo";
57− localResult.icon_hint = "xyz";
58− localResult.category_index = 1;
59− localResult.result_type = 2;
60− localResult.mimetype = "abc";
61− localResult.name = "baz";
62− localResult.comment = "qwerty";
63− localResult.dnd_uri = "zzz";
64− localResult.hints = hints;
65−
66− auto corePrv = unity::dash::Preview::PreviewForProtocolObject(genPrv);
67− corePrv->preview_result = localResult;
68−
69− auto prv = Preview::newFromUnityPreview(corePrv);
70−
71− QCOMPARE(prv != nullptr, true);
72− QCOMPARE(prv->title(), QString("Metallica"));
73− QCOMPARE(prv->subtitle(), QString("Ride The Lightning"));
74− QCOMPARE(prv->description(), QString("Lorem ipsum dolor sit amet"));
75−
76− auto actions = prv->actions().value<QList<QObject *>>();
77− QCOMPARE(actions.size(), 1);
78− auto act = dynamic_cast<PreviewAction *>(actions[0]);
79− QVERIFY(act != nullptr);
80− QCOMPARE(act->id(), QString("1"));
81− QCOMPARE(act->displayName(), QString("Action1"));
82− QCOMPARE(act->iconHint(), QString("/foo.png"));
83−
84− Result* res = prv->result().value<Result*>();
85− QCOMPARE(res->uri(), QString("http://foo"));
86− QCOMPARE(res->iconHint(), QString("xyz"));
87− QCOMPARE(res->categoryIndex(), 1u);
88− QCOMPARE(res->resultType(), 2u);
89− QCOMPARE(res->mimeType(), QString("abc"));
90− QCOMPARE(res->title(), QString("baz"));
91− QCOMPARE(res->dndUri(), QString("zzz"));
92− QCOMPARE(res->metadata().toHash()["a"].toString(), QString("b"));
93−
94− g_object_unref(icon);
95− g_object_unref(iconFile);
96−}
97−
98−void PreviewBindingsTest::testApplicationPreview()
99−{
100− auto rawPreview = (GObject *)unity_protocol_application_preview_new();
101− unity_protocol_preview_set_title(UNITY_PROTOCOL_PREVIEW(rawPreview), "Firefox");
102− unity_protocol_preview_set_subtitle(UNITY_PROTOCOL_PREVIEW(rawPreview), "Web Browser");
103− unity_protocol_preview_set_description(UNITY_PROTOCOL_PREVIEW(rawPreview), "Lorem ipsum dolor sit amet");
104− unity_protocol_application_preview_set_license(UNITY_PROTOCOL_APPLICATION_PREVIEW(rawPreview), "GPL");
105− unity_protocol_application_preview_set_rating(UNITY_PROTOCOL_APPLICATION_PREVIEW(rawPreview), 0.5f);
106− unity_protocol_application_preview_set_num_ratings(UNITY_PROTOCOL_APPLICATION_PREVIEW(rawPreview), 4);
107− unity::glib::Object<GObject> genPrv(rawPreview);
108−
109− auto corePrv = unity::dash::Preview::PreviewForProtocolObject(genPrv);
110− auto prv = Preview::newFromUnityPreview(corePrv);
111− auto appPrv = dynamic_cast<ApplicationPreview*>(prv);
112−
113− QCOMPARE(appPrv != nullptr, true);
114− QCOMPARE(appPrv->title(), QString("Firefox"));
115− QCOMPARE(appPrv->subtitle(), QString("Web Browser"));
116− QCOMPARE(appPrv->description(), QString("Lorem ipsum dolor sit amet"));
117− QCOMPARE(appPrv->license(), QString("GPL"));
118− QCOMPARE(appPrv->rating(), 0.5f);
119− QCOMPARE(appPrv->numRatings(), unsigned (4));
120−}
121−
122−void PreviewBindingsTest::testMoviePreview()
123−{
124− auto rawPreview = (GObject *)unity_protocol_movie_preview_new();
125− unity_protocol_preview_set_title(UNITY_PROTOCOL_PREVIEW(rawPreview), "Blade Runner");
126− unity_protocol_preview_set_subtitle(UNITY_PROTOCOL_PREVIEW(rawPreview), "Ridley Scott");
127− unity_protocol_preview_set_description(UNITY_PROTOCOL_PREVIEW(rawPreview), "Lorem ipsum dolor sit amet");
128− unity_protocol_movie_preview_set_year(UNITY_PROTOCOL_MOVIE_PREVIEW(rawPreview), "1982");
129− unity::glib::Object<GObject> genPrv(rawPreview);
130−
131− auto corePrv = unity::dash::Preview::PreviewForProtocolObject(genPrv);
132− auto prv = Preview::newFromUnityPreview(corePrv);
133− auto moviePrv = dynamic_cast<MoviePreview*>(prv);
134−
135− QCOMPARE(moviePrv != nullptr, true);
136− QCOMPARE(moviePrv->title(), QString("Blade Runner"));
137− QCOMPARE(moviePrv->subtitle(), QString("Ridley Scott"));
138− QCOMPARE(moviePrv->description(), QString("Lorem ipsum dolor sit amet"));
139− QCOMPARE(moviePrv->year(), QString("1982"));
140−}
141−
142−void PreviewBindingsTest::testMusicPreview()
143−{
144− auto rawPreview = (GObject *)unity_protocol_music_preview_new();
145− unity_protocol_preview_set_title(UNITY_PROTOCOL_PREVIEW(rawPreview), "Metallica");
146− unity_protocol_preview_set_subtitle(UNITY_PROTOCOL_PREVIEW(rawPreview), "Death Magnetic");
147− unity_protocol_preview_set_description(UNITY_PROTOCOL_PREVIEW(rawPreview), "Lorem ipsum dolor sit amet");
148− unity::glib::Object<GObject> genPrv(rawPreview);
149−
150− auto corePrv = unity::dash::Preview::PreviewForProtocolObject(genPrv);
151− auto prv = Preview::newFromUnityPreview(corePrv);
152− auto musicPrv = dynamic_cast<MusicPreview*>(prv);
153−
154− QCOMPARE(musicPrv != nullptr, true);
155− QCOMPARE(musicPrv->title(), QString("Metallica"));
156− QCOMPARE(musicPrv->subtitle(), QString("Death Magnetic"));
157− QCOMPARE(musicPrv->description(), QString("Lorem ipsum dolor sit amet"));
158−}
159−
160−void PreviewBindingsTest::testSocialPreview()
161−{
162− GFile *iconFile = g_file_new_for_path("/foo.png");
163− GIcon *icon = g_file_icon_new(iconFile);
164−
165− auto rawPreview = (GObject *)unity_protocol_social_preview_new();
166− unity_protocol_social_preview_set_sender(UNITY_PROTOCOL_SOCIAL_PREVIEW(rawPreview), "John");
167− unity_protocol_social_preview_set_avatar(UNITY_PROTOCOL_SOCIAL_PREVIEW(rawPreview), icon);
168− unity_protocol_social_preview_set_content(UNITY_PROTOCOL_SOCIAL_PREVIEW(rawPreview), "Lorem ipsum dolor sit amet");
169− unity_protocol_social_preview_add_comment(UNITY_PROTOCOL_SOCIAL_PREVIEW(rawPreview), "1", "comment1", "Ubuntu", "2013-07-04 14:10");
170− unity::glib::Object<GObject> genPrv(rawPreview);
171−
172− auto corePrv = unity::dash::Preview::PreviewForProtocolObject(genPrv);
173− auto prv = Preview::newFromUnityPreview(corePrv);
174− auto socialPrv = dynamic_cast<SocialPreview*>(prv);
175−
176− QCOMPARE(socialPrv != nullptr, true);
177− QCOMPARE(socialPrv->sender(), QString("John"));
178− QCOMPARE(socialPrv->content(), QString("Lorem ipsum dolor sit amet"));
179− QCOMPARE(socialPrv->avatar(), QString("/foo.png"));
180−
181− auto comments = socialPrv->comments().value<QList<QObject *>>();
182− QCOMPARE(comments.size(), 1);
183− auto cmt = dynamic_cast<SocialPreviewComment *>(comments[0]);
184− QVERIFY(cmt != nullptr);
185− QCOMPARE(cmt->id(), QString("1"));
186− QCOMPARE(cmt->displayName(), QString("comment1"));
187− QCOMPARE(cmt->content(), QString("Ubuntu"));
188− QCOMPARE(cmt->time(), QString("2013-07-04 14:10"));
189−
190− g_object_unref(icon);
191− g_object_unref(iconFile);
192−}
193−
194−QTEST_MAIN(PreviewBindingsTest)
tests/plugins/Unity/previewbindingstest.hdeleted−35
@@ -1,35 +0,0 @@
1−/*
2− * Copyright (C) 2011, 2013 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#ifndef PREVIEWBINDINGSTEST_H
18−#define PREVIEWBINDINGSTEST_H
19−
20−#include <QObject>
21−
22−class PreviewBindingsTest : public QObject
23−{
24− Q_OBJECT
25−
26− private Q_SLOTS:
27− void initTestCase();
28− void testGenericPreview();
29− void testApplicationPreview();
30− void testMoviePreview();
31− void testMusicPreview();
32− void testSocialPreview();
33−};
34−
35−#endif
tests/plugins/Unity/resultstest.cppdeleted−248
@@ -1,248 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− *
16− * Authors:
17− * Michal Hruby <michal.hruby@canonical.com>
18− */
19−
20−#include <QTest>
21−#include <dee.h>
22−#include <glib.h>
23−
24−#include "resultstest.h"
25−#include "categoryresults.h"
26−#include "variantutils.h"
27−
28−static DeeModel* createBackendModel()
29−{
30− auto model = dee_sequence_model_new();
31− dee_model_set_schema(model, "s", "s", "u", "u", "s", "s", "s", "s", "a{sv}", NULL);
32−
33− return model;
34−}
35−
36−void ResultsTest::testAllColumns()
37−{
38− auto deeModel = createBackendModel();
39− GVariantBuilder builder;
40− g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT);
41− g_variant_builder_add(&builder, "{sv}", "metadata-field", g_variant_new_string("foo"));
42− dee_model_append (deeModel,
43− "test:uri",
44− "themed-icon",
45− 4,
46− 0,
47− "application/octet-stream",
48− "Test",
49− "Comment",
50− "test:dnd-uri",
51− g_variant_builder_end(&builder));
52−
53− CategoryResults* results = new CategoryResults(this);
54− results->setModel(deeModel);
55−
56− auto index = results->index(0, 0); // there's just one result
57− QCOMPARE(index.data(CategoryResults::Roles::RoleUri).toString(), QString("test:uri"));
58− QCOMPARE(index.data(CategoryResults::Roles::RoleIconHint).toString(), QString("image://theme/themed-icon"));
59− QCOMPARE(index.data(CategoryResults::Roles::RoleCategory).toInt(), 4);
60− QCOMPARE(index.data(CategoryResults::Roles::RoleMimetype).toString(), QString("application/octet-stream"));
61− QCOMPARE(index.data(CategoryResults::Roles::RoleTitle).toString(), QString("Test"));
62− QCOMPARE(index.data(CategoryResults::Roles::RoleComment).toString(), QString("Comment"));
63− QCOMPARE(index.data(CategoryResults::Roles::RoleDndUri).toString(), QString("test:dnd-uri"));
64− auto metadata = index.data(CategoryResults::Roles::RoleMetadata).toHash();
65− QCOMPARE(metadata["metadata-field"].toString(), QString("foo"));
66−}
67−
68−void ResultsTest::testIconColumn_data()
69−{
70− QTest::addColumn<QString>("uri");
71− QTest::addColumn<QString>("giconString");
72− QTest::addColumn<QString>("result");
73−
74− QTest::newRow("unspecified") << "test:uri" << "" << "";
75− QTest::newRow("absolute path") << "test:uri" << "/usr/share/icons/example.png" << "/usr/share/icons/example.png";
76− QTest::newRow("file uri") << "test:uri" << "file:///usr/share/icons/example.png" << "file:///usr/share/icons/example.png";
77− QTest::newRow("http uri") << "test:uri" << "http://images.ubuntu.com/example.jpg" << "http://images.ubuntu.com/example.jpg";
78− QTest::newRow("image uri") << "test:uri" << "image://thumbnail/with/arguments?passed_to=ImageProvider" << "image://thumbnail/with/arguments?passed_to=ImageProvider";
79− QTest::newRow("themed icon") << "test:uri" << "accessories-other" << "image://theme/accessories-other";
80− QTest::newRow("fileicon") << "test:uri" << ". GFileIcon http://example.org/resource.gif" << "http://example.org/resource.gif";
81− QTest::newRow("themedicon") << "test:uri" << ". GThemedIcon accessories-other accessories generic" << "image://theme/accessories-other,accessories,generic";
82− QTest::newRow("annotatedicon") << "test:uri" << ". UnityProtocolAnnotatedIcon %7B'base-icon':%20%3C'.%20GThemedIcon%20accessories-other%20accessories%20generic'%3E%7D" << "image://theme/accessories-other,accessories,generic";
83− QTest::newRow("thumbnailer icon") << "file:///usr/share/samples/video/foo.avi" << "" << "image://thumbnailer//usr/share/samples/video/foo.avi";
84−}
85−
86−void ResultsTest::testIconColumn()
87−{
88− QFETCH(QString, uri);
89− QFETCH(QString, giconString);
90− QFETCH(QString, result);
91− auto deeModel = createBackendModel();
92− dee_model_append (deeModel,
93− uri.toLocal8Bit().constData(),
94− giconString.toLocal8Bit().constData(),
95− 0,
96− 0,
97− "application/octet-stream",
98− "Test",
99− "",
100− "test:dnd-uri",
101− g_variant_new_array(g_variant_type_element(G_VARIANT_TYPE_VARDICT), NULL, 0));
102−
103− CategoryResults* results = new CategoryResults(this);
104− results->setModel(deeModel);
105−
106− auto index = results->index(0, 0); // there's just one result
107− auto transformedIcon = index.data(CategoryResults::Roles::RoleIconHint).toString();
108− QCOMPARE(transformedIcon, result);
109−}
110−
111−class GVariantWrapper
112−{
113−public:
114− GVariantWrapper() : variant(NULL) {}
115− GVariantWrapper(GVariant* v) {
116− variant = v ? g_variant_ref_sink(v) : NULL;
117− }
118− GVariantWrapper(const GVariantWrapper& other) {
119− variant = other.variant ? g_variant_ref(other.variant) : NULL;
120− }
121− ~GVariantWrapper() {
122− if (variant) g_variant_unref(variant);
123− }
124−
125− GVariant* variant;
126−};
127−
128−Q_DECLARE_METATYPE(GVariantWrapper)
129−
130−void ResultsTest::testSpecialIcons_data()
131−{
132− QTest::addColumn<QString>("uri");
133− QTest::addColumn<GVariantWrapper>("metadata");
134− QTest::addColumn<QString>("result");
135−
136− GVariant *inner;
137− GVariantBuilder builder, inner_builder;
138−
139− g_variant_builder_init(&inner_builder, G_VARIANT_TYPE_VARDICT);
140− g_variant_builder_add(&inner_builder, "{sv}", "artist", g_variant_new_string("U2"));
141− g_variant_builder_add(&inner_builder, "{sv}", "album", g_variant_new_string("War"));
142−
143− g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT);
144− g_variant_builder_add(&builder, "{sv}", "content", g_variant_builder_end(&inner_builder));
145−
146− QTest::newRow("simple") << "file:///foo.mp3" << GVariantWrapper(g_variant_builder_end(&builder)) << "image://albumart/U2/War";
147−
148− g_variant_builder_init(&inner_builder, G_VARIANT_TYPE_VARDICT);
149− g_variant_builder_add(&inner_builder, "{sv}", "artist", g_variant_new_string("U2"));
150− g_variant_builder_add(&inner_builder, "{sv}", "album", g_variant_new_string("War/Joshua tree"));
151− inner = g_variant_builder_end(&inner_builder);
152−
153− g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT);
154− g_variant_builder_add(&builder, "{sv}", "content", inner);
155−
156− QTest::newRow("with-slash") << "file:///foo.mp3" << GVariantWrapper(g_variant_builder_end(&builder)) << "image://albumart/U2/War%2FJoshua%20tree";
157−
158− g_variant_builder_init(&inner_builder, G_VARIANT_TYPE_VARDICT);
159− g_variant_builder_add(&inner_builder, "{sv}", "artist", g_variant_new_string("U2"));
160− g_variant_builder_add(&inner_builder, "{sv}", "album", g_variant_new_string("War"));
161− inner = g_variant_builder_end(&inner_builder);
162−
163− g_variant_builder_init(&inner_builder, G_VARIANT_TYPE_VARDICT);
164− g_variant_builder_add(&inner_builder, "{sv}", "content", inner);
165−
166− g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT);
167− g_variant_builder_add(&builder, "{sv}", "content", g_variant_builder_end(&inner_builder));
168−
169− QTest::newRow("nested") << "file:///foo.mp3" << GVariantWrapper(g_variant_builder_end(&builder)) << "image://albumart/U2/War";
170−}
171−
172−void ResultsTest::testSpecialIcons()
173−{
174− QFETCH(QString, uri);
175− QFETCH(GVariantWrapper, metadata);
176− QFETCH(QString, result);
177− auto deeModel = createBackendModel();
178− dee_model_append (deeModel,
179− uri.toLocal8Bit().constData(),
180− "",
181− 0,
182− 0,
183− "audio/mp3",
184− "Test",
185− "",
186− uri.toLocal8Bit().constData(),
187− metadata.variant);
188−
189− CategoryResults* results = new CategoryResults(this);
190− results->setModel(deeModel);
191−
192− auto index = results->index(0, 0); // there's just one result
193− auto transformedIcon = index.data(CategoryResults::Roles::RoleIconHint).toString();
194− QCOMPARE(transformedIcon, result);
195−}
196−
197−void ResultsTest::testMetadataOverride_data()
198−{
199− QTest::addColumn<QString>("uri");
200− QTest::addColumn<QVariantHash>("result");
201−
202− QVariantHash expected_result;
203− QVariantHash inner_hash;
204−
205− expected_result = QVariantHash();
206− expected_result["scope-id"] = QVariant::fromValue(QString("applications.scope"));
207− expected_result["content"] = QVariant::fromValue(QVariantHash());
208−
209− QTest::newRow("single scope") << "subscope:applications.scope" << expected_result;
210−
211− expected_result = QVariantHash();
212− expected_result["scope-id"] = QVariant::fromValue(QString("applications.scope"));
213− inner_hash = QVariantHash();
214− inner_hash["foo"] = QVariant::fromValue(QString("bar"));
215− inner_hash["qoo"] = QVariant::fromValue(QString("baz"));
216− expected_result["content"] = QVariant::fromValue(inner_hash);
217−
218− QTest::newRow("single scope with data") << "subscope:applications.scope?foo=bar&qoo=baz" << expected_result;
219−
220− expected_result = QVariantHash();
221− inner_hash = QVariantHash();
222− inner_hash["scope-id"] = QVariant::fromValue(QString("applications-local.scope"));
223− inner_hash["content"] = QVariant::fromValue(QVariantHash());
224− expected_result["scope-id"] = QVariant::fromValue(QString("applications.scope"));
225− expected_result["content"] = QVariant::fromValue(inner_hash);
226− QTest::newRow("master scope") << "subscope:applications.scope/applications-local.scope" << expected_result;
227−
228− expected_result = QVariantHash();
229− expected_result["foo"] = QVariant::fromValue(QString("baz"));
230− expected_result["qoo"] = QVariant::fromValue(QString("baz"));
231− inner_hash = QVariantHash();
232− inner_hash["scope-id"] = QVariant::fromValue(QString("applications-local.scope"));
233− inner_hash["content"] = QVariant::fromValue(expected_result);
234− expected_result = QVariantHash();
235− expected_result["scope-id"] = QVariant::fromValue(QString("applications.scope"));
236− expected_result["content"] = QVariant::fromValue(inner_hash);
237− QTest::newRow("nested with data") << "subscope:applications.scope/applications-local.scope?foo=baz&qoo=baz" << expected_result;
238−}
239−
240−void ResultsTest::testMetadataOverride()
241−{
242− QFETCH(QString, uri);
243− QFETCH(QVariantHash, result);
244−
245− QCOMPARE(subscopeUriToMetadataHash(uri), result);
246−}
247−
248−QTEST_MAIN(ResultsTest)
tests/plugins/Unity/signalslisttest.cppdeleted−57
@@ -1,57 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−// local
18−#include "signalslisttest.h"
19−#include "signalslist.h"
20−
21−// Qt
22−#include <QTest>
23−
24−class TestSource
25−{
26− public:
27− TestSource(): m_count(0) {}
28− void update()
29− {
30− countChanged(++m_count);
31− }
32−
33− sigc::signal<void, int> countChanged;
34− int m_count;
35−};
36−
37−void SignalsListTest::testSignalsList()
38−{
39− TestSource src;
40− SignalsList signals;
41− int counter = -1;
42−
43− signals << src.countChanged.connect([&counter](int val) {
44− counter = val;
45− });
46−
47− src.update();
48− QCOMPARE(counter, 1);
49− src.update();
50− QCOMPARE(counter, 2);
51−
52− signals.disconnectAll();
53− src.update();
54− QCOMPARE(counter, 2);
55−}
56−
57−QTEST_MAIN(SignalsListTest)
tests/qmltests/CMakeLists.txt+5−5
@@ -13,11 +13,8 @@ set(qmltest_DEFAULT_NO_ADD_TEST FALSE)
1313set(qmltest_DEFAULT_PROPERTIES ENVIRONMENT "QT_QPA_PLATFORM=minimal")
1414add_qml_test(Components AnimationControllerWithSignals)
1515add_qml_test(Components Carousel)
16−add_qml_test(Components MathLocal)
1716add_qml_test(Components OpenEffect)
1817add_qml_test(Components RatingStars)
19−add_qml_test(Components TimeLocal)
20−add_qml_test(Greeter Clock IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/plugins)
2118add_qml_test(Panel IndicatorItem)
2219add_qml_test(utils/Unity/Test UnityTest)
2320
@@ -47,7 +44,6 @@ add_qml_test(Dash DashContent IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest
4744add_qml_test(Dash DashPreview)
4845add_qml_test(Dash GenericPreview)
4946add_qml_test(Dash GenericScopeView IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
50−add_qml_test(Dash ScopeView IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
5147add_qml_test(Dash FilterGrids IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/plugins ${CMAKE_CURRENT_SOURCE_DIR}/plugins
5248 ${CMAKE_BINARY_DIR}/tests/mocks)
5349add_qml_test(Dash/Apps RunningApplicationsGrid IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
@@ -61,15 +57,19 @@ add_qml_test(Greeter Phone IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DE
6157 ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/libusermetrics:${CMAKE_BINARY_DIR}/tests/mocks/LightDM/single")
6258add_qml_test(Greeter Infographics IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS}
6359 ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/libusermetrics:${CMAKE_BINARY_DIR}/tests/mocks/LightDM/full")
60+add_qml_test(Greeter Clock IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS}
61+ ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/QMenuModel")
6462add_qml_test(Hud Hud)
6563add_qml_test(Hud Result)
6664add_qml_test(Launcher Launcher IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
67−add_qml_test(Notifications Notifications IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_SOURCE_DIR}/tests/mocks)
65+add_qml_test(Notifications Notifications IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/plugins)
6866add_qml_test(Panel IndicatorRow)
6967add_qml_test(Panel Indicators IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
7068add_qml_test(Panel MenuContent IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
7169add_qml_test(Panel Panel IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
7270add_qml_test(Panel SearchIndicator)
71+add_qml_test(Panel/Indicators DefaultIndicatorWidget IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS}
72+ ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/QMenuModel")
7373add_qml_test(SideStage SideStage IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS}
7474 ${CMAKE_BINARY_DIR}/tests/mocks
7575 ${CMAKE_BINARY_DIR}/plugins)
tests/qmltests/Components/tst_DragHandle.cpp+4−5
@@ -41,7 +41,7 @@ class FakeTimeSource : public UbuntuGestures::TimeSource
4141{
4242public:
4343 FakeTimeSource() { m_msecsSinceReference = 0; }
44− virtual qint64 msecsSinceReference() {return m_msecsSinceReference;}
44+ qint64 msecsSinceReference() override {return m_msecsSinceReference;}
4545 qint64 m_msecsSinceReference;
4646};
4747
@@ -73,7 +73,7 @@ private:
7373 QQuickView *m_view;
7474 QTouchDevice *m_device;
7575 FakeTimer *m_fakeTimer;
76− FakeTimeSource *m_fakeTimeSource;
76+ QSharedPointer<FakeTimeSource> m_fakeTimeSource;
7777};
7878
7979
@@ -102,7 +102,7 @@ void tst_DragHandle::init()
102102 qApp->processEvents();
103103
104104 m_fakeTimer = new FakeTimer;
105− m_fakeTimeSource = new FakeTimeSource;
105+ m_fakeTimeSource.reset(new FakeTimeSource);
106106}
107107
108108void tst_DragHandle::cleanup()
@@ -113,8 +113,7 @@ void tst_DragHandle::cleanup()
113113 delete m_fakeTimer;
114114 m_fakeTimer = 0;
115115
116− delete m_fakeTimeSource;
117− m_fakeTimeSource = 0;
116+ m_fakeTimeSource.reset();
118117}
119118
120119QQuickView *tst_DragHandle::createView()
tests/qmltests/Components/tst_EdgeDemoOverlay.qml+2−2
@@ -112,8 +112,8 @@ Item {
112112 // Test that the 'none' edge skips anywhere
113113 signalSpy.target = none
114114 signalSpy.clear()
115− var backgroundShade = findChild(none, "backgroundShade")
116− tryCompare(none, "opacity", 1)
115+ var backgroundShade = findChild(none, "backgroundShadeMouseArea")
116+ tryCompare(backgroundShade, "enabled", true)
117117 mousePress(backgroundShade, 1, 1)
118118 mouseRelease(backgroundShade, 1, 1)
119119 signalSpy.wait()
tests/qmltests/Components/tst_MathLocal.qmldeleted−91
@@ -1,91 +0,0 @@
1−/*
2− * Copyright 2013 Canonical Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.0
18−import QtTest 1.0
19−import "../../../Components/Math.js" as MathLocal
20−
21−TestCase {
22− name: "MathLocal"
23−
24− property int minValue
25− property int maxValue
26− property int clampValue
27− property int clamped
28−
29− function test_clamp_positive_lower() {
30− minValue = 9
31− maxValue = 42
32− clampValue = -7
33−
34− clamped = MathLocal.clamp(clampValue, minValue, maxValue)
35− compare(clamped, minValue, "clamped value not within range")
36− }
37−
38− function test_clamp_positive_greater() {
39− minValue = 9
40− maxValue = 42
41− clampValue = 111
42−
43− clamped = MathLocal.clamp(clampValue, minValue, maxValue)
44− compare(clamped, maxValue, "clamped value not within range")
45− }
46−
47− function test_clamp_positive_within() {
48− minValue = 9
49− maxValue = 53
50− clampValue = 42
51−
52− clamped = MathLocal.clamp(clampValue, minValue, maxValue)
53− compare(clamped, clampValue, "clamped value changed even though it shouldn't have")
54− }
55−
56− function test_clamp_positive_on_border() {
57− minValue = 9
58− maxValue = 42
59− clampValue = 9
60−
61− clamped = MathLocal.clamp(clampValue, minValue, maxValue)
62− compare(clamped, clampValue, "clamped value changed even though it shouldn't have")
63− }
64−
65− function test_clamp_negative_lower() {
66− minValue = -42
67− maxValue = -9
68− clampValue = -50
69−
70− clamped = MathLocal.clamp(clampValue, minValue, maxValue)
71− compare(clamped, minValue, "clamped value not within range")
72− }
73−
74− function test_clamp_negative_greater() {
75− minValue = -42
76− maxValue = -9
77− clampValue = 50
78−
79− clamped = MathLocal.clamp(clampValue, minValue, maxValue)
80− compare(clamped, maxValue, "clamped value not within range")
81− }
82−
83− function test_clamp_postive_and_negative_greater() {
84− minValue = -42
85− maxValue = 9
86− clampValue = 50
87−
88− clamped = MathLocal.clamp(clampValue, minValue, maxValue)
89− compare(clamped, maxValue, "clamped value not within range")
90− }
91−}
tests/qmltests/Components/tst_PageHeader.qml+44−3
@@ -37,6 +37,10 @@ Item {
3737 property alias searchEnabled : pageHeader.searchEntryEnabled
3838 property alias searchQuery : pageHeader.searchQuery
3939
40+ function init() {
41+ searchEnabled = true;
42+ }
43+
4044 function test_search_disabled() {
4145 searchEnabled = false
4246 pageHeader.resetSearch()
@@ -151,12 +155,48 @@ Item {
151155 scopeMock.searchInProgress = true
152156 compare(searchIndicator.running, true, "Search indicator isn't running.")
153157 tryCompare(primaryImage, "visible", false)
154−
155− pageHeader.resetSearch()
156158 }
157159
158160 function cleanup() {
159− scopeMock.searchInProgress = false
161+ scopeMock.searchInProgress = false;
162+ pageHeader.resetSearch();
163+ }
164+
165+ function test_popover() {
166+ searchEnabled = true;
167+ pageHeader.searchHistory.clear();
168+
169+ pageHeader.searchHistory.addQuery("Search1");
170+ pageHeader.searchHistory.addQuery("Search2");
171+
172+ pageHeader.triggerSearch();
173+
174+ var searchContainer = findChild(pageHeader, "searchContainer");
175+ verify(searchContainer !== undefined, "searchContainer != undefined");
176+ tryCompareFunction(function() { return searchContainer.popover !== null; }, true);
177+
178+ tryCompare(searchContainer.popover, "visible", true);
179+ }
180+
181+ function test_resetSearch_onPopupClose() {
182+ searchEnabled = true;
183+ pageHeader.searchHistory.clear();
184+
185+ pageHeader.searchHistory.addQuery("Search1");
186+ pageHeader.searchHistory.addQuery("Search2");
187+
188+ pageHeader.triggerSearch();
189+
190+ var searchContainer = findChild(pageHeader, "searchContainer");
191+ verify(searchContainer !== undefined, "searchContainer != undefined");
192+ tryCompareFunction(function() { return searchContainer.popover !== null; }, true);
193+ compare(searchContainer.popover.visible, true);
194+
195+ pageHeader.searchQuery = "test";
196+ tryCompareFunction( function() { return (searchContainer.popover===null || !searchContainer.popover.visible) }, true);
197+
198+ pageHeader.resetSearch();
199+ compare((searchContainer.popover===null || !searchContainer.popover.visible), true);
160200 }
161201 }
162202
@@ -174,6 +214,7 @@ Item {
174214 scope: scopeMock
175215
176216 searchEntryEnabled: true
217+ searchHistory: SearchHistoryModel {}
177218 text: "%^$%^%^&%^&%^$%GHR%"
178219 }
179220
tests/qmltests/Components/tst_TimeLocal.qmldeleted−117
@@ -1,117 +0,0 @@
1−/*
2− * Copyright 2013 Canonical Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.0
18−import QtTest 1.0
19−import "../../../Components/Time.js" as TimeLocal
20−
21−TestCase {
22− name: "TimeLocal"
23−
24− property var readableDate
25−
26− function test_readableFromNow_dateUndefined() {
27− readableDate = TimeLocal.readableFromNow()
28− compare(readableDate, "", "readable date should have been null")
29− }
30−
31− function test_readableFromNow_dateNaN() {
32− readableDate = TimeLocal.readableFromNow("this is a string, not a date")
33− compare(readableDate, "", "readable date should have been null")
34− }
35−
36− function test_readableFromNow_justNow() {
37− readableDate = TimeLocal.readableFromNow(new Date())
38− compare(readableDate, "just now", "readable date should have been now")
39− }
40−
41− function test_readableFromNow_nowNaN() {
42− var fail = false
43− try {
44− TimeLocal.readableFromNow(new Date(), "this is a string, not a date")
45− } catch (err) {
46− fail = true
47− } finally {
48− compare(fail, true, "readable date should have thrown an exception")
49− }
50− }
51−
52− function cycleTime(diff, previous, next, units, endIterator) {
53− var now = new Date()
54− var time = now.getTime()
55− readableDate = TimeLocal.readableFromNow(time - diff, now)
56− compare(readableDate, previous, "different time predicted")
57− readableDate = TimeLocal.readableFromNow(time + diff, now)
58− compare(readableDate, next, "different time predicted")
59− for (var i = 2; i < endIterator; i++) {
60− var tmpDiff = i * diff
61− readableDate = TimeLocal.readableFromNow(time - tmpDiff, now)
62− compare(readableDate, i + " " + units + " ago", "different time predicted")
63− readableDate = TimeLocal.readableFromNow(time + tmpDiff, now)
64− compare(readableDate, "in " + i + " " + units, "different time predicted")
65− }
66− }
67−
68− function test_readableFromNow_seconds() {
69− cycleTime(1000, "a second ago", "in a second", "seconds", 60)
70− }
71−
72− function test_readableFromNow_minutes() {
73− cycleTime(1000 * 60, "a minute ago", "in a minute", "minutes", 60)
74− }
75−
76− function test_readableFromNow_hours() {
77− cycleTime(1000 * 60 * 60, "an hour ago", "in an hour", "hours", 24)
78− }
79−
80− function test_readableFromNow_days() {
81− cycleTime(1000 * 60 * 60 * 24, "yesterday", "tomorrow", "days", 7)
82− }
83−
84− function test_readableFromNow_weeks() {
85− var now = new Date()
86− for (var i = 7; i < 30; i++) {
87− readableDate = TimeLocal.readableFromNow(now.getTime() - i * 1000 * 60 * 60 * 24, now)
88− if (i < 14)
89− compare(readableDate, "a week ago", "different time predicted")
90− else if (i < 18)
91− compare(readableDate, "about 2 weeks ago", "different time predicted")
92− else if (i < 25)
93− compare(readableDate, "about 3 weeks ago", "different time predicted")
94− else
95− compare(readableDate, "about 4 weeks ago", "different time predicted")
96− }
97− for (var i = 7; i < 30; i++) {
98− readableDate = TimeLocal.readableFromNow(now.getTime() + i * 1000 * 60 * 60 * 24, now)
99− if (i < 14)
100− compare(readableDate, "in a week", "different time predicted")
101− else if (i < 18)
102− compare(readableDate, "in about 2 weeks", "different time predicted")
103− else if (i < 25)
104− compare(readableDate, "in about 3 weeks", "different time predicted")
105− else
106− compare(readableDate, "in about 4 weeks", "different time predicted")
107− }
108− }
109−
110− function test_readableFromNow_months() {
111− cycleTime(1000 * 60 * 60 * 24 * 30.45, "a month ago", "in a month", "months", 12)
112− }
113−
114− function test_readableFromNow_years() {
115− cycleTime(1000 * 60 * 60 * 24 * 366, "a year ago", "in a year", "years", 5)
116− }
117−}
tests/qmltests/Dash/Apps/tst_RunningApplicationsGrid.qml+1
@@ -226,6 +226,7 @@ Item {
226226 verify(fakeRunningAppsModel.contains("calendar"))
227227
228228 mouseClick(calendarTileCloseButton, calendarTileCloseButton.width/2, calendarTileCloseButton.height/2)
229+ wait(0) // spin event loop to start any pending animation
229230
230231 verify(!fakeRunningAppsModel.contains("calendar"))
231232
tests/qmltests/Dash/qml/FakeScopeView.qml+3−68
@@ -19,13 +19,13 @@ import Unity 0.1
1919
2020import "../../../../Dash"
2121
22−ScopeView {
22+GenericScopeView {
2323 id: fakeScopeView
2424
2525 property alias backColor : back.color
2626
2727 onEndReached: {
28− if (shell != undefined && shell.scopeStatus != undefined) {
28+ if (scope != undefined && shell != undefined && shell.scopeStatus != undefined) {
2929 shell.scopeStatus[scope.id].endReached++;
3030 }
3131 }
@@ -44,71 +44,6 @@ ScopeView {
4444 id: back
4545 anchors.fill: parent
4646 color: "grey"
47− }
48−
49− function randomBg()
50− {
51− var hex1=new Array("4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F")
52− var bg="#"+hex1[Math.floor(Math.random()*hex1.length)]+
53− hex1[Math.floor(Math.random()*hex1.length)]+
54− hex1[Math.floor(Math.random()*hex1.length)]+
55− hex1[Math.floor(Math.random()*hex1.length)]+
56− hex1[Math.floor(Math.random()*hex1.length)]+
57− hex1[Math.floor(Math.random()*hex1.length)]
58− return bg
59− }
60−
61−
62− ListView {
63− id: listView
64− anchors.fill: parent
65− model: scope ? scope.categories : null
66− orientation: ListView.Vertical
67−
68− delegate: Column {
69− id: column
70− width: listView.width
71− height: childrenRect.height
72−
73− Rectangle {
74− width: listView.width
75− height: units.gu(3)
76− color: randomBg()
77−
78− Text {
79− text: name
80− font.family: "Ubuntu"
81− font.weight: Font.Bold
82− font.pixelSize: 20
83− anchors.horizontalCenter: parent.horizontalCenter
84− }
85− }
86− GridView {
87− id: resultsGrid
88− model: results
89− cellWidth: units.gu(10); cellHeight: units.gu(10)
90− height: childrenRect.height
91− width: listView.width
92− interactive: false
93−
94− delegate: Component {
95− id: resultDelegate
96− Item {
97− width: resultsGrid.cellWidth; height: resultsGrid.cellHeight
98− Column {
99− anchors.verticalCenter: parent.verticalCenter
100− anchors.horizontalCenter: parent.horizontalCenter
101− Image {
102− width: units.gu(5)
103− height: units.gu(5)
104− source: icon
105− anchors.horizontalCenter: parent.horizontalCenter
106− }
107− Text { text: title; anchors.horizontalCenter: parent.horizontalCenter }
108− }
109− }
110− }
111− }
112− }
47+ z: -1
11348 }
11449}
tests/qmltests/Dash/tst_Dash.qml+7−1
@@ -102,9 +102,15 @@ Item {
102102 console.log("Not testing " + data.tag + ": not visible");
103103 return;
104104 }
105+ var dashContentList = findChild(dash, "dashContentList");
106+
105107 dash.showScopeOnLoaded = data.tag
108+ scopes.clear();
109+ tryCompare(dashContentList, "count", 0);
110+ scopes.load();
111+ tryCompare(scopes, "loaded", true);
112+ tryCompare(dashContentList, "count", 4);
106113
107− var dashContentList = findChild(dash, "dashContentList");
108114 verify(dashContentList != undefined);
109115 tryCompare(dashContentList, "currentIndex", data.visualIndex);
110116 }
tests/qmltests/Dash/tst_DashContent.qml+37−3
@@ -26,7 +26,17 @@ Item {
2626 width: units.gu(40)
2727 height: units.gu(80)
2828
29− property ListModel searchHistory: ListModel {}
29+ Item {
30+ // Fake. Make a few components less noisy
31+ id: greeter
32+ signal shownChanged
33+ }
34+
35+ Item {
36+ // Fake. Make a few components less noisy
37+ id: panel
38+ signal searchClicked
39+ }
3040
3141 property var scopeStatus: {
3242 'MockScope1': { 'movementStarted': 0, 'positionedAtBeginning': 0 },
@@ -48,6 +58,7 @@ Item {
4858 scopes : scopesModel
4959
5060 scopeMapper : scopeDelegateMapper
61+ searchHistory: ListModel {}
5162 }
5263
5364 ScopeDelegateMapper {
@@ -111,10 +122,10 @@ Item {
111122 clear_scope_status();
112123 dashContent.visible = true;
113124
114− scopesModel.clear();
115− // wait for dash to empty scopes.
116125 var dashContentList = findChild(dashContent, "dashContentList");
117126 verify(dashContentList != undefined);
127+ scopesModel.clear();
128+ // wait for dash to empty scopes.
118129 tryCompare(dashContentList, "count", 0);
119130 }
120131
@@ -229,5 +240,28 @@ Item {
229240 tryCompare(scopesModel.get(1), "isActive", data.active1);
230241 tryCompare(scopesModel.get(2), "isActive", data.active2);
231242 }
243+
244+ function checkFlickMovingAndNotInteractive()
245+ {
246+ var dashContentList = findChild(dashContent, "dashContentList");
247+
248+ if (dashContentList.currentItem.moving && !dashContentList.interactive)
249+ return true;
250+
251+ var startX = dashContentList.width/2;
252+ var startY = dashContentList.height/2;
253+ touchFlick(dashContentList, startX, startY, startX, startY - units.gu(40));
254+
255+ return dashContentList.currentItem.moving && !dashContentList.interactive;
256+ }
257+
258+
259+ function test_hswipe_disabled_vswipe() {
260+ var dashContentList = findChild(dashContent, "dashContentList");
261+
262+ tryCompare(dashContentList, "interactive", true);
263+
264+ tryCompareFunction(checkFlickMovingAndNotInteractive, true);
265+ }
232266 }
233267}
tests/qmltests/Dash/tst_FilterGrids.qml+1−2
@@ -108,8 +108,7 @@ Rectangle {
108108 function test_clicked_signal_data() {
109109 return [
110110 {tag: "VideoFilterGrid", component: "Video/VideoFilterGrid.qml"},
111− {tag: "MusicFilterGrid", component: "Music/MusicFilterGrid.qml"},
112− {tag: "ApplicationsFilterGrid", component: "Apps/ApplicationsFilterGrid.qml"}
111+ {tag: "MusicFilterGrid", component: "Music/MusicFilterGrid.qml"}
113112 ]
114113 }
115114
tests/qmltests/Dash/tst_GenericScopeView.qml+27−2
@@ -74,6 +74,9 @@ Item {
7474 }
7575
7676 function openPreview() {
77+ var categoryListView = findChild(genericScopeView, "categoryListView");
78+ categoryListView.positionAtBeginning();
79+
7780 var tile = findChild(genericScopeView, "delegate0");
7881 mouseClick(tile, tile.width / 2, tile.height / 2);
7982 var openEffect = findChild(genericScopeView, "openEffect");
@@ -129,7 +132,23 @@ Item {
129132 tryCompare(previewListView, "open", false);
130133 }
131134
132− function test_previewCycleOne() {
135+ function test_hiddenPreviewOpen() {
136+ var categoryListView = findChild(genericScopeView, "categoryListView");
137+ categoryListView.positionAtBeginning();
138+ waitForRendering(categoryListView);
139+ categoryListView.flick(0, -units.gu(80));
140+ tryCompare(categoryListView.flicking, false);
141+
142+ var tile = findChild(genericScopeView, "delegate0");
143+ mouseClick(tile, tile.width / 2, tile.height - 1);
144+ var openEffect = findChild(genericScopeView, "openEffect");
145+ tryCompare(openEffect, "gap", 1);
146+
147+ var pageHeader = findChild(genericScopeView, "pageHeader");
148+ verify(openEffect.positionPx >= pageHeader.height + categoryListView.stickyHeaderHeight);
149+ }
150+
151+ function test_previewCycle() {
133152 var previewListView = findChild(genericScopeView, "previewListView");
134153 tryCompare(previewListView, "open", false);
135154
@@ -170,7 +189,6 @@ Item {
170189
171190 checkArrowPosition(i);
172191 }
173−
174192 closePreview();
175193 }
176194
@@ -187,6 +205,13 @@ Item {
187205
188206 closePreview();
189207 }
208+
209+ function test_changeScope() {
210+ genericScopeView.scope.searchQuery = "test"
211+ genericScopeView.scope = scopes.get(1)
212+ genericScopeView.scope = scopes.get(0)
213+ tryCompare(genericScopeView.scope, "searchQuery", "")
214+ }
190215 }
191216 }
192217}
tests/qmltests/Dash/tst_ScopeView.qmldeleted−52
@@ -1,52 +0,0 @@
1−/*
2− * Copyright 2013 Canonical Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.0
18−import QtTest 1.0
19−import Unity 0.1
20−import ".."
21−import "../../../Dash"
22−import Ubuntu.Components 0.1
23−
24−Item {
25− width: units.gu(120)
26− height: units.gu(80)
27−
28− Scopes {
29− id: scopes
30− }
31−
32− ScopeView {
33− id: scopeView
34− anchors.fill: parent
35−
36− TestCase {
37− name: "ScopeView"
38− when: scopes.loaded
39−
40− function init() {
41− scopeView.scope = scopes.get(0)
42− }
43−
44− function test_changeScope() {
45− scopeView.scope.searchQuery = "test"
46− scopeView.scope = scopes.get(1)
47− scopeView.scope = scopes.get(0)
48− tryCompare(scopeView.scope, "searchQuery", "")
49− }
50− }
51− }
52−}
tests/qmltests/Greeter/tst_Clock.qml+16
@@ -19,6 +19,7 @@ import QtTest 1.0
1919import ".."
2020import "../../../Greeter"
2121import Ubuntu.Components 0.1
22+import QMenuModel 0.1
2223import Unity.Test 0.1 as UT
2324
2425Rectangle {
@@ -35,9 +36,24 @@ Rectangle {
3536 }
3637 }
3738
39+ UnityMenuModel {
40+ id: menuModel
41+ modelData: [{
42+ "rowData": {
43+ "actionState": { "label": Qt.formatTime(new Date("October 13, 1975 11:13:00")) }
44+ }
45+ }]
46+ }
47+
3848 UT.UnityTestCase {
3949 name: "Clock"
4050
51+ function init() {
52+ var cachedModel = findChild(clock, "timeModel");
53+ verify(cachedModel !== undefined);
54+ cachedModel.model = menuModel;
55+ }
56+
4157 function test_customDate() {
4258 var dateObj = new Date("October 13, 1975 11:13:00")
4359 var dateString = Qt.formatDate(dateObj, Qt.DefaultLocaleLongDate)
tests/qmltests/Greeter/tst_Lockscreen.qml+81−15
@@ -41,7 +41,7 @@ Rectangle {
4141 target: lockscreen
4242
4343 onEmergencyCall: emergencyCheckBox.checked = true
44− onUnlocked: unlockedCheckBox.checked = true
44+ onEntered: enteredLabel.text = passphrase
4545 }
4646
4747 Connections {
@@ -99,12 +99,11 @@ Rectangle {
9999 anchors.verticalCenter: parent.verticalCenter
100100 }
101101 Row {
102− CheckBox {
103− id: unlockedCheckBox
102+ Label {
103+ text: "Entered:"
104104 }
105105 Label {
106− text: "Unlocked signal"
107− anchors.verticalCenter: parent.verticalCenter
106+ id: enteredLabel
108107 }
109108 }
110109 Button {
@@ -176,15 +175,17 @@ Rectangle {
176175
177176 function test_unlock_data() {
178177 return [
179− {tag: "numeric", alphanumeric: false, username: "has-pin", password: "1234", unlockedSignal: true},
180− {tag: "alphanumeric", alphanumeric: true, username: "has-password", password: "password", unlockedSignal: true},
181− {tag: "numeric (wrong)", alphanumeric: false, username: "has-pin", password: "4321", unlockedSignal: false},
182− {tag: "alphanumeric (wrong)", alphanumeric: true, username: "has-password", password: "drowssap", unlockedSignal: false},
178+ {tag: "numeric", alphanumeric: false, username: "has-pin", password: "1234", pinLength: 4},
179+ {tag: "alphanumeric", alphanumeric: true, username: "has-password", password: "password", pinLength: -1},
180+ {tag: "numeric (wrong)", alphanumeric: false, username: "has-pin", password: "4321", pinLength: 4},
181+ {tag: "alphanumeric (wrong)", alphanumeric: true, username: "has-password", password: "drowssap", pinLength: -1},
182+ {tag: "flexible length", alphanumeric: false, username: "has-pin", password: "1234", pinLength: -1},
183183 ]
184184 }
185185
186186 function test_unlock(data) {
187− unlockedCheckBox.checked = false
187+ enteredLabel.text = ""
188+ pinLengthTextField.text = data.pinLength
188189 LightDM.Greeter.authenticate(data.username)
189190 waitForRendering(lockscreen)
190191
@@ -199,14 +200,79 @@ Rectangle {
199200 var button = findChild(lockscreen, "pinPadButton" + character)
200201 mouseClick(button, units.gu(1), units.gu(1))
201202 }
203+ if (data.pinLength == -1) {
204+ var pinPadButtonErase = findChild(lockscreen, "pinPadButtonErase");
205+ mouseClick(pinPadButtonErase, units.gu(1), units.gu(1));
206+ }
207+ }
208+ tryCompare(enteredLabel, "text", data.password)
209+ }
210+
211+ function test_clear_data() {
212+ return [
213+ {tag: "animated PIN", animation: true, alphanumeric: false},
214+ {tag: "not animated PIN", animation: false, alphanumeric: false},
215+ {tag: "animated passphrase", animation: true, alphanumeric: true},
216+ {tag: "not animated passphrase", animation: false, alphanumeric: true}
217+ ];
218+ }
219+
220+ function test_clear(data) {
221+ pinPadCheckBox.checked = data.alphanumeric
222+ waitForRendering(lockscreen)
223+
224+ var inputField = findChild(lockscreen, "pinentryField")
225+ if (data.alphanumeric) {
226+ mouseClick(inputField, units.gu(1), units.gu(1))
227+ typeString("1")
228+ } else {
229+ var button = findChild(lockscreen, "pinPadButton1")
230+ mouseClick(button, units.gu(1), units.gu(1))
202231 }
203− tryCompare(unlockedCheckBox, "checked", data.unlockedSignal)
204− if (!data.unlockedSignal) {
205− // make sure the input is cleared on wrong input
206− tryCompareFunction(function() {return inputField.text.length == 0}, true)
232+
233+ var animation = findInvisibleChild(lockscreen, "wrongPasswordAnimation")
234+
235+ tryCompare(inputField, "text", "1")
236+
237+ lockscreen.clear(data.animation)
238+ tryCompare(inputField, "text", "")
239+
240+ wait(0) // Trigger event loop to make sure the animation would start running
241+ compare(animation.running, data.animation)
242+
243+ // wait for animation to finish to not disturb other tests
244+ tryCompare(animation, "running", false)
245+ }
246+
247+ function test_backspace_data() {
248+ return [
249+ {tag: "fixed length", pinLength: 4},
250+ {tag: "variable length", pinLength: -1}
251+ ];
252+ }
253+
254+ function test_backspace(data) {
255+ pinPadCheckBox.checked = false
256+ pinLengthTextField.text = data.pinLength
257+ waitForRendering(lockscreen);
258+
259+ var pinPadButtonErase = findChild(lockscreen, "pinPadButtonErase");
260+ var backspaceIcon = findChild(lockscreen, "backspaceIcon");
261+ var pinEntryField = findChild(lockscreen, "pinentryField");
262+
263+ compare(pinPadButtonErase.iconName, data.pinLength == -1 ? "" : "erase");
264+ compare(backspaceIcon.visible, data.pinLength == -1);
265+
266+ var pinPadButton5 = findChild(lockscreen, "pinPadButton5");
267+ mouseClick(pinPadButton5, units.gu(1), units.gu(1));
268+ compare(pinEntryField.text, "5");
269+
270+ if (data.pinLength == -1) {
271+ mouseClick(backspaceIcon, units.gu(1), units.gu(1));
207272 } else {
208− tryCompareFunction(function() {return inputField.text.length > 0}, true)
273+ mouseClick(pinPadButtonErase, units.gu(1), units.gu(1));
209274 }
275+ compare(pinEntryField.text, "");
210276 }
211277 }
212278}
tests/qmltests/Greeter/tst_Phone.qml+5−5
@@ -133,7 +133,7 @@ Item {
133133 tryCompare(LightDM.Infographic, "username", "single")
134134 }
135135
136− function test_wallpaper_data() {
136+ function test_background_data() {
137137 return [
138138 {tag: "set", accounts: "../tests/data/unity/backgrounds/blue.png", expected: "blue.png"},
139139 {tag: "unset", accounts: "", expected: "background.jpg"},
@@ -141,12 +141,12 @@ Item {
141141 ]
142142 }
143143
144− function test_wallpaper(data) {
144+ function test_background(data) {
145145 var loader = findChild(greeter, "greeterContentLoader")
146− var wallpaper = findChild(loader.item, "wallpaper")
146+ var background = findChild(loader.item, "greeterBackground")
147147 AccountsService.backgroundFile = data.accounts
148− tryCompareFunction(function() { return wallpaper.source.toString().indexOf(data.expected) !== -1; }, true)
149− tryCompare(wallpaper, "status", Image.Ready)
148+ tryCompareFunction(function() { return background.source.toString().indexOf(data.expected) !== -1; }, true)
149+ tryCompare(background, "status", Image.Ready)
150150 }
151151 }
152152}
tests/qmltests/Notifications/tst_Notifications.qml+56
@@ -76,6 +76,20 @@ Row {
7676 mockModel.append(n)
7777 }
7878
79+ function addEphemeralNonShapedIconNotification() {
80+ var n = {
81+ type: Notification.Ephemeral,
82+ hints: {"x-canonical-non-shaped-icon": "true"},
83+ summary: "Contacts",
84+ body: "Synchronised contacts-database with cloud-storage.",
85+ icon: "../graphics/applicationIcons/contacts-app.png",
86+ secondaryIcon: "",
87+ actions: []
88+ }
89+
90+ mockModel.append(n)
91+ }
92+
7993 function addEphemeralIconSummaryNotification() {
8094 var n = {
8195 type: Notification.Ephemeral,
@@ -156,6 +170,12 @@ Row {
156170 onClicked: addEphemeralNotification()
157171 }
158172
173+ Button {
174+ width: parent.width
175+ text: "add an non-shaped-icon-summary-body"
176+ onClicked: addEphemeralNonShapedIconNotification()
177+ }
178+
159179 Button {
160180 width: parent.width
161181 text: "add an icon-summary"
@@ -206,6 +226,8 @@ Row {
206226 bodyVisible: true,
207227 interactiveAreaEnabled: false,
208228 iconVisible: true,
229+ shapedIcon: true,
230+ nonShapedIcon: false,
209231 secondaryIconVisible: true,
210232 buttonRowVisible: true,
211233 buttonTinted: true
@@ -223,6 +245,8 @@ Row {
223245 bodyVisible: false,
224246 interactiveAreaEnabled: false,
225247 iconVisible: false,
248+ shapedIcon: false,
249+ nonShapedIcon: false,
226250 secondaryIconVisible: true,
227251 buttonRowVisible: false,
228252 buttonTinted: false
@@ -240,6 +264,8 @@ Row {
240264 bodyVisible: false,
241265 interactiveAreaEnabled: false,
242266 iconVisible: false,
267+ shapedIcon: false,
268+ nonShapedIcon: false,
243269 secondaryIconVisible: true,
244270 buttonRowVisible: false,
245271 buttonTinted: false
@@ -257,6 +283,8 @@ Row {
257283 bodyVisible: true,
258284 interactiveAreaEnabled: true,
259285 iconVisible: true,
286+ shapedIcon: true,
287+ nonShapedIcon: false,
260288 secondaryIconVisible: false,
261289 buttonRowVisible: false,
262290 buttonTinted: false
@@ -275,6 +303,8 @@ Row {
275303 bodyVisible: true,
276304 interactiveAreaEnabled: false,
277305 iconVisible: true,
306+ shapedIcon: true,
307+ nonShapedIcon: false,
278308 secondaryIconVisible: false,
279309 buttonRowVisible: true,
280310 buttonTinted: false
@@ -292,9 +322,31 @@ Row {
292322 bodyVisible: true,
293323 interactiveAreaEnabled: false,
294324 iconVisible: true,
325+ shapedIcon: true,
326+ nonShapedIcon: false,
295327 secondaryIconVisible: true,
296328 buttonRowVisible: false,
297329 buttonTinted: false
330+ },
331+ {
332+ tag: "Ephemeral notification with non-shaped icon",
333+ type: Notification.Ephemeral,
334+ hints: {"x-canonical-private-button-tint": "false",
335+ "x-canonical-non-shaped-icon": "true"},
336+ summary: "Contacts",
337+ body: "Synchronised contacts-database with cloud-storage.",
338+ icon: "../graphics/applicationIcons/contacts-app.png",
339+ secondaryIcon: "",
340+ actions: [],
341+ summaryVisible: true,
342+ bodyVisible: true,
343+ interactiveAreaEnabled: false,
344+ iconVisible: true,
345+ shapedIcon: false,
346+ nonShapedIcon: true,
347+ secondaryIconVisible: false,
348+ buttonRowVisible: false,
349+ buttonTinted: false
298350 }
299351 ]
300352 }
@@ -330,6 +382,8 @@ Row {
330382 verify(notification !== undefined, "notification wasn't found");
331383
332384 var icon = findChild(notification, "icon")
385+ var shapedIcon = findChild(notification, "shapedIcon")
386+ var nonShapedIcon = findChild(notification, "nonShapedIcon")
333387 var interactiveArea = findChild(notification, "interactiveArea")
334388 var secondaryIcon = findChild(notification, "secondaryIcon")
335389 var summaryLabel = findChild(notification, "summaryLabel")
@@ -338,6 +392,8 @@ Row {
338392 waitForRendering(buttonRow)
339393
340394 compare(icon.visible, data.iconVisible, "avatar-icon visibility is incorrect")
395+ compare(shapedIcon.visible, data.shapedIcon, "shaped-icon visibility is incorrect")
396+ compare(nonShapedIcon.visible, data.nonShapedIcon, "non-shaped-icon visibility is incorrect")
341397 compare(interactiveArea.enabled, data.interactiveAreaEnabled, "check for interactive area")
342398
343399 if(data.interactiveAreaEnabled) {
tests/qmltests/Panel/Indicators/tst_DefaultIndicatorWidget.qmlnew file+97
@@ -0,0 +1,97 @@
1+/*
2+ * Copyright 2013 Canonical Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.0
18+import QtTest 1.0
19+import Unity.Test 0.1 as UT
20+import QMenuModel 0.1
21+import "../../../../Panel/Indicators"
22+
23+Item {
24+ id: testView
25+ width: units.gu(40)
26+ height: units.gu(70)
27+
28+ DefaultIndicatorWidget {
29+ id: widget
30+
31+ anchors {
32+ left: parent.left
33+ top: parent.top
34+ }
35+
36+ busName: "test"
37+ actionsObjectPath: "test"
38+ deviceMenuObjectPath: "test"
39+
40+ rootMenuType: ""
41+
42+ iconSize: units.gu(3.2)
43+ height: units.gu(3)
44+
45+ rootActionState {
46+ icons: [ "image://theme/audio-volume-high", "image://theme/audio-volume-low" ]
47+ leftLabel: "left"
48+ rightLabel: "right"
49+ }
50+ }
51+
52+ UT.UnityTestCase {
53+ name: "DefaultIndicatorWidget"
54+ when: windowShown
55+
56+ function init() {
57+ widget.rootActionState.icons = [];
58+ widget.rootActionState.leftLabel = "";
59+ widget.rootActionState.rightLabel = "";
60+ wait(50);
61+ }
62+
63+ function test_guRoundedWidth_data() {
64+ return [
65+ { tag: "empty", icons: [], leftLabel: "", rightLabel: "" },
66+ { tag: "1-icon-no-label", icons: [ "image://theme/audio-volume-high" ], leftLabel: "", rightLabel: "" },
67+ { tag: "2-icon-no-label", icons: [ "image://theme/audio-volume-high", "image://theme/audio-volume-low" ], leftLabel: "", rightLabel: "" },
68+ { tag: "no-icon-l-label", icons: [], leftLabel: "left", rightLabel: "" },
69+ { tag: "no-icon-lr-label", icons: [], leftLabel: "left", rightLabel: "right" },
70+ { tag: "1-icon-l-label", icons: [ "image://theme/audio-volume-high" ], leftLabel: "left", rightLabel: "" },
71+ { tag: "1-icon-lr-label", icons: [ "image://theme/audio-volume-high" ], leftLabel: "left", rightLabel: "right" },
72+ { tag: "2-icon-l-label", icons: [ "image://theme/audio-volume-high", "image://theme/audio-volume-low" ], leftLabel: "left", rightLabel: "" },
73+ { tag: "2-icon-lr-label", icons: [ "image://theme/audio-volume-high", "image://theme/audio-volume-low" ], leftLabel: "left", rightLabel: "right" }
74+ ];
75+ }
76+
77+ function test_guRoundedWidth(data) {
78+ widget.rootActionState.icons = data.icons
79+ widget.rootActionState.leftLabel = data.leftLabel;
80+ widget.rootActionState.rightLabel = data.rightLabel;
81+ wait(50);
82+
83+ compare(widget.width, guRoundUp(widget.width));
84+ }
85+ }
86+
87+ // TODO: Use toolkit function https://bugs.launchpad.net/ubuntu-ui-toolkit/+bug/1242575
88+ function guRoundUp(width) {
89+ if (width == 0) {
90+ return 0;
91+ }
92+ var gu1 = units.gu(1.0);
93+ var mod = (width % gu1);
94+
95+ return mod == 0 ? width : width + (gu1 - mod);
96+ }
97+}
tests/qmltests/Panel/tst_Panel.qml+13−5
@@ -48,10 +48,12 @@ Item {
4848
4949 function get_window_data() {
5050 return [
51− {tag: "pinned", fullscreenFlag: false },
52− {tag: "fullscreen", fullscreenFlag: true }
53− ]}
54−
51+ {tag: "pinned", fullscreenFlag: false, alreadyOpen: false },
52+ {tag: "fullscreen", fullscreenFlag: true, alreadyOpen: false },
53+ {tag: "pinned-alreadyOpen", fullscreenFlag: false, alreadyOpen: true },
54+ {tag: "fullscreen-alreadyOpen", fullscreenFlag: true, alreadyOpen: true }
55+ ];
56+ }
5557
5658 function init() {
5759 searchClicked = false;
@@ -135,6 +137,10 @@ Item {
135137 // expose more of the panel, binding it to the selected indicator and opening it's menu.
136138 function test_drag_show(data) {
137139 panel.fullscreenMode = data.fullscreenFlag;
140+ if (data.alreadyOpen) {
141+ panel.indicators.show();
142+ tryCompare(panel.indicators, "fullyOpened", true);
143+ }
138144
139145 var indicatorRow = findChild(panel.indicators, "indicatorRow");
140146 verify(indicatorRow != undefined);
@@ -186,7 +192,9 @@ Item {
186192 compare(menuContent.currentMenuIndex, i, "Menu conetent should be enabled for item at position " + i);
187193
188194 // init for next indicatorItem
189− init();
195+ if (!data.alreadyOpen) {
196+ init();
197+ }
190198 }
191199 }
192200
tests/qmltests/tst_Shell.qml+74−13
@@ -55,19 +55,45 @@ Item {
5555 when: windowShown
5656
5757 function initTestCase() {
58− swipeAwayGreeter();
58+ var ok = false;
59+ var attempts = 0;
60+ var maxAttempts = 1000;
61+
62+ // Qt loads a qml scene asynchronously. So early on, some findChild() calls made in
63+ // tests may fail because the desired child item wasn't loaded yet.
64+ // Thus here we try to ensure the scene has been fully loaded before proceeding with the tests.
65+ // As I couldn't find an API in QQuickView & friends to tell me that the scene is 100% loaded
66+ // (all items instantiated, etc), I resort to checking the existence of some key items until
67+ // repeatedly until they're all there.
68+ do {
69+ var dashContentList = findChild(shell, "dashContentList");
70+ waitForRendering(dashContentList);
71+ var homeLoader = findChild(dashContentList, "home.scope loader");
72+ ok = homeLoader !== undefined
73+ && homeLoader.item !== undefined;
5974
60− // Ensure DashHome is loaded before continuing
61− var dashContentList = findChild(shell, "dashContentList");
62− waitForRendering(dashContentList);
63− var homeLoader = findChild(dashContentList, "home.scope loader");
64− verify(homeLoader);
65− tryCompareFunction(function() {return homeLoader.item !== undefined;}, true);
75+ var dashHome = findChild(shell, "DashHome");
76+ ok &= dashHome !== undefined;
77+
78+ var greeter = findChild(shell, "greeter");
79+ ok &= greeter !== undefined;
80+
81+ var launcherPanel = findChild(shell, "launcherPanel");
82+ ok &= launcherPanel !== undefined;
6683
67− // FIXME: Desperate measure to ensure Jenkins has the scene graph fully loaded
68− // before it calls the test functions (otherwise findChild calls will fail).
69− // The code above just didn't solve it.
70− wait(2000);
84+ attempts++;
85+ if (!ok) {
86+ console.log("Attempt " + attempts + " failed. Waiting a bit before trying again.");
87+ // wait a bit before retrying
88+ wait(100);
89+ } else {
90+ console.log("All seem fine after " + attempts + " attempts.");
91+ }
92+ } while (!ok && attempts <= maxAttempts);
93+
94+ verify(ok);
95+
96+ swipeAwayGreeter();
7197 }
7298
7399 function cleanup() {
@@ -297,6 +323,10 @@ Item {
297323
298324 waitUntilApplicationWindowIsFullyVisible();
299325
326+ // Dragging launcher into view with a little bit of gap (units.gu(1)) should switch to Apps scope
327+ dragLauncherIntoView();
328+ verify(itemIsOnScreen(dashApps));
329+
300330 // Minimize the application we just launched
301331 swipeFromLeftEdge(units.gu(27));
302332
@@ -437,7 +467,7 @@ Item {
437467 } while (!isStill);
438468 }
439469
440− function test_wallpaper_data() {
470+ function test_background_data() {
441471 return [
442472 {tag: "red", url: "tests/data/unity/backgrounds/red.png", expectedUrl: "tests/data/unity/backgrounds/red.png"},
443473 {tag: "blue", url: "tests/data/unity/backgrounds/blue.png", expectedUrl: "tests/data/unity/backgrounds/blue.png"},
@@ -446,13 +476,21 @@ Item {
446476 ]
447477 }
448478
449− function test_wallpaper(data) {
479+ function test_background(data) {
450480 var backgroundImage = findChild(shell, "backgroundImage")
451481 GSettingsController.setPictureUri(data.url)
452482 tryCompareFunction(function() { return backgroundImage.source.toString().indexOf(data.expectedUrl) !== -1; }, true)
453483 tryCompare(backgroundImage, "status", Image.Ready)
454484 }
455485
486+ function test_lockscreen_background() {
487+ var backgroundImage = findChild(shell, "backgroundImage")
488+ var lockscreen = findChild(shell, "lockscreen")
489+ var lockscreenBackground = findChild(lockscreen, "lockscreenBackground")
490+ var lockscreenBackgroundMapped = lockscreenBackground.mapToItem(shell, 0, 0)
491+ compare(backgroundImage.y, lockscreenBackgroundMapped.y)
492+ }
493+
456494 function test_DashShown_data() {
457495 return [
458496 {tag: "in focus", greeter: false, app: false, launcher: false, indicators: false, expectedShown: true},
@@ -488,5 +526,28 @@ Item {
488526 var dash = findChild(shell, "dash");
489527 tryCompare(dash, "shown", data.expectedShown);
490528 }
529+
530+ function test_searchIndicatorHidesOnAppFocus() {
531+ var searchIndicator = findChild(shell, "container")
532+ tryCompare(searchIndicator, "opacity", 1)
533+ dragLauncherIntoView();
534+
535+ // Launch an app from the launcher
536+ tapOnAppIconInLauncher();
537+ waitUntilApplicationWindowIsFullyVisible();
538+
539+ tryCompare(searchIndicator, "opacity", 0);
540+ }
541+
542+ function test_searchIndicatorHidesOnGreeterShown() {
543+ var searchIndicator = findChild(shell, "container")
544+ var greeter = findChild(shell, "greeter");
545+
546+ tryCompare(searchIndicator, "opacity", 1)
547+
548+ greeter.show()
549+ tryCompare(greeter, "shown", true)
550+ tryCompare(searchIndicator, "opacity", 0)
551+ }
491552 }
492553}
tests/utils/modules/Unity/Test/UnityTestCase.qml+36
@@ -14,6 +14,7 @@
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1515 */
1616
17+import QtQuick 2.0
1718import QtTest 1.0
1819import Ubuntu.Components 0.1
1920import Unity.Test 0.1 as UT
@@ -213,6 +214,8 @@ TestCase {
213214
214215 // speed is in pixels/second
215216 function touchFlick(item, x, y, toX, toY, beginTouch, endTouch, speed, iterations) {
217+ // Make sure the item is rendered
218+ waitForRendering(item);
216219
217220 // Default to true for beginTouch if not present
218221 beginTouch = (beginTouch !== undefined) ? beginTouch : true
@@ -297,4 +300,37 @@ TestCase {
297300 event.release(0 /* touchId */, x, y)
298301 event.commit()
299302 }
303+
304+ Component.onCompleted: {
305+ var rootItem = parent;
306+ while (rootItem.parent != undefined) {
307+ rootItem = rootItem.parent;
308+ }
309+ removeTimeConstraintsFromDirectionalDragAreas(rootItem);
310+ }
311+
312+ /*
313+ In qmltests, sequences of touch events are sent all at once, unlike in "real life".
314+ Also qmltests might run really slowly, e.g. when run from inside virtual machines.
315+ Thus to remove a variable that qmltests cannot really control, namely time, this
316+ function removes all constraints from DirectionalDragAreas that are sensible to
317+ elapsed time.
318+
319+ This effectively makes DirectionalDragAreas easier to fool.
320+ */
321+ function removeTimeConstraintsFromDirectionalDragAreas(item) {
322+
323+ // use duck-typing to identify a DirectionalDragArea
324+ if (item.minSpeed != undefined
325+ && item.maxSilenceTime != undefined
326+ && item.compositionTime != undefined) {
327+ item.minSpeed = 0;
328+ item.maxSilenceTime = 60 * 60 * 1000;
329+ item.compositionTime = 0;
330+ } else {
331+ for (var i in item.children) {
332+ removeTimeConstraintsFromDirectionalDragAreas(item.children[i]);
333+ }
334+ }
335+ }
300336}