on xenial help sign in
Merged with trunk
commitf3837eefd672adf4bd8915bafb11c13862177a1e authorNick Dedekind <nicholas.dedekind@gmail.com> dateWed 3 Jul 2013, 17:33 (13 years ago) parent79e5c53c3c1984
66 files changed+2484−911
Components/DragHandle.qml+4 Greeter/GreeterContent.qml+1 Panel/Indicators.qml+114−28 Panel/MenuContent.qml+1−1 Panel/Panel.qml+3−74 debian/control+2 debian/rules+4 plugins/LightDM/CMakeLists.txt+4−1 plugins/LightDM/Greeter.cpp+6−6 plugins/LightDM/Greeter.h+4−4 plugins/LightDM/plugin.cpp+5−4 plugins/ListViewWithPageHeader/listviewwithpageheader.cpp+3 plugins/Ubuntu/Gestures/DirectionalDragArea.cpp+3−3 plugins/Ubuntu/Gestures/DirectionalDragArea.h+3−3 plugins/Unity/CMakeLists.txt+8 plugins/Unity/applicationpreview.cpp+96 plugins/Unity/applicationpreview.h+66 plugins/LightDM/InfographicModel.h → plugins/Unity/genericpreview.cpp+10−11 plugins/Unity/genericpreview.h+40 plugins/Unity/moviepreview.cpp+67 plugins/Unity/moviepreview.h+60 plugins/Unity/musicpreview.cpp+54 plugins/Unity/musicpreview.h+62 plugins/Unity/plugin.cpp+6 plugins/Unity/preview.cpp+173 plugins/Unity/preview.h+80 plugins/Unity/previewaction.cpp+75 plugins/Unity/previewaction.h+71 plugins/Unity/previewinfohint.cpp+67 plugins/Unity/previewinfohint.h+58 plugins/Unity/scope.cpp+79−11 plugins/Unity/scope.h+20−3 plugins/Unity/variantutils.cpp+158 plugins/Unity/variantutils.h+34 plugins/Utils/qlimitproxymodelqml.cpp+4−4 run+5−5 tests/autopilot/unity8/tests/__init__.py+2−2 tests/mocks/CMakeLists.txt+1 tests/mocks/LightDM/CMakeLists.txt+3 tests/mocks/LightDM/InfographicModel.cpp−416 tests/mocks/LightDM/InfographicModelPrivate.h−99 tests/mocks/LightDM/demo/CMakeLists.txt+11−2 tests/mocks/LightDM/demo/UsersModelPrivate.cpp+1−1 tests/mocks/LightDM/full/CMakeLists.txt−2 tests/mocks/LightDM/single-passphrase/CMakeLists.txt−2 tests/mocks/LightDM/single-passphrase/UsersModelPrivate.cpp+1−1 tests/mocks/LightDM/single-pin/CMakeLists.txt−2 tests/mocks/LightDM/single-pin/UsersModelPrivate.cpp+1−1 tests/mocks/LightDM/single/CMakeLists.txt−2 tests/mocks/LightDM/single/UsersModelPrivate.cpp+1−1 tests/mocks/libusermetrics/CMakeLists.txt+17 tests/mocks/libusermetrics/ColorTheme.cpp+128 tests/mocks/libusermetrics/ColorTheme.h+68 tests/mocks/libusermetrics/UserMetrics.cpp+465 tests/mocks/LightDM/InfographicModel.h → tests/mocks/libusermetrics/UserMetrics.h+22−60 tests/mocks/libusermetrics/libusermetricsoutput/ColorTheme.h+1 tests/mocks/libusermetrics/libusermetricsoutput/UserMetrics.h+1 tests/plugins/CMakeLists.txt+1 tests/plugins/ListViewWithPageHeader/listviewwithpageheadertest.cpp+6 tests/plugins/Unity/CMakeLists.txt+38 tests/plugins/Unity/previewbindingstest.cpp+114 tests/plugins/Unity/previewbindingstest.h+34 tests/plugins/Utils/qlimitproxymodeltest.cpp+15 tests/qmltests/CMakeLists.txt+4−4 tests/qmltests/Panel/tst_Indicators.qml+34−45 tests/qmltests/Panel/tst_Panel.qml+65−113
Components/DragHandle.qml+4
@@ -48,6 +48,10 @@ EdgeDragArea {
4848 id: dragArea
4949 objectName: "dragHandle"
5050
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)
54+
5155 property bool stretch: false
5256
5357 property alias autoCompleteDragThreshold: dragEvaluator.dragThreshold
Greeter/GreeterContent.qml+1
@@ -124,6 +124,7 @@ MouseArea {
124124
125125 function updateUsername(uid) {
126126 greeterContentLoader.infographicModel.username = greeterContentLoader.model.data(uid, LightDM.UserRoles.NameRole)
127+ greeterContentLoader.infographicModel.readyForDataChangeSlot();
127128 }
128129
129130 anchors {
Panel/Indicators.qml+114−28
@@ -16,35 +16,51 @@
1616
1717import QtQuick 2.0
1818import Ubuntu.Components 0.1
19+import Ubuntu.Gestures 0.1
1920
2021import "../Components"
22+import "../Components/ListItems"
2123import "../Components/Math.js" as MathLocal
2224
2325Showable {
2426 id: indicators
2527
26− property int progress: panelHeight
27− property int openedHeight: units.gu(71)
28+ property int referenceOpenedHeight: units.gu(71)
29+ property real openedHeight: pinnedMode ? referenceOpenedHeight - panelHeight
30+ : referenceOpenedHeight
2831 property int panelHeight: units.gu(3)
2932 property bool pinnedMode: true //should be set true if indicators menu can cover whole screen
3033
3134 property int hintValue
32− readonly property int lockThreshold: shell.height/2
33− property bool fullyOpened: revealer ? progress == revealer.openedValue : false
34− property bool partiallyOpened: revealer ? progress > revealer.closedValue && progress < revealer.openedValue : false
35+ readonly property int lockThreshold: referenceOpenedHeight / 2
36+ property bool fullyOpened: height == openedHeight
37+ property bool partiallyOpened: height > panelHeight && !fullyOpened
38+
39+ // TODO: Perhaps we need a animation standard for showing/hiding? Each showable seems to
40+ // use its own values. Need to ask design about this.
41+ showAnimation: StandardAnimation {
42+ property: "height"
43+ duration: 350
44+ to: openedHeight
45+ easing.type: Easing.OutCubic
46+ }
3547
36− property Revealer revealer: null
48+ hideAnimation: StandardAnimation {
49+ property: "height"
50+ duration: 350
51+ to: panelHeight
52+ easing.type: Easing.OutCubic
53+ }
3754
38− height: menuContent.height + handle.height + menuContent.y
55+ height: panelHeight
3956
40− onProgressChanged: {
41− // need to use handle.get_height(). As the handle height depends on progress changes (but this is called first!)
42− var contentProgress = progress - handle.get_height()
43− if (!showAnimation.running && !hideAnimation.running && !revealer.hintingAnimation.running) {
57+ onHeightChanged: {
58+ // need to use handle.get_height(). As the handle height depends on indicators.height changes (but this is called first!)
59+ var contentProgress = indicators.height - handle.get_height()
60+ if (!showAnimation.running && !hideAnimation.running) {
4461 if (contentProgress <= hintValue && indicators.state == "reveal") {
4562 indicators.state = "hint"
4663 menuContent.hideAll()
47− menuContent.releaseContent()
4864 } else if (contentProgress > hintValue && contentProgress < lockThreshold) {
4965 menuContent.showMenu()
5066 indicators.state = "reveal"
@@ -59,12 +75,10 @@ Showable {
5975 indicators.state = "locked"
6076 }
6177 }
62− }
6378
64− function handlePress() {
65− menuContent.hideAll()
66− menuContent.activateContent()
67− indicators.state = "hint"
79+ if (contentProgress == 0) {
80+ menuContent.releaseContent()
81+ }
6882 }
6983
7084 function openOverview() {
@@ -86,7 +100,9 @@ Showable {
86100 If bar is dragged down a distance greater than or equal to lockThreshold, this is 1.
87101 Otherwise it contains the bar's location as a fraction of the distance between hintValue (is 0) and lockThreshold (is 1).
88102 */
89− var verticalProgress = MathLocal.clamp((indicators.progress - handle.height - hintValue) / (lockThreshold - hintValue), 0, 1)
103+ var verticalProgress =
104+ MathLocal.clamp((indicators.height - handle.height - hintValue) /
105+ (lockThreshold - hintValue), 0, 1)
90106
91107 /*
92108 Percentage of an indicator icon's width the user's press can stray horizontally from the
@@ -134,6 +150,17 @@ Showable {
134150 }
135151 }
136152
153+ VerticalThinDivider {
154+ anchors {
155+ top: indicators.top
156+ topMargin: panelHeight
157+ bottom: handle.bottom
158+ right: indicators.left
159+ }
160+ width: units.dp(2)
161+ source: "graphics/VerticalDivider.png"
162+ }
163+
137164 MenuContent {
138165 id: menuContent
139166 objectName: "menuContent"
@@ -142,8 +169,8 @@ Showable {
142169 left: parent.left
143170 right: parent.right
144171 top: indicatorRow.bottom
172+ bottom: parent.bottom
145173 }
146− height: progress - y
147174 indicatorsModel: indicatorsModel
148175 animate: false
149176 clip: indicators.partiallyOpened
@@ -182,7 +209,7 @@ Showable {
182209 clip: height < handleImage.height
183210
184211 function get_height() {
185− return Math.max(Math.min(handleImage.height, progress - handleImage.height), 0)
212+ return Math.max(Math.min(handleImage.height, indicators.height - handleImage.height), 0)
186213 }
187214
188215 BorderImage {
@@ -200,6 +227,29 @@ Showable {
200227 }
201228 }
202229
230+ PanelSeparatorLine {
231+ id: indicatorsSeparatorLine
232+ visible: true
233+ anchors {
234+ top: handle.bottom
235+ left: indicators.left
236+ right: indicators.right
237+ }
238+ }
239+
240+ BorderImage {
241+ id: dropShadow
242+ anchors {
243+ top: indicators.top
244+ bottom: indicatorsSeparatorLine.bottom
245+ left: indicators.left
246+ right: indicators.right
247+ margins: -units.gu(1)
248+ }
249+ visible: indicators.height > panelHeight
250+ source: "graphics/rectangular_dropshadow.sci"
251+ }
252+
203253 PanelBackground {
204254 anchors.fill: indicatorRow
205255 }
@@ -230,7 +280,6 @@ Showable {
230280 if (hideAnimation.running) {
231281 indicators.state = "initial"
232282 menuContent.hideAll()
233− menuContent.releaseContent()
234283 } else {
235284 if (state == "initial") indicatorRow.setDefaultItem()
236285 }
@@ -243,7 +292,7 @@ Showable {
243292 if (indicators.state == "initial") {
244293 openOverview()
245294 } else {
246− indicators.calculateCurrentItem(revealer.lateralPosition, false)
295+ indicators.calculateCurrentItem(dragHandle.touchX, false)
247296 menuContent.showMenu()
248297 }
249298 indicators.state = "commit"
@@ -252,10 +301,10 @@ Showable {
252301 }
253302
254303 Connections {
255− target: revealer
256− onLateralPositionChanged: {
257− var buffer = revealer.dragging ? true : false
258− indicators.calculateCurrentItem(revealer.lateralPosition, buffer)
304+ target: dragHandle
305+ onTouchXChanged: {
306+ var buffer = dragHandle.dragging ? true : false
307+ indicators.calculateCurrentItem(dragHandle.touchX, buffer)
259308 }
260309 }
261310
@@ -271,6 +320,43 @@ Showable {
271320 state = last_state;
272321 }
273322
323+ property var dragHandle: showDragHandle.dragging ? showDragHandle : hideDragHandle
324+ DragHandle {
325+ id: showDragHandle
326+ anchors.bottom: parent.bottom
327+ // go beyond parent so that it stays reachable, at the top of the screen.
328+ anchors.bottomMargin: pinnedMode ? 0 : -panelHeight
329+ anchors.left: parent.left
330+ anchors.right: parent.right
331+ height: panelHeight
332+ direction: Direction.Downwards
333+ enabled: !indicators.shown
334+ hintDisplacement: pinnedMode ? indicators.hintValue : 0
335+ autoCompleteDragThreshold: maxTotalDragDistance / 2
336+ stretch: true
337+ maxTotalDragDistance: openedHeight - handle.height
338+ distanceThreshold: pinnedMode ? 0 : units.gu(3)
339+
340+ onStatusChanged: {
341+ if (status === DirectionalDragArea.Recognized) {
342+ menuContent.hideAll()
343+ menuContent.activateContent()
344+ }
345+ }
346+ }
347+ DragHandle {
348+ id: hideDragHandle
349+ anchors.fill: handle
350+ height: panelHeight
351+ direction: Direction.Upwards
352+ enabled: indicators.shown
353+ hintDisplacement: units.gu(2)
354+ autoCompleteDragThreshold: maxTotalDragDistance / 6
355+ stretch: true
356+ maxTotalDragDistance: referenceOpenedHeight - 2*panelHeight
357+ distanceThreshold: 0
358+ }
359+
274360 property list<State> offScreenModeStates: [
275361 State {
276362 name: "initial"
@@ -283,7 +369,7 @@ Showable {
283369 name: "reveal"
284370 extend: "hint"
285371 PropertyChanges { target: menuContent; animate: true }
286− StateChangeScript { script: calculateCurrentItem(revealer.lateralPosition, false); }
372+ StateChangeScript { script: calculateCurrentItem(dragHandle.touchX, false); }
287373 },
288374 State {
289375 name: "locked"
@@ -305,7 +391,7 @@ Showable {
305391 State {
306392 name: "reveal"
307393 PropertyChanges { target: menuContent; animate: true }
308− StateChangeScript { script: calculateCurrentItem(revealer.lateralPosition, false); }
394+ StateChangeScript { script: calculateCurrentItem(dragHandle.touchX, false); }
309395 },
310396 State {
311397 name: "locked"
Panel/MenuContent.qml+1−1
@@ -99,7 +99,7 @@ Rectangle {
9999 visible: content.__shown
100100 onVisibleChanged: {
101101 // Reset the indicator states
102− if (!visible && item) {
102+ if (!visible && item && item["reset"]) {
103103 item.reset()
104104 }
105105 }
Panel/Panel.qml+3−74
@@ -17,7 +17,6 @@
1717import QtQuick 2.0
1818import Ubuntu.Components 0.1
1919import "../Components"
20−import "../Components/ListItems"
2120
2221Item {
2322 id: root
@@ -75,29 +74,6 @@ Item {
7574 }
7675 }
7776
78− BorderImage {
79− id: dropShadow
80− anchors {
81− top: indicatorsMenu.top
82− bottom: indicatorsSeparatorLine.bottom
83− left: indicatorsMenu.left
84− right: indicatorsMenu.right
85− margins: -units.gu(1)
86− }
87− visible: indicatorsMenu.progress != indicatorRevealer.closedValue
88− source: "graphics/rectangular_dropshadow.sci"
89− }
90−
91− VerticalThinDivider {
92− anchors {
93− top: leftSeparatorLine.top
94− bottom: indicatorsSeparatorLine.top
95− right: indicatorsMenu.left
96− }
97− width: units.dp(2)
98− source: "graphics/VerticalDivider.png"
99− }
100−
10177 Indicators {
10278 id: indicatorsMenu
10379
@@ -105,58 +81,13 @@ Item {
10581 y: 0
10682 width: root.indicatorsMenuWidth
10783 shown: false
108− revealer: indicatorRevealer
109− hintValue: indicatorRevealer.hintDisplacement
84+ hintValue: __panelMinusSeparatorLineHeight * 3
11085 panelHeight: __panelMinusSeparatorLineHeight
111− showAnimation: StandardAnimation { property: "progress"; duration: 350; to: indicatorRevealer.openedValue; easing.type: Easing.OutCubic }
112− hideAnimation: StandardAnimation { property: "progress"; duration: 350; to: indicatorRevealer.closedValue; easing.type: Easing.OutCubic }
113− openedHeight: parent.height
86+ referenceOpenedHeight: parent.height
11487
11588 pinnedMode: !fullscreenMode
11689
117− property real unitProgress: (indicatorRevealer.closedValue - progress) / (indicatorRevealer.closedValue - indicatorRevealer.openedValue)
118− }
119−
120− PanelSeparatorLine {
121− id: indicatorsSeparatorLine
122− anchors {
123− top: indicatorsMenu.bottom
124− left: indicatorsMenu.left
125− right: parent.right
126− }
127− }
128−
129− Revealer {
130− id: indicatorRevealer
131− objectName: "indicatorRevealer"
132−
133− width: root.indicatorsMenuWidth
134− anchors {
135− top: parent.top
136− bottom: parent.bottom
137− right: parent.right
138− }
139− target: indicatorsMenu
140− handleSize: __panelMinusSeparatorLineHeight
141− closedValue: __panelMinusSeparatorLineHeight
142− dragVelocityThreshold: units.dp(1)
143− boundProperty: "progress"
144− hintDisplacement: __panelMinusSeparatorLineHeight * 3
145− openOnPress: !fullscreenMode
146− orientation: Qt.Vertical
147−
148− onOpenClicked: {
149− indicatorsMenu.openOverview();
150− indicatorsMenu.show();
151− }
152− onCloseClicked: indicatorsMenu.hide();
153−
154− onOpenPressed: indicatorsMenu.handlePress()
155−
156− function dragToValue(dragPosition) {
157− var offset = target.shown ? 0 : -hintDisplacement + handleSize;
158− return dragPosition + offset;
159− }
90+ property real unitProgress: (height - panelHeight) / (openedHeight - panelHeight)
16091 }
16192
16293 SearchIndicator {
@@ -192,13 +123,11 @@ Item {
192123 name: "in" //fully opaque and visible at top edge of screen
193124 when: !fullscreenMode
194125 PropertyChanges { target: panelBackground; y: 0 }
195− PropertyChanges { target: indicatorRevealer; openedValue: indicatorsMenu.openedHeight - panelHeight }
196126 },
197127 State {
198128 name: "out" //pushed off screen
199129 when: fullscreenMode
200130 PropertyChanges { target: panelBackground; y: -panelHeight }
201− PropertyChanges { target: indicatorRevealer; openedValue: indicatorsMenu.openedHeight }
202131 }
203132 ]
204133}
debian/control+2
@@ -16,6 +16,8 @@ Build-Depends: cmake,
1616 libqmenumodel-dev,
1717 libqt5v8-5-private-dev,
1818 libunity-core-6.0-dev (<< 7.80),
19+ libunity-dev (>= 7.0.3),
20+ libusermetricsoutput1-dev,
1921 libxcb1-dev,
2022 pkg-config,
2123 python3,
debian/rules+4
@@ -9,6 +9,10 @@ export NO_PNG_PKG_MANGLE=1
99%:
1010 dh $@ --parallel
1111
12+override_dh_auto_clean:
13+ dh_auto_clean
14+ rm -rf builddir
15+
1216override_dh_install:
1317 dh_install --fail-missing
1418
plugins/LightDM/CMakeLists.txt+4−1
@@ -1,6 +1,7 @@
11# Dependencies
2+include(FindPkgConfig)
3+pkg_check_modules(LIBUSERMETRICSOUTPUT REQUIRED libusermetricsoutput-1)
24# TODO: Once we split out a separate greeter process, uncomment these lines
3−#include(FindPkgConfig)
45#pkg_check_modules(LIBLIGHTDM REQUIRED liblightdm-qt5-2)
56
67include_directories(
@@ -8,6 +9,7 @@ include_directories(
89 ${CMAKE_CURRENT_BINARY_DIR}
910 ${CMAKE_SOURCE_DIR}/tests/mocks/LightDM
1011 #${LIBLIGHTDM_INCLUDE_DIRS}
12+ ${LIBUSERMETRICSOUTPUT_INCLUDE_DIRS}
1113)
1214
1315set(QMLPLUGIN_SRC
@@ -25,6 +27,7 @@ target_link_libraries(LightDM-qml
2527 MockLightDM-demo
2628# TODO: Once we split out a separate greeter process, uncomment these lines
2729# ${LIBLIGHTDM_LDFLAGS}
30+ ${LIBUSERMETRICSOUTPUT_LDFLAGS}
2831 )
2932
3033qt5_use_modules(LightDM-qml Gui Qml)
plugins/LightDM/Greeter.cpp+6−6
@@ -102,21 +102,21 @@ bool Greeter::startSessionSync(const QString &session)
102102 return d->m_greeter->startSessionSync(session);
103103}
104104
105−void Greeter::showPromptFilter(QString text, QLightDM::Greeter::PromptType type)
105+void Greeter::showPromptFilter(const QString &text, QLightDM::Greeter::PromptType type)
106106{
107107 Q_D(Greeter);
108108 d->wasPrompted = true;
109109
110110 // Strip prompt of any colons at the end
111− text = text.trimmed();
112− if (text.endsWith(":") || text.endsWith(":")) {
113− text.chop(1);
111+ QString trimmedText = text.trimmed();
112+ if (trimmedText.endsWith(":") || trimmedText.endsWith(":")) {
113+ trimmedText.chop(1);
114114 }
115115
116− Q_EMIT showPrompt(text, type == QLightDM::Greeter::PromptTypeSecret);
116+ Q_EMIT showPrompt(trimmedText, type == QLightDM::Greeter::PromptTypeSecret);
117117}
118118
119−void Greeter::showMessageFilter(QString text, QLightDM::Greeter::MessageType type)
119+void Greeter::showMessageFilter(const QString &text, QLightDM::Greeter::MessageType type)
120120{
121121 Q_EMIT showMessage(text, type == QLightDM::Greeter::MessageTypeError);
122122}
plugins/LightDM/Greeter.h+4−4
@@ -51,8 +51,8 @@ public Q_SLOTS:
5151 bool startSessionSync(const QString &session=QString());
5252
5353Q_SIGNALS:
54− void showMessage(QString text, bool isError);
55− void showPrompt(QString text, bool isSecret);
54+ void showMessage(const QString &text, bool isError);
55+ void showPrompt(const QString &text, bool isSecret);
5656 void authenticationComplete();
5757 void promptlessChanged();
5858
@@ -62,8 +62,8 @@ private:
6262 Q_DECLARE_PRIVATE(Greeter)
6363
6464private Q_SLOTS:
65− void showMessageFilter(QString text, QLightDM::Greeter::MessageType type);
66− void showPromptFilter(QString text, QLightDM::Greeter::PromptType type);
65+ void showMessageFilter(const QString &text, QLightDM::Greeter::MessageType type);
66+ void showPromptFilter(const QString &text, QLightDM::Greeter::PromptType type);
6767 void authenticationCompleteFilter();
6868};
6969
plugins/LightDM/plugin.cpp+5−4
@@ -20,8 +20,9 @@
2020#include "plugin.h"
2121#include "Greeter.h"
2222#include "UsersModel.h"
23+#include <libusermetricsoutput/ColorTheme.h>
24+#include <libusermetricsoutput/UserMetrics.h>
2325#include <QLightDM/UsersModel>
24−#include "InfographicModel.h"
2526
2627#include <QtCore/QAbstractItemModel>
2728#include <QtQml>
@@ -44,17 +45,17 @@ static QObject *infographic_provider(QQmlEngine *engine, QJSEngine *scriptEngine
4445{
4546 Q_UNUSED(engine)
4647 Q_UNUSED(scriptEngine)
47− return InfographicModel::getInstance();
48+ return UserMetricsOutput::UserMetrics::getInstance();
4849}
4950
5051void LightDMPlugin::registerTypes(const char *uri)
5152{
5253 qmlRegisterType<QAbstractItemModel>();
53− qmlRegisterType<InfographicColorTheme>();
54+ qmlRegisterType<UserMetricsOutput::ColorTheme>();
5455
5556 Q_ASSERT(uri == QLatin1String("LightDM"));
5657 qmlRegisterSingletonType<Greeter>(uri, 0, 1, "Greeter", greeter_provider);
5758 qmlRegisterSingletonType<UsersModel>(uri, 0, 1, "Users", users_provider);
5859 qmlRegisterUncreatableType<QLightDM::UsersModel>(uri, 0, 1, "UserRoles", "Type is not instantiable");
59− qmlRegisterSingletonType<InfographicModel>(uri, 0, 1, "Infographic", infographic_provider);
60+ qmlRegisterSingletonType<UserMetricsOutput::UserMetrics>(uri, 0, 1, "Infographic", infographic_provider);
6061}
plugins/ListViewWithPageHeader/listviewwithpageheader.cpp+3
@@ -342,6 +342,9 @@ void ListViewWithPageHeader::positionAtBeginning()
342342
343343void ListViewWithPageHeader::showHeader()
344344{
345+ if (!m_headerItem)
346+ return;
347+
345348 auto to = qMax(-minYExtent(), contentY() - m_headerItem->height() + m_headerItemShownHeight);
346349 if (to != contentY()) {
347350 m_headerShowAnimation->setTo(to);
plugins/Ubuntu/Gestures/DirectionalDragArea.cpp+3−3
@@ -404,7 +404,7 @@ void DirectionalDragArea::setStatus(DirectionalDragArea::Status newStatus)
404404 }
405405}
406406
407−void DirectionalDragArea::setPreviousPos(QPointF point)
407+void DirectionalDragArea::setPreviousPos(const QPointF &point)
408408{
409409 Q_ASSERT(m_status != Rejected);
410410
@@ -426,7 +426,7 @@ void DirectionalDragArea::setPreviousPos(QPointF point)
426426 }
427427}
428428
429−void DirectionalDragArea::setPreviousScenePos(QPointF point)
429+void DirectionalDragArea::setPreviousScenePos(const QPointF &point)
430430{
431431 Q_ASSERT(m_status != Rejected);
432432
@@ -448,7 +448,7 @@ void DirectionalDragArea::setPreviousScenePos(QPointF point)
448448 }
449449}
450450
451−void DirectionalDragArea::updateVelocityCalculator(QPointF point)
451+void DirectionalDragArea::updateVelocityCalculator(const QPointF &point)
452452{
453453 if (Direction::isHorizontal(m_direction)) {
454454 m_velocityCalculator->setTrackedPosition(point.x());
plugins/Ubuntu/Gestures/DirectionalDragArea.h+3−3
@@ -219,9 +219,9 @@ private:
219219 bool movedFarEnough(const QPointF &point) const;
220220 const QTouchEvent::TouchPoint *fetchTargetTouchPoint(QTouchEvent *event);
221221 void setStatus(Status newStatus);
222− void setPreviousPos(QPointF point);
223− void setPreviousScenePos(QPointF point);
224− void updateVelocityCalculator(QPointF point);
222+ void setPreviousPos(const QPointF &point);
223+ void setPreviousScenePos(const QPointF &point);
224+ void updateVelocityCalculator(const QPointF &point);
225225
226226 Status m_status;
227227
plugins/Unity/CMakeLists.txt+8
@@ -20,6 +20,14 @@ set(QMLPLUGIN_SRC
2020 plugin.cpp
2121 bottombarvisibilitycommunicatorshell.cpp
2222 launchermodel.cpp
23+ applicationpreview.cpp
24+ genericpreview.cpp
25+ moviepreview.cpp
26+ musicpreview.cpp
27+ preview.cpp
28+ previewaction.cpp
29+ previewinfohint.cpp
30+ variantutils.cpp
2331 )
2432
2533add_library(Unity-qml MODULE
plugins/Unity/applicationpreview.cppnew file+96
@@ -0,0 +1,96 @@
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+
23+#include <QDebug>
24+
25+ApplicationPreview::ApplicationPreview(QObject *parent):
26+ Preview(parent),
27+ m_unityAppPreview(nullptr)
28+{
29+}
30+
31+QString ApplicationPreview::lastUpdate() const
32+{
33+ if (m_unityAppPreview) {
34+ return QString::fromStdString(m_unityAppPreview->last_update());
35+ } else {
36+ qWarning() << "Preview not set";
37+ }
38+ return QString();
39+}
40+
41+QString ApplicationPreview::copyright() const
42+{
43+ if (m_unityAppPreview) {
44+ return QString::fromStdString(m_unityAppPreview->copyright());
45+ } else {
46+ qWarning() << "Preview not set";
47+ }
48+ return QString();
49+}
50+
51+QString ApplicationPreview::license() const
52+{
53+ if (m_unityAppPreview) {
54+ return QString::fromStdString(m_unityAppPreview->license());
55+ } else {
56+ qWarning() << "Preview not set";
57+ }
58+ return QString();
59+}
60+
61+QString ApplicationPreview::appIcon() const
62+{
63+ if (m_unityAppPreview) {
64+ return QString::fromUtf8(g_icon_to_string(m_unityAppPreview->app_icon()));
65+ } else {
66+ qWarning() << "Preview not set";
67+ }
68+ return QString();
69+}
70+
71+float ApplicationPreview::rating() const
72+{
73+ if (m_unityAppPreview) {
74+ return m_unityAppPreview->rating();
75+ } else {
76+ qWarning() << "Preview not set";
77+ }
78+ return 0.0f;
79+}
80+
81+unsigned int ApplicationPreview::numRatings() const
82+{
83+ if (m_unityAppPreview) {
84+ return m_unityAppPreview->num_ratings();
85+ } else {
86+ qWarning() << "Preview not set";
87+ }
88+ return 0;
89+}
90+
91+void ApplicationPreview::setUnityPreview(unity::dash::Preview::Ptr unityPreview)
92+{
93+ m_unityAppPreview = std::dynamic_pointer_cast<unity::dash::ApplicationPreview>(unityPreview);
94+
95+ Q_EMIT previewChanged();
96+}
plugins/Unity/applicationpreview.hnew file+66
@@ -0,0 +1,66 @@
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/LightDM/InfographicModel.h → plugins/Unity/genericpreview.cpprenamed+10−11
@@ -1,5 +1,8 @@
11/*
2− * Copyright (C) 2012,2013 Canonical, Ltd.
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * Authors:
5+ * Pawel Stolowski <pawel.stolowski@canonical.com>
36 *
47 * This program is free software; you can redistribute it and/or modify
58 * it under the terms of the GNU General Public License as published by
@@ -12,16 +15,12 @@
1215 *
1316 * You should have received a copy of the GNU General Public License
1417 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− *
16− * Authors: Pete Woods <pete.woods@canonical.com>
1718 */
1819
19−#ifndef INFOGRAPHICMODEL_H
20−#define INFOGRAPHICMODEL_H
21−
22−#include <QLightDM/InfographicModel>
23−
24−typedef QLightDM::InfographicModel InfographicModel;
25−typedef QLightDM::InfographicColorTheme InfographicColorTheme;
20+// local
21+#include "genericpreview.h"
2622
27−#endif
23+GenericPreview::GenericPreview(QObject *parent):
24+ Preview(parent)
25+{
26+}
plugins/Unity/genericpreview.hnew file+40
@@ -0,0 +1,40 @@
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 GENERICPREVIEW_H
21+#define GENERICPREVIEW_H
22+
23+// local
24+#include "preview.h"
25+
26+// Qt
27+#include <QObject>
28+#include <QMetaType>
29+
30+class GenericPreview : public Preview
31+{
32+ Q_OBJECT
33+
34+public:
35+ explicit GenericPreview(QObject *parent = 0);
36+};
37+
38+Q_DECLARE_METATYPE(GenericPreview *)
39+
40+#endif
plugins/Unity/moviepreview.cppnew file+67
@@ -0,0 +1,67 @@
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.hnew file+60
@@ -0,0 +1,60 @@
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/musicpreview.cppnew file+54
@@ -0,0 +1,54 @@
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.hnew file+62
@@ -0,0 +1,62 @@
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.cpp+6
@@ -24,6 +24,9 @@
2424#include "plugin.h"
2525
2626// local
27+#include "preview.h"
28+#include "previewaction.h"
29+#include "previewinfohint.h"
2730#include "scope.h"
2831#include "scopes.h"
2932#include "categories.h"
@@ -40,6 +43,9 @@ static const char* DBUS_SERVICE = "com.canonical.Shell.BottomBarVisibilityCommun
4043void UnityPlugin::registerTypes(const char *uri)
4144{
4245 Q_ASSERT(uri == QLatin1String("Unity"));
46+ qmlRegisterUncreatableType<Preview>(uri, 0, 1, "Preview", "Can't create Preview object in QML.");
47+ qmlRegisterUncreatableType<PreviewAction>(uri, 0, 1, "PreviewAction", "Can't create PreviewAction object in QML.");
48+ qmlRegisterUncreatableType<PreviewInfoHint>(uri, 0, 1, "PreviewInfoHint", "Can't create PreviewInfoHint object in QML.");
4349 qmlRegisterType<Scope>(uri, 0, 1, "Scope");
4450 qmlRegisterType<Scopes>(uri, 0, 1, "Scopes");
4551 qmlRegisterType<Categories>(uri, 0, 1, "Categories");
plugins/Unity/preview.cppnew file+173
@@ -0,0 +1,173 @@
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 "variantutils.h"
29+
30+// Qt
31+#include <QDebug>
32+#include <QtAlgorithms>
33+
34+#include <UnityCore/GenericPreview.h>
35+#include <UnityCore/ApplicationPreview.h>
36+#include <UnityCore/MoviePreview.h>
37+#include <UnityCore/MusicPreview.h>
38+
39+Preview::Preview(QObject *parent):
40+ QObject(parent),
41+ m_unityPreview(nullptr)
42+{
43+}
44+
45+QString Preview::rendererName() const
46+{
47+ if (m_unityPreview) {
48+ return QString::fromStdString(m_unityPreview->renderer_name());
49+ } else {
50+ qWarning() << "Preview not set";
51+ }
52+ return QString();
53+}
54+
55+QString Preview::title() const
56+{
57+ if (m_unityPreview) {
58+ return QString::fromStdString(m_unityPreview->title());
59+ } else {
60+ qWarning() << "Preview not set";
61+ }
62+ return QString();
63+}
64+
65+QString Preview::subtitle () const
66+{
67+ if (m_unityPreview) {
68+ return QString::fromStdString(m_unityPreview->subtitle());
69+ } else {
70+ qWarning() << "Preview not set";
71+ }
72+ return QString();
73+}
74+
75+QString Preview::description() const
76+{
77+ if (m_unityPreview) {
78+ return QString::fromStdString(m_unityPreview->description());
79+ } else {
80+ qWarning() << "Preview not set";
81+ }
82+ return QString();
83+}
84+
85+QVariant Preview::actions()
86+{
87+ return QVariant::fromValue(m_actions);
88+}
89+
90+QVariant Preview::infoHints()
91+{
92+ return QVariant::fromValue(m_infoHints);
93+}
94+
95+QString Preview::image() const
96+{
97+ if (m_unityPreview) {
98+ return QString::fromUtf8(g_icon_to_string(m_unityPreview->image()));
99+ } else {
100+ qWarning() << "Preview not set";
101+ }
102+ return QString::null;
103+}
104+
105+QString Preview::imageSourceUri() const
106+{
107+ if (m_unityPreview) {
108+ return QString::fromStdString(m_unityPreview->image_source_uri());
109+ } else {
110+ qWarning() << "Preview not set";
111+ }
112+ return QString::null;
113+}
114+
115+Preview* Preview::newFromUnityPreview(unity::dash::Preview::Ptr unityPreview)
116+{
117+ Preview* preview = nullptr;
118+
119+ if (dynamic_cast<unity::dash::GenericPreview *>(unityPreview.get()) != nullptr) {
120+ preview = new GenericPreview();
121+ } else if (dynamic_cast<unity::dash::MusicPreview *>(unityPreview.get()) != nullptr) {
122+ preview = new MusicPreview();
123+ } else if (dynamic_cast<unity::dash::MoviePreview *>(unityPreview.get()) != nullptr) {
124+ preview = new MoviePreview();
125+ } else if (dynamic_cast<unity::dash::ApplicationPreview *>(unityPreview.get()) != nullptr) {
126+ preview = new ApplicationPreview();
127+ } else {
128+ qWarning() << "Unknown preview type: " << typeid(*unityPreview).name();
129+ preview = new GenericPreview();
130+ }
131+
132+ preview->setUnityPreviewBase(unityPreview);
133+ preview->setUnityPreview(unityPreview);
134+
135+ return preview;
136+}
137+
138+void Preview::setUnityPreviewBase(unity::dash::Preview::Ptr unityPreview)
139+{
140+ m_unityPreview = unityPreview;
141+
142+ qDeleteAll(m_infoHints);
143+ m_infoHints.clear();
144+ qDeleteAll(m_actions);
145+ m_actions.clear();
146+
147+ for (auto unityInfoHint: m_unityPreview->GetInfoHints()) {
148+ auto hint = new PreviewInfoHint(this);
149+ hint->setUnityInfoHint(unityInfoHint);
150+ m_infoHints.append(hint);
151+ }
152+
153+ for (auto unityAction: m_unityPreview->GetActions()) {
154+ auto action = new PreviewAction(this);
155+ action->setUnityAction(unityAction);
156+ m_actions.append(action);
157+ }
158+}
159+
160+void Preview::setUnityPreview(unity::dash::Preview::Ptr /* unityPreview */)
161+{
162+ // default implementation does nothing
163+}
164+
165+void Preview::execute(const QString& actionId, const QHash<QString, QVariant>& hints)
166+{
167+ if (m_unityPreview) {
168+ auto unityHints = convertToHintsMap(hints);
169+ m_unityPreview->PerformAction(actionId.toStdString(), unityHints);
170+ } else {
171+ qWarning() << "Preview not set";
172+ }
173+}
plugins/Unity/preview.hnew file+80
@@ -0,0 +1,80 @@
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+
29+// libunity-core
30+#include <UnityCore/Preview.h>
31+
32+// local
33+#include "previewaction.h"
34+
35+class Q_DECL_EXPORT Preview : public QObject
36+{
37+ Q_OBJECT
38+
39+ Q_PROPERTY(QString rendererName READ rendererName NOTIFY previewChanged)
40+ Q_PROPERTY(QString title READ title NOTIFY previewChanged)
41+ Q_PROPERTY(QString subtitle READ subtitle NOTIFY previewChanged)
42+ Q_PROPERTY(QString description READ description NOTIFY previewChanged)
43+ Q_PROPERTY(QVariant actions READ actions NOTIFY previewChanged)
44+ Q_PROPERTY(QVariant infoHints READ infoHints NOTIFY previewChanged)
45+ Q_PROPERTY(QString image READ image NOTIFY previewChanged)
46+ Q_PROPERTY(QString imageSourceUri READ imageSourceUri NOTIFY previewChanged)
47+
48+public:
49+ explicit Preview(QObject *parent = 0);
50+ static Preview* newFromUnityPreview(unity::dash::Preview::Ptr unityPreview);
51+
52+ QString rendererName() const;
53+ QString title() const;
54+ QString subtitle() const;
55+ QString description() const;
56+ QVariant actions();
57+ QVariant infoHints();
58+ QString image() const;
59+ QString imageSourceUri() const;
60+
61+ Q_INVOKABLE void execute(const QString& actionId, const QHash<QString, QVariant>& hints);
62+
63+Q_SIGNALS:
64+ void previewChanged();
65+
66+protected:
67+ virtual void setUnityPreview(unity::dash::Preview::Ptr unityPreview);
68+
69+ unity::dash::Preview::Ptr m_unityPreview;
70+
71+private:
72+ void setUnityPreviewBase(unity::dash::Preview::Ptr unityPreview);
73+
74+ QList<QObject *> m_actions;
75+ QList<QObject *> m_infoHints;
76+};
77+
78+Q_DECLARE_METATYPE(Preview *)
79+
80+#endif
plugins/Unity/previewaction.cppnew file+75
@@ -0,0 +1,75 @@
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.hnew file+71
@@ -0,0 +1,71 @@
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 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.cppnew file+67
@@ -0,0 +1,67 @@
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 "previewinfohint.h"
22+#include "variantutils.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 QVariantFromGVariant(m_unityInfoHint->value);
65+ }
66+ return QVariant();
67+}
plugins/Unity/previewinfohint.hnew file+58
@@ -0,0 +1,58 @@
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/scope.cpp+79−11
@@ -19,12 +19,19 @@
1919
2020// Self
2121#include "scope.h"
22+
23+// local
2224#include "categories.h"
25+#include "preview.h"
26+#include "variantutils.h"
2327
2428// Qt
2529#include <QUrl>
2630#include <QDebug>
2731#include <QtGui/QDesktopServices>
32+#include <QQmlEngine>
33+
34+#include <UnityCore/Variant.h>
2835
2936#include <libintl.h>
3037
@@ -118,21 +125,80 @@ void Scope::setNoResultsHint(const QString& hint) {
118125 }
119126}
120127
121−void Scope::activate(const QString& /*uri*/)
128+
129+unity::dash::LocalResult Scope::createLocalResult(const QVariant &uri, const QVariant &icon_hint,
130+ const QVariant &category, const QVariant &result_type,
131+ const QVariant &mimetype, const QVariant &title,
132+ const QVariant &comment, const QVariant &dnd_uri,
133+ const QVariant &metadata)
134+{
135+ unity::dash::LocalResult res;
136+ res.uri = uri.toString().toStdString();
137+ res.icon_hint = icon_hint.toString().toStdString();
138+ res.category_index = category.toUInt();
139+ res.result_type = result_type.toUInt();
140+ res.mimetype = mimetype.toString().toStdString();
141+ res.name = title.toString().toStdString();
142+ res.comment = comment.toString().toStdString();
143+ res.dnd_uri = dnd_uri.toString().toStdString();
144+ res.hints = convertToHintsMap(metadata);
145+
146+ return res;
147+}
148+
149+// FIXME: Change to use row index.
150+void Scope::activate(const QVariant &uri, const QVariant &icon_hint, const QVariant &category,
151+ const QVariant &result_type, const QVariant &mimetype, const QVariant &title,
152+ const QVariant &comment, const QVariant &dnd_uri, const QVariant &metadata)
153+{
154+ auto res = createLocalResult(uri, icon_hint, category, result_type, mimetype, title, comment, dnd_uri, metadata);
155+ m_unityScope->Activate(res);
156+}
157+
158+// FIXME: Change to use row index.
159+void Scope::preview(const QVariant &uri, const QVariant &icon_hint, const QVariant &category,
160+ const QVariant &result_type, const QVariant &mimetype, const QVariant &title,
161+ const QVariant &comment, const QVariant &dnd_uri, const QVariant &metadata)
122162{
123− // TODO:
124− // we need to create unity::dash::LocalResult (see UnityCore/Result.h) and pass it to Activate;
125− // this requires entire row from the model, so we need row index rather than uri.
126− // m_unityScope->Activate(QByteArray::fromPercentEncoding(uri.toUtf8()).constData());
163+ auto res = createLocalResult(uri, icon_hint, category, result_type, mimetype, title, comment, dnd_uri, metadata);
164+ m_unityScope->Preview(res);
127165}
128166
129−void Scope::onActivated(unity::dash::LocalResult const& result, unity::dash::ScopeHandledType type, unity::glib::HintsMap const&)
167+void Scope::onActivated(unity::dash::LocalResult const& result, unity::dash::ScopeHandledType type, unity::glib::HintsMap const& hints)
130168{
131− if (type == unity::dash::NOT_HANDLED) {
132− fallbackActivate(QString::fromStdString(result.uri));
169+ // note: we will not get called on SHOW_PREVIEW, instead UnityCore will signal preview_ready.
170+ switch (type)
171+ {
172+ case unity::dash::NOT_HANDLED:
173+ fallbackActivate(QString::fromStdString(result.uri));
174+ break;
175+ case unity::dash::SHOW_DASH:
176+ Q_EMIT showDash();
177+ break;
178+ case unity::dash::HIDE_DASH:
179+ Q_EMIT hideDash();
180+ break;
181+ case unity::dash::GOTO_DASH_URI:
182+ if (hints.find("goto-uri") != hints.end()) {
183+ Q_EMIT gotoUri(QString::fromStdString(g_variant_get_string(hints.at("goto-uri"), nullptr)));
184+ } else {
185+ qWarning() << "Missing goto-uri hint for GOTO_DASH_URI activation reply";
186+ }
187+ break;
188+ default:
189+ qWarning() << "Unhandled activation response:" << type;
133190 }
134191}
135192
193+void Scope::onPreviewReady(unity::dash::LocalResult const& /* result */, unity::dash::Preview::Ptr const& preview)
194+{
195+ auto prv = Preview::newFromUnityPreview(preview);
196+ // is this the best solution? QML may need to keep more than one preview instance around, so we can't own it.
197+ // passing it by value is not possible.
198+ QQmlEngine::setObjectOwnership(prv, QQmlEngine::JavaScriptOwnership);
199+ Q_EMIT previewReady(prv);
200+}
201+
136202void Scope::fallbackActivate(const QString& uri)
137203{
138204 /* FIXME: stripping all content before the first column because for some
@@ -161,10 +227,10 @@ void Scope::fallbackActivate(const QString& uri)
161227 return;
162228 }
163229
164− qWarning() << "FIXME: Possibly no handler for scheme: " << url.scheme();
165− qWarning() << "Trying to open" << tweakedUri;
230+ qDebug() << "Trying to open" << uri;
231+
166232 /* Try our luck */
167− QDesktopServices::openUrl(url);
233+ QDesktopServices::openUrl(uri); //url?
168234}
169235
170236void Scope::setUnityScope(const unity::dash::Scope::Ptr& scope)
@@ -204,6 +270,8 @@ void Scope::setUnityScope(const unity::dash::Scope::Ptr& scope)
204270 /* FIXME: signal should be forwarded instead of calling the handler directly */
205271 m_unityScope->activated.connect(sigc::mem_fun(this, &Scope::onActivated));
206272
273+ m_unityScope->preview_ready.connect(sigc::mem_fun(this, &Scope::onPreviewReady));
274+
207275 /* Synchronize local states with m_unityScope right now and whenever
208276 m_unityScope becomes connected */
209277 /* FIXME: should emit change notification signals for all properties */
plugins/Unity/scope.h+20−3
@@ -33,6 +33,7 @@
3333#include "deelistmodel.h"
3434
3535class Categories;
36+class Preview;
3637
3738class Scope : public QObject
3839{
@@ -73,7 +74,12 @@ public:
7374 void setSearchQuery(const QString& search_query);
7475 void setNoResultsHint(const QString& hint);
7576
76− Q_INVOKABLE void activate(const QString& uri);
77+ Q_INVOKABLE void activate(const QVariant &uri, const QVariant &icon_hint, const QVariant &category,
78+ const QVariant &result_type, const QVariant &mimetype, const QVariant &title,
79+ const QVariant &comment, const QVariant &dnd_uri, const QVariant &metadata);
80+ Q_INVOKABLE void preview(const QVariant &uri, const QVariant &icon_hint, const QVariant &category,
81+ const QVariant &result_type, const QVariant &mimetype, const QVariant &title,
82+ const QVariant &comment, const QVariant &dnd_uri, const QVariant &metadata);
7783 void setUnityScope(const unity::dash::Scope::Ptr& scope);
7884 unity::dash::Scope::Ptr unityScope() const;
7985
@@ -94,6 +100,12 @@ Q_SIGNALS:
94100 void searchQueryChanged();
95101 void noResultsHintChanged();
96102
103+ // signals triggered by activate(..) or preview(..) requests.
104+ void previewReady(Preview *preview);
105+ void showDash();
106+ void hideDash();
107+ void gotoUri(const QString &uri);
108+
97109private Q_SLOTS:
98110 void synchronizeStates();
99111 void onSearchFinished(const std::string &, unity::glib::HintsMap const &);
@@ -105,8 +117,13 @@ private:
105117 void onCategoriesSwarmNameChanged(const std::string&);
106118 void onCategoriesModelChanged(unity::glib::Object<DeeModel>);
107119 void onCategoriesChanged(const unity::dash::Categories::Ptr&);
108−
109− void onActivated(unity::dash::LocalResult const& result, unity::dash::ScopeHandledType type, unity::glib::HintsMap const&);
120+ unity::dash::LocalResult createLocalResult(const QVariant &uri, const QVariant &icon_hint,
121+ const QVariant &category, const QVariant &result_type,
122+ const QVariant &mimetype, const QVariant &title,
123+ const QVariant &comment, const QVariant &dnd_uri,
124+ const QVariant &metadata);
125+ void onActivated(unity::dash::LocalResult const& result, unity::dash::ScopeHandledType type, unity::glib::HintsMap const& hints);
126+ void onPreviewReady(unity::dash::LocalResult const& result, unity::dash::Preview::Ptr const& preview);
110127 void fallbackActivate(const QString& uri);
111128
112129 unity::dash::Scope::Ptr m_unityScope;
plugins/Unity/variantutils.cppnew file+158
@@ -0,0 +1,158 @@
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 "variantutils.h"
21+
22+/* Returns floating ref */
23+GVariant* GVariantFromQVariant(const QVariant &var)
24+{
25+ GVariant *gv = nullptr;
26+
27+ switch (var.type()) {
28+ case QVariant::String:
29+ gv = g_variant_new_string(var.toString().toUtf8());
30+ break;
31+ case QVariant::UInt:
32+ gv = g_variant_new_uint32(var.toUInt());
33+ break;
34+ case QVariant::Int:
35+ gv = g_variant_new_int32(var.toInt());
36+ break;
37+ case QVariant::LongLong:
38+ gv = g_variant_new_int64(var.toLongLong());
39+ break;
40+ case QVariant::ULongLong:
41+ gv = g_variant_new_uint64(var.toULongLong());
42+ break;
43+ case QVariant::Double:
44+ gv = g_variant_new_double(var.toDouble());
45+ break;
46+ case QVariant::Bool:
47+ gv = g_variant_new_boolean(var.toBool());
48+ break;
49+ case QVariant::Hash: {
50+ const auto hash = var.toHash();
51+ GVariant **children = new GVariant*[hash.size()];
52+ int cnt = 0;
53+ QHash<QString, QVariant>::const_iterator it = hash.constBegin();
54+ while (it != hash.constEnd()) {
55+ GVariant *key = g_variant_new_string(it.key().toUtf8());
56+ children[cnt++] = g_variant_new_dict_entry(key, g_variant_new_variant(GVariantFromQVariant(it.value())));
57+ ++it;
58+ }
59+ gv = g_variant_new_array(G_VARIANT_TYPE("{sv}"), children, hash.size());
60+ delete [] children;
61+ break;
62+ }
63+ default:
64+ break;
65+ }
66+ return gv;
67+}
68+
69+// implementation of this conversion taken from libdee-qt private utility function.
70+QVariant QVariantFromGVariant(GVariant *value)
71+{
72+ /* We need to special-case a{sv} here as G_VARIANT_CLASS_ARRAY handles simple arrays;
73+ we need to create QVariantHash, not a list */
74+ if (g_variant_is_of_type(value, G_VARIANT_TYPE_VARDICT)) {
75+ const gsize nChildren = g_variant_n_children(value);
76+ QVariantHash hash;
77+ for (gsize i = 0; i < nChildren; ++i)
78+ {
79+ GVariant* dict_entry = g_variant_get_child_value(value, i);
80+
81+ gchar* dict_key;
82+ GVariant *dict_var;
83+ g_variant_get(dict_entry, "{&sv}", &dict_key, &dict_var);
84+ hash.insert(QString::fromUtf8(dict_key), QVariantFromGVariant(dict_var));
85+ g_variant_unref(dict_var);
86+ g_variant_unref(dict_entry);
87+ }
88+ return hash;
89+ }
90+
91+ switch (g_variant_classify(value)) {
92+ case G_VARIANT_CLASS_BOOLEAN:
93+ return QVariant((bool) g_variant_get_boolean(value));
94+ case G_VARIANT_CLASS_BYTE:
95+ return QVariant((uchar) g_variant_get_byte(value));
96+ case G_VARIANT_CLASS_INT16:
97+ return QVariant((qint16) g_variant_get_int16(value));
98+ case G_VARIANT_CLASS_UINT16:
99+ return QVariant((quint16) g_variant_get_uint16(value));
100+ case G_VARIANT_CLASS_INT32:
101+ return QVariant((qint32) g_variant_get_int32(value));
102+ case G_VARIANT_CLASS_UINT32:
103+ return QVariant((quint32) g_variant_get_uint32(value));
104+ case G_VARIANT_CLASS_INT64:
105+ return QVariant((qint64) g_variant_get_int64(value));
106+ case G_VARIANT_CLASS_UINT64:
107+ return QVariant((quint64) g_variant_get_uint64(value));
108+ case G_VARIANT_CLASS_DOUBLE:
109+ return QVariant(g_variant_get_double(value));
110+ case G_VARIANT_CLASS_STRING:
111+ return QVariant(QString::fromUtf8(g_variant_get_string(value, NULL)));
112+ case G_VARIANT_CLASS_ARRAY:
113+ case G_VARIANT_CLASS_TUPLE:
114+ {
115+ const gsize nChildren = g_variant_n_children(value);
116+ QList<QVariant> array;
117+ for (gsize i = 0; i < nChildren; ++i)
118+ {
119+ GVariant* gvariant = g_variant_get_child_value(value, i);
120+ array << QVariantFromGVariant(gvariant);
121+ g_variant_unref(gvariant);
122+ }
123+ return array;
124+ }
125+ default:
126+ /* Fallback on an empty QVariant.
127+ FIXME: Missing conversion of following GVariant types:
128+ - G_VARIANT_CLASS_HANDLE
129+ - G_VARIANT_CLASS_OBJECT_PATH
130+ - G_VARIANT_CLASS_SIGNATURE
131+ - G_VARIANT_CLASS_VARIANT
132+ - G_VARIANT_CLASS_MAYBE
133+ - G_VARIANT_CLASS_DICT_ENTRY
134+ */
135+ return QVariant();
136+ }
137+}
138+
139+unity::glib::HintsMap convertToHintsMap(const QHash<QString, QVariant> &val)
140+{
141+ unity::glib::HintsMap hintsMap;
142+ QHash<QString, QVariant>::const_iterator it = val.constBegin();
143+ while (it != val.constEnd()) {
144+ hintsMap[it.key().toStdString()] = GVariantFromQVariant(it.value());
145+ ++it;
146+ }
147+ return hintsMap;
148+}
149+
150+unity::glib::HintsMap convertToHintsMap(const QVariant &var)
151+{
152+ if (var.type() == QVariant::Hash) {
153+ unity::glib::HintsMap hintsMap;
154+ const auto hash = var.toHash();
155+ return convertToHintsMap(hash);
156+ }
157+ return unity::glib::HintsMap();
158+}
plugins/Unity/variantutils.hnew file+34
@@ -0,0 +1,34 @@
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+GVariant* GVariantFromQVariant(const QVariant &value);
30+QVariant QVariantFromGVariant(GVariant *value);
31+unity::glib::HintsMap convertToHintsMap(const QHash<QString, QVariant> &val);
32+unity::glib::HintsMap convertToHintsMap(const QVariant &var);
33+
34+#endif
plugins/Utils/qlimitproxymodelqml.cpp+4−4
@@ -39,11 +39,11 @@ QHash<int, QByteArray> QLimitProxyModelQML::roleNames() const
3939void
4040QLimitProxyModelQML::setModel(QAbstractItemModel *itemModel)
4141{
42− if (sourceModel() != NULL) {
43− sourceModel()->disconnect(this);
44− }
45−
4642 if (itemModel != sourceModel()) {
43+ if (sourceModel() != NULL) {
44+ sourceModel()->disconnect(this);
45+ }
46+
4747 setSourceModel(itemModel);
4848
4949 if (sourceModel() != NULL) {
run+5−5
@@ -41,17 +41,17 @@ done
4141
4242if $FAKE; then
4343 export QML2_IMPORT_PATH=$PWD/builddir/tests/mocks:$PWD/builddir/plugins:$PWD/builddir/modules
44− export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/builddir/tests/mocks/LightDM/single
44+ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/builddir/tests/mocks/libusermetrics:$PWD/builddir/tests/mocks/LightDM/single
4545fi
4646
4747if $PINLOCK; then
48− export QML2_IMPORT_PATH=$PWD/builddir/tests/mocks:$PWD/builddir/plugins
49− export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/builddir/tests/mocks/LightDM/single-pin
48+ export QML2_IMPORT_PATH=$PWD/builddir/tests/mocks:$PWD/builddir/plugins:$PWD/builddir/modules
49+ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/builddir/tests/mocks/libusermetrics:$PWD/builddir/tests/mocks/LightDM/single-pin
5050fi
5151
5252if $KEYLOCK; then
53− export QML2_IMPORT_PATH=$PWD/builddir/tests/mocks:$PWD/builddir/plugins
54− export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/builddir/tests/mocks/LightDM/single-passphrase
53+ export QML2_IMPORT_PATH=$PWD/builddir/tests/mocks:$PWD/builddir/plugins:$PWD/builddir/modules
54+ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/builddir/tests/mocks/libusermetrics:$PWD/builddir/tests/mocks/LightDM/single-passphrase
5555fi
5656
5757# Force icon theme if running on the desktop, otherwise gnome theme (if running
tests/autopilot/unity8/tests/__init__.py+2−2
@@ -39,7 +39,7 @@ class ShellTestCase(AutopilotTestCase):
3939 self.launch_test_local(geometry)
4040
4141 def launch_test_local(self, geometry):
42− os.environ['LD_LIBRARY_PATH'] = "../../../unity_build/build/lib:../../builddir/tests/mocks/LightDM/" + self.lightdm_mock
42+ os.environ['LD_LIBRARY_PATH'] = "../../../unity_build/build/lib:../../builddir/tests/mocks/libusermetrics:../../builddir/tests/mocks/LightDM/" + self.lightdm_mock
4343 os.environ['QML2_IMPORT_PATH'] = "../../builddir/tests/mocks:../../builddir/plugins:../../builddir/modules"
4444 if geometry != "0x0":
4545 self.app = self.launch_test_application(
@@ -49,7 +49,7 @@ class ShellTestCase(AutopilotTestCase):
4949 "../../builddir/unity8", "-fullscreen", app_type='qt')
5050
5151 def launch_test_installed(self, geometry):
52− os.environ['LD_LIBRARY_PATH'] = "/usr/share/unity8/plugins/mocks/LightDM/" + self.lightdm_mock
52+ os.environ['LD_LIBRARY_PATH'] = "/usr/share/unity8/plugins/mocks/libusermetrics:/usr/share/unity8/plugins/mocks/LightDM/" + self.lightdm_mock
5353 os.environ['QML2_IMPORT_PATH'] = "/usr/share/unity8/plugins/mocks:/usr/share/unity8/plugins:/usr/share/unity8/modules"
5454 if model() == 'Desktop' and geometry != "0x0":
5555 self.app = self.launch_test_application(
tests/mocks/CMakeLists.txt+1
@@ -1,2 +1,3 @@
1+add_subdirectory(libusermetrics)
12add_subdirectory(LightDM)
23add_subdirectory(Ubuntu)
tests/mocks/LightDM/CMakeLists.txt+3
@@ -13,6 +13,7 @@ add_subdirectory(single-passphrase)
1313include_directories(
1414 ${CMAKE_CURRENT_SOURCE_DIR}
1515 ${CMAKE_CURRENT_BINARY_DIR}
16+ ${CMAKE_SOURCE_DIR}/tests/mocks/libusermetrics
1617)
1718
1819set(QMLPLUGIN_SRC
@@ -34,6 +35,8 @@ add_dependencies(MockLightDM-qml MockLightDM-full)
3435target_link_libraries(MockLightDM-qml
3536 -L${CMAKE_CURRENT_BINARY_DIR}/full
3637 -llightdm-qt5-2
38+ -L${CMAKE_BINARY_DIR}/tests/mocks/libusermetrics
39+ -lusermetricsoutput
3740 )
3841
3942qt5_use_modules(MockLightDM-qml Gui Qml)
tests/mocks/LightDM/InfographicModel.cppdeleted−416
@@ -1,416 +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− * Author: Pete Woods <pete.woods@canonical.com>
17− */
18−
19−#include "InfographicModelPrivate.h"
20−#include "InfographicModel.h"
21−
22−#include <QtCore/QDir>
23−#include <QtCore/QString>
24−#include <QtGui/QIcon>
25−#include <QMultiMap>
26−
27−using namespace QLightDM;
28−
29−namespace QLightDM
30−{
31−
32−class InfographicColorThemePrivate: QObject
33−{
34−public:
35− explicit InfographicColorThemePrivate(InfographicColorTheme *parent = 0);
36−
37− InfographicColorThemePrivate(const QColor &start, const QColor &main,
38− const QColor &end, InfographicColorTheme *parent = 0);
39−
40− ~InfographicColorThemePrivate();
41−
42− InfographicColorTheme * const q_ptr;
43−
44− QColor m_start;
45−
46− QColor m_main;
47−
48− QColor m_end;
49−
50−protected:
51− int calculateLength();
52−
53−private:
54− Q_DECLARE_PUBLIC(InfographicColorTheme)
55−};
56−
57−class InfographicDataPrivate: QObject
58−{
59−public:
60− explicit InfographicDataPrivate(InfographicData *parent);
61−
62− InfographicDataPrivate(const QString &label,
63− const InfographicColorTheme &firstColor,
64− const QVariantList &firstMonth,
65− const InfographicColorTheme &secondColor,
66− const QVariantList &secondMonth, InfographicData *parent);
67−
68− ~InfographicDataPrivate();
69−
70− InfographicData * const q_ptr;
71− QString m_label;
72− InfographicColorTheme m_firstColor;
73− QVariantList m_firstMonth;
74− InfographicColorTheme m_secondColor;
75− QVariantList m_secondMonth;
76− int m_length;
77−
78−protected:
79− int calculateLength();
80−
81−private:
82− Q_DECLARE_PUBLIC(InfographicData)
83−};
84−
85−}
86−
87−InfographicColorThemePrivate::InfographicColorThemePrivate(
88− InfographicColorTheme *parent) :
89− q_ptr(parent)
90−{
91−}
92−
93−InfographicColorThemePrivate::InfographicColorThemePrivate(const QColor &start,
94− const QColor &main, const QColor &end, InfographicColorTheme *parent) :
95− q_ptr(parent), m_start(start), m_main(main), m_end(end)
96−{
97−}
98−
99−InfographicColorThemePrivate::~InfographicColorThemePrivate()
100−{
101−}
102−
103−InfographicColorTheme::InfographicColorTheme(QObject *parent) :
104− QObject(parent), d_ptr(new InfographicColorThemePrivate(this))
105−{
106−}
107−
108−InfographicColorTheme::InfographicColorTheme(QColor &first, QColor &main,
109− QColor &end, QObject *parent) :
110− QObject(parent), d_ptr(
111− new InfographicColorThemePrivate(first, main, end, this))
112−{
113−
114−}
115−
116−InfographicColorTheme & InfographicColorTheme::operator=(
117− const InfographicColorTheme & other)
118−{
119− if (d_ptr->m_start != other.d_ptr->m_start)
120− {
121− d_ptr->m_start = other.d_ptr->m_start;
122− startChanged(d_ptr->m_start);
123− }
124− if (d_ptr->m_main != other.d_ptr->m_main)
125− {
126− d_ptr->m_main = other.d_ptr->m_main;
127− mainChanged(d_ptr->m_main);
128− }
129−
130− if (d_ptr->m_end != other.d_ptr->m_end)
131− {
132− d_ptr->m_end = other.d_ptr->m_end;
133− endChanged(d_ptr->m_end);
134− }
135−
136− return *this;
137−}
138−
139−InfographicColorTheme::~InfographicColorTheme()
140−{
141− delete d_ptr;
142−}
143−
144−QColor InfographicColorTheme::start() const
145−{
146− return d_ptr->m_start;
147−}
148−
149−QColor InfographicColorTheme::main() const
150−{
151− return d_ptr->m_main;
152−}
153−
154−QColor InfographicColorTheme::end() const
155−{
156− return d_ptr->m_end;
157−}
158−
159−InfographicDataPrivate::InfographicDataPrivate(InfographicData *parent) :
160− q_ptr(parent), m_firstColor(this), m_secondColor(this)
161−{
162− m_length = calculateLength();
163−}
164−
165−InfographicDataPrivate::InfographicDataPrivate(const QString &label,
166− const InfographicColorTheme &firstColor, const QVariantList &firstMonth,
167− const InfographicColorTheme &secondColor,
168− const QVariantList &secondMonth, InfographicData *parent) :
169− q_ptr(parent), m_label(label), m_firstColor(this), m_firstMonth(
170− firstMonth), m_secondColor(this), m_secondMonth(secondMonth)
171−{
172− m_length = calculateLength();
173− m_firstColor = firstColor;
174− m_secondColor = secondColor;
175−}
176−
177−InfographicDataPrivate::~InfographicDataPrivate()
178−{
179−}
180−
181−int InfographicDataPrivate::calculateLength()
182−{
183− int day(m_firstMonth.size());
184− auto it = m_firstMonth.end(), end = m_firstMonth.begin();
185− while (it != end)
186− {
187− --it;
188− --day;
189− if (!it->isNull())
190− {
191− return day;
192− }
193− }
194−
195− return -1;
196−}
197−
198−InfographicData::InfographicData(QObject *parent) :
199− QObject(parent), d_ptr(new InfographicDataPrivate(this))
200−{
201−}
202−
203−InfographicData::InfographicData(const QString &label,
204− const InfographicColorTheme &firstColor, const QVariantList &firstMonth,
205− const InfographicColorTheme &secondColor,
206− const QVariantList &secondMonth, QObject* parent) :
207− QObject(parent), d_ptr(
208− new InfographicDataPrivate(label, firstColor, firstMonth,
209− secondColor, secondMonth, this))
210−{
211−}
212−
213−InfographicData::~InfographicData()
214−{
215− delete d_ptr;
216−}
217−
218−const QString & InfographicData::label() const
219−{
220− return d_ptr->m_label;
221−}
222−
223−const InfographicColorTheme & InfographicData::firstColor() const
224−{
225− return d_ptr->m_firstColor;
226−}
227−
228−const QVariantList & InfographicData::firstMonth() const
229−{
230− return d_ptr->m_firstMonth;
231−}
232−
233−const InfographicColorTheme & InfographicData::secondColor() const
234−{
235− return d_ptr->m_secondColor;
236−}
237−
238−const QVariantList & InfographicData::secondMonth() const
239−{
240− return d_ptr->m_secondMonth;
241−}
242−
243−int InfographicData::length() const
244−{
245− return d_ptr->m_length;
246−}
247−
248−InfographicModelPrivate::InfographicModelPrivate(InfographicModel *parent) :
249− q_ptr(parent), m_currentDay(0)
250−{
251− m_fakeData.insert("", InfographicDataPtr(new InfographicData(this)));
252−}
253−
254−InfographicModelPrivate::~InfographicModelPrivate()
255−{
256−}
257−
258−void InfographicModelPrivate::setUsername(const QString &username)
259−{
260− if(m_username == username) {
261− return;
262− }
263−
264− m_username = username;
265−
266− m_dataIndex = m_fakeData.constFind(m_username);
267− if (m_dataIndex == m_fakeData.end())
268− {
269− m_dataIndex = m_fakeData.constFind("");
270− }
271−
272− loadFakeData();
273−
274− q_ptr->usernameChanged(m_username);
275−}
276−
277−void InfographicModelPrivate::loadFakeData()
278−{
279− m_newData = *m_dataIndex;
280−
281− bool oldLabelEmpty = m_label.isEmpty();
282− bool newLabelEmpty = m_newData->label().isEmpty();
283−
284− if (oldLabelEmpty && !newLabelEmpty)
285− {
286− q_ptr->dataAboutToAppear();
287− finishSetFakeData();
288− } else if (!oldLabelEmpty && newLabelEmpty)
289− {
290− q_ptr->dataAboutToDisappear();
291− } else if (!oldLabelEmpty && !newLabelEmpty)
292− {
293− q_ptr->dataAboutToChange();
294− }
295− // we emit no signal if the data has stayed empty
296−}
297−
298−void InfographicModelPrivate::finishSetFakeData()
299−{
300− bool oldLabelEmpty = m_label.isEmpty();
301− bool newLabelEmpty = m_newData->label().isEmpty();
302−
303− m_label = m_newData->label();
304− m_firstColor = m_newData->firstColor();
305− m_firstMonth.setVariantList(m_newData->firstMonth());
306− m_secondColor = m_newData->secondColor();
307− m_secondMonth.setVariantList(m_newData->secondMonth());
308−
309− bool currentDayChanged = m_currentDay != m_newData->length();
310− m_currentDay = m_newData->length();
311−
312− q_ptr->labelChanged(m_label);
313− if (currentDayChanged)
314− {
315− q_ptr->currentDayChanged(m_currentDay);
316− }
317−
318− if (oldLabelEmpty && !newLabelEmpty)
319− {
320− q_ptr->dataAppeared();
321− } else if (!oldLabelEmpty && newLabelEmpty)
322− {
323− q_ptr->dataDisappeared();
324− } else if (!oldLabelEmpty && !newLabelEmpty)
325− {
326− q_ptr->dataChanged();
327− }
328− // we emit no signal if the data has stayed empty
329−}
330−
331−void InfographicModelPrivate::nextFakeData()
332−{
333− ++m_dataIndex;
334− if (m_dataIndex == m_fakeData.end() || m_dataIndex.key() != m_username)
335− {
336− m_dataIndex = m_fakeData.constFind(m_username);
337− }
338−
339− loadFakeData();
340−}
341−
342−InfographicModel::InfographicModel(QObject *parent) :
343− QObject(parent), d_ptr(new InfographicModelPrivate(this))
344−{
345− d_ptr->generateFakeData();
346− setUsername("");
347−
348− connect(this, SIGNAL(nextDataSource()), this, SLOT(nextDataSourceSlot()),
349− Qt::QueuedConnection);
350− connect(this, SIGNAL(readyForDataChange()), this,
351− SLOT(readyForDataChangeSlot()), Qt::QueuedConnection);
352−}
353−
354−InfographicModel::~InfographicModel()
355−{
356− delete d_ptr;
357−}
358−
359−QString InfographicModel::label() const
360−{
361− return d_ptr->m_label;
362−}
363−
364−QString InfographicModel::username() const
365−{
366− return d_ptr->m_username;
367−}
368−
369−void InfographicModel::setUsername(const QString &username)
370−{
371− d_ptr->setUsername(username);
372−}
373−
374−InfographicColorTheme * InfographicModel::firstColor() const
375−{
376− return &d_ptr->m_firstColor;
377−}
378−
379−InfographicColorTheme * InfographicModel::secondColor() const
380−{
381− return &d_ptr->m_secondColor;
382−}
383−
384−QAbstractItemModel * InfographicModel::firstMonth() const
385−{
386− return &d_ptr->m_firstMonth;
387−}
388−
389−QAbstractItemModel * InfographicModel::secondMonth() const
390−{
391− return &d_ptr->m_secondMonth;
392−}
393−
394−int InfographicModel::currentDay() const
395−{
396− return d_ptr->m_currentDay;
397−}
398−
399−void InfographicModel::nextDataSourceSlot()
400−{
401− d_ptr->nextFakeData();
402−}
403−
404−void InfographicModel::readyForDataChangeSlot()
405−{
406− d_ptr->finishSetFakeData();
407−}
408−
409−/**
410− * Factory methods
411− */
412−
413−InfographicModel * InfographicModel::getInstance()
414−{
415− return new InfographicModel();
416−}
tests/mocks/LightDM/InfographicModelPrivate.hdeleted−99
@@ -1,99 +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− * Author: Pete Woods <pete.woods@canonical.com>
17− */
18−
19−#ifndef INFOGRAPHICMODEL_PRIVATE_H
20−#define INFOGRAPHICMODEL_PRIVATE_H
21−
22−#include <QtCore/QSharedPointer>
23−
24−#include "InfographicModel.h"
25−#include "plugins/Utils/qvariantlistmodel.h"
26−
27−namespace QLightDM
28−{
29−class InfographicDataPrivate;
30−
31−class Q_DECL_EXPORT InfographicData: public QObject
32−{
33−public:
34− explicit InfographicData(QObject *parent);
35−
36− InfographicData(const QString &label,
37− const InfographicColorTheme &firstColor,
38− const QVariantList &firstMonth,
39− const InfographicColorTheme &secondColor,
40− const QVariantList &secondMonth, QObject* parent);
41−
42− ~InfographicData();
43−
44−protected:
45− InfographicDataPrivate * const d_ptr;
46−
47−public:
48− const QString & label() const;
49− const InfographicColorTheme & firstColor() const;
50− const QVariantList & firstMonth() const;
51− const InfographicColorTheme & secondColor() const;
52− const QVariantList & secondMonth() const;
53− int length() const;
54−
55−private:
56− Q_DECLARE_PRIVATE(InfographicData)
57−};
58−
59−class InfographicModelPrivate: QObject
60−{
61−
62−public:
63− explicit InfographicModelPrivate(InfographicModel *parent);
64−
65− ~InfographicModelPrivate();
66−
67−public:
68− typedef QSharedPointer<InfographicData> InfographicDataPtr;
69− typedef QMultiMap<QString, InfographicDataPtr> FakeDataMap;
70−
71− InfographicModel * const q_ptr;
72− QString m_label;
73− InfographicColorTheme m_firstColor;
74− QVariantListModel m_firstMonth;
75− InfographicColorTheme m_secondColor;
76− QVariantListModel m_secondMonth;
77− int m_currentDay;
78− QString m_username;
79− FakeDataMap::const_iterator m_dataIndex;
80− InfographicDataPtr m_newData;
81− FakeDataMap m_fakeData;
82−
83− void setUsername(const QString &username);
84−
85−protected:
86− void nextFakeData();
87−
88− void generateFakeData();
89−
90− void loadFakeData();
91−
92− void finishSetFakeData();
93−
94−private:
95− Q_DECLARE_PUBLIC(InfographicModel)
96−};
97−}
98−
99−#endif // INFOGRAPHICMODEL_PRIVATE_H
tests/mocks/LightDM/demo/CMakeLists.txt+11−2
@@ -1,13 +1,22 @@
1+include(FindPkgConfig)
2+pkg_check_modules(LIBUSERMETRICSOUTPUT REQUIRED libusermetricsoutput-1)
3+
14set(LibLightDM_SOURCES
25 ../Greeter.cpp
36 ../UsersModel.cpp
4− ../InfographicModel.cpp
57 GreeterPrivate.cpp
68 UsersModelPrivate.cpp
7− InfographicModelPrivate.cpp
89 ${CMAKE_SOURCE_DIR}/plugins/Utils/qvariantlistmodel.cpp
910 )
1011
1112add_library(MockLightDM-demo STATIC ${LibLightDM_SOURCES})
1213
14+include_directories(
15+ ${LIBUSERMETRICSOUTPUT_INCLUDE_DIRS}
16+)
17+
18+target_link_libraries(MockLightDM-demo
19+ ${LIBUSERMETRICSOUTPUT_LDFLAGS}
20+ )
21+
1322qt5_use_modules(MockLightDM-demo Gui)
tests/mocks/LightDM/demo/UsersModelPrivate.cpp+1−1
@@ -26,7 +26,7 @@ UsersModelPrivate::UsersModelPrivate(UsersModel* parent)
2626{
2727 entries =
2828 {
29− { "guest", "Guest", 0, 0, false, false, 0, 0 },
29+ { "single", "Guest", 0, 0, false, false, 0, 0 },
3030 };
3131}
3232
tests/mocks/LightDM/full/CMakeLists.txt−2
@@ -1,10 +1,8 @@
11set(LibLightDM_SOURCES
22 ../Greeter.cpp
33 ../UsersModel.cpp
4− ../InfographicModel.cpp
54 GreeterPrivate.cpp
65 UsersModelPrivate.cpp
7− InfographicModelPrivate.cpp
86 ${CMAKE_SOURCE_DIR}/plugins/Utils/qvariantlistmodel.cpp
97 )
108
tests/mocks/LightDM/single-passphrase/CMakeLists.txt−2
@@ -1,10 +1,8 @@
11set(LibLightDM_SOURCES
22 ../Greeter.cpp
33 ../UsersModel.cpp
4− ../InfographicModel.cpp
54 GreeterPrivate.cpp
65 UsersModelPrivate.cpp
7− InfographicModelPrivate.cpp
86 ${CMAKE_SOURCE_DIR}/plugins/Utils/qvariantlistmodel.cpp
97 )
108
tests/mocks/LightDM/single-passphrase/UsersModelPrivate.cpp+1−1
@@ -26,7 +26,7 @@ UsersModelPrivate::UsersModelPrivate(UsersModel* parent)
2626{
2727 entries =
2828 {
29− { "has-pin", "Has PIN", 0, 0, false, false, 0, 0 },
29+ { "single", "Has Passphrase", 0, 0, false, false, 0, 0 },
3030 };
3131}
3232
tests/mocks/LightDM/single-pin/CMakeLists.txt−2
@@ -1,10 +1,8 @@
11set(LibLightDM_SOURCES
22 ../Greeter.cpp
33 ../UsersModel.cpp
4− ../InfographicModel.cpp
54 GreeterPrivate.cpp
65 UsersModelPrivate.cpp
7− InfographicModelPrivate.cpp
86 ${CMAKE_SOURCE_DIR}/plugins/Utils/qvariantlistmodel.cpp
97 )
108
tests/mocks/LightDM/single-pin/UsersModelPrivate.cpp+1−1
@@ -26,7 +26,7 @@ UsersModelPrivate::UsersModelPrivate(UsersModel* parent)
2626{
2727 entries =
2828 {
29− { "has-pin", "Has PIN", 0, 0, false, false, 0, 0 },
29+ { "single", "Has PIN", 0, 0, false, false, 0, 0 },
3030 };
3131}
3232
tests/mocks/LightDM/single/CMakeLists.txt−2
@@ -1,9 +1,7 @@
11set(LibLightDM_SOURCES
22 ../Greeter.cpp
3− ../InfographicModel.cpp
43 ../UsersModel.cpp
54 GreeterPrivate.cpp
6− InfographicModelPrivate.cpp
75 UsersModelPrivate.cpp
86 ${CMAKE_SOURCE_DIR}/plugins/Utils/qvariantlistmodel.cpp
97 )
tests/mocks/LightDM/single/UsersModelPrivate.cpp+1−1
@@ -26,7 +26,7 @@ UsersModelPrivate::UsersModelPrivate(UsersModel* parent)
2626{
2727 entries =
2828 {
29− { "one", "Only User", 0, 0, false, false, 0, 0 },
29+ { "single", "Single User", 0, 0, false, false, 0, 0 },
3030 };
3131}
3232
tests/mocks/libusermetrics/CMakeLists.txtnew file+17
@@ -0,0 +1,17 @@
1+set(mock_SOURCES
2+ ColorTheme.cpp
3+ UserMetrics.cpp
4+ ${CMAKE_SOURCE_DIR}/plugins/Utils/qvariantlistmodel.cpp
5+ )
6+
7+add_library(MockUserMetrics SHARED ${mock_SOURCES})
8+
9+qt5_use_modules(MockUserMetrics Gui)
10+
11+set_target_properties(MockUserMetrics PROPERTIES
12+ OUTPUT_NAME usermetricsoutput
13+ VERSION 1)
14+
15+install(TARGETS MockUserMetrics
16+ DESTINATION ${SHELL_APP_DIR}/plugins/mocks/libusermetrics
17+ )
tests/mocks/libusermetrics/ColorTheme.cppnew file+128
@@ -0,0 +1,128 @@
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+ * Author: Pete Woods <pete.woods@canonical.com>
17+ */
18+
19+#include "ColorTheme.h"
20+
21+#include <QtCore/QDir>
22+#include <QtCore/QString>
23+#include <QtGui/QIcon>
24+#include <QMultiMap>
25+
26+using namespace UserMetricsOutput;
27+
28+namespace UserMetricsOutput
29+{
30+
31+class ColorThemePrivate: QObject
32+{
33+public:
34+ explicit ColorThemePrivate(ColorTheme *parent = 0);
35+
36+ ColorThemePrivate(const QColor &start, const QColor &main,
37+ const QColor &end, ColorTheme *parent = 0);
38+
39+ ~ColorThemePrivate();
40+
41+ ColorTheme * const q_ptr;
42+
43+ QColor m_start;
44+
45+ QColor m_main;
46+
47+ QColor m_end;
48+
49+protected:
50+ int calculateLength();
51+
52+private:
53+ Q_DECLARE_PUBLIC(ColorTheme)
54+};
55+
56+}
57+
58+ColorThemePrivate::ColorThemePrivate(
59+ ColorTheme *parent) :
60+ q_ptr(parent)
61+{
62+}
63+
64+ColorThemePrivate::ColorThemePrivate(const QColor &start,
65+ const QColor &main, const QColor &end, ColorTheme *parent) :
66+ q_ptr(parent), m_start(start), m_main(main), m_end(end)
67+{
68+}
69+
70+ColorThemePrivate::~ColorThemePrivate()
71+{
72+}
73+
74+ColorTheme::ColorTheme(QObject *parent) :
75+ QObject(parent), d_ptr(new ColorThemePrivate(this))
76+{
77+}
78+
79+ColorTheme::ColorTheme(QColor &first, QColor &main,
80+ QColor &end, QObject *parent) :
81+ QObject(parent), d_ptr(
82+ new ColorThemePrivate(first, main, end, this))
83+{
84+
85+}
86+
87+ColorTheme & ColorTheme::operator=(
88+ const ColorTheme & other)
89+{
90+ if (d_ptr->m_start != other.d_ptr->m_start)
91+ {
92+ d_ptr->m_start = other.d_ptr->m_start;
93+ startChanged(d_ptr->m_start);
94+ }
95+ if (d_ptr->m_main != other.d_ptr->m_main)
96+ {
97+ d_ptr->m_main = other.d_ptr->m_main;
98+ mainChanged(d_ptr->m_main);
99+ }
100+
101+ if (d_ptr->m_end != other.d_ptr->m_end)
102+ {
103+ d_ptr->m_end = other.d_ptr->m_end;
104+ endChanged(d_ptr->m_end);
105+ }
106+
107+ return *this;
108+}
109+
110+ColorTheme::~ColorTheme()
111+{
112+ delete d_ptr;
113+}
114+
115+QColor ColorTheme::start() const
116+{
117+ return d_ptr->m_start;
118+}
119+
120+QColor ColorTheme::main() const
121+{
122+ return d_ptr->m_main;
123+}
124+
125+QColor ColorTheme::end() const
126+{
127+ return d_ptr->m_end;
128+}
tests/mocks/libusermetrics/ColorTheme.hnew file+68
@@ -0,0 +1,68 @@
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+ * Author: Pete Woods <pete.woods@canonical.com>
17+ */
18+
19+#ifndef UNITY_MOCK_COLORTHEME_H
20+#define UNITY_MOCK_COLORTHEME_H
21+
22+#include <QtGui/QColor>
23+
24+namespace UserMetricsOutput
25+{
26+class ColorThemePrivate;
27+
28+class Q_DECL_EXPORT ColorTheme: public QObject
29+{
30+Q_OBJECT
31+
32+Q_PROPERTY(QColor start READ start NOTIFY startChanged FINAL)
33+Q_PROPERTY(QColor main READ main NOTIFY mainChanged FINAL)
34+Q_PROPERTY(QColor end READ end NOTIFY endChanged FINAL)
35+
36+public:
37+ explicit ColorTheme(QObject *parent = 0);
38+
39+ explicit ColorTheme(QColor &first, QColor &main, QColor &end,
40+ QObject *parent = 0);
41+
42+ ColorTheme & operator=(const ColorTheme & other);
43+
44+ ~ColorTheme();
45+
46+ QColor start() const;
47+
48+ QColor main() const;
49+
50+ QColor end() const;
51+
52+Q_SIGNALS:
53+ void startChanged(const QColor &color);
54+
55+ void mainChanged(const QColor &color);
56+
57+ void endChanged(const QColor &color);
58+
59+protected:
60+ ColorThemePrivate * const d_ptr;
61+
62+ Q_DECLARE_PRIVATE(ColorTheme)
63+
64+};
65+
66+}
67+
68+#endif // UNITY_MOCK_COLORTHEME_H
tests/mocks/libusermetrics/UserMetrics.cppnew file+465
@@ -0,0 +1,465 @@
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+ * Author: Pete Woods <pete.woods@canonical.com>
17+ */
18+
19+#include "UserMetrics.h"
20+#include "plugins/Utils/qvariantlistmodel.h"
21+
22+#include <QtCore/QDir>
23+#include <QtCore/QString>
24+#include <QtGui/QIcon>
25+#include <QMultiMap>
26+
27+using namespace UserMetricsOutput;
28+
29+namespace UserMetricsOutput
30+{
31+class UserMetricsDataPrivate;
32+class UserMetricsPrivate;
33+
34+class Q_DECL_EXPORT UserMetricsData: public QObject
35+{
36+public:
37+ explicit UserMetricsData(QObject *parent);
38+
39+ UserMetricsData(const QString &label,
40+ const ColorTheme &firstColor,
41+ const QVariantList &firstMonth,
42+ const ColorTheme &secondColor,
43+ const QVariantList &secondMonth, QObject* parent);
44+
45+ ~UserMetricsData();
46+
47+protected:
48+ UserMetricsDataPrivate * const d_ptr;
49+
50+public:
51+ const QString & label() const;
52+ const ColorTheme & firstColor() const;
53+ const QVariantList & firstMonth() const;
54+ const ColorTheme & secondColor() const;
55+ const QVariantList & secondMonth() const;
56+ int length() const;
57+
58+private:
59+ Q_DECLARE_PRIVATE(UserMetricsData)
60+};
61+
62+class UserMetricsPrivate: QObject
63+{
64+public:
65+ explicit UserMetricsPrivate(UserMetrics *parent);
66+
67+ ~UserMetricsPrivate();
68+
69+public:
70+ typedef QSharedPointer<UserMetricsData> UserMetricsDataPtr;
71+ typedef QMultiMap<QString, UserMetricsDataPtr> FakeDataMap;
72+
73+ UserMetrics * const q_ptr;
74+ QString m_label;
75+ ColorTheme m_firstColor;
76+ QVariantListModel m_firstMonth;
77+ ColorTheme m_secondColor;
78+ QVariantListModel m_secondMonth;
79+ int m_currentDay;
80+ QString m_username;
81+ FakeDataMap::const_iterator m_dataIndex;
82+ UserMetricsDataPtr m_newData;
83+ FakeDataMap m_fakeData;
84+
85+ void setUsername(const QString &username);
86+
87+protected:
88+ void nextFakeData();
89+
90+ void generateFakeData();
91+
92+ void loadFakeData();
93+
94+ void finishSetFakeData();
95+
96+private:
97+ Q_DECLARE_PUBLIC(UserMetrics)
98+};
99+
100+class UserMetricsDataPrivate: QObject
101+{
102+public:
103+ explicit UserMetricsDataPrivate(UserMetricsData *parent);
104+
105+ UserMetricsDataPrivate(const QString &label,
106+ const ColorTheme &firstColor,
107+ const QVariantList &firstMonth,
108+ const ColorTheme &secondColor,
109+ const QVariantList &secondMonth, UserMetricsData *parent);
110+
111+ ~UserMetricsDataPrivate();
112+
113+ UserMetricsData * const q_ptr;
114+ QString m_label;
115+ ColorTheme m_firstColor;
116+ QVariantList m_firstMonth;
117+ ColorTheme m_secondColor;
118+ QVariantList m_secondMonth;
119+ int m_length;
120+
121+protected:
122+ int calculateLength();
123+
124+private:
125+ Q_DECLARE_PUBLIC(UserMetricsData)
126+};
127+
128+}
129+
130+UserMetricsDataPrivate::UserMetricsDataPrivate(UserMetricsData *parent) :
131+ q_ptr(parent), m_firstColor(this), m_secondColor(this)
132+{
133+ m_length = calculateLength();
134+}
135+
136+UserMetricsDataPrivate::UserMetricsDataPrivate(const QString &label,
137+ const ColorTheme &firstColor, const QVariantList &firstMonth,
138+ const ColorTheme &secondColor,
139+ const QVariantList &secondMonth, UserMetricsData *parent) :
140+ q_ptr(parent), m_label(label), m_firstColor(this), m_firstMonth(
141+ firstMonth), m_secondColor(this), m_secondMonth(secondMonth)
142+{
143+ m_length = calculateLength();
144+ m_firstColor = firstColor;
145+ m_secondColor = secondColor;
146+}
147+
148+UserMetricsDataPrivate::~UserMetricsDataPrivate()
149+{
150+}
151+
152+int UserMetricsDataPrivate::calculateLength()
153+{
154+ int day(m_firstMonth.size());
155+ auto it = m_firstMonth.end(), end = m_firstMonth.begin();
156+ while (it != end)
157+ {
158+ --it;
159+ --day;
160+ if (!it->isNull())
161+ {
162+ return day;
163+ }
164+ }
165+
166+ return -1;
167+}
168+
169+UserMetricsData::UserMetricsData(QObject *parent) :
170+ QObject(parent), d_ptr(new UserMetricsDataPrivate(this))
171+{
172+}
173+
174+UserMetricsData::UserMetricsData(const QString &label,
175+ const ColorTheme &firstColor, const QVariantList &firstMonth,
176+ const ColorTheme &secondColor,
177+ const QVariantList &secondMonth, QObject* parent) :
178+ QObject(parent), d_ptr(
179+ new UserMetricsDataPrivate(label, firstColor, firstMonth,
180+ secondColor, secondMonth, this))
181+{
182+}
183+
184+UserMetricsData::~UserMetricsData()
185+{
186+ delete d_ptr;
187+}
188+
189+const QString & UserMetricsData::label() const
190+{
191+ return d_ptr->m_label;
192+}
193+
194+const ColorTheme & UserMetricsData::firstColor() const
195+{
196+ return d_ptr->m_firstColor;
197+}
198+
199+const QVariantList & UserMetricsData::firstMonth() const
200+{
201+ return d_ptr->m_firstMonth;
202+}
203+
204+const ColorTheme & UserMetricsData::secondColor() const
205+{
206+ return d_ptr->m_secondColor;
207+}
208+
209+const QVariantList & UserMetricsData::secondMonth() const
210+{
211+ return d_ptr->m_secondMonth;
212+}
213+
214+int UserMetricsData::length() const
215+{
216+ return d_ptr->m_length;
217+}
218+
219+UserMetricsPrivate::UserMetricsPrivate(UserMetrics *parent) :
220+ q_ptr(parent), m_firstColor(this), m_secondColor(this)
221+{
222+ m_fakeData.insert("", UserMetricsDataPtr(new UserMetricsData(this)));
223+}
224+
225+UserMetricsPrivate::~UserMetricsPrivate()
226+{
227+}
228+
229+void UserMetricsPrivate::setUsername(const QString &username)
230+{
231+ if (m_username == username) {
232+ return;
233+ }
234+
235+ m_username = username;
236+
237+ m_dataIndex = m_fakeData.constFind(m_username);
238+ if (m_dataIndex == m_fakeData.end())
239+ {
240+ m_dataIndex = m_fakeData.constFind("");
241+ }
242+
243+ loadFakeData();
244+
245+ q_ptr->usernameChanged(m_username);
246+}
247+
248+void UserMetricsPrivate::generateFakeData()
249+{
250+ std::default_random_engine generator;
251+ std::normal_distribution<qreal> distribution(0.5, 0.2);
252+ auto rand = std::bind(distribution, generator);
253+
254+ QVector<QColor> colours;
255+ colours.push_back(QColor::fromRgbF(0.3, 0.27, 0.32));
256+ colours.push_back(QColor::fromRgbF(0.83, 0.49, 0.58));
257+ colours.push_back(QColor::fromRgbF(0.63, 0.51, 0.59));
258+
259+ colours.push_back(QColor::fromRgbF(0.28, 0.26, 0.4));
260+ colours.push_back(QColor::fromRgbF(0.47, 0.38, 0.56));
261+ colours.push_back(QColor::fromRgbF(0.69, 0.65, 0.78));
262+
263+ colours.push_back(QColor::fromRgbF(0.32, 0.21, 0.16));
264+ colours.push_back(QColor::fromRgbF(0.55, 0.45, 0.32));
265+ colours.push_back(QColor::fromRgbF(0.85, 0.74, 0.53));
266+
267+ colours.push_back(QColor::fromRgbF(0.25, 0.31, 0.19));
268+ colours.push_back(QColor::fromRgbF(0.63, 0.53, 0.3));
269+ colours.push_back(QColor::fromRgbF(0.89, 0.56, 0.31));
270+
271+ ColorTheme first(colours[0], colours[1], colours[2]);
272+ ColorTheme second(colours[3], colours[4], colours[5]);
273+ ColorTheme eighth(colours[6], colours[7], colours[8]);
274+ ColorTheme ninth(colours[9], colours[10], colours[11]);
275+
276+ {
277+ QVariantList firstMonth;
278+ while (firstMonth.size() < 17)
279+ firstMonth.push_back(QVariant(rand()));
280+ while (firstMonth.size() < 31)
281+ firstMonth.push_back(QVariant());
282+ QVariantList secondMonth;
283+ while (secondMonth.size() < 31)
284+ secondMonth.push_back(QVariant(rand()));
285+ QSharedPointer<UserMetricsData> data(
286+ new UserMetricsData("<b>52km</b> travelled", first, firstMonth,
287+ ninth, secondMonth, this));
288+ m_fakeData.insert("single", data);
289+ }
290+
291+ {
292+ QVariantList firstMonth;
293+ while (firstMonth.size() < 17)
294+ firstMonth.push_back(QVariant(rand()));
295+ while (firstMonth.size() < 31)
296+ firstMonth.push_back(QVariant());
297+ QVariantList secondMonth;
298+ while (secondMonth.size() < 31)
299+ secondMonth.push_back(QVariant(rand()));
300+ QSharedPointer<UserMetricsData> data(
301+ new UserMetricsData("<b>33</b> messages today", second,
302+ firstMonth, eighth, secondMonth, this));
303+ m_fakeData.insert("single", data);
304+ }
305+
306+ {
307+ QVariantList firstMonth;
308+ while (firstMonth.size() < 17)
309+ firstMonth.push_back(QVariant(rand()));
310+ while (firstMonth.size() < 31)
311+ firstMonth.push_back(QVariant());
312+ QVariantList secondMonth;
313+ while (secondMonth.size() < 31)
314+ secondMonth.push_back(QVariant(rand()));
315+ QSharedPointer<UserMetricsData> data(
316+ new UserMetricsData("<b>19</b> minutes talk time", eighth,
317+ firstMonth, second, secondMonth, this));
318+ m_fakeData.insert("single", data);
319+ // Also use same data for some tablet users
320+ m_fakeData.insert("has-password", data);
321+ m_fakeData.insert("no-password", data);
322+ m_fakeData.insert("empty-name", data);
323+ }
324+}
325+
326+void UserMetricsPrivate::loadFakeData()
327+{
328+ m_newData = *m_dataIndex;
329+
330+ bool oldLabelEmpty = m_label.isEmpty();
331+ bool newLabelEmpty = m_newData->label().isEmpty();
332+
333+ if (oldLabelEmpty && !newLabelEmpty)
334+ {
335+ q_ptr->dataAboutToAppear();
336+ finishSetFakeData();
337+ } else if (!oldLabelEmpty && newLabelEmpty)
338+ {
339+ q_ptr->dataAboutToDisappear();
340+ } else if (!oldLabelEmpty && !newLabelEmpty)
341+ {
342+ q_ptr->dataAboutToChange();
343+ }
344+ // we emit no signal if the data has stayed empty
345+}
346+
347+void UserMetricsPrivate::finishSetFakeData()
348+{
349+ bool oldLabelEmpty = m_label.isEmpty();
350+ bool newLabelEmpty = m_newData->label().isEmpty();
351+
352+ m_label = m_newData->label();
353+ m_firstColor = m_newData->firstColor();
354+ m_firstMonth.setVariantList(m_newData->firstMonth());
355+ m_secondColor = m_newData->secondColor();
356+ m_secondMonth.setVariantList(m_newData->secondMonth());
357+
358+ bool currentDayChanged = m_currentDay != m_newData->length();
359+ m_currentDay = m_newData->length();
360+
361+ q_ptr->labelChanged(m_label);
362+ if (currentDayChanged)
363+ {
364+ q_ptr->currentDayChanged(m_currentDay);
365+ }
366+
367+ if (oldLabelEmpty && !newLabelEmpty)
368+ {
369+ q_ptr->dataAppeared();
370+ } else if (!oldLabelEmpty && newLabelEmpty)
371+ {
372+ q_ptr->dataDisappeared();
373+ } else if (!oldLabelEmpty && !newLabelEmpty)
374+ {
375+ q_ptr->dataChanged();
376+ }
377+ // we emit no signal if the data has stayed empty
378+}
379+
380+void UserMetricsPrivate::nextFakeData()
381+{
382+ ++m_dataIndex;
383+ if (m_dataIndex == m_fakeData.end() || m_dataIndex.key() != m_username)
384+ {
385+ m_dataIndex = m_fakeData.constFind(m_username);
386+ }
387+
388+ loadFakeData();
389+}
390+
391+UserMetrics::UserMetrics(QObject *parent) :
392+ QObject(parent), d_ptr(new UserMetricsPrivate(this))
393+{
394+ d_ptr->generateFakeData();
395+ setUsername("");
396+
397+ connect(this, SIGNAL(nextDataSource()), this, SLOT(nextDataSourceSlot()),
398+ Qt::QueuedConnection);
399+ connect(this, SIGNAL(readyForDataChange()), this,
400+ SLOT(readyForDataChangeSlot()), Qt::QueuedConnection);
401+}
402+
403+UserMetrics::~UserMetrics()
404+{
405+ delete d_ptr;
406+}
407+
408+QString UserMetrics::label() const
409+{
410+ return d_ptr->m_label;
411+}
412+
413+QString UserMetrics::username() const
414+{
415+ return d_ptr->m_username;
416+}
417+
418+void UserMetrics::setUsername(const QString &username)
419+{
420+ d_ptr->setUsername(username);
421+}
422+
423+ColorTheme *UserMetrics::firstColor() const
424+{
425+ return &d_ptr->m_firstColor;
426+}
427+
428+ColorTheme *UserMetrics::secondColor() const
429+{
430+ return &d_ptr->m_secondColor;
431+}
432+
433+QAbstractItemModel *UserMetrics::firstMonth() const
434+{
435+ return &d_ptr->m_firstMonth;
436+}
437+
438+QAbstractItemModel *UserMetrics::secondMonth() const
439+{
440+ return &d_ptr->m_secondMonth;
441+}
442+
443+int UserMetrics::currentDay() const
444+{
445+ return d_ptr->m_currentDay;
446+}
447+
448+void UserMetrics::nextDataSourceSlot()
449+{
450+ d_ptr->nextFakeData();
451+}
452+
453+void UserMetrics::readyForDataChangeSlot()
454+{
455+ d_ptr->finishSetFakeData();
456+}
457+
458+/**
459+ * Factory methods
460+ */
461+
462+UserMetrics * UserMetrics::getInstance()
463+{
464+ return new UserMetrics();
465+}
tests/mocks/LightDM/InfographicModel.h → tests/mocks/libusermetrics/UserMetrics.hrenamed+22−60
@@ -16,74 +16,34 @@
1616 * Author: Pete Woods <pete.woods@canonical.com>
1717 */
1818
19−#ifndef LIGHTDM_INFOGRAPHICMODEL_H
20−#define LIGHTDM_INFOGRAPHICMODEL_H
19+#ifndef UNITY_MOCK_USERMETRICS_H
20+#define UNITY_MOCK_USERMETRICS_H
2121
22+#include "ColorTheme.h"
23+#include <QtCore/QAbstractListModel>
2224#include <QtCore/QString>
23−#include <QtGui/qcolor.h>
24−#include <QAbstractListModel>
25+#include <QtGui/QColor>
2526
26−namespace QLightDM
27+namespace UserMetricsOutput
2728{
28−class InfographicColorThemePrivate;
29+class UserMetricsPrivate;
2930
30−class Q_DECL_EXPORT InfographicColorTheme: public QObject
31−{
32−Q_OBJECT
33−
34−Q_PROPERTY(QColor start READ start NOTIFY startChanged FINAL)
35−Q_PROPERTY(QColor main READ main NOTIFY mainChanged FINAL)
36−Q_PROPERTY(QColor end READ end NOTIFY endChanged FINAL)
37−
38−public:
39− explicit InfographicColorTheme(QObject *parent = 0);
40−
41− explicit InfographicColorTheme(QColor &first, QColor &main, QColor &end,
42− QObject *parent = 0);
43−
44− InfographicColorTheme & operator=(const InfographicColorTheme & other);
45−
46− ~InfographicColorTheme();
47−
48− QColor start() const;
49−
50− QColor main() const;
51−
52− QColor end() const;
53−
54−Q_SIGNALS:
55− void startChanged(const QColor &color);
56−
57− void mainChanged(const QColor &color);
58−
59− void endChanged(const QColor &color);
60−
61−protected:
62− InfographicColorThemePrivate * const d_ptr;
63−
64− Q_DECLARE_PRIVATE(InfographicColorTheme)
65−
66−};
67−
68−class InfographicModelPrivate;
69−
70−class Q_DECL_EXPORT InfographicModel: public QObject
31+class Q_DECL_EXPORT UserMetrics: public QObject
7132{
7233Q_OBJECT
7334
7435Q_PROPERTY(QString label READ label NOTIFY labelChanged FINAL)
7536Q_PROPERTY(QString username READ username WRITE setUsername NOTIFY usernameChanged FINAL)
76−Q_PROPERTY(QLightDM::InfographicColorTheme* firstColor READ firstColor NOTIFY firstColorChanged FINAL)
77−Q_PROPERTY(QLightDM::InfographicColorTheme* secondColor READ secondColor NOTIFY secondColorChanged FINAL)
37+Q_PROPERTY(UserMetricsOutput::ColorTheme* firstColor READ firstColor NOTIFY firstColorChanged FINAL)
38+Q_PROPERTY(UserMetricsOutput::ColorTheme* secondColor READ secondColor NOTIFY secondColorChanged FINAL)
7839Q_PROPERTY(QAbstractItemModel *firstMonth READ firstMonth NOTIFY firstMonthChanged FINAL)
7940Q_PROPERTY(QAbstractItemModel *secondMonth READ secondMonth NOTIFY secondMonthChanged FINAL)
8041Q_PROPERTY(int currentDay READ currentDay NOTIFY currentDayChanged FINAL)
8142
8243public:
83− static InfographicModel *getInstance();
44+ static UserMetrics *getInstance();
8445
85− explicit InfographicModel(QObject *parent = 0);
86− ~InfographicModel();
46+ ~UserMetrics();
8747
8848 QString label() const;
8949
@@ -91,13 +51,13 @@ public:
9151
9252 void setUsername(const QString &username);
9353
94− InfographicColorTheme * firstColor() const;
54+ ColorTheme * firstColor() const;
9555
9656 QAbstractItemModel *firstMonth() const;
9757
9858 int currentDay() const;
9959
100− InfographicColorTheme * secondColor() const;
60+ ColorTheme * secondColor() const;
10161
10262 QAbstractItemModel *secondMonth() const;
10363
@@ -106,13 +66,13 @@ Q_SIGNALS:
10666
10767 void usernameChanged(const QString &username);
10868
109− void firstColorChanged(InfographicColorTheme *color);
69+ void firstColorChanged(ColorTheme *color);
11070
11171 void firstMonthChanged(QAbstractItemModel *firstMonth);
11272
11373 void currentDayChanged(int length);
11474
115− void secondColorChanged(InfographicColorTheme *color);
75+ void secondColorChanged(ColorTheme *color);
11676
11777 void secondMonthChanged(QAbstractItemModel *secondMonth);
11878
@@ -138,13 +98,15 @@ protected Q_SLOTS:
13898 void readyForDataChangeSlot();
13999
140100protected:
141− InfographicModelPrivate * const d_ptr;
101+ UserMetricsPrivate * const d_ptr;
102+
103+ explicit UserMetrics(QObject *parent = 0);
142104
143− Q_DISABLE_COPY(InfographicModel)
144− Q_DECLARE_PRIVATE(InfographicModel)
105+ Q_DISABLE_COPY(UserMetrics)
106+ Q_DECLARE_PRIVATE(UserMetrics)
145107
146108};
147109
148110}
149111
150−#endif // LIGHTDM_INFOGRAPHICMODEL_H
112+#endif // UNITY_MOCK_USERMETRICS_H
tests/mocks/libusermetrics/libusermetricsoutput/ColorTheme.hnew file+1
@@ -0,0 +1 @@
1+../ColorTheme.h
tests/mocks/libusermetrics/libusermetricsoutput/UserMetrics.hnew file+1
@@ -0,0 +1 @@
1+../UserMetrics.h
tests/plugins/CMakeLists.txt+1
@@ -1,3 +1,4 @@
11add_subdirectory(Utils)
22add_subdirectory(Ubuntu)
3+add_subdirectory(Unity)
34add_subdirectory(ListViewWithPageHeader)
tests/plugins/ListViewWithPageHeader/listviewwithpageheadertest.cpp+6
@@ -1299,6 +1299,12 @@ private Q_SLOTS:
12991299 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
13001300 }
13011301
1302+ void testCrashShowHeaderWithNoHeader()
1303+ {
1304+ lvwph->setHeader(nullptr);
1305+ lvwph->showHeader();
1306+ }
1307+
13021308private:
13031309 QQuickView *view;
13041310 ListViewWithPageHeader *lvwph;
tests/plugins/Unity/CMakeLists.txtnew file+38
@@ -0,0 +1,38 @@
1+pkg_check_modules(UNITYCORE REQUIRED unity-core-6.0)
2+pkg_check_modules(LIBUNITYPROTO REQUIRED unity-protocol-private)
3+
4+include_directories(
5+ ${Unity-qml_SOURCE_DIR}
6+ ${CMAKE_CURRENT_SOURCE_DIR}/../../../plugins/Unity
7+ ${CMAKE_CURRENT_BINARY_DIR}
8+ ${LIBUNITYPROTO_INCLUDE_DIRS}
9+ ${UNITYCORE_INCLUDE_DIRS}
10+ )
11+
12+macro(run_tests)
13+ set(_test_list "")
14+ foreach(_test ${ARGN})
15+ set(testCommand
16+ ${CMAKE_CURRENT_BINARY_DIR}/${_test}Exec
17+ -o ${CMAKE_BINARY_DIR}/${_test}.xml,xunitxml
18+ -o -,txt)
19+ add_test(NAME test${CLASSNAME}${_test} COMMAND ${testCommand})
20+ add_custom_target(${_test} ${testCommand})
21+ add_executable(${_test}Exec ${_test}.cpp previewbindingstest.cpp)
22+ qt5_use_modules(${_test}Exec Test Core Qml)
23+ set_tests_properties(test${CLASSNAME}${_test}
24+ PROPERTIES ENVIRONMENT LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/plugins/Unity:${LIBUNITYPROTO_LIBRARY_DIRS})
25+
26+ target_link_libraries(${_test}Exec
27+ Unity-qml
28+ ${UNITYCORE_LDFLAGS}
29+ ${LIBUNITYPROTO_LDFLAGS}
30+ )
31+
32+ set(_test_list "${_test_list};${_test}")
33+ endforeach()
34+endmacro(run_tests)
35+
36+run_tests(
37+ previewbindingstest
38+ )
tests/plugins/Unity/previewbindingstest.cppnew file+114
@@ -0,0 +1,114 @@
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 <unity-protocol.h>
23+
24+#include "genericpreview.h"
25+#include "applicationpreview.h"
26+#include "moviepreview.h"
27+#include "musicpreview.h"
28+
29+void PreviewBindingsTest::initTestCase()
30+{
31+}
32+
33+void PreviewBindingsTest::testGenericPreview()
34+{
35+ auto raw_preview = (GObject *)unity_protocol_generic_preview_new();
36+ unity_protocol_preview_set_title(UNITY_PROTOCOL_PREVIEW(raw_preview), "Metallica");
37+ unity_protocol_preview_set_subtitle(UNITY_PROTOCOL_PREVIEW(raw_preview), "Ride The Lightning");
38+ unity_protocol_preview_set_description(UNITY_PROTOCOL_PREVIEW(raw_preview), "Lorem ipsum dolor sit amet");
39+ unity::glib::Object<GObject> gen_prv(raw_preview);
40+
41+ auto core_prv = unity::dash::Preview::PreviewForProtocolObject(gen_prv);
42+ auto prv = Preview::newFromUnityPreview(core_prv);
43+
44+ QCOMPARE(prv != nullptr, true);
45+ QCOMPARE(prv->title(), QString("Metallica"));
46+ QCOMPARE(prv->subtitle(), QString("Ride The Lightning"));
47+ QCOMPARE(prv->description(), QString("Lorem ipsum dolor sit amet"));
48+}
49+
50+void PreviewBindingsTest::testApplicationPreview()
51+{
52+ auto raw_preview = (GObject *)unity_protocol_application_preview_new();
53+ unity_protocol_preview_set_title(UNITY_PROTOCOL_PREVIEW(raw_preview), "Firefox");
54+ unity_protocol_preview_set_subtitle(UNITY_PROTOCOL_PREVIEW(raw_preview), "Web Browser");
55+ unity_protocol_preview_set_description(UNITY_PROTOCOL_PREVIEW(raw_preview), "Lorem ipsum dolor sit amet");
56+ unity_protocol_application_preview_set_license(UNITY_PROTOCOL_APPLICATION_PREVIEW(raw_preview), "GPL");
57+ unity_protocol_application_preview_set_rating(UNITY_PROTOCOL_APPLICATION_PREVIEW(raw_preview), 0.5f);
58+ unity_protocol_application_preview_set_num_ratings(UNITY_PROTOCOL_APPLICATION_PREVIEW(raw_preview), 4);
59+ unity::glib::Object<GObject> gen_prv(raw_preview);
60+
61+ auto core_prv = unity::dash::Preview::PreviewForProtocolObject(gen_prv);
62+ auto prv = Preview::newFromUnityPreview(core_prv);
63+ auto app_prv = dynamic_cast<ApplicationPreview*>(prv);
64+
65+ QCOMPARE(app_prv != nullptr, true);
66+ QCOMPARE(app_prv->title(), QString("Firefox"));
67+ QCOMPARE(app_prv->subtitle(), QString("Web Browser"));
68+ QCOMPARE(app_prv->description(), QString("Lorem ipsum dolor sit amet"));
69+ QCOMPARE(app_prv->license(), QString("GPL"));
70+ QCOMPARE(app_prv->rating(), 0.5f);
71+ QCOMPARE(app_prv->numRatings(), unsigned (4));
72+}
73+
74+void PreviewBindingsTest::testMoviePreview()
75+{
76+ auto raw_preview = (GObject *)unity_protocol_movie_preview_new();
77+ unity_protocol_preview_set_title(UNITY_PROTOCOL_PREVIEW(raw_preview), "Blade Runner");
78+ unity_protocol_preview_set_subtitle(UNITY_PROTOCOL_PREVIEW(raw_preview), "Ridley Scott");
79+ unity_protocol_preview_set_description(UNITY_PROTOCOL_PREVIEW(raw_preview), "Lorem ipsum dolor sit amet");
80+ unity_protocol_movie_preview_set_year(UNITY_PROTOCOL_MOVIE_PREVIEW(raw_preview), "1982");
81+ unity::glib::Object<GObject> gen_prv(raw_preview);
82+
83+ auto core_prv = unity::dash::Preview::PreviewForProtocolObject(gen_prv);
84+ auto prv = Preview::newFromUnityPreview(core_prv);
85+ auto movie_prv = dynamic_cast<MoviePreview*>(prv);
86+
87+ QCOMPARE(movie_prv != nullptr, true);
88+ QCOMPARE(movie_prv->title(), QString("Blade Runner"));
89+ QCOMPARE(movie_prv->subtitle(), QString("Ridley Scott"));
90+ QCOMPARE(movie_prv->description(), QString("Lorem ipsum dolor sit amet"));
91+ QCOMPARE(movie_prv->year(), QString("1982"));
92+}
93+
94+void PreviewBindingsTest::testMusicPreview()
95+{
96+ auto raw_preview = (GObject *)unity_protocol_music_preview_new();
97+ unity_protocol_preview_set_title(UNITY_PROTOCOL_PREVIEW(raw_preview), "Metallica");
98+ unity_protocol_preview_set_subtitle(UNITY_PROTOCOL_PREVIEW(raw_preview), "Death Magnetic");
99+ unity_protocol_preview_set_description(UNITY_PROTOCOL_PREVIEW(raw_preview), "Lorem ipsum dolor sit amet");
100+ unity::glib::Object<GObject> gen_prv(raw_preview);
101+
102+ auto core_prv = unity::dash::Preview::PreviewForProtocolObject(gen_prv);
103+ auto prv = Preview::newFromUnityPreview(core_prv);
104+ auto music_prv = dynamic_cast<MusicPreview*>(prv);
105+
106+ QCOMPARE(music_prv != nullptr, true);
107+ QCOMPARE(music_prv->title(), QString("Metallica"));
108+ QCOMPARE(music_prv->subtitle(), QString("Death Magnetic"));
109+ QCOMPARE(music_prv->description(), QString("Lorem ipsum dolor sit amet"));
110+}
111+
112+QTEST_MAIN(PreviewBindingsTest)
113+
114+#include "previewbindingstest.moc"
tests/plugins/Unity/previewbindingstest.hnew file+34
@@ -0,0 +1,34 @@
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+};
33+
34+#endif
tests/plugins/Utils/qlimitproxymodeltest.cpp+15
@@ -446,6 +446,7 @@ private Q_SLOTS:
446446
447447 ModelTest t1(&proxy);
448448 }
449+
449450 void testModelChanged() {
450451 QLimitProxyModelQML proxy;
451452 MockListModel model, model2;
@@ -464,6 +465,20 @@ private Q_SLOTS:
464465 proxy.setModel(&model);
465466 QCOMPARE(spyOnModelChanged.count(), 3);
466467 }
468+
469+ void setSameModelTwice() {
470+ QLimitProxyModelQML proxy;
471+ MockListModel model;
472+
473+ proxy.setModel(&model);
474+ proxy.setModel(&model);
475+
476+ QSignalSpy spyOnCountChanged(&proxy, SIGNAL(countChanged()));
477+
478+ model.insertRows(0, 5);
479+ QCOMPARE(proxy.rowCount(), 5);
480+ QCOMPARE(spyOnCountChanged.count(), 1);
481+ }
467482};
468483
469484QTEST_MAIN(QLimitProxyModelTest)
tests/qmltests/CMakeLists.txt+4−4
@@ -50,13 +50,13 @@ add_qml_test(Dash FilterGrids IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMA
5050 ${CMAKE_BINARY_DIR}/tests/mocks)
5151add_qml_test(Dash/Apps RunningApplicationsGrid IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
5252add_qml_test(Greeter Lockscreen IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/plugins ${CMAKE_BINARY_DIR}/tests/mocks
53− PROPERTIES ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/LightDM/full")
53+ ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/libusermetrics:${CMAKE_BINARY_DIR}/tests/mocks/LightDM/full")
5454add_qml_test(Greeter Tablet IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/plugins ${CMAKE_BINARY_DIR}/tests/mocks
55− ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/LightDM/full")
55+ ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/libusermetrics:${CMAKE_BINARY_DIR}/tests/mocks/LightDM/full")
5656add_qml_test(Greeter Phone IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/plugins ${CMAKE_BINARY_DIR}/tests/mocks
57− ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/LightDM/single")
57+ ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/libusermetrics:${CMAKE_BINARY_DIR}/tests/mocks/LightDM/single")
5858add_qml_test(Greeter Infographics IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/plugins ${CMAKE_BINARY_DIR}/tests/mocks
59− ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/LightDM/full")
59+ ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/libusermetrics:${CMAKE_BINARY_DIR}/tests/mocks/LightDM/full")
6060add_qml_test(Hud Hud)
6161add_qml_test(Hud Result)
6262add_qml_test(Launcher Launcher IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
tests/qmltests/Panel/tst_Indicators.qml+34−45
@@ -42,23 +42,9 @@ Item {
4242 }
4343 width: (shell.width > units.gu(60)) ? units.gu(40) : shell.width
4444 y: 0
45− hintValue: indicatorRevealer.hintDisplacement
4645 shown: false
47− revealer: indicatorRevealer
4846
4947 openedHeight: parent.height - click_me.height
50−
51− showAnimation: NumberAnimation { property: "progress"; duration: 350; to: indicatorRevealer.openedValue; easing.type: Easing.OutCubic }
52− hideAnimation: NumberAnimation { property: "progress"; duration: 350; to: indicatorRevealer.closedValue; easing.type: Easing.OutCubic }
53− }
54−
55− Revealer {
56− anchors.fill: indicators
57− id: indicatorRevealer
58− hintDisplacement: indicators.panelHeight * 3
59−
60− openedValue: indicators.openedHeight - indicators.panelHeight
61− closedValue: indicators.panelHeight
6248 }
6349
6450 // Just a rect for clicking to open the indicators.
@@ -152,60 +138,63 @@ Item {
152138 {
153139 // tests changing the lateral position of the revealer activates the correct indicator items.
154140
155− // This "should" put the indicators in "hint" state
156− indicators.progress = indicators.hintValue;
157−
158141 var indicator_row = findChild(indicators, "indicatorRow")
159142 var row_repeater = findChild(indicators, "rowRepeater")
160143
161144 for (var i = 0; i < row_repeater.count; i++) {
162145 var indicator_item = row_repeater.itemAt(i);
163146
164− var indicator_position = indicator_row.row.x + indicator_item.x + indicator_item.width/2;
147+ var indicator_position = indicators.mapFromItem(indicator_item,
148+ indicator_item.width/2, indicator_item.height/2)
165149
166− indicatorRevealer.lateralPosition = indicator_position;
150+ touchFlick(indicators,
151+ indicator_position.x, indicator_position.y,
152+ indicator_position.x, indicators.openedHeight * 0.4,
153+ true /* beginTouch */, false /* endTouch */)
167154
168− compare(indicator_row.currentItem, indicator_item, "Incorrect item activated at position " + i);
155+ compare(indicator_row.currentItem, indicator_item,
156+ "Incorrect item activated at position " + i);
157+
158+ touchFlick(indicators,
159+ indicator_position.x, indicators.openedHeight * 0.4,
160+ indicator_position.x, indicator_position.y,
161+ false /* beginTouch */, true /* endTouch */)
162+
163+ // wait until fully closed
164+ tryCompare(indicators, "height", indicators.panelHeight)
169165 }
170166 }
171167
172− // PROGRESS TESTS
173−
174− // values for specific state changes are subject to internal decisions, so we can't determine the true progress value
175− // which would cause the state to change without making too many assuptyions
176− // However, we can assume that a partially opened panel will not be initial, and fully opened panel will be locked.
168+ // values for specific state changes are subject to internal decisions, so we can't
169+ // determine the true height value which would cause the state to change without making
170+ // too many assuptyions
171+ // However, we can assume that a partially opened panel will not be initial, and fully
172+ // opened panel will be locked.
177173
178174 function test_progress_changes_state_to_not_initial() {
179− indicators.progress = indicatorRevealer.closedValue + (indicatorRevealer.openedValue - indicatorRevealer.closedValue)/2;
180− compare(indicators.state!="initial", true, "Indicators should not be in initial state when partially opened.");
175+ indicators.height = indicators.openedHeight / 2
176+ compare(indicators.state!="initial", true,
177+ "Indicators should not be in initial state when partially opened.")
181178 }
182179
183180 function test_progress_changes_state_to_locked() {
184− indicators.progress = indicators.openedHeight;
185− compare(indicators.state, "locked", "Indicators should be locked when fully opened.");
181+ indicators.height = indicators.openedHeight - indicators.panelHeight
182+ compare(indicators.state, "locked", "Indicators should be locked when fully opened.")
186183 }
187184
188185 function test_partially_open() {
189− indicators.progress = indicatorRevealer.closedValue + (indicatorRevealer.openedValue - indicatorRevealer.closedValue)/2;
190− compare(indicators.partiallyOpened, true, "Indicator should show as partially opened when in between revealer closedValue & openedValue height");
191− compare(indicators.fullyOpened, false, "Indicator should not show as fully opened when in between revealer closedValue & openedValue height");
186+ indicators.height = indicators.openedHeight / 2
187+ compare(indicators.partiallyOpened, true,
188+ "Indicator should show as partially opened when height is half of openedHeight")
189+ compare(indicators.fullyOpened, false,
190+ "Indicator should not show as fully opened when height is half of openedHeight")
192191 }
193192
194193 function test_fully_open() {
195− indicators.progress = indicatorRevealer.openedValue
196− compare(indicators.partiallyOpened, false, "Indicator should show as fully opened when in between revealer closedValue & openedValue height");
197− compare(indicators.fullyOpened, true, "Indicator should not show as fully opened when at revealer openedValue height");
194+ indicators.height = indicators.openedHeight
195+ compare(indicators.partiallyOpened, false);
196+ compare(indicators.fullyOpened, true);
198197 }
199198
200− // The indicator menu content should be shown if the indicators are show through an animation before they
201− // enter a furthur state through a progress change (eg press indicator row, drag down a less then hint
202− // threshold and release to show
203− function test_menu_open_on_hint_drag() {
204− indicators.handlePress();
205− indicators.show()
206−
207− var menuContent = findChild(indicators, "menuContent")
208− compare(menuContent.__shown, true, "Indicator menu content should be shown after a indicator show.");
209− }
210199 }
211200}
tests/qmltests/Panel/tst_Panel.qml+65−113
@@ -77,92 +77,56 @@ Item {
7777 return panel.mapFromItem(indicator_item, indicator_item.width/2, indicator_item.height/2);
7878 }
7979
80− function test_hint_data() { return get_window_data() }
81−
8280 // Pressing on the indicator panel should activate the indicator hints
8381 // and expose a portion of the conent.
84− function test_hint(data) {
85− panel.fullscreenMode = data.fullscreenFlag;
86−
87− var indicator_item_coord = get_indicator_item_position(0);
88− var indicator_revealer = findChild(panel, "indicatorRevealer");
89− verify(indicator_revealer != undefined)
90−
91− mousePress(panel,
92− indicator_item_coord.x, panel.panelHeight/2,
93− Qt.LeftButton, Qt.NoModifier , 0);
94−
95− if (!panel.fullscreenMode)
96− {
97− compare(indicator_revealer.hintingAnimation.running, true, "Indicator revealer hint animation should be running after mouse press on indicator panel in pinned mode");
98− tryCompare(indicator_revealer.hintingAnimation, "running", false);
99− tryCompare(panel.indicators, "partiallyOpened", true);
100− }
101− else
102− {
103− // nothing should happen
104− compare(indicator_revealer.hintingAnimation.running, false, "Indicator revealer hint animation should not be running after mouse press on indicator panel in fullscreen mode");
105− compare(panel.indicators.partiallyOpened, false, "Indicator should not be partially opened when panel is pressed in fullscreenmode");
106− compare(panel.indicators.fullyOpened, false, "Indicator should not be partially opened when panel is pressed in fullscreenmode");
107− }
108−
109− mouseRelease(panel,
110− indicator_item_coord.x, panel.panelHeight/2,
111− Qt.LeftButton, Qt.NoModifier , 0);
112− }
113−
114− function test_show_click_data() { return get_window_data() }
115−
116− // Clicking the indicator panel should fully open the inidicators
117− function test_show_click(data) {
118− panel.fullscreenMode = data.fullscreenFlag;
82+ function test_hint() {
83+ panel.fullscreenMode = false;
84+ // Wait for the indicators to get into position.
85+ // (switches between normal and fullscreen modes are animated)
86+ tryCompare(panel.indicators, "y", 0)
11987
12088 var indicator_item_coord = get_indicator_item_position(0);
12189
122− mouseClick(panel,
123− indicator_item_coord.x, panel.panelHeight/2,
124− Qt.LeftButton, Qt.NoModifier , 0);
90+ touchPress(panel, indicator_item_coord.x, panel.panelHeight / 2)
12591
126− if (!panel.fullscreenMode)
127− {
128− compare(panel.indicators.showAnimation.running, true, "Show animation should run after panel is clicked in pinned mode.");
129− tryCompare(panel.indicators, "fullyOpened", true);
92+ // hint animation should be run, meaning that indicators will move downwards
93+ // by hintValue pixels without any drag taking place
94+ tryCompare(panel.indicators, "height",
95+ panel.indicators.panelHeight + panel.indicators.hintValue);
96+ tryCompare(panel.indicators, "partiallyOpened", true);
97+ tryCompare(panel.indicators, "fullyOpened", false);
13098
131− // click will activate device overview.
132− compare(findChild(panel.indicators, "indicatorRow").overviewActive, true, "Overview indicator should be avtive when indicators clicked.")
133− }
134− else
135− {
136− compare(panel.indicators.showAnimation.running, false, "Indicators should not open when panel is clicked in pinned mode.");
137− }
99+ touchRelease(panel, indicator_item_coord.x, panel.panelHeight/2)
138100 }
139101
140− function test_show_press_release_data() { return get_window_data() }
141−
142− // Pressing and releasing on the indicator panel will fully open the indicators
143− function test_show_press_release(data) {
144− panel.fullscreenMode = data.fullscreenFlag;
102+ // Pressing on the top edge of the screen should have no effect if the panel
103+ // is hidden (!pinned), which is the case when a fullscreen app is being shown
104+ function test_noHintOnFullscreenMode() {
105+ panel.fullscreenMode = true;
106+ // Wait for the indicators to get into position.
107+ // (switches between normal and fullscreen modes are animated)
108+ tryCompare(panel.indicators, "y", -panel.panelHeight)
145109
146110 var indicator_item_coord = get_indicator_item_position(0);
147111
148− mousePress(panel,
149− indicator_item_coord.x, panel.panelHeight/2,
150− Qt.LeftButton, Qt.NoModifier , 0);
112+ touchPress(panel, indicator_item_coord.x, panel.panelHeight / 2)
151113
152− mouseRelease(panel,
153− indicator_item_coord.x, panel.panelHeight/2,
154− Qt.LeftButton, Qt.NoModifier , 0);
114+ // Give some time for a hint animation to change things, if any
115+ wait(500)
155116
156− if (!panel.fullscreenMode)
157− {
158− compare(panel.indicators.showAnimation.running, true, "Show animation should run after panel is clicked in pinned mode.");
159− tryCompare(panel.indicators, "fullyOpened", true);
160− }
161− else
162− {
163− // nothing should happen.
164− compare(panel.indicators.showAnimation.running, false, "Indicators should not open when panel is clicked in pinned mode.");
165− }
117+ // no hint animation when fullscreen
118+ compare(panel.indicators.y, -panel.panelHeight)
119+ var indicatorRow = findChild(panel.indicators, "indicatorRow");
120+ verify(indicatorRow != undefined)
121+ compare(indicatorRow.y, 0)
122+ compare(panel.indicators.height, panel.indicators.panelHeight)
123+ compare(panel.indicators.partiallyOpened, false,
124+ "Indicator should not be partially opened when panel is pressed in" +
125+ " fullscreenmode")
126+ compare(panel.indicators.fullyOpened, false, "Indicator should not be partially" +
127+ " opened when panel is pressed in fullscreenmode")
128+
129+ touchRelease(panel, indicator_item_coord.x, panel.panelHeight/2)
166130 }
167131
168132 function test_drag_show_data() { return get_window_data() }
@@ -173,9 +137,6 @@ Item {
173137 function test_drag_show(data) {
174138 panel.fullscreenMode = data.fullscreenFlag;
175139
176− var indicator_revealer = findChild(panel, "indicatorRevealer");
177− verify(indicator_revealer != undefined)
178−
179140 var indicator_row = findChild(panel.indicators, "indicatorRow");
180141 verify(indicator_row != undefined)
181142
@@ -185,6 +146,14 @@ Item {
185146 var menu_content = findChild(panel.indicators, "menuContent");
186147 verify(indicator_row != undefined)
187148
149+ // Wait for the indicators to get into position.
150+ // (switches between normal and fullscreen modes are animated)
151+ if (data.fullscreenFlag) {
152+ tryCompare(panel.indicators, "y", -panel.panelHeight)
153+ } else {
154+ tryCompare(panel.indicators, "y", 0)
155+ }
156+
188157 // do this for each indicator item
189158 for (var i = 0; i < row_repeater.count; i++) {
190159
@@ -193,40 +162,25 @@ Item {
193162
194163 var indicator_item_coord = get_indicator_item_position(i);
195164
196− // 1) Press on the panel
197− mousePress(panel,
198− indicator_item_coord.x, panel.panelHeight/2,
199− Qt.LeftButton, Qt.NoModifier , 0);
200−
201− if (!panel.fullscreenMode)
202− {
203− // hint animation should be run, and panel will end in partiallyOpened state.
204− compare(indicator_revealer.hintingAnimation.running, true, "Indicator revealer hint animation should be running after mouse press on indicator panel");
205− tryCompare(indicator_revealer.hintingAnimation, "running", false);
206− tryCompare(panel.indicators, "partiallyOpened", true);
207− }
208−
209− // 2) Drag the mouse down
210− var old_progress = panel.indicators.progress
211− mouseMove(panel,
212− indicator_item_coord.x, old_progress + (panel.height - old_progress)/2,
213− 0, Qt.LeftButton);
214−
215− // progress should increase.
216− var progress_increases = panel.indicators.progress > old_progress;
217− compare(progress_increases, true, "Progress has not increased on dragging indicator.");
165+ touchPress(panel,
166+ indicator_item_coord.x, panel.panelHeight / 2)
218167
219− mouseMove(panel,
220− indicator_item_coord.x, shell.y + shell.height,
221− 0, Qt.LeftButton);
168+ // 1) Drag the mouse down
169+ touchFlick(panel,
170+ indicator_item_coord.x, panel.panelHeight / 2,
171+ indicator_item_coord.x, panel.height * 0.8,
172+ false /* beginTouch */, false /* endTouch */)
222173
223− tryCompare(panel.indicators, "fullyOpened", true);
174+ // Indicators height should follow the drag, and therefore increase accordingly.
175+ // They should be at least half-way through the screen
176+ tryCompareFunction(
177+ function() {return panel.indicators.height >= panel.height * 0.5},
178+ true)
224179
225− mouseRelease(panel,
226− indicator_item_coord.x, indicator_item_coord.y + panel.height/2,
227− Qt.LeftButton, Qt.NoModifier , 0);
180+ touchRelease(panel, indicator_item_coord.x, panel.height * 0.8)
228181
229− compare(indicator_row.currentItem, indicator_item, "Incorrect item activated at position " + i);
182+ compare(indicator_row.currentItem, indicator_item,
183+ "Incorrect item activated at position " + i)
230184 compare(menu_content.__shown, true, "Menu conetent should be enabled for item at position " + i);
231185
232186 // init for next indicator_item
@@ -241,11 +195,10 @@ Item {
241195 var search_indicator = findChild(panel, "search");
242196 verify(search_indicator != undefined);
243197
244− mouseClick(search_indicator,
245− 1, 1,
246− Qt.LeftButton, Qt.NoModifier , 0);
198+ tap(search_indicator, 1, 1)
247199
248− compare(search_clicked, true, "Clicking search indicator while it was enabled did not emit searchClicked signal")
200+ compare(search_clicked, true,
201+ "Tapping search indicator while it was enabled did not emit searchClicked signal")
249202 }
250203
251204 function test_search_click_when_not_visible() {
@@ -255,11 +208,10 @@ Item {
255208 var search_indicator = findChild(panel, "search");
256209 verify(search_indicator != undefined);
257210
258− mouseClick(search_indicator,
259− 1, 1,
260− Qt.LeftButton, Qt.NoModifier , 0);
211+ tap(search_indicator, 1, 1)
261212
262− compare(search_clicked, false, "Clicking search indicator while it was not visible emitted searchClicked signal")
213+ compare(search_clicked, false,
214+ "Tapping search indicator while it was not visible emitted searchClicked signal")
263215 }
264216 }
265217}