on xenial help sign in
Merge
7f3c417Albert Astals
debian/changelog+23
@@ -1,3 +1,26 @@
1+unity8 (8.02+15.04.20141215.3-0ubuntu1) vivid; urgency=low
2+
3+ [ Albert Astals Cid ]
4+ * ScopesList: Use the default scope style for the header
5+
6+ [ Daniel d'Andrada ]
7+ * Refactor Dialogs.qml to use proper in-scene dialogs
8+ * Make Greeter nicely handle being resized
9+
10+ [ Albert Astals ]
11+ * Rework how we set the ranges so we get some more asynchronousity
12+ from item views (LP: #1384374)
13+ * clickscope is back to being unfavoritable (LP: #1400762)
14+ * Fix clicking on the manage dash list after having moved the current
15+ scope
16+ * Make the drag range be a multiple of the drag "rate" value.
17+ Workarounds https://bugs.launchpad.net/mir/+bug/1399690
18+
19+ [ Gerry Boland ]
20+ * MockAppMan: emit SIGSTOP so AP test apps are run (LP: #1394208)
21+
22+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Mon, 15 Dec 2014 22:43:16 +0000
23+
1unity8 (8.02+15.04.20141212.1-0ubuntu1) vivid; urgency=low
24unity8 (8.02+15.04.20141212.1-0ubuntu1) vivid; urgency=low
2
25
3 [ Ubuntu daily release ]
26 [ Ubuntu daily release ]
plugins/Dash/abstractdashview.cpp+24−5
@@ -16,13 +16,12 @@
16
16
17#include "abstractdashview.h"
17#include "abstractdashview.h"
18
18
19−static const qreal bufferRatio = 0.5;
20−
21AbstractDashView::AbstractDashView()
19AbstractDashView::AbstractDashView()
22 : m_delegateModel(nullptr)
20 : m_delegateModel(nullptr)
23 , m_asyncRequestedIndex(-1)
21 , m_asyncRequestedIndex(-1)
24 , m_columnSpacing(0)
22 , m_columnSpacing(0)
25 , m_rowSpacing(0)
23 , m_rowSpacing(0)
24+ , m_buffer(320) // Same value used in qquickitemview.cpp in Qt 5.4
26 , m_displayMarginBeginning(0)
25 , m_displayMarginBeginning(0)
27 , m_displayMarginEnd(0)
26 , m_displayMarginEnd(0)
28 , m_needsRelayout(false)
27 , m_needsRelayout(false)
@@ -112,6 +111,27 @@ void AbstractDashView::setRowSpacing(qreal rowSpacing)
112 }
111 }
113}
112}
114
113
114+int AbstractDashView::cacheBuffer() const
115+{
116+ return m_buffer;
117+}
118+
119+void AbstractDashView::setCacheBuffer(int buffer)
120+{
121+ if (buffer < 0) {
122+ qmlInfo(this) << "Cannot set a negative cache buffer";
123+ return;
124+ }
125+
126+ if (m_buffer != buffer) {
127+ m_buffer = buffer;
128+ if (isComponentComplete()) {
129+ polish();
130+ }
131+ emit cacheBufferChanged();
132+ }
133+}
134+
115qreal AbstractDashView::displayMarginBeginning() const
135qreal AbstractDashView::displayMarginBeginning() const
116{
136{
117 return m_displayMarginBeginning;
137 return m_displayMarginBeginning;
@@ -160,9 +180,8 @@ void AbstractDashView::refill()
160
180
161 const qreal from = -m_displayMarginBeginning;
181 const qreal from = -m_displayMarginBeginning;
162 const qreal to = height() + m_displayMarginEnd;
182 const qreal to = height() + m_displayMarginEnd;
163− const qreal buffer = (to - from) * bufferRatio;
164− const qreal bufferFrom = from - buffer;
183+ const qreal bufferFrom = from - m_buffer;
165− const qreal bufferTo = to + buffer;
184+ const qreal bufferTo = to + m_buffer;
166
185
167 bool added = addVisibleItems(from, to, false);
186 bool added = addVisibleItems(from, to, false);
168 bool removed = removeNonVisibleItems(bufferFrom, bufferTo);
187 bool removed = removeNonVisibleItems(bufferFrom, bufferTo);
plugins/Dash/abstractdashview.h+6
@@ -35,6 +35,7 @@ class AbstractDashView : public QQuickItem
35 Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
35 Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
36 Q_PROPERTY(qreal columnSpacing READ columnSpacing WRITE setColumnSpacing NOTIFY columnSpacingChanged)
36 Q_PROPERTY(qreal columnSpacing READ columnSpacing WRITE setColumnSpacing NOTIFY columnSpacingChanged)
37 Q_PROPERTY(qreal rowSpacing READ rowSpacing WRITE setRowSpacing NOTIFY rowSpacingChanged)
37 Q_PROPERTY(qreal rowSpacing READ rowSpacing WRITE setRowSpacing NOTIFY rowSpacingChanged)
38+ Q_PROPERTY(int cacheBuffer READ cacheBuffer WRITE setCacheBuffer NOTIFY cacheBufferChanged)
38 Q_PROPERTY(qreal displayMarginBeginning READ displayMarginBeginning
39 Q_PROPERTY(qreal displayMarginBeginning READ displayMarginBeginning
39 WRITE setDisplayMarginBeginning
40 WRITE setDisplayMarginBeginning
40 NOTIFY displayMarginBeginningChanged)
41 NOTIFY displayMarginBeginningChanged)
@@ -61,6 +62,9 @@ public:
61 qreal rowSpacing() const;
62 qreal rowSpacing() const;
62 void setRowSpacing(qreal rowSpacing);
63 void setRowSpacing(qreal rowSpacing);
63
64
65+ int cacheBuffer() const;
66+ void setCacheBuffer(int);
67+
64 qreal displayMarginBeginning() const;
68 qreal displayMarginBeginning() const;
65 void setDisplayMarginBeginning(qreal);
69 void setDisplayMarginBeginning(qreal);
66
70
@@ -72,6 +76,7 @@ Q_SIGNALS:
72 void delegateChanged();
76 void delegateChanged();
73 void columnSpacingChanged();
77 void columnSpacingChanged();
74 void rowSpacingChanged();
78 void rowSpacingChanged();
79+ void cacheBufferChanged();
75 void displayMarginBeginningChanged();
80 void displayMarginBeginningChanged();
76 void displayMarginEndChanged();
81 void displayMarginEndChanged();
77
82
@@ -117,6 +122,7 @@ private:
117
122
118 int m_columnSpacing;
123 int m_columnSpacing;
119 int m_rowSpacing;
124 int m_rowSpacing;
125+ int m_buffer;
120 qreal m_displayMarginBeginning;
126 qreal m_displayMarginBeginning;
121 qreal m_displayMarginEnd;
127 qreal m_displayMarginEnd;
122 bool m_needsRelayout;
128 bool m_needsRelayout;
plugins/Dash/listviewwithpageheader.cpp+7−2
@@ -334,13 +334,18 @@ qreal ListViewWithPageHeader::headerItemShownHeight() const
334 return m_headerItemShownHeight;
334 return m_headerItemShownHeight;
335}
335}
336
336
337−qreal ListViewWithPageHeader::cacheBuffer() const
337+int ListViewWithPageHeader::cacheBuffer() const
338{
338{
339 return m_cacheBuffer;
339 return m_cacheBuffer;
340}
340}
341
341
342−void ListViewWithPageHeader::setCacheBuffer(qreal cacheBuffer)
342+void ListViewWithPageHeader::setCacheBuffer(int cacheBuffer)
343{
343{
344+ if (cacheBuffer < 0) {
345+ qmlInfo(this) << "Cannot set a negative cache buffer";
346+ return;
347+ }
348+
344 if (cacheBuffer != m_cacheBuffer) {
349 if (cacheBuffer != m_cacheBuffer) {
345 m_cacheBuffer = cacheBuffer;
350 m_cacheBuffer = cacheBuffer;
346 Q_EMIT cacheBufferChanged();
351 Q_EMIT cacheBufferChanged();
plugins/Dash/listviewwithpageheader.h+4−4
@@ -54,7 +54,7 @@ class ListViewWithPageHeader : public QQuickFlickable, public QQuickItemChangeLi
54 Q_PROPERTY(bool forceNoClip READ forceNoClip WRITE setForceNoClip NOTIFY forceNoClipChanged)
54 Q_PROPERTY(bool forceNoClip READ forceNoClip WRITE setForceNoClip NOTIFY forceNoClipChanged)
55 Q_PROPERTY(int stickyHeaderHeight READ stickyHeaderHeight NOTIFY stickyHeaderHeightChanged)
55 Q_PROPERTY(int stickyHeaderHeight READ stickyHeaderHeight NOTIFY stickyHeaderHeightChanged)
56 Q_PROPERTY(qreal headerItemShownHeight READ headerItemShownHeight NOTIFY headerItemShownHeightChanged)
56 Q_PROPERTY(qreal headerItemShownHeight READ headerItemShownHeight NOTIFY headerItemShownHeightChanged)
57− Q_PROPERTY(qreal cacheBuffer READ cacheBuffer WRITE setCacheBuffer NOTIFY cacheBufferChanged)
57+ Q_PROPERTY(int cacheBuffer READ cacheBuffer WRITE setCacheBuffer NOTIFY cacheBufferChanged)
58
58
59 friend class ListViewWithPageHeaderTest;
59 friend class ListViewWithPageHeaderTest;
60 friend class ListViewWithPageHeaderTestSection;
60 friend class ListViewWithPageHeaderTestSection;
@@ -85,8 +85,8 @@ public:
85 int stickyHeaderHeight() const;
85 int stickyHeaderHeight() const;
86 qreal headerItemShownHeight() const;
86 qreal headerItemShownHeight() const;
87
87
88− qreal cacheBuffer() const;
88+ int cacheBuffer() const;
89− void setCacheBuffer(qreal cacheBuffer);
89+ void setCacheBuffer(int cacheBuffer);
90
90
91 Q_INVOKABLE void positionAtBeginning();
91 Q_INVOKABLE void positionAtBeginning();
92 Q_INVOKABLE void showHeader();
92 Q_INVOKABLE void showHeader();
@@ -204,7 +204,7 @@ private:
204 bool m_forceNoClip;
204 bool m_forceNoClip;
205 bool m_inLayout;
205 bool m_inLayout;
206 bool m_inContentHeightKeepHeaderShown;
206 bool m_inContentHeightKeepHeaderShown;
207− qreal m_cacheBuffer;
207+ int m_cacheBuffer;
208
208
209 // Qt 5.0 doesn't like releasing the items just after itemCreated
209 // Qt 5.0 doesn't like releasing the items just after itemCreated
210 // so we delay the releasing until the next updatePolish
210 // so we delay the releasing until the next updatePolish
plugins/Ubuntu/Gestures/Direction.cpp+6−2
@@ -18,7 +18,9 @@
18
18
19bool Direction::isHorizontal(Direction::Type type)
19bool Direction::isHorizontal(Direction::Type type)
20{
20{
21− return type == Direction::Leftwards || type == Direction::Rightwards;
21+ return type == Direction::Leftwards
22+ || type == Direction::Rightwards
23+ || type == Direction::Horizontal;
22}
24}
23
25
24bool Direction::isVertical(Direction::Type type)
26bool Direction::isVertical(Direction::Type type)
@@ -28,5 +30,7 @@ bool Direction::isVertical(Direction::Type type)
28
30
29bool Direction::isPositive(Direction::Type type)
31bool Direction::isPositive(Direction::Type type)
30{
32{
31− return type == Rightwards || type == Downwards;
33+ return type == Rightwards
34+ || type == Downwards
35+ || type == Horizontal;
32}
36}
plugins/Ubuntu/Gestures/Direction.h+2−1
@@ -33,7 +33,8 @@ public:
33 Rightwards, // Along the positive direction of the X axis
33 Rightwards, // Along the positive direction of the X axis
34 Leftwards, // Along the negative direction of the X axis
34 Leftwards, // Along the negative direction of the X axis
35 Downwards, // Along the positive direction of the Y axis
35 Downwards, // Along the positive direction of the Y axis
36− Upwards // Along the negative direction of the Y axis
36+ Upwards, // Along the negative direction of the Y axis
37+ Horizontal // Along the X axis, in any direction
37 };
38 };
38
39
39 Q_INVOKABLE static bool isHorizontal(Direction::Type type);
40 Q_INVOKABLE static bool isHorizontal(Direction::Type type);
plugins/Ubuntu/Gestures/DirectionalDragArea.cpp+27−37
@@ -36,7 +36,7 @@
36using namespace UbuntuGestures;
36using namespace UbuntuGestures;
37
37
38#if DIRECTIONALDRAGAREA_DEBUG
38#if DIRECTIONALDRAGAREA_DEBUG
39−#define DDA_DEBUG(msg) qDebug("[DDA] " msg)
39+#define ddaDebug(params) qDebug().nospace() << "[DDA(" << qPrintable(objectName()) << ")] " << params
40#include "DebugHelpers.h"
40#include "DebugHelpers.h"
41
41
42namespace {
42namespace {
@@ -53,7 +53,7 @@ const char *statusToString(DirectionalDragArea::Status status)
53
53
54} // namespace {
54} // namespace {
55#else // DIRECTIONALDRAGAREA_DEBUG
55#else // DIRECTIONALDRAGAREA_DEBUG
56−#define DDA_DEBUG(msg) do{}while(0)
56+#define ddaDebug(params) ((void)0)
57#endif // DIRECTIONALDRAGAREA_DEBUG
57#endif // DIRECTIONALDRAGAREA_DEBUG
58
58
59
59
@@ -253,7 +253,7 @@ void DirectionalDragArea::touchOwnershipEvent(TouchOwnershipEvent *event)
253 if (event->gained()) {
253 if (event->gained()) {
254 QVector<int> ids;
254 QVector<int> ids;
255 ids.append(event->touchId());
255 ids.append(event->touchId());
256− DDA_DEBUG("grabbing touch");
256+ ddaDebug("grabbing touch");
257 grabTouchPoints(ids);
257 grabTouchPoints(ids);
258
258
259 // Work around for Qt bug. If we grab a touch that is being used for mouse pointer
259 // Work around for Qt bug. If we grab a touch that is being used for mouse pointer
@@ -265,7 +265,7 @@ void DirectionalDragArea::touchOwnershipEvent(TouchOwnershipEvent *event)
265 if (window()) {
265 if (window()) {
266 QQuickWindowPrivate *windowPrivate = QQuickWindowPrivate::get(window());
266 QQuickWindowPrivate *windowPrivate = QQuickWindowPrivate::get(window());
267 if (windowPrivate->touchMouseId == event->touchId() && window()->mouseGrabberItem()) {
267 if (windowPrivate->touchMouseId == event->touchId() && window()->mouseGrabberItem()) {
268− DDA_DEBUG("removing mouse grabber");
268+ ddaDebug("removing mouse grabber");
269 window()->mouseGrabberItem()->ungrabMouse();
269 window()->mouseGrabberItem()->ungrabMouse();
270 }
270 }
271 }
271 }
@@ -283,11 +283,7 @@ void DirectionalDragArea::unownedTouchEvent(UnownedTouchEvent *unownedTouchEvent
283
283
284 Q_ASSERT(!event->touchPointStates().testFlag(Qt::TouchPointPressed));
284 Q_ASSERT(!event->touchPointStates().testFlag(Qt::TouchPointPressed));
285
285
286− #if DIRECTIONALDRAGAREA_DEBUG
287− // TODO Consider using qCDebug() when available (Qt 5.2)
288− qDebug() << "[DDA] Unowned" << m_timeSource->msecsSinceReference()
286+ ddaDebug("Unowned " << m_timeSource->msecsSinceReference() << " " << qPrintable(touchEventToString(event)));
289− << qPrintable(touchEventToString(event));
290− #endif
291
287
292 switch (m_status) {
288 switch (m_status) {
293 case WaitingForTouch:
289 case WaitingForTouch:
@@ -322,7 +318,7 @@ void DirectionalDragArea::unownedTouchEvent_undecided(UnownedTouchEvent *unowned
322
318
323 if (touchPoint->state() == Qt::TouchPointReleased) {
319 if (touchPoint->state() == Qt::TouchPointReleased) {
324 // touch has ended before recognition concluded
320 // touch has ended before recognition concluded
325− DDA_DEBUG("Touch has ended before recognition concluded");
321+ ddaDebug("Touch has ended before recognition concluded");
326 TouchRegistry::instance()->removeCandidateOwnerForTouch(m_touchId, this);
322 TouchRegistry::instance()->removeCandidateOwnerForTouch(m_touchId, this);
327 emitSignalIfTapped();
323 emitSignalIfTapped();
328 setStatus(WaitingForTouch);
324 setStatus(WaitingForTouch);
@@ -335,7 +331,7 @@ void DirectionalDragArea::unownedTouchEvent_undecided(UnownedTouchEvent *unowned
335 updateVelocityCalculator(touchScenePos);
331 updateVelocityCalculator(touchScenePos);
336
332
337 if (!pointInsideAllowedArea()) {
333 if (!pointInsideAllowedArea()) {
338− DDA_DEBUG("Rejecting gesture because touch point is outside allowed area.");
334+ ddaDebug("Rejecting gesture because touch point is outside allowed area.");
339 TouchRegistry::instance()->removeCandidateOwnerForTouch(m_touchId, this);
335 TouchRegistry::instance()->removeCandidateOwnerForTouch(m_touchId, this);
340 // We still wanna know when it ends for keeping the composition time window up-to-date
336 // We still wanna know when it ends for keeping the composition time window up-to-date
341 TouchRegistry::instance()->addTouchWatcher(m_touchId, this);
337 TouchRegistry::instance()->addTouchWatcher(m_touchId, this);
@@ -344,7 +340,7 @@ void DirectionalDragArea::unownedTouchEvent_undecided(UnownedTouchEvent *unowned
344 }
340 }
345
341
346 if (!movingInRightDirection()) {
342 if (!movingInRightDirection()) {
347− DDA_DEBUG("Rejecting gesture because touch point is moving in the wrong direction.");
343+ ddaDebug("Rejecting gesture because touch point is moving in the wrong direction.");
348 TouchRegistry::instance()->removeCandidateOwnerForTouch(m_touchId, this);
344 TouchRegistry::instance()->removeCandidateOwnerForTouch(m_touchId, this);
349 // We still wanna know when it ends for keeping the composition time window up-to-date
345 // We still wanna know when it ends for keeping the composition time window up-to-date
350 TouchRegistry::instance()->addTouchWatcher(m_touchId, this);
346 TouchRegistry::instance()->addTouchWatcher(m_touchId, this);
@@ -358,7 +354,7 @@ void DirectionalDragArea::unownedTouchEvent_undecided(UnownedTouchEvent *unowned
358 if (isWithinTouchCompositionWindow()) {
354 if (isWithinTouchCompositionWindow()) {
359 // There's still time for some new touch to appear and ruin our party as it would be combined
355 // There's still time for some new touch to appear and ruin our party as it would be combined
360 // with our m_touchId one and therefore deny the possibility of a single-finger gesture.
356 // with our m_touchId one and therefore deny the possibility of a single-finger gesture.
361− DDA_DEBUG("Sill within composition window. Let's wait more.");
357+ ddaDebug("Sill within composition window. Let's wait more.");
362 return;
358 return;
363 }
359 }
364
360
@@ -366,7 +362,7 @@ void DirectionalDragArea::unownedTouchEvent_undecided(UnownedTouchEvent *unowned
366 TouchRegistry::instance()->requestTouchOwnership(m_touchId, this);
362 TouchRegistry::instance()->requestTouchOwnership(m_touchId, this);
367 setStatus(Recognized);
363 setStatus(Recognized);
368 } else {
364 } else {
369− DDA_DEBUG("Didn't move far enough yet. Let's wait more.");
365+ ddaDebug("Didn't move far enough yet. Let's wait more.");
370 }
366 }
371}
367}
372
368
@@ -375,11 +371,7 @@ void DirectionalDragArea::touchEvent(QTouchEvent *event)
375 // TODO: Consider when more than one touch starts in the same event (although it's not possible
371 // TODO: Consider when more than one touch starts in the same event (although it's not possible
376 // with Mir's android-input). Have to track them all. Consider it a plus/bonus.
372 // with Mir's android-input). Have to track them all. Consider it a plus/bonus.
377
373
378− #if DIRECTIONALDRAGAREA_DEBUG
379− // TODO Consider using qCDebug() when available (Qt 5.2)
380− qDebug() << "[DDA]" << m_timeSource->msecsSinceReference()
381− << qPrintable(touchEventToString(event));
374+ ddaDebug(m_timeSource->msecsSinceReference() << " " << qPrintable(touchEventToString(event)));
382− #endif
383
375
384 if (!isEnabled() || !isVisible()) {
376 if (!isEnabled() || !isVisible()) {
385 QQuickItem::touchEvent(event);
377 QQuickItem::touchEvent(event);
@@ -416,9 +408,7 @@ void DirectionalDragArea::touchEvent_absent(QTouchEvent *event)
416 if (isWithinTouchCompositionWindow()) {
408 if (isWithinTouchCompositionWindow()) {
417 // too close to the last touch start. So we consider them as starting roughly at the same time.
409 // too close to the last touch start. So we consider them as starting roughly at the same time.
418 // Can't be a single-touch gesture.
410 // Can't be a single-touch gesture.
419− #if DIRECTIONALDRAGAREA_DEBUG
420− qDebug("[DDA] A new touch point came in but we're still within time composition window. Ignoring it.");
411+ ddaDebug("A new touch point came in but we're still within time composition window. Ignoring it.");
421− #endif
422 allGood = false;
412 allGood = false;
423 }
413 }
424
414
@@ -456,6 +446,7 @@ void DirectionalDragArea::touchEvent_absent(QTouchEvent *event)
456
446
457 if (recognitionIsDisabled()) {
447 if (recognitionIsDisabled()) {
458 // Behave like a dumb TouchArea
448 // Behave like a dumb TouchArea
449+ ddaDebug("Gesture recognition is disabled. Requesting touch ownership immediately.");
459 TouchRegistry::instance()->requestTouchOwnership(m_touchId, this);
450 TouchRegistry::instance()->requestTouchOwnership(m_touchId, this);
460 setStatus(Recognized);
451 setStatus(Recognized);
461 event->accept();
452 event->accept();
@@ -487,7 +478,7 @@ void DirectionalDragArea::touchEvent_undecided(QTouchEvent *event)
487
478
488 if (event->touchPointStates().testFlag(Qt::TouchPointPressed) && isWithinTouchCompositionWindow()) {
479 if (event->touchPointStates().testFlag(Qt::TouchPointPressed) && isWithinTouchCompositionWindow()) {
489 // multi-finger drags are not accepted
480 // multi-finger drags are not accepted
490− DDA_DEBUG("Multi-finger drags are not accepted");
481+ ddaDebug("Multi-finger drags are not accepted");
491
482
492 TouchRegistry::instance()->removeCandidateOwnerForTouch(m_touchId, this);
483 TouchRegistry::instance()->removeCandidateOwnerForTouch(m_touchId, this);
493 // We still wanna know when it ends for keeping the composition time window up-to-date
484 // We still wanna know when it ends for keeping the composition time window up-to-date
@@ -581,12 +572,16 @@ bool DirectionalDragArea::pointInsideAllowedArea() const
581
572
582bool DirectionalDragArea::movingInRightDirection() const
573bool DirectionalDragArea::movingInRightDirection() const
583{
574{
575+ if (m_direction == Direction::Horizontal) {
576+ return true;
577+ } else {
584− QPointF movementVector(m_dampedScenePos.x() - m_previousDampedScenePos.x(),
578+ QPointF movementVector(m_dampedScenePos.x() - m_previousDampedScenePos.x(),
585− m_dampedScenePos.y() - m_previousDampedScenePos.y());
579+ m_dampedScenePos.y() - m_previousDampedScenePos.y());
586
580
587− qreal scalarProjection = projectOntoDirectionVector(movementVector);
581+ qreal scalarProjection = projectOntoDirectionVector(movementVector);
588
582
589− return scalarProjection >= 0.;
583+ return scalarProjection >= 0.;
584+ }
590}
585}
591
586
592bool DirectionalDragArea::movedFarEnough(const QPointF &point) const
587bool DirectionalDragArea::movedFarEnough(const QPointF &point) const
@@ -614,7 +609,7 @@ void DirectionalDragArea::checkSpeed()
614 qreal minSpeedMsecs = m_minSpeed / 1000.0;
609 qreal minSpeedMsecs = m_minSpeed / 1000.0;
615
610
616 if (speed < minSpeedMsecs) {
611 if (speed < minSpeedMsecs) {
617− DDA_DEBUG("Rejecting gesture because it's below minimum speed.");
612+ ddaDebug("Rejecting gesture because it's below minimum speed.");
618 TouchRegistry::instance()->removeCandidateOwnerForTouch(m_touchId, this);
613 TouchRegistry::instance()->removeCandidateOwnerForTouch(m_touchId, this);
619 TouchRegistry::instance()->addTouchWatcher(m_touchId, this);
614 TouchRegistry::instance()->addTouchWatcher(m_touchId, this);
620 setStatus(WaitingForTouch);
615 setStatus(WaitingForTouch);
@@ -625,7 +620,7 @@ void DirectionalDragArea::checkSpeed()
625 m_silenceTime += m_recognitionTimer->interval();
620 m_silenceTime += m_recognitionTimer->interval();
626
621
627 if (m_silenceTime > m_maxSilenceTime) {
622 if (m_silenceTime > m_maxSilenceTime) {
628− DDA_DEBUG("Rejecting gesture because its silence time has been exceeded.");
623+ ddaDebug("Rejecting gesture because its silence time has been exceeded.");
629 TouchRegistry::instance()->removeCandidateOwnerForTouch(m_touchId, this);
624 TouchRegistry::instance()->removeCandidateOwnerForTouch(m_touchId, this);
630 TouchRegistry::instance()->addTouchWatcher(m_touchId, this);
625 TouchRegistry::instance()->addTouchWatcher(m_touchId, this);
631 setStatus(WaitingForTouch);
626 setStatus(WaitingForTouch);
@@ -646,7 +641,7 @@ void DirectionalDragArea::giveUpIfDisabledOrInvisible()
646 }
641 }
647
642
648 if (m_status != WaitingForTouch) {
643 if (m_status != WaitingForTouch) {
649− DDA_DEBUG("Resetting status because got disabled or made invisible");
644+ ddaDebug("Resetting status because got disabled or made invisible");
650 setStatus(WaitingForTouch);
645 setStatus(WaitingForTouch);
651 }
646 }
652 }
647 }
@@ -666,9 +661,7 @@ void DirectionalDragArea::setStatus(DirectionalDragArea::Status newStatus)
666 m_status = newStatus;
661 m_status = newStatus;
667 Q_EMIT statusChanged(m_status);
662 Q_EMIT statusChanged(m_status);
668
663
669− #if DIRECTIONALDRAGAREA_DEBUG
670− qDebug() << "[DDA]" << statusToString(oldStatus) << "->" << statusToString(newStatus);
664+ ddaDebug(statusToString(oldStatus) << " -> " << statusToString(newStatus));
671− #endif
672
665
673 switch (newStatus) {
666 switch (newStatus) {
674 case WaitingForTouch:
667 case WaitingForTouch:
@@ -875,7 +868,7 @@ void DirectionalDragArea::updateSceneDirectionVector()
875 localDirection.rx() = -1.;
868 localDirection.rx() = -1.;
876 localDirection.ry() = 0.;
869 localDirection.ry() = 0.;
877 break;
870 break;
878− default: // Direction::Rightwards:
871+ default: // Direction::Rightwards || Direction.Horizontal
879 localDirection.rx() = 1.;
872 localDirection.rx() = 1.;
880 localDirection.ry() = 0.;
873 localDirection.ry() = 0.;
881 break;
874 break;
@@ -891,6 +884,3 @@ qreal DirectionalDragArea::projectOntoDirectionVector(const QPointF &sceneVector
891 return sceneVector.x() * m_sceneDirectionVector.x() +
884 return sceneVector.x() * m_sceneDirectionVector.x() +
892 sceneVector.y() * m_sceneDirectionVector.y();
885 sceneVector.y() * m_sceneDirectionVector.y();
893}
886}
894−
895−// Because we are defining a new QObject-based class (RecognitionTimer) here.
896−#include "DirectionalDragArea.moc"
plugins/Unity/Session/dbusunitysessionservice.h+5
@@ -35,6 +35,11 @@ public:
35 DBusUnitySessionService();
35 DBusUnitySessionService();
36 ~DBusUnitySessionService();
36 ~DBusUnitySessionService();
37
37
38+ // For use in QML. Javascript doesn't accept functions beginning with capital letters
39+ Q_INVOKABLE void logout() { Logout(); }
40+ Q_INVOKABLE void reboot() { Reboot(); }
41+ Q_INVOKABLE void shutdown() { Shutdown(); }
42+
38Q_SIGNALS:
43Q_SIGNALS:
39 /**
44 /**
40 * logoutRequested signal
45 * logoutRequested signal
po/br.po+45−37
@@ -8,14 +8,14 @@ msgstr ""
8"Project-Id-Version: unity8\n"
8"Project-Id-Version: unity8\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2014-12-10 10:55+0100\n"
10"POT-Creation-Date: 2014-12-10 10:55+0100\n"
11−"PO-Revision-Date: 2014-12-10 07:14+0000\n"
11+"PO-Revision-Date: 2014-12-16 07:27+0000\n"
12"Last-Translator: Fohanno Thierry <thierry.fohanno@ofis-bzh.org>\n"
12"Last-Translator: Fohanno Thierry <thierry.fohanno@ofis-bzh.org>\n"
13"Language-Team: Breton <br@li.org>\n"
13"Language-Team: Breton <br@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n > 1;\n"
17"Plural-Forms: nplurals=2; plural=n > 1;\n"
18−"X-Launchpad-Export-Date: 2014-12-13 07:11+0000\n"
18+"X-Launchpad-Export-Date: 2014-12-16 07:34+0000\n"
19"X-Generator: Launchpad (build 17286)\n"
19"X-Generator: Launchpad (build 17286)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:130
21#: plugins/LightDM/Greeter.cpp:130
@@ -358,98 +358,100 @@ msgstr ""
358
358
359#: qml/Wizard/Page.qml:89
359#: qml/Wizard/Page.qml:89
360msgid "Back"
360msgid "Back"
361−msgstr ""
361+msgstr "Distreiñ"
362
362
363#: qml/Wizard/Pages/10-welcome.qml:27
363#: qml/Wizard/Pages/10-welcome.qml:27
364msgid "Hi!"
364msgid "Hi!"
365−msgstr ""
365+msgstr "Salud deoc'h !"
366
366
367#: qml/Wizard/Pages/10-welcome.qml:44
367#: qml/Wizard/Pages/10-welcome.qml:44
368msgid "Welcome to your Ubuntu phone."
368msgid "Welcome to your Ubuntu phone."
369−msgstr ""
369+msgstr "Deuet-mat oc'h en ho pellgomzer Ubuntu."
370
370
371#: qml/Wizard/Pages/10-welcome.qml:52
371#: qml/Wizard/Pages/10-welcome.qml:52
372msgid "Let’s get started."
372msgid "Let’s get started."
373−msgstr ""
373+msgstr "Krogomp ganti."
374
374
375#: qml/Wizard/Pages/10-welcome.qml:88 qml/Wizard/Pages/30-passwd-type.qml:128
375#: qml/Wizard/Pages/10-welcome.qml:88 qml/Wizard/Pages/30-passwd-type.qml:128
376#: qml/Wizard/Pages/40-wifi.qml:197 qml/Wizard/Pages/50-location.qml:131
376#: qml/Wizard/Pages/40-wifi.qml:197 qml/Wizard/Pages/50-location.qml:131
377#: qml/Wizard/Pages/60-reporting.qml:50 qml/Wizard/Pages/passwd-confirm.qml:82
377#: qml/Wizard/Pages/60-reporting.qml:50 qml/Wizard/Pages/passwd-confirm.qml:82
378#: qml/Wizard/Pages/passwd-set.qml:90
378#: qml/Wizard/Pages/passwd-set.qml:90
379msgid "Continue"
379msgid "Continue"
380−msgstr ""
380+msgstr "Kenderc'hel"
381
381
382#: qml/Wizard/Pages/20-sim.qml:25
382#: qml/Wizard/Pages/20-sim.qml:25
383msgid "Add a SIM card and restart your device"
383msgid "Add a SIM card and restart your device"
384−msgstr ""
384+msgstr "Lakait ur gartenn SIM hag adloc'hit ho penveg"
385
385
386#: qml/Wizard/Pages/20-sim.qml:55
386#: qml/Wizard/Pages/20-sim.qml:55
387msgid "Without it, you won’t be able to make calls or use text messaging."
387msgid "Without it, you won’t be able to make calls or use text messaging."
388−msgstr ""
388+msgstr "Ne vioc'h ket evit pellgomz pe kas kemennadennoù hepti."
389
389
390#: qml/Wizard/Pages/20-sim.qml:69 qml/Wizard/Pages/40-wifi.qml:197
390#: qml/Wizard/Pages/20-sim.qml:69 qml/Wizard/Pages/40-wifi.qml:197
391msgid "Skip"
391msgid "Skip"
392−msgstr ""
392+msgstr "Tremen hebiou"
393
393
394#: qml/Wizard/Pages/30-passwd-type.qml:39
394#: qml/Wizard/Pages/30-passwd-type.qml:39
395msgid "Lock security"
395msgid "Lock security"
396−msgstr ""
396+msgstr "Surentez ar prennañ"
397
397
398#: qml/Wizard/Pages/30-passwd-type.qml:74
398#: qml/Wizard/Pages/30-passwd-type.qml:74
399msgid "Please select how you’d like to unlock your phone."
399msgid "Please select how you’d like to unlock your phone."
400msgstr ""
400msgstr ""
401+"Diuzit e peseurt mod e fell deoc'h dibrennañ ho pellgomzer, mar plij."
401
402
402#: qml/Wizard/Pages/30-passwd-type.qml:97
403#: qml/Wizard/Pages/30-passwd-type.qml:97
403msgid "Swipe"
404msgid "Swipe"
404−msgstr ""
405+msgstr "Riklañ"
405
406
406#: qml/Wizard/Pages/30-passwd-type.qml:98
407#: qml/Wizard/Pages/30-passwd-type.qml:98
407msgid "No security"
408msgid "No security"
408−msgstr ""
409+msgstr "Tamm surentez ebet"
409
410
410#: qml/Wizard/Pages/30-passwd-type.qml:100
411#: qml/Wizard/Pages/30-passwd-type.qml:100
411msgid "Passcode"
412msgid "Passcode"
412−msgstr ""
413+msgstr "Kod-tremen"
413
414
414#: qml/Wizard/Pages/30-passwd-type.qml:101
415#: qml/Wizard/Pages/30-passwd-type.qml:101
415msgid "4 digits only"
416msgid "4 digits only"
416−msgstr ""
417+msgstr "4 sifr hepken"
417
418
418#: qml/Wizard/Pages/30-passwd-type.qml:103
419#: qml/Wizard/Pages/30-passwd-type.qml:103
419msgid "Passphrase"
420msgid "Passphrase"
420−msgstr ""
421+msgstr "Frazenn-dremen"
421
422
422#: qml/Wizard/Pages/30-passwd-type.qml:104
423#: qml/Wizard/Pages/30-passwd-type.qml:104
423msgid "Numbers and letters"
424msgid "Numbers and letters"
424−msgstr ""
425+msgstr "Sifroù ha lizherennoù"
425
426
426#: qml/Wizard/Pages/40-wifi.qml:28
427#: qml/Wizard/Pages/40-wifi.qml:28
427msgid "Connect to Wi‑Fi"
428msgid "Connect to Wi‑Fi"
428−msgstr ""
429+msgstr "Kevreañ ouzh ar Wi-Fi"
429
430
430#: qml/Wizard/Pages/40-wifi.qml:147
431#: qml/Wizard/Pages/40-wifi.qml:147
431msgid "Available networks…"
432msgid "Available networks…"
432−msgstr ""
433+msgstr "Rouedadoù a c'haller kaout..."
433
434
434#: qml/Wizard/Pages/40-wifi.qml:148
435#: qml/Wizard/Pages/40-wifi.qml:148
435msgid "No available networks."
436msgid "No available networks."
436−msgstr ""
437+msgstr "N'eus rouedad ebet da gaout."
437
438
438#: qml/Wizard/Pages/50-location.qml:27
439#: qml/Wizard/Pages/50-location.qml:27
439msgid "Location"
440msgid "Location"
440−msgstr ""
441+msgstr "Lec'h"
441
442
442#: qml/Wizard/Pages/50-location.qml:62
443#: qml/Wizard/Pages/50-location.qml:62
443msgid "Let the phone detect your location:"
444msgid "Let the phone detect your location:"
444−msgstr ""
445+msgstr "Lezel ar pellgomzer da gavout pelec'h emaoc'h :"
445
446
446#: qml/Wizard/Pages/50-location.qml:69
447#: qml/Wizard/Pages/50-location.qml:69
447msgid "Using GPS only (less accurate)"
448msgid "Using GPS only (less accurate)"
448−msgstr ""
449+msgstr "Implijout ar GPS hepken (n'eo ket ken resis)"
449
450
450#: qml/Wizard/Pages/50-location.qml:86
451#: qml/Wizard/Pages/50-location.qml:86
451msgid "Using GPS, anonymized Wi-Fi and cellular network info (recommended)"
452msgid "Using GPS, anonymized Wi-Fi and cellular network info (recommended)"
452msgstr ""
453msgstr ""
454+"Implijout ar GPS, Wi-Fi dizanv pe titouroù ar rouedad kelligel (aliet)"
453
455
454#. TRANSLATORS: HERE is a trademark for Nokia's location service, you probably shouldn't translate it
456#. TRANSLATORS: HERE is a trademark for Nokia's location service, you probably shouldn't translate it
455#: qml/Wizard/Pages/50-location.qml:103
457#: qml/Wizard/Pages/50-location.qml:103
@@ -457,81 +459,87 @@ msgid ""
457"By selecting this option you agree to the Nokia HERE <a href='#'>terms and "
459"By selecting this option you agree to the Nokia HERE <a href='#'>terms and "
458"conditions</a>."
460"conditions</a>."
459msgstr ""
461msgstr ""
462+"Pa ziuzit an dibarzh-mañ ez asantit da <a href='#'>zivizoù implij</a> Nokia."
460
463
461#: qml/Wizard/Pages/50-location.qml:112
464#: qml/Wizard/Pages/50-location.qml:112
462msgid "Not at all"
465msgid "Not at all"
463−msgstr ""
466+msgstr "Tamm ebet"
464
467
465#: qml/Wizard/Pages/50-location.qml:124
468#: qml/Wizard/Pages/50-location.qml:124
466msgid "You can change your mind later in <b>System Settings</b>."
469msgid "You can change your mind later in <b>System Settings</b>."
467msgstr ""
470msgstr ""
471+"Gallout a rit cheñch soñj diwezhatoc'h en <b>Arventennoù ar reizhad</b>."
468
472
469#: qml/Wizard/Pages/60-reporting.qml:24
473#: qml/Wizard/Pages/60-reporting.qml:24
470msgid "Improving your experience"
474msgid "Improving your experience"
471−msgstr ""
475+msgstr "Gwellaat ho skiant-prenet"
472
476
473#: qml/Wizard/Pages/60-reporting.qml:36
477#: qml/Wizard/Pages/60-reporting.qml:36
474msgid ""
478msgid ""
475"Your phone is set up to automatically report errors to Canonical and its "
479"Your phone is set up to automatically report errors to Canonical and its "
476"partners, the makers of the operating system."
480"partners, the makers of the operating system."
477msgstr ""
481msgstr ""
482+"Arventennet eo ho pellgomzer evit titourañ ent emgefre ar fazioù da "
483+"gCanonical ha d'e gevelerien, ar re o deus savet ar reizhiad korvoiñ."
478
484
479#: qml/Wizard/Pages/60-reporting.qml:43
485#: qml/Wizard/Pages/60-reporting.qml:43
480msgid ""
486msgid ""
481"This can be disabled in <b>System Settings</b> under <b>Security &amp; "
487"This can be disabled in <b>System Settings</b> under <b>Security &amp; "
482"Privacy</b>"
488"Privacy</b>"
483msgstr ""
489msgstr ""
490+"Gallout a ra bezañ diweredekaet e-barzh <b>Arventennoù ar reizhiad</b> "
491+"dindan <b>Surentez &amp; Prevezded</b>"
484
492
485#: qml/Wizard/Pages/80-finished.qml:24
493#: qml/Wizard/Pages/80-finished.qml:24
486msgid "All done"
494msgid "All done"
487−msgstr ""
495+msgstr "Echu penn-da-benn"
488
496
489#: qml/Wizard/Pages/80-finished.qml:39
497#: qml/Wizard/Pages/80-finished.qml:39
490msgid "Nice work!"
498msgid "Nice work!"
491−msgstr ""
499+msgstr "Gwellat labour !"
492
500
493#: qml/Wizard/Pages/80-finished.qml:46
501#: qml/Wizard/Pages/80-finished.qml:46
494msgid "Your phone is now ready to use."
502msgid "Your phone is now ready to use."
495−msgstr ""
503+msgstr "Prest eo ho pellgomzer da vezañ implijet bremañ."
496
504
497#: qml/Wizard/Pages/80-finished.qml:53
505#: qml/Wizard/Pages/80-finished.qml:53
498msgid "Finish"
506msgid "Finish"
499−msgstr ""
507+msgstr "Echuiñ"
500
508
501#: qml/Wizard/Pages/here-terms.qml:27
509#: qml/Wizard/Pages/here-terms.qml:27
502msgid "Terms & Conditions"
510msgid "Terms & Conditions"
503−msgstr ""
511+msgstr "Penndivizoù implij"
504
512
505#: qml/Wizard/Pages/passwd-confirm.qml:49
513#: qml/Wizard/Pages/passwd-confirm.qml:49
506msgid "Confirm passphrase"
514msgid "Confirm passphrase"
507−msgstr ""
515+msgstr "Kadarnaat ar frazenn-dremen"
508
516
509#: qml/Wizard/Pages/passwd-confirm.qml:50
517#: qml/Wizard/Pages/passwd-confirm.qml:50
510msgid "Confirm passcode"
518msgid "Confirm passcode"
511−msgstr ""
519+msgstr "Kadarnaat ar c'hod-tremen"
512
520
513#: qml/Wizard/Pages/passwd-confirm.qml:53
521#: qml/Wizard/Pages/passwd-confirm.qml:53
514#: qml/Wizard/Pages/passwd-confirm.qml:54
522#: qml/Wizard/Pages/passwd-confirm.qml:54
515msgid "Please try again."
523msgid "Please try again."
516−msgstr ""
524+msgstr "Esaeit en-dro, mar plij."
517
525
518#: qml/Wizard/Pages/passwd-set.qml:61
526#: qml/Wizard/Pages/passwd-set.qml:61
519msgid "Choose your passcode"
527msgid "Choose your passcode"
520−msgstr ""
528+msgstr "Choaz ho kod-tremen"
521
529
522#: qml/Wizard/Pages/passwd-set.qml:68
530#: qml/Wizard/Pages/passwd-set.qml:68
523msgid "Passphrase must be 4 characters long"
531msgid "Passphrase must be 4 characters long"
524−msgstr ""
532+msgstr "4 arouezenn a rank bezañ er frazenn-dremen"
525
533
526#: qml/Wizard/StackButton.qml:39
534#: qml/Wizard/StackButton.qml:39
527#, qt-format
535#, qt-format
528msgid "〈 %1"
536msgid "〈 %1"
529−msgstr ""
537+msgstr "〈 %1"
530
538
531#: qml/Wizard/StackButton.qml:42
539#: qml/Wizard/StackButton.qml:42
532#, qt-format
540#, qt-format
533msgid "%1 〉"
541msgid "%1 〉"
534−msgstr ""
542+msgstr "%1 〉"
535
543
536#~ msgid "Loading. Please Wait..."
544#~ msgid "Loading. Please Wait..."
537#~ msgstr "O kargañ. Gortozit, mar plij..."
545#~ msgstr "O kargañ. Gortozit, mar plij..."
po/hu.po+47−39
@@ -8,14 +8,14 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2014-12-10 10:55+0100\n"
10"POT-Creation-Date: 2014-12-10 10:55+0100\n"
11−"PO-Revision-Date: 2014-11-05 15:45+0000\n"
11+"PO-Revision-Date: 2014-12-15 15:26+0000\n"
12"Last-Translator: Richard Somlói <ricsipontaz@gmail.com>\n"
12"Last-Translator: Richard Somlói <ricsipontaz@gmail.com>\n"
13"Language-Team: Hungarian <hu@li.org>\n"
13"Language-Team: Hungarian <hu@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2014-12-13 07:11+0000\n"
18+"X-Launchpad-Export-Date: 2014-12-16 07:34+0000\n"
19"X-Generator: Launchpad (build 17286)\n"
19"X-Generator: Launchpad (build 17286)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:130
21#: plugins/LightDM/Greeter.cpp:130
@@ -237,7 +237,7 @@ msgstr ""
237
237
238#: qml/Dash/ScopesList.qml:108
238#: qml/Dash/ScopesList.qml:108
239msgid "Also installed"
239msgid "Also installed"
240−msgstr ""
240+msgstr "Szintén telepítve"
241
241
242#: qml/Greeter/Greeter.qml:174
242#: qml/Greeter/Greeter.qml:174
243msgid "Unlock"
243msgid "Unlock"
@@ -351,98 +351,100 @@ msgstr ""
351
351
352#: qml/Wizard/Page.qml:89
352#: qml/Wizard/Page.qml:89
353msgid "Back"
353msgid "Back"
354−msgstr ""
354+msgstr "Vissza"
355
355
356#: qml/Wizard/Pages/10-welcome.qml:27
356#: qml/Wizard/Pages/10-welcome.qml:27
357msgid "Hi!"
357msgid "Hi!"
358−msgstr ""
358+msgstr "Üdv!"
359
359
360#: qml/Wizard/Pages/10-welcome.qml:44
360#: qml/Wizard/Pages/10-welcome.qml:44
361msgid "Welcome to your Ubuntu phone."
361msgid "Welcome to your Ubuntu phone."
362−msgstr ""
362+msgstr "Üdvözöljük az Ubuntu telefonos változatában."
363
363
364#: qml/Wizard/Pages/10-welcome.qml:52
364#: qml/Wizard/Pages/10-welcome.qml:52
365msgid "Let’s get started."
365msgid "Let’s get started."
366−msgstr ""
366+msgstr "Kezdjünk is bele."
367
367
368#: qml/Wizard/Pages/10-welcome.qml:88 qml/Wizard/Pages/30-passwd-type.qml:128
368#: qml/Wizard/Pages/10-welcome.qml:88 qml/Wizard/Pages/30-passwd-type.qml:128
369#: qml/Wizard/Pages/40-wifi.qml:197 qml/Wizard/Pages/50-location.qml:131
369#: qml/Wizard/Pages/40-wifi.qml:197 qml/Wizard/Pages/50-location.qml:131
370#: qml/Wizard/Pages/60-reporting.qml:50 qml/Wizard/Pages/passwd-confirm.qml:82
370#: qml/Wizard/Pages/60-reporting.qml:50 qml/Wizard/Pages/passwd-confirm.qml:82
371#: qml/Wizard/Pages/passwd-set.qml:90
371#: qml/Wizard/Pages/passwd-set.qml:90
372msgid "Continue"
372msgid "Continue"
373−msgstr ""
373+msgstr "Folytatás"
374
374
375#: qml/Wizard/Pages/20-sim.qml:25
375#: qml/Wizard/Pages/20-sim.qml:25
376msgid "Add a SIM card and restart your device"
376msgid "Add a SIM card and restart your device"
377−msgstr ""
377+msgstr "Helyezzen be egy SIM kártyát és indítsa újra az eszközét"
378
378
379#: qml/Wizard/Pages/20-sim.qml:55
379#: qml/Wizard/Pages/20-sim.qml:55
380msgid "Without it, you won’t be able to make calls or use text messaging."
380msgid "Without it, you won’t be able to make calls or use text messaging."
381msgstr ""
381msgstr ""
382+"Anélkül nem indíthat vagy fogadhat hívásokat és nem küldhet vagy fogadhat "
383+"üzeneteket."
382
384
383#: qml/Wizard/Pages/20-sim.qml:69 qml/Wizard/Pages/40-wifi.qml:197
385#: qml/Wizard/Pages/20-sim.qml:69 qml/Wizard/Pages/40-wifi.qml:197
384msgid "Skip"
386msgid "Skip"
385−msgstr ""
387+msgstr "Kihagyás"
386
388
387#: qml/Wizard/Pages/30-passwd-type.qml:39
389#: qml/Wizard/Pages/30-passwd-type.qml:39
388msgid "Lock security"
390msgid "Lock security"
389−msgstr ""
391+msgstr "Képernyőzárolás"
390
392
391#: qml/Wizard/Pages/30-passwd-type.qml:74
393#: qml/Wizard/Pages/30-passwd-type.qml:74
392msgid "Please select how you’d like to unlock your phone."
394msgid "Please select how you’d like to unlock your phone."
393−msgstr ""
395+msgstr "Válassza ki, hogy milyen módon kívánja feloldani a telefonját."
394
396
395#: qml/Wizard/Pages/30-passwd-type.qml:97
397#: qml/Wizard/Pages/30-passwd-type.qml:97
396msgid "Swipe"
398msgid "Swipe"
397−msgstr ""
399+msgstr "Csúsztatás"
398
400
399#: qml/Wizard/Pages/30-passwd-type.qml:98
401#: qml/Wizard/Pages/30-passwd-type.qml:98
400msgid "No security"
402msgid "No security"
401−msgstr ""
403+msgstr "Nem biztonságos"
402
404
403#: qml/Wizard/Pages/30-passwd-type.qml:100
405#: qml/Wizard/Pages/30-passwd-type.qml:100
404msgid "Passcode"
406msgid "Passcode"
405−msgstr ""
407+msgstr "Jelkód"
406
408
407#: qml/Wizard/Pages/30-passwd-type.qml:101
409#: qml/Wizard/Pages/30-passwd-type.qml:101
408msgid "4 digits only"
410msgid "4 digits only"
409−msgstr ""
411+msgstr "4 számjegy"
410
412
411#: qml/Wizard/Pages/30-passwd-type.qml:103
413#: qml/Wizard/Pages/30-passwd-type.qml:103
412msgid "Passphrase"
414msgid "Passphrase"
413−msgstr ""
415+msgstr "Jelmondat"
414
416
415#: qml/Wizard/Pages/30-passwd-type.qml:104
417#: qml/Wizard/Pages/30-passwd-type.qml:104
416msgid "Numbers and letters"
418msgid "Numbers and letters"
417−msgstr ""
419+msgstr "Betűk és számok"
418
420
419#: qml/Wizard/Pages/40-wifi.qml:28
421#: qml/Wizard/Pages/40-wifi.qml:28
420msgid "Connect to Wi‑Fi"
422msgid "Connect to Wi‑Fi"
421−msgstr ""
423+msgstr "Csatlakozás Wi-Fi hálózathoz"
422
424
423#: qml/Wizard/Pages/40-wifi.qml:147
425#: qml/Wizard/Pages/40-wifi.qml:147
424msgid "Available networks…"
426msgid "Available networks…"
425−msgstr ""
427+msgstr "Elérhető hálózatok…"
426
428
427#: qml/Wizard/Pages/40-wifi.qml:148
429#: qml/Wizard/Pages/40-wifi.qml:148
428msgid "No available networks."
430msgid "No available networks."
429−msgstr ""
431+msgstr "Nincsenek elérhető hálózatok."
430
432
431#: qml/Wizard/Pages/50-location.qml:27
433#: qml/Wizard/Pages/50-location.qml:27
432msgid "Location"
434msgid "Location"
433−msgstr ""
435+msgstr "Tartózkodási hely"
434
436
435#: qml/Wizard/Pages/50-location.qml:62
437#: qml/Wizard/Pages/50-location.qml:62
436msgid "Let the phone detect your location:"
438msgid "Let the phone detect your location:"
437−msgstr ""
439+msgstr "A telefon megpróbálja megállapítani az Ön tartózkodási helyét:"
438
440
439#: qml/Wizard/Pages/50-location.qml:69
441#: qml/Wizard/Pages/50-location.qml:69
440msgid "Using GPS only (less accurate)"
442msgid "Using GPS only (less accurate)"
441−msgstr ""
443+msgstr "Csak GPS használata (kevésbé pontos)"
442
444
443#: qml/Wizard/Pages/50-location.qml:86
445#: qml/Wizard/Pages/50-location.qml:86
444msgid "Using GPS, anonymized Wi-Fi and cellular network info (recommended)"
446msgid "Using GPS, anonymized Wi-Fi and cellular network info (recommended)"
445−msgstr ""
447+msgstr "GPS és névtelen Wi-Fi és mobilhálózati adatok (ajánlott)"
446
448
447#. TRANSLATORS: HERE is a trademark for Nokia's location service, you probably shouldn't translate it
449#. TRANSLATORS: HERE is a trademark for Nokia's location service, you probably shouldn't translate it
448#: qml/Wizard/Pages/50-location.qml:103
450#: qml/Wizard/Pages/50-location.qml:103
@@ -450,6 +452,8 @@ msgid ""
450"By selecting this option you agree to the Nokia HERE <a href='#'>terms and "
452"By selecting this option you agree to the Nokia HERE <a href='#'>terms and "
451"conditions</a>."
453"conditions</a>."
452msgstr ""
454msgstr ""
455+"A lehetőség kiválasztásával elfogadja a Nokia HERE <a href='#'>felhasználási "
456+"feltételeit</a>."
453
457
454#: qml/Wizard/Pages/50-location.qml:112
458#: qml/Wizard/Pages/50-location.qml:112
455msgid "Not at all"
459msgid "Not at all"
@@ -457,74 +461,78 @@ msgstr ""
457
461
458#: qml/Wizard/Pages/50-location.qml:124
462#: qml/Wizard/Pages/50-location.qml:124
459msgid "You can change your mind later in <b>System Settings</b>."
463msgid "You can change your mind later in <b>System Settings</b>."
460−msgstr ""
464+msgstr "Ezt később a <b>Rendszerbeállítások</b> alatt módosíthatja."
461
465
462#: qml/Wizard/Pages/60-reporting.qml:24
466#: qml/Wizard/Pages/60-reporting.qml:24
463msgid "Improving your experience"
467msgid "Improving your experience"
464−msgstr ""
468+msgstr "Javítson az élményen"
465
469
466#: qml/Wizard/Pages/60-reporting.qml:36
470#: qml/Wizard/Pages/60-reporting.qml:36
467msgid ""
471msgid ""
468"Your phone is set up to automatically report errors to Canonical and its "
472"Your phone is set up to automatically report errors to Canonical and its "
469"partners, the makers of the operating system."
473"partners, the makers of the operating system."
470msgstr ""
474msgstr ""
475+"A telefonja automatikus hibajelentéseket küld az operációs rendszert készítő "
476+"Canonical, és annak partnerei felé."
471
477
472#: qml/Wizard/Pages/60-reporting.qml:43
478#: qml/Wizard/Pages/60-reporting.qml:43
473msgid ""
479msgid ""
474"This can be disabled in <b>System Settings</b> under <b>Security &amp; "
480"This can be disabled in <b>System Settings</b> under <b>Security &amp; "
475"Privacy</b>"
481"Privacy</b>"
476msgstr ""
482msgstr ""
483+"Ezt kikapcsolhatja a <b>Rendszerbeállítások</b> alatt található <b>Biztonság "
484+"és adatvédelem</b> alatt"
477
485
478#: qml/Wizard/Pages/80-finished.qml:24
486#: qml/Wizard/Pages/80-finished.qml:24
479msgid "All done"
487msgid "All done"
480−msgstr ""
488+msgstr "Készen van"
481
489
482#: qml/Wizard/Pages/80-finished.qml:39
490#: qml/Wizard/Pages/80-finished.qml:39
483msgid "Nice work!"
491msgid "Nice work!"
484−msgstr ""
492+msgstr "Szép munka!"
485
493
486#: qml/Wizard/Pages/80-finished.qml:46
494#: qml/Wizard/Pages/80-finished.qml:46
487msgid "Your phone is now ready to use."
495msgid "Your phone is now ready to use."
488−msgstr ""
496+msgstr "A telefonja készen áll a használatra."
489
497
490#: qml/Wizard/Pages/80-finished.qml:53
498#: qml/Wizard/Pages/80-finished.qml:53
491msgid "Finish"
499msgid "Finish"
492−msgstr ""
500+msgstr "Befejezés"
493
501
494#: qml/Wizard/Pages/here-terms.qml:27
502#: qml/Wizard/Pages/here-terms.qml:27
495msgid "Terms & Conditions"
503msgid "Terms & Conditions"
496−msgstr ""
504+msgstr "Felhasználási feltételek"
497
505
498#: qml/Wizard/Pages/passwd-confirm.qml:49
506#: qml/Wizard/Pages/passwd-confirm.qml:49
499msgid "Confirm passphrase"
507msgid "Confirm passphrase"
500−msgstr ""
508+msgstr "Jelmondat megerősítése"
501
509
502#: qml/Wizard/Pages/passwd-confirm.qml:50
510#: qml/Wizard/Pages/passwd-confirm.qml:50
503msgid "Confirm passcode"
511msgid "Confirm passcode"
504−msgstr ""
512+msgstr "Jelkód megerősítése"
505
513
506#: qml/Wizard/Pages/passwd-confirm.qml:53
514#: qml/Wizard/Pages/passwd-confirm.qml:53
507#: qml/Wizard/Pages/passwd-confirm.qml:54
515#: qml/Wizard/Pages/passwd-confirm.qml:54
508msgid "Please try again."
516msgid "Please try again."
509−msgstr ""
517+msgstr "Próbálja újra."
510
518
511#: qml/Wizard/Pages/passwd-set.qml:61
519#: qml/Wizard/Pages/passwd-set.qml:61
512msgid "Choose your passcode"
520msgid "Choose your passcode"
513−msgstr ""
521+msgstr "Jelkód kiválasztása"
514
522
515#: qml/Wizard/Pages/passwd-set.qml:68
523#: qml/Wizard/Pages/passwd-set.qml:68
516msgid "Passphrase must be 4 characters long"
524msgid "Passphrase must be 4 characters long"
517−msgstr ""
525+msgstr "A jelmondat legalább 4 karakter hosszú legyen"
518
526
519#: qml/Wizard/StackButton.qml:39
527#: qml/Wizard/StackButton.qml:39
520#, qt-format
528#, qt-format
521msgid "〈 %1"
529msgid "〈 %1"
522−msgstr ""
530+msgstr "〈 %1"
523
531
524#: qml/Wizard/StackButton.qml:42
532#: qml/Wizard/StackButton.qml:42
525#, qt-format
533#, qt-format
526msgid "%1 〉"
534msgid "%1 〉"
527−msgstr ""
535+msgstr "%1 〉"
528
536
529#~ msgid "Confirm"
537#~ msgid "Confirm"
530#~ msgstr "Megerősítés"
538#~ msgstr "Megerősítés"
qml/Components/Dialogs.qml+61−67
@@ -19,11 +19,22 @@ import QtQuick 2.0
19import Unity.Application 0.1
19import Unity.Application 0.1
20import Unity.Session 0.1
20import Unity.Session 0.1
21import Ubuntu.Components 1.1
21import Ubuntu.Components 1.1
22−import Ubuntu.Components.Popups 0.1
23
22
24Item {
23Item {
25 id: root
24 id: root
26
25
26+ // to be set from outside, useful mostly for testing purposes
27+ property var unitySessionService: DBusUnitySessionService
28+ property var closeAllApps: function() {
29+ while (true) {
30+ var app = ApplicationManager.get(0);
31+ if (app === null) {
32+ break;
33+ }
34+ ApplicationManager.stopApplication(app.appId);
35+ }
36+ }
37+
27 function onPowerKeyPressed() {
38 function onPowerKeyPressed() {
28 // FIXME: event.isAutoRepeat is always false on Nexus 4.
39 // FIXME: event.isAutoRepeat is always false on Nexus 4.
29 // So we use powerKeyTimer.running to avoid the PowerOff key repeat
40 // So we use powerKeyTimer.running to avoid the PowerOff key repeat
@@ -41,16 +52,21 @@ Item {
41
52
42 QtObject {
53 QtObject {
43 id: d // private stuff
54 id: d // private stuff
55+ objectName: "dialogsPrivate"
44
56
45− property bool dialogShown: false
46
57
47 function showPowerDialog() {
58 function showPowerDialog() {
48− if (!d.dialogShown) {
59+ if (!dialogLoader.active) {
49− d.dialogShown = true;
60+ dialogLoader.sourceComponent = powerDialogComponent;
50− PopupUtils.open(powerDialog, root, {"z": root.z});
61+ dialogLoader.active = true;
51 }
62 }
52 }
63 }
53 }
64 }
65+ Loader {
66+ id: dialogLoader
67+ anchors.fill: parent
68+ active: false
69+ }
54
70
55 Timer {
71 Timer {
56 id: powerKeyTimer
72 id: powerKeyTimer
@@ -64,91 +80,84 @@ Item {
64 }
80 }
65
81
66 Component {
82 Component {
67− id: logoutDialog
83+ id: logoutDialogComponent
68− Dialog {
84+ ShellDialog {
69− id: dialogueLogout
85+ id: logoutDialog
70 title: i18n.tr("Log out")
86 title: i18n.tr("Log out")
71 text: i18n.tr("Are you sure you want to log out?")
87 text: i18n.tr("Are you sure you want to log out?")
72 Button {
88 Button {
73 text: i18n.tr("No")
89 text: i18n.tr("No")
74 onClicked: {
90 onClicked: {
75− PopupUtils.close(dialogueLogout);
91+ logoutDialog.hide();
76− d.dialogShown = false;
77 }
92 }
78 }
93 }
79 Button {
94 Button {
80 text: i18n.tr("Yes")
95 text: i18n.tr("Yes")
81 onClicked: {
96 onClicked: {
82− DBusUnitySessionService.Logout();
97+ unitySessionService.logout();
83− PopupUtils.close(dialogueLogout);
98+ logoutDialog.hide();
84− d.dialogShown = false;
85 }
99 }
86 }
100 }
87 }
101 }
88 }
102 }
89
103
90 Component {
104 Component {
91− id: shutdownDialog
105+ id: shutdownDialogComponent
92− Dialog {
106+ ShellDialog {
93− id: dialogueShutdown
107+ id: shutdownDialog
94 title: i18n.tr("Shut down")
108 title: i18n.tr("Shut down")
95 text: i18n.tr("Are you sure you want to shut down?")
109 text: i18n.tr("Are you sure you want to shut down?")
96 Button {
110 Button {
97 text: i18n.tr("No")
111 text: i18n.tr("No")
98 onClicked: {
112 onClicked: {
99− PopupUtils.close(dialogueShutdown);
113+ shutdownDialog.hide();
100− d.dialogShown = false;
101 }
114 }
102 }
115 }
103 Button {
116 Button {
104 text: i18n.tr("Yes")
117 text: i18n.tr("Yes")
105 onClicked: {
118 onClicked: {
106− dBusUnitySessionServiceConnection.closeAllApps();
119+ root.closeAllApps();
107− DBusUnitySessionService.Shutdown();
120+ unitySessionService.shutdown();
108− PopupUtils.close(dialogueShutdown);
121+ shutdownDialog.hide();
109− d.dialogShown = false;
110 }
122 }
111 }
123 }
112 }
124 }
113 }
125 }
114
126
115 Component {
127 Component {
116− id: rebootDialog
128+ id: rebootDialogComponent
117− Dialog {
129+ ShellDialog {
118− id: dialogueReboot
130+ id: rebootDialog
119 title: i18n.tr("Reboot")
131 title: i18n.tr("Reboot")
120 text: i18n.tr("Are you sure you want to reboot?")
132 text: i18n.tr("Are you sure you want to reboot?")
121 Button {
133 Button {
122 text: i18n.tr("No")
134 text: i18n.tr("No")
123 onClicked: {
135 onClicked: {
124− PopupUtils.close(dialogueReboot)
136+ rebootDialog.hide();
125− d.dialogShown = false;
126 }
137 }
127 }
138 }
128 Button {
139 Button {
129 text: i18n.tr("Yes")
140 text: i18n.tr("Yes")
130 onClicked: {
141 onClicked: {
131− dBusUnitySessionServiceConnection.closeAllApps();
142+ root.closeAllApps();
132− DBusUnitySessionService.Reboot();
143+ unitySessionService.reboot();
133− PopupUtils.close(dialogueReboot);
144+ rebootDialog.hide();
134− d.dialogShown = false;
135 }
145 }
136 }
146 }
137 }
147 }
138 }
148 }
139
149
140 Component {
150 Component {
141− id: powerDialog
151+ id: powerDialogComponent
142− Dialog {
152+ ShellDialog {
143− id: dialoguePower
153+ id: powerDialog
144 title: i18n.tr("Power")
154 title: i18n.tr("Power")
145 text: i18n.tr("Are you sure you would like\nto power off?")
155 text: i18n.tr("Are you sure you would like\nto power off?")
146 Button {
156 Button {
147 text: i18n.tr("Power off")
157 text: i18n.tr("Power off")
148 onClicked: {
158 onClicked: {
149− dBusUnitySessionServiceConnection.closeAllApps();
159+ root.closeAllApps();
150− PopupUtils.close(dialoguePower);
160+ powerDialog.hide();
151− d.dialogShown = false;
152 root.powerOffClicked();
161 root.powerOffClicked();
153 }
162 }
154 color: UbuntuColors.red
163 color: UbuntuColors.red
@@ -156,66 +165,51 @@ Item {
156 Button {
165 Button {
157 text: i18n.tr("Restart")
166 text: i18n.tr("Restart")
158 onClicked: {
167 onClicked: {
159− dBusUnitySessionServiceConnection.closeAllApps();
168+ root.closeAllApps();
160− DBusUnitySessionService.Reboot();
169+ unitySessionService.reboot();
161− PopupUtils.close(dialoguePower);
170+ powerDialog.hide();
162− d.dialogShown = false;
163 }
171 }
164 color: UbuntuColors.green
172 color: UbuntuColors.green
165 }
173 }
166 Button {
174 Button {
167 text: i18n.tr("Cancel")
175 text: i18n.tr("Cancel")
168 onClicked: {
176 onClicked: {
169− PopupUtils.close(dialoguePower);
177+ powerDialog.hide();
170− d.dialogShown = false;
171 }
178 }
172 color: UbuntuColors.coolGrey
179 color: UbuntuColors.coolGrey
173 }
180 }
174 }
181 }
175 }
182 }
176
183
177−
178 Connections {
184 Connections {
179− id: dBusUnitySessionServiceConnection
185+ target: root.unitySessionService
180− objectName: "dBusUnitySessionServiceConnection"
181− target: DBusUnitySessionService
182−
183− function closeAllApps() {
184− while (true) {
185− var app = ApplicationManager.get(0);
186− if (app === null) {
187− break;
188− }
189− ApplicationManager.stopApplication(app.appId);
190− }
191− }
192
186
193 onLogoutRequested: {
187 onLogoutRequested: {
194 // Display a dialog to ask the user to confirm.
188 // Display a dialog to ask the user to confirm.
195− if (!d.dialogShown) {
189+ if (!dialogLoader.active) {
196− d.dialogShown = true;
190+ dialogLoader.sourceComponent = logoutDialogComponent;
197− PopupUtils.open(logoutDialog, root, {"z": root.z});
191+ dialogLoader.active = true;
198 }
192 }
199 }
193 }
200
194
201 onShutdownRequested: {
195 onShutdownRequested: {
202 // Display a dialog to ask the user to confirm.
196 // Display a dialog to ask the user to confirm.
203− if (!d.dialogShown) {
197+ if (!dialogLoader.active) {
204− d.dialogShown = true;
198+ dialogLoader.sourceComponent = shutdownDialogComponent;
205− PopupUtils.open(shutdownDialog, root, {"z": root.z});
199+ dialogLoader.active = true;
206 }
200 }
207 }
201 }
208
202
209 onRebootRequested: {
203 onRebootRequested: {
210 // Display a dialog to ask the user to confirm.
204 // Display a dialog to ask the user to confirm.
211− if (!d.dialogShown) {
205+ if (!dialogLoader.active) {
212− d.dialogShown = true;
206+ dialogLoader.sourceComponent = rebootDialogComponent;
213− PopupUtils.open(rebootDialog, root, {"z": root.z});
207+ dialogLoader.active = true;
214 }
208 }
215 }
209 }
216
210
217 onLogoutReady: {
211 onLogoutReady: {
218− closeAllApps();
212+ root.closeAllApps();
219 Qt.quit();
213 Qt.quit();
220 }
214 }
221 }
215 }
qml/Components/DragHandle.qml+10−2
@@ -100,8 +100,16 @@ EdgeDragArea {
100 id: d
100 id: d
101 property var previousStatus: DirectionalDragArea.WaitingForTouch
101 property var previousStatus: DirectionalDragArea.WaitingForTouch
102 property real startValue
102 property real startValue
103+ property real minValue: {
104+ if (direction == Direction.Horizontal) {
105+ return startValue - maxTotalDragDistance;
103− property real minValue: Direction.isPositive(direction) ? startValue
106+ } else if (Direction.isPositive(direction)) {
107+ return startValue;
108+ } else {
104− : startValue - maxTotalDragDistance
109+ return startValue - maxTotalDragDistance;
110+ }
111+ }
112+
105 property real maxValue: Direction.isPositive(direction) ? startValue + maxTotalDragDistance
113 property real maxValue: Direction.isPositive(direction) ? startValue + maxTotalDragDistance
106 : startValue
114 : startValue
107
115
qml/Components/EdgeDragEvaluator.qml+11−5
@@ -53,20 +53,26 @@ AxisVelocityCalculator {
53 // Returns whether the drag should continue by itself until completed.
53 // Returns whether the drag should continue by itself until completed.
54 function shouldAutoComplete() {
54 function shouldAutoComplete() {
55 var deltaPos = trackedPosition - __startPosition;
55 var deltaPos = trackedPosition - __startPosition;
56+
56 if (Math.abs(deltaPos) < minDragDistance) {
57 if (Math.abs(deltaPos) < minDragDistance) {
57 velocity = 0;
58 velocity = 0;
58 minVelocity = 0;
59 minVelocity = 0;
59 return false;
60 return false;
60 }
61 }
61
62
62− minVelocity = __calculateMinimumVelocityForAutoCompletion(deltaPos);
63 velocity = calculate();
63 velocity = calculate();
64
64
65− if (Direction.isPositive(direction) && (velocity >= minVelocity)
65+ if (direction == Direction.Horizontal) {
66− || !Direction.isPositive(direction) && (velocity <= minVelocity)) {
66+ minVelocity = __calculateMinimumVelocityForAutoCompletion(Math.abs(deltaPos));
67− return true;
67+ return Math.abs(velocity) >= minVelocity;
68 } else {
68 } else {
69+ minVelocity = __calculateMinimumVelocityForAutoCompletion(deltaPos);
70+ if (Direction.isPositive(direction) && (velocity >= minVelocity)
71+ || !Direction.isPositive(direction) && (velocity <= minVelocity)) {
72+ return true;
73+ } else {
69− return false;
74+ return false;
75+ }
70 }
76 }
71 }
77 }
72
78
qml/Components/ResponsiveVerticalJournal.qml+1
@@ -45,6 +45,7 @@ Item {
45 property alias rowSpacing: verticalJournalView.rowSpacing
45 property alias rowSpacing: verticalJournalView.rowSpacing
46 property alias model: verticalJournalView.model
46 property alias model: verticalJournalView.model
47 property alias delegate: verticalJournalView.delegate
47 property alias delegate: verticalJournalView.delegate
48+ property alias cacheBuffer: verticalJournalView.cacheBuffer
48 property alias displayMarginBeginning: verticalJournalView.displayMarginBeginning
49 property alias displayMarginBeginning: verticalJournalView.displayMarginBeginning
49 property alias displayMarginEnd: verticalJournalView.displayMarginEnd
50 property alias displayMarginEnd: verticalJournalView.displayMarginEnd
50
51
qml/Components/ShellDialog.qmlnew file+37
@@ -0,0 +1,37 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.0
18+
19+import Ubuntu.Components 1.1
20+import Ubuntu.Components.Popups 0.1
21+
22+/*
23+ A Dialog configured for use as a proper in-scene Dialog
24+
25+ This is a helper component for Dialogs.qml, thus some assumptions
26+ on context are (or will be) made here.
27+ */
28+Dialog {
29+ automaticOrientation: false
30+
31+ // NB: PopupBase, Dialog's superclass, will check for the existence of this property
32+ property bool reparentToRootItem: false
33+
34+ onVisibleChanged: { if (!visible) { dialogLoader.active = false; } }
35+
36+ Component.onCompleted: show()
37+}
qml/Components/Showable.qml+13
@@ -99,10 +99,23 @@ Item {
99 return true;
99 return true;
100 }
100 }
101
101
102+ /*
103+ Will be called right before starting the hideAnimation.
104+ */
105+ property var prepareToHide: function(){}
106+
102 function hide() {
107 function hide() {
103 if (showAnimation != undefined && showAnimation.running) {
108 if (showAnimation != undefined && showAnimation.running) {
104 showAnimation.stop()
109 showAnimation.stop()
105 }
110 }
111+
112+ if (typeof prepareToHide === "function") {
113+ prepareToHide();
114+ } else {
115+ console.warn("Showable.prepareToHide should be a function, but it's a " +
116+ (typeof prepareToHide) + " instead");
117+ }
118+
106 if (hideAnimation != undefined) {
119 if (hideAnimation != undefined) {
107 if (!hideAnimation.running) {
120 if (!hideAnimation.running) {
108 hideAnimation.restart()
121 hideAnimation.restart()
qml/Dash/CardGrid.qml+1−2
@@ -50,7 +50,7 @@ DashRenderer {
50 model: root.model
50 model: root.model
51 displayMarginBeginning: root.displayMarginBeginning
51 displayMarginBeginning: root.displayMarginBeginning
52 displayMarginEnd: root.displayMarginEnd
52 displayMarginEnd: root.displayMarginEnd
53− cacheBuffer: 0
53+ cacheBuffer: root.cacheBuffer
54 interactive: false
54 interactive: false
55 delegate: Item {
55 delegate: Item {
56 width: grid.cellWidth
56 width: grid.cellWidth
@@ -59,7 +59,6 @@ DashRenderer {
59 id: loader
59 id: loader
60 sourceComponent: cardTool.cardComponent
60 sourceComponent: cardTool.cardComponent
61 anchors.horizontalCenter: parent.horizontalCenter
61 anchors.horizontalCenter: parent.horizontalCenter
62− asynchronous: true
63 onLoaded: {
62 onLoaded: {
64 item.objectName = "delegate" + index;
63 item.objectName = "delegate" + index;
65 item.width = Qt.binding(function() { return cardTool.cardWidth; });
64 item.width = Qt.binding(function() { return cardTool.cardWidth; });
qml/Dash/CardVerticalJournal.qml+1
@@ -59,6 +59,7 @@ DashRenderer {
59 rowSpacing: minimumColumnSpacing
59 rowSpacing: minimumColumnSpacing
60 columnWidth: cardTool.cardWidth
60 columnWidth: cardTool.cardWidth
61
61
62+ cacheBuffer: root.cacheBuffer
62 displayMarginBeginning: root.displayMarginBeginning
63 displayMarginBeginning: root.displayMarginBeginning
63 displayMarginEnd: root.displayMarginEnd
64 displayMarginEnd: root.displayMarginEnd
64
65
qml/Dash/Dash.qml+1
@@ -75,6 +75,7 @@ Showable {
75 return
75 return
76 }
76 }
77
77
78+ dashContent.workaroundRestoreIndex = -1;
78 dashContent.setCurrentScopeAtIndex(scopeIndex, animate, reset)
79 dashContent.setCurrentScopeAtIndex(scopeIndex, animate, reset)
79 }
80 }
80
81
qml/Dash/DashContent.qml+2
@@ -163,6 +163,7 @@ Item {
163
163
164 delegate:
164 delegate:
165 Loader {
165 Loader {
166+ id: loader
166 width: ListView.view.width
167 width: ListView.view.width
167 height: ListView.view.height
168 height: ListView.view.height
168 opacity: { // hide delegate if offscreen
169 opacity: { // hide delegate if offscreen
@@ -191,6 +192,7 @@ Item {
191 dashContent.scopeLoaded(item.scope.id)
192 dashContent.scopeLoaded(item.scope.id)
192 item.paginationCount = Qt.binding(function() { return dashContentList.count } )
193 item.paginationCount = Qt.binding(function() { return dashContentList.count } )
193 item.paginationIndex = Qt.binding(function() { return dashContentList.currentIndex } )
194 item.paginationIndex = Qt.binding(function() { return dashContentList.currentIndex } )
195+ item.visibleToParent = Qt.binding(function() { return loader.opacity != 0 });
194 item.holdingList = dashContentList;
196 item.holdingList = dashContentList;
195 item.forceNonInteractive = Qt.binding(function() { return dashContent.forceNonInteractive } )
197 item.forceNonInteractive = Qt.binding(function() { return dashContent.forceNonInteractive } )
196 }
198 }
qml/Dash/DashRenderer.qml+2
@@ -23,6 +23,8 @@ Item {
23
23
24 property int collapsedItemCount: -1
24 property int collapsedItemCount: -1
25
25
26+ property int cacheBuffer: 0
27+
26 property int displayMarginBeginning: 0
28 property int displayMarginBeginning: 0
27
29
28 property int displayMarginEnd: 0
30 property int displayMarginEnd: 0
qml/Dash/GenericScopeView.qml+46−20
@@ -38,6 +38,7 @@ FocusScope {
38 readonly property alias subPageShown: subPageLoader.subPageShown
38 readonly property alias subPageShown: subPageLoader.subPageShown
39 property int paginationCount: 0
39 property int paginationCount: 0
40 property int paginationIndex: 0
40 property int paginationIndex: 0
41+ property bool visibleToParent: false
41 property alias pageHeaderTotallyVisible: categoryView.pageHeaderTotallyVisible
42 property alias pageHeaderTotallyVisible: categoryView.pageHeaderTotallyVisible
42 property var holdingList: null
43 property var holdingList: null
43
44
@@ -357,6 +358,7 @@ FocusScope {
357 Connections {
358 Connections {
358 target: scopeView
359 target: scopeView
359 onIsCurrentChanged: rendererLoader.updateRanges();
360 onIsCurrentChanged: rendererLoader.updateRanges();
361+ onVisibleToParentChanged: rendererLoader.updateRanges();
360 }
362 }
361 Connections {
363 Connections {
362 target: holdingList
364 target: holdingList
@@ -364,7 +366,9 @@ FocusScope {
364 }
366 }
365
367
366 function updateRanges() {
368 function updateRanges() {
369+ // Don't want to create stress by requesting more items during scope
370+ // changes so unless you're not part of the visible scopes just return
367− if (holdingList && holdingList.moving) {
371+ if (holdingList && holdingList.moving && !scopeView.visibleToParent) {
368 return;
372 return;
369 }
373 }
370
374
@@ -380,28 +384,50 @@ FocusScope {
380 }
384 }
381
385
382 if (item && item.hasOwnProperty("displayMarginBeginning")) {
386 if (item && item.hasOwnProperty("displayMarginBeginning")) {
383− // A item view is considered visible from
387+ // A item view creates its delegates synchronously from
384 // -displayMarginBeginning
388 // -displayMarginBeginning
385 // to
389 // to
386− // height + item.displayMarginEnd
390+ // height + displayMarginEnd
391+ // Around that area it adds the cacheBuffer area where delegates are created async
392+ //
387 // We adjust displayMarginBeginning and displayMarginEnd so
393 // We adjust displayMarginBeginning and displayMarginEnd so
388− // * In non visible scopes only the viewport is considered visible
394+ // * In non visible scopes nothing is considered visible and we set cacheBuffer
389− // that way when you switch to it the visible items are there
395+ // so that creates the items that would be in the viewport asynchronously
390− // * For visible scopes we increase the visible range by categoryView.height * 1.5
396+ // * For the current scope set the visible range to the viewport and then
397+ // use cacheBuffer to create extra items for categoryView.height * 1.5
391− // in both directions to make scrolling nicer by mantaining a higher number of
398+ // to make scrolling nicer by mantaining a higher number of
392 // cached items
399 // cached items
393− // TODO Improvements
400+ // * For non current but visible scopes (i.e. when the user changes from one scope
394− // - For non visible scopes we should always have a visible range of 0 and
401+ // to the next, we set the visible range to the viewport so
395− // make sure the items in the viewport are created with the cache buffer feature
402+ // items are not culled (invisible) but still use no cacheBuffer
396− // - For visible scopes we should always the have a visible range be exactly the
403+ // (it will be set once the scope is the current one)
397− // viewport and make sure the rest of items are created with the cache buffer feature
404+ var displayMarginBeginning = baseItem.y;
398− // To be able to implement that feature VerticalJournal/AbstractDashView needs to
405+ displayMarginBeginning = -Math.max(-displayMarginBeginning, 0);
399− // make the cache buffer value setable externally
406+ displayMarginBeginning = -Math.min(-displayMarginBeginning, baseItem.height);
407+ displayMarginBeginning = Math.round(displayMarginBeginning);
408+ var displayMarginEnd = -baseItem.height + seeAll.height + categoryView.height - baseItem.y;
409+ displayMarginEnd = -Math.max(-displayMarginEnd, 0);
410+ displayMarginEnd = -Math.min(-displayMarginEnd, baseItem.height);
411+ displayMarginEnd = Math.round(displayMarginEnd);
412+ if (scopeView.isCurrent || scopeView.visibleToParent) {
413+ item.displayMarginBeginning = displayMarginBeginning;
414+ item.displayMarginEnd = displayMarginEnd;
400− var extraMargins = scopeView.isCurrent ? categoryView.height * 1.5 : 0;
415+ item.cacheBuffer = scopeView.isCurrent ? categoryView.height * 1.5 : 0;
401−
416+ } else {
402− item.displayMarginBeginning = Math.round(-Math.max(-baseItem.y - extraMargins, 0));
417+ var visibleRange = baseItem.height + displayMarginEnd + displayMarginBeginning;
403− item.displayMarginEnd = -Math.round(Math.max(baseItem.height - extraMargins - seeAll.height -
418+ if (visibleRange < 0) {
404− categoryView.height + baseItem.y, 0));
419+ item.displayMarginBeginning = displayMarginBeginning;
420+ item.displayMarginEnd = displayMarginEnd;
421+ item.cacheBuffer = 0;
422+ } else {
423+ // This should be visibleRange/2 in each of the properties
424+ // but some item views still (like GridView) like creating sync delegates even if
425+ // the visible range is 0 so let's make sure the visible range is negative
426+ item.displayMarginBeginning = displayMarginBeginning - visibleRange;
427+ item.displayMarginEnd = displayMarginEnd - visibleRange;
428+ item.cacheBuffer = visibleRange;
429+ }
430+ }
405 }
431 }
406 }
432 }
407 }
433 }
@@ -494,7 +520,7 @@ FocusScope {
494 showBackButton: scopeView.hasBackAction
520 showBackButton: scopeView.hasBackAction
495 searchEntryEnabled: true
521 searchEntryEnabled: true
496 settingsEnabled: scopeView.scope && scopeView.scope.settings && scopeView.scope.settings.count > 0 || false
522 settingsEnabled: scopeView.scope && scopeView.scope.settings && scopeView.scope.settings.count > 0 || false
497− favoriteEnabled: scopeView.scope
523+ favoriteEnabled: scopeView.scope && scopeView.scope.id !== "clickscope"
498 favorite: scopeView.scope && scopeView.scope.favorite
524 favorite: scopeView.scope && scopeView.scope.favorite
499 scopeStyle: scopeView.scopeStyle
525 scopeStyle: scopeView.scopeStyle
500 paginationCount: scopeView.paginationCount
526 paginationCount: scopeView.paginationCount
qml/Dash/ScopeListView.qml+4−2
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2013 Canonical, Ltd.
2+ * Copyright (C) 2014 Canonical, Ltd.
3 *
3 *
4 * This program is free software; you can redistribute it and/or modify
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
5 * it under the terms of the GNU General Public License as published by
@@ -20,5 +20,7 @@ import Dash 0.1
20ListViewWithPageHeader {
20ListViewWithPageHeader {
21 maximumFlickVelocity: height * 10
21 maximumFlickVelocity: height * 10
22 flickDeceleration: height * 2
22 flickDeceleration: height * 2
23+ // 1073741823 is s^30 -1. A quite big number so that you have "infinite" cache, but not so
24+ // big so that if you add if with itself you're outside the 2^31 int range
23− cacheBuffer: Number.MAX_VALUE
25+ cacheBuffer: 1073741823
24}
26}
qml/Dash/ScopesList.qml+5−1
@@ -34,6 +34,9 @@ Item {
34
34
35 state: "browse"
35 state: "browse"
36
36
37+ property var scopeStyle: ScopeStyle {
38+ }
39+
37 onStateChanged: {
40 onStateChanged: {
38 if (state == "edit") {
41 if (state == "edit") {
39 // As per design entering edit mode clears the possible existing search
42 // As per design entering edit mode clears the possible existing search
@@ -66,6 +69,7 @@ Item {
66 backIsClose: root.state == "edit"
69 backIsClose: root.state == "edit"
67 storeEntryEnabled: root.state == "browse"
70 storeEntryEnabled: root.state == "browse"
68 searchEntryEnabled: false // Disable search for now
71 searchEntryEnabled: false // Disable search for now
72+ scopeStyle: root.scopeStyle
69 onBackClicked: {
73 onBackClicked: {
70 if (backIsClose) {
74 if (backIsClose) {
71 root.state = "browse"
75 root.state = "browse"
@@ -111,7 +115,7 @@ Item {
111
115
112 editMode: root.state == "edit"
116 editMode: root.state == "edit"
113
117
114− scopeStyle: root.scope.scopeStyle
118+ scopeStyle: root.scopeStyle
115 isFavoritesFeed: categoryId == "favorites"
119 isFavoritesFeed: categoryId == "favorites"
116 isAlsoInstalled: categoryId == "other"
120 isAlsoInstalled: categoryId == "other"
117
121
qml/Dash/ScopesListCategory.qml+2−2
@@ -78,7 +78,7 @@ Item {
78 clip: height < listItemHeight
78 clip: height < listItemHeight
79 Behavior on height { enabled: visible; UbuntuNumberAnimation { } }
79 Behavior on height { enabled: visible; UbuntuNumberAnimation { } }
80 sourceComponent: ScopesListCategoryItem {
80 sourceComponent: ScopesListCategoryItem {
81− objectName: "delegate" + index
81+ objectName: "delegate" + model.scopeId
82
82
83 width: root.width
83 width: root.width
84 topMargin: height > listItemHeight ? height - listItemHeight : 0
84 topMargin: height > listItemHeight ? height - listItemHeight : 0
@@ -86,7 +86,7 @@ Item {
86 icon: model.art || model.mascot || ""
86 icon: model.art || model.mascot || ""
87 text: model.title || ""
87 text: model.title || ""
88 subtext: model.subtitle || ""
88 subtext: model.subtitle || ""
89− showStar: root.isFavoritesFeed || root.isAlsoInstalled
89+ showStar: model.scopeId !== "clickscope" && (root.isFavoritesFeed || root.isAlsoInstalled)
90 isFavorite: root.isFavoritesFeed
90 isFavorite: root.isFavoritesFeed
91
91
92 hideChildren: dragItem.loaderToShrink == loader
92 hideChildren: dragItem.loaderToShrink == loader
qml/Dash/ScopesListCategoryItem.qml+3−1
@@ -29,8 +29,8 @@ MouseArea {
29 property alias icon: shapeImage.source
29 property alias icon: shapeImage.source
30 property alias text: titleLabel.text
30 property alias text: titleLabel.text
31 property alias subtext: subtitleLabel.text
31 property alias subtext: subtitleLabel.text
32− property alias showStar: star.visible
33
32
33+ property bool showStar: false
34 property bool isFavorite: false
34 property bool isFavorite: false
35 property bool hideChildren: false
35 property bool hideChildren: false
36
36
@@ -84,12 +84,14 @@ MouseArea {
84 }
84 }
85 MouseArea {
85 MouseArea {
86 id: starArea
86 id: starArea
87+ objectName: "starArea"
87 height: parent.height
88 height: parent.height
88 width: height
89 width: height
89 anchors.right: parent.right
90 anchors.right: parent.right
90 onClicked: if (!editMode) root.requestFavorite(model.scopeId, !isFavorite);
91 onClicked: if (!editMode) root.requestFavorite(model.scopeId, !isFavorite);
91 onPressed: if (editMode) root.handlePressed(starArea);
92 onPressed: if (editMode) root.handlePressed(starArea);
92 onReleased: if (editMode) root.handleReleased(starArea);
93 onReleased: if (editMode) root.handleReleased(starArea);
94+ visible: editMode || showStar
93 Icon {
95 Icon {
94 id: star
96 id: star
95 anchors.centerIn: parent
97 anchors.centerIn: parent
qml/Greeter/Greeter.qml+91−82
@@ -25,16 +25,26 @@ Showable {
25 enabled: shown
25 enabled: shown
26 created: greeterContentLoader.status == Loader.Ready && greeterContentLoader.item.ready
26 created: greeterContentLoader.status == Loader.Ready && greeterContentLoader.item.ready
27
27
28+ property real dragHandleLeftMargin: 0
29+ property alias dragging: dragHandle.dragging
30+
28 property url background
31 property url background
32+
33+ prepareToHide: function () {
34+ hideTranslation.to = greeter.x > 0 || d.forceRightOnNextHideAnimation ? greeter.width : -greeter.width;
35+ d.forceRightOnNextHideAnimation = false;
36+ }
37+
38+ QtObject {
39+ id: d
40+ property bool forceRightOnNextHideAnimation: false
41+ }
42+
29 property bool loadContent: required
43 property bool loadContent: required
30
44
31 // 1 when fully shown and 0 when fully hidden
45 // 1 when fully shown and 0 when fully hidden
32− property real showProgress: MathUtils.clamp((width - Math.abs(x)) / width, 0, 1)
46+ property real showProgress: visible ? MathUtils.clamp((width - Math.abs(x)) / width, 0, 1) : 0
33−
34− showAnimation: StandardAnimation { property: "x"; to: 0; duration: UbuntuAnimation.FastDuration }
35− hideAnimation: __leftHideAnimation
36
47
37− property alias dragHandleWidth: dragHandle.width
38 property alias model: greeterContentLoader.model
48 property alias model: greeterContentLoader.model
39 property bool locked: true
49 property bool locked: true
40
50
@@ -43,18 +53,13 @@ Showable {
43
53
44 readonly property int currentIndex: greeterContentLoader.currentIndex
54 readonly property int currentIndex: greeterContentLoader.currentIndex
45
55
46− property var __leftHideAnimation: StandardAnimation { property: "x"; to: -width }
47− property var __rightHideAnimation: StandardAnimation { property: "x"; to: width }
48−
49 signal selected(int uid)
56 signal selected(int uid)
50 signal unlocked(int uid)
57 signal unlocked(int uid)
51− signal tease()
58+ signal tapped()
52
59
53 function hideRight() {
60 function hideRight() {
54− if (shown) {
61+ d.forceRightOnNextHideAnimation = true;
55− hideAnimation = __rightHideAnimation
56− hide()
62+ hide();
57− }
58 }
63 }
59
64
60 function tryToUnlock() {
65 function tryToUnlock() {
@@ -69,71 +74,9 @@ Showable {
69 }
74 }
70 }
75 }
71
76
72− onRequiredChanged: {
77+ // event eater
73− // Reset hide animation to default once we're finished with it
78+ // Nothing should leak to items behind the greeter
74− if (required) {
75− // Reset hide animation so that a hide() call is reliably left
76− hideAnimation = __leftHideAnimation
77− }
78− }
79−
80− // Bi-directional revealer
81− DraggingArea {
82− id: dragHandle
83− anchors.fill: parent
84− enabled: (greeter.narrowMode || !greeter.locked) && greeter.enabled && greeter.shown
85− orientation: Qt.Horizontal
86− propagateComposedEvents: true
87−
88− Component.onCompleted: {
89− // set evaluators to baseline of dragValue == 0
90− leftEvaluator.reset()
91− rightEvaluator.reset()
92− }
93−
94− function maybeTease() {
95− if (!greeter.locked || greeter.narrowMode)
96− greeter.tease();
97− }
98−
99− onClicked: maybeTease()
100− onDragStart: maybeTease()
101− onPressAndHold: {} // eat event, but no need to tease, as drag will cover it
102−
103− onDragEnd: {
104− if (greeter.x > 0 && rightEvaluator.shouldAutoComplete()) {
105− greeter.hideRight()
106− } else if (greeter.x < 0 && leftEvaluator.shouldAutoComplete()) {
107− greeter.hide();
108− } else {
109− greeter.show(); // undo drag
110− }
111− }
112−
113− onDragValueChanged: {
114− // dragValue is kept as a "step" value since we do this x adjusting on the fly
115− greeter.x += dragValue
116− }
117−
118− EdgeDragEvaluator {
119− id: rightEvaluator
120− trackedPosition: dragHandle.dragValue + greeter.x
121− maxDragDistance: parent.width
122− direction: Direction.Rightwards
123− }
124−
125− EdgeDragEvaluator {
126− id: leftEvaluator
127− trackedPosition: dragHandle.dragValue + greeter.x
128− maxDragDistance: parent.width
129− direction: Direction.Leftwards
130− }
131− }
132− TouchGate {
133− targetItem: dragHandle
134− anchors.fill: targetItem
79+ MouseArea { anchors.fill: parent }
135− enabled: targetItem.enabled
136− }
137
80
138 Loader {
81 Loader {
139 id: greeterContentLoader
82 id: greeterContentLoader
@@ -161,11 +104,27 @@ Showable {
161 }
104 }
162 }
105 }
163
106
107+ DragHandle {
108+ id: dragHandle
109+ anchors.fill: parent
110+ anchors.leftMargin: greeter.dragHandleLeftMargin
111+ enabled: (greeter.narrowMode || !greeter.locked) && greeter.enabled && greeter.shown
112+ direction: Direction.Horizontal
113+
114+ onTapped: {
115+ greeter.tapped();
116+ showLabelAnimation.start();
117+ }
118+
119+ onDraggingChanged: {
120+ if (dragging) {
164− onTease: showLabelAnimation.start()
121+ showLabelAnimation.start();
122+ }
123+ }
124+ }
165
125
166 Label {
126 Label {
167 id: swipeHint
127 id: swipeHint
168− visible: greeter.shown
169 property real baseOpacity: 0.5
128 property real baseOpacity: 0.5
170 opacity: 0.0
129 opacity: 0.0
171 anchors.horizontalCenter: parent.horizontalCenter
130 anchors.horizontalCenter: parent.horizontalCenter
@@ -199,7 +158,6 @@ Showable {
199 anchors.left: parent.right
158 anchors.left: parent.right
200 anchors.top: parent.top
159 anchors.top: parent.top
201 anchors.bottom: parent.bottom
160 anchors.bottom: parent.bottom
202− visible: parent.required
203 fillMode: Image.Tile
161 fillMode: Image.Tile
204 source: "../graphics/dropshadow_right.png"
162 source: "../graphics/dropshadow_right.png"
205 }
163 }
@@ -209,8 +167,59 @@ Showable {
209 anchors.right: parent.left
167 anchors.right: parent.left
210 anchors.top: parent.top
168 anchors.top: parent.top
211 anchors.bottom: parent.bottom
169 anchors.bottom: parent.bottom
212− visible: parent.required
213 fillMode: Image.Tile
170 fillMode: Image.Tile
214 source: "../graphics/dropshadow_left.png"
171 source: "../graphics/dropshadow_left.png"
215 }
172 }
173+
174+ Binding {
175+ id: positionLock
176+
177+ property bool enabled: false
178+ onEnabledChanged: {
179+ if (enabled === __enabled) {
180+ return;
181+ }
182+
183+ if (enabled) {
184+ if (greeter.x > 0) {
185+ value = Qt.binding(function() { return greeter.width; })
186+ } else {
187+ value = Qt.binding(function() { return -greeter.width; })
188+ }
189+ }
190+
191+ __enabled = enabled;
192+ }
193+
194+ property bool __enabled: false
195+
196+ target: greeter
197+ when: __enabled
198+ property: "x"
199+ }
200+
201+ hideAnimation: SequentialAnimation {
202+ id: hideAnimation
203+ objectName: "hideAnimation"
204+ StandardAnimation {
205+ id: hideTranslation
206+ property: "x"
207+ target: greeter
208+ }
209+ PropertyAction { target: greeter; property: "visible"; value: false }
210+ PropertyAction { target: positionLock; property: "enabled"; value: true }
211+ }
212+
213+ showAnimation: SequentialAnimation {
214+ id: showAnimation
215+ objectName: "showAnimation"
216+ PropertyAction { target: greeter; property: "visible"; value: true }
217+ PropertyAction { target: positionLock; property: "enabled"; value: false }
218+ StandardAnimation {
219+ property: "x"
220+ target: greeter
221+ to: 0
222+ duration: UbuntuAnimation.FastDuration
223+ }
224+ }
216}
225}
qml/Greeter/Infographics.qml−3
@@ -406,8 +406,5 @@ Item {
406 infographic.model.nextDataSource()
406 infographic.model.nextDataSource()
407 }
407 }
408 }
408 }
409−
410− onClicked: mouse.accepted = false
411− onPressed: mouse.accepted = false
412 }
409 }
413}
410}
qml/Shell.qml+12−4
@@ -554,9 +554,7 @@ Item {
554 property string lockedApp: ""
554 property string lockedApp: ""
555 property bool hasLockedApp: lockedApp !== ""
555 property bool hasLockedApp: lockedApp !== ""
556
556
557− available: true
558 hides: [launcher, panel.indicators]
557 hides: [launcher, panel.indicators]
559− shown: true
560 loadContent: required || lockscreen.required // keeps content in memory for quick show()
558 loadContent: required || lockscreen.required // keeps content in memory for quick show()
561
559
562 locked: shell.locked
560 locked: shell.locked
@@ -566,7 +564,12 @@ Item {
566 width: parent.width
564 width: parent.width
567 height: parent.height
565 height: parent.height
568
566
569− dragHandleWidth: shell.edgeSize
567+
568+ // avoid overlapping with Launcher's edge drag area
569+ // FIXME: Fix TouchRegistry & friends and remove this workaround
570+ // Issue involves launcher's DDA getting disabled on a long
571+ // left-edge drag
572+ dragHandleLeftMargin: launcher.available ? launcher.dragAreaWidth + 1 : 0
570
573
571 function startUnlock() {
574 function startUnlock() {
572 if (narrowMode) {
575 if (narrowMode) {
@@ -620,7 +623,12 @@ Item {
620 LauncherModel.setUser(user);
623 LauncherModel.setUser(user);
621 }
624 }
622
625
623− onTease: launcher.tease()
626+ onTapped: launcher.tease()
627+ onDraggingChanged: {
628+ if (dragging) {
629+ launcher.tease();
630+ }
631+ }
624
632
625 Binding {
633 Binding {
626 target: ApplicationManager
634 target: ApplicationManager
tests/autopilot/unity8/shell/emulators/dash.py+22−8
@@ -90,8 +90,12 @@ class Dash(emulators.UnityEmulatorBase):
90
90
91 def _get_scope_loader(self, scope_id):
91 def _get_scope_loader(self, scope_id):
92 try:
92 try:
93− return self.dash_content_list.wait_select_single(
93+ aux = self.dash_content_list.get_children_by_type('QQuickItem')[0]
94− 'QQuickLoader', scopeId=scope_id)
94+ for l in aux.get_children_by_type('QQuickLoader'):
95+ if (l.scopeId == scope_id):
96+ return l;
97+ raise emulators.UnityEmulatorException(
98+ 'No scope found with id {0}'.format(scope_id))
95 except dbus.StateNotFoundError:
99 except dbus.StateNotFoundError:
96 raise emulators.UnityEmulatorException(
100 raise emulators.UnityEmulatorException(
97 'No scope found with id {0}'.format(scope_id))
101 'No scope found with id {0}'.format(scope_id))
@@ -125,10 +129,15 @@ class Dash(emulators.UnityEmulatorBase):
125 original_index = self.dash_content_list.currentIndex
129 original_index = self.dash_content_list.currentIndex
126 dash_content = self.select_single(objectName="dashContent")
130 dash_content = self.select_single(objectName="dashContent")
127 x, y, width, height = dash_content.globalRect
131 x, y, width, height = dash_content.globalRect
132+ # Make the drag range be a multiple of the drag "rate" value.
133+ # Workarounds https://bugs.launchpad.net/mir/+bug/1399690
134+ rate = 10
135+ divisions = 5
136+ jump = ( width / divisions ) // rate * rate
128− start_x = x + width / 3
137+ start_x = x + jump
129− stop_x = x + width / 3 * 2
138+ stop_x = x + jump * (divisions - 1)
130 start_y = stop_y = y + 1
139 start_y = stop_y = y + 1
131− self.pointing_device.drag(start_x, start_y, stop_x, stop_y)
140+ self.pointing_device.drag(start_x, start_y, stop_x, stop_y, rate)
132 self.dash_content_list.currentIndex.wait_for(original_index - 1)
141 self.dash_content_list.currentIndex.wait_for(original_index - 1)
133
142
134 @autopilot_logging.log_action(logger.info)
143 @autopilot_logging.log_action(logger.info)
@@ -136,10 +145,15 @@ class Dash(emulators.UnityEmulatorBase):
136 original_index = self.dash_content_list.currentIndex
145 original_index = self.dash_content_list.currentIndex
137 dash_content = self.select_single(objectName="dashContent")
146 dash_content = self.select_single(objectName="dashContent")
138 x, y, width, height = dash_content.globalRect
147 x, y, width, height = dash_content.globalRect
148+ # Make the drag range be a multiple of the drag "rate" value.
149+ # Workarounds https://bugs.launchpad.net/mir/+bug/1399690
150+ rate = 10
151+ divisions = 5
152+ jump = ( width / divisions ) // rate * rate
139− start_x = x + width / 3 * 2
153+ start_x = x + jump * (divisions - 1)
140− stop_x = x + width / 3
154+ stop_x = x + jump
141 start_y = stop_y = y + 1
155 start_y = stop_y = y + 1
142− self.pointing_device.drag(start_x, start_y, stop_x, stop_y)
156+ self.pointing_device.drag(start_x, start_y, stop_x, stop_y, rate)
143 self.dash_content_list.currentIndex.wait_for(original_index + 1)
157 self.dash_content_list.currentIndex.wait_for(original_index + 1)
144
158
145 def enter_search_query(self, query):
159 def enter_search_query(self, query):
tests/mocks/Unity/Application/ApplicationManager.cpp+7
@@ -20,6 +20,7 @@
20#include "ApplicationTestInterface.h"
20#include "ApplicationTestInterface.h"
21
21
22#include <paths.h>
22#include <paths.h>
23+#include <csignal>
23
24
24#include <QDir>
25#include <QDir>
25#include <QGuiApplication>
26#include <QGuiApplication>
@@ -36,6 +37,12 @@ ApplicationManager *ApplicationManager::singleton()
36{
37{
37 if (!the_application_manager) {
38 if (!the_application_manager) {
38 the_application_manager = new ApplicationManager();
39 the_application_manager = new ApplicationManager();
40+
41+ // Emit signal to notify Upstart that Mir is ready to receive client connections
42+ // see http://upstart.ubuntu.com/cookbook/#expect-stop
43+ if (qgetenv("UNITY_MIR_EMITS_SIGSTOP") == "1") {
44+ raise(SIGSTOP);
45+ }
39 }
46 }
40 return the_application_manager;
47 return the_application_manager;
41}
48}
tests/plugins/Dash/horizontaljournaltest.qml+1
@@ -25,6 +25,7 @@ Item {
25 rowHeight: 150
25 rowHeight: 150
26 columnSpacing: 10
26 columnSpacing: 10
27 rowSpacing: 10
27 rowSpacing: 10
28+ cacheBuffer: Math.max(0, (height + displayMarginEnd + displayMarginBeginning) / 2)
28
29
29 delegate: Rectangle {
30 delegate: Rectangle {
30 property real randomValue: Math.random()
31 property real randomValue: Math.random()
tests/plugins/Dash/listviewwithpageheadertest.cpp+1−1
@@ -1920,7 +1920,7 @@ private Q_SLOTS:
1920
1920
1921 void testAllCacheBuffer()
1921 void testAllCacheBuffer()
1922 {
1922 {
1923− lvwph->setCacheBuffer(std::numeric_limits<qreal>::max());
1923+ lvwph->setCacheBuffer(std::numeric_limits<int>::max());
1924 QTRY_COMPARE(lvwph->m_visibleItems.count(), 6);
1924 QTRY_COMPARE(lvwph->m_visibleItems.count(), 6);
1925 QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1925 QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1926 verifyItem(0, 50., 150., false);
1926 verifyItem(0, 50., 150., false);
tests/plugins/Dash/organicgridtest.qml+1
@@ -27,6 +27,7 @@ Item {
27 rowSpacing: 10
27 rowSpacing: 10
28 smallDelegateSize: Qt.size(90, 90)
28 smallDelegateSize: Qt.size(90, 90)
29 bigDelegateSize: Qt.size(180, 180)
29 bigDelegateSize: Qt.size(180, 180)
30+ cacheBuffer: Math.max(0, (height + displayMarginEnd + displayMarginBeginning) / 2)
30
31
31 delegate: Rectangle {
32 delegate: Rectangle {
32 property real randomValue: Math.random()
33 property real randomValue: Math.random()
tests/plugins/Dash/verticaljournaltest.qml+1
@@ -26,6 +26,7 @@ Item {
26 columnWidth: 150
26 columnWidth: 150
27 columnSpacing: 10
27 columnSpacing: 10
28 rowSpacing: 10
28 rowSpacing: 10
29+ cacheBuffer: Math.max(0, (height + displayMarginEnd + displayMarginBeginning) / 2)
29
30
30 delegate: Rectangle {
31 delegate: Rectangle {
31 property real randomValue: Math.random()
32 property real randomValue: Math.random()
tests/qmltests/CMakeLists.txt+1
@@ -23,6 +23,7 @@ add_qml_test(. ShellWithPin ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tes
23add_qml_test(. TabletShell ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/LightDM/full:${CMAKE_BINARY_DIR}/tests/mocks/QMenuModel")
23add_qml_test(. TabletShell ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/LightDM/full:${CMAKE_BINARY_DIR}/tests/mocks/QMenuModel")
24add_qml_test(Components Background)
24add_qml_test(Components Background)
25add_qml_test(Components Carousel)
25add_qml_test(Components Carousel)
26+add_qml_test(Components Dialogs)
26add_qml_test(Components DraggingArea)
27add_qml_test(Components DraggingArea)
27add_qml_test(Components EdgeDemoOverlay)
28add_qml_test(Components EdgeDemoOverlay)
28add_qml_test(Components LazyImage)
29add_qml_test(Components LazyImage)
tests/qmltests/Components/tst_Dialogs.qmlnew file+104
@@ -0,0 +1,104 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.2
18+import QtTest 1.0
19+import Ubuntu.Components 1.1
20+import Unity.Test 0.1
21+
22+import "../../../qml/Components"
23+
24+Rectangle {
25+ id: root
26+ color: "black"
27+ width: units.gu(70)
28+ height: fakeShell.longestDimension
29+
30+ QtObject {
31+ id: fakeUnitySession
32+ signal logoutRequested
33+ signal shutdownRequested
34+ signal rebootRequested
35+ function logout() {}
36+ function shutdown() {}
37+ function reboot() {}
38+ }
39+
40+ Rectangle {
41+ id: fakeShell
42+ color: "green"
43+ readonly property real longestDimension: units.gu(71)
44+ readonly property real shortestDimension: units.gu(40)
45+ readonly property bool landscape: rotation === 90 || rotation === 270
46+ x: (shortestDimension - width) / 2
47+ y: (longestDimension - height) / 2
48+ width: landscape ? longestDimension : shortestDimension
49+ height: landscape ? shortestDimension : longestDimension
50+
51+ Text {
52+ text: "Shell"
53+ color: "black"
54+ anchors.fill: parent
55+ fontSizeMode: Text.Fit
56+ minimumPixelSize: 10
57+ font.pixelSize: 200
58+ verticalAlignment: Text.AlignVCenter
59+ horizontalAlignment: Text.AlignHCenter
60+ }
61+
62+ Dialogs {
63+ id: dialogs
64+ anchors.fill: parent
65+ unitySessionService: fakeUnitySession
66+ closeAllApps: function() {}
67+ }
68+ }
69+
70+ Rectangle {
71+ color: "white"
72+ x: fakeShell.shortestDimension
73+ width: root.width - x
74+ anchors {
75+ top: parent.top
76+ bottom: parent.bottom
77+ }
78+
79+ Column {
80+ anchors { left: parent.left; right: parent.right; top: parent.top; margins: units.gu(1) }
81+ spacing: units.gu(1)
82+ Button { text: "Power dialog"; onClicked: { testCase.showPowerDialog(); } }
83+ Button { text: "Logout Requested"; onClicked: { fakeUnitySession.logoutRequested(); } }
84+ Button { text: "Shutdown Requested"; onClicked: { fakeUnitySession.shutdownRequested(); } }
85+ Button { text: "Reboot Requested"; onClicked: { fakeUnitySession.rebootRequested(); } }
86+ Label { text: "Rotation:" }
87+ Button { text: "0"; onClicked: {fakeShell.rotation = 0;} }
88+ Button { text: "90"; onClicked: {fakeShell.rotation = 90;} }
89+ Button { text: "180"; onClicked: {fakeShell.rotation = 180;} }
90+ Button { text: "270"; onClicked: {fakeShell.rotation = 270;} }
91+ }
92+ }
93+
94+ UnityTestCase {
95+ id: testCase
96+ name: "Dialogs"
97+ when: windowShown
98+
99+ function showPowerDialog() {
100+ var dialogsPrivate = findInvisibleChild(dialogs, "dialogsPrivate");
101+ dialogsPrivate.showPowerDialog();
102+ }
103+ }
104+}
tests/qmltests/Components/tst_DragHandle.cpp+4
@@ -101,6 +101,10 @@ void tst_DragHandle::init()
101 QVERIFY(m_view->rootObject() != 0);
101 QVERIFY(m_view->rootObject() != 0);
102 qApp->processEvents();
102 qApp->processEvents();
103
103
104+ // Hide the controls to ensure we don't hit them accidentally
105+ QQuickItem *controls = m_view->rootObject()->findChild<QQuickItem*>("controls");
106+ controls->setVisible(false);
107+
104 m_fakeTimer = new FakeTimer;
108 m_fakeTimer = new FakeTimer;
105 m_fakeTimeSource.reset(new FakeTimeSource);
109 m_fakeTimeSource.reset(new FakeTimeSource);
106}
110}
tests/qmltests/Components/tst_DragHandle.qml+43−8
@@ -27,8 +27,9 @@ import Ubuntu.Gestures 0.1
27 A black vertical line marks the point where a drag needs no forward velocity to
27 A black vertical line marks the point where a drag needs no forward velocity to
28 achieve auto-completion (i.e., get Showable.show() called after touch release).
28 achieve auto-completion (i.e., get Showable.show() called after touch release).
29 */
29 */
30−Item {
30+Rectangle {
31 id: root
31 id: root
32+ color: "darkblue"
32 width: units.gu(70)
33 width: units.gu(70)
33 height: units.gu(70)
34 height: units.gu(70)
34
35
@@ -36,19 +37,35 @@ Item {
36
37
37 property bool stretch: false
38 property bool stretch: false
38 property real hintDisplacement: 0
39 property real hintDisplacement: 0
40+ property bool bidirectional: false
39
41
40 Item {
42 Item {
41 id: baseItem
43 id: baseItem
42 objectName: "baseItem"
44 objectName: "baseItem"
43 anchors.fill: parent
45 anchors.fill: parent
44
46
47+ Button {
48+ visible: root.bidirectional && bidirectionalShowable.fullyHidden
49+ text: "bidirectionalShowable.show()"
50+ anchors.centerIn: parent
51+ onClicked: { bidirectionalShowable.show(); }
52+ }
53+
54+ BidirectionalShowable {
55+ id: bidirectionalShowable
56+ visible: root.bidirectional
57+ onDragHandleRecognizedGesture: { root.dragHandle = dragHandle }
58+ }
59+
45 VerticalShowable {
60 VerticalShowable {
61+ visible: !root.bidirectional
46 onDragHandleRecognizedGesture: { root.dragHandle = dragHandle }
62 onDragHandleRecognizedGesture: { root.dragHandle = dragHandle }
47 stretch: root.stretch
63 stretch: root.stretch
48 hintDisplacement: root.hintDisplacement
64 hintDisplacement: root.hintDisplacement
49 }
65 }
50
66
51 HorizontalShowable {
67 HorizontalShowable {
68+ visible: !root.bidirectional
52 onDragHandleRecognizedGesture: { root.dragHandle = dragHandle }
69 onDragHandleRecognizedGesture: { root.dragHandle = dragHandle }
53 stretch: root.stretch
70 stretch: root.stretch
54 hintDisplacement: root.hintDisplacement
71 hintDisplacement: root.hintDisplacement
@@ -60,15 +77,28 @@ Item {
60 width: 2
77 width: 2
61 height: parent.height
78 height: parent.height
62
79
63− visible: dragHandle !== undefined && Direction.isHorizontal(dragHandle.direction)
80+ visible: dragHandle !== undefined
81+ && (dragHandle.direction === Direction.Horizontal || dragHandle.direction === Direction.Rightwards)
64
82
65 x: {
83 x: {
66 if (dragHandle) {
84 if (dragHandle) {
85+ dragHandle.edgeDragEvaluator.dragThreshold;
86+ } else {
87+ 0
88+ }
89+ }
90+ }
91+ Rectangle {
92+ color: "black"
93+ width: 2
94+ height: parent.height
95+
96+ visible: dragHandle !== undefined
97+ && (dragHandle.direction === Direction.Horizontal || dragHandle.direction === Direction.Leftwards)
98+
99+ x: {
67− if (dragHandle.direction === Direction.Rightwards) {
100+ if (dragHandle) {
68− dragHandle.edgeDragEvaluator.dragThreshold;
69− } else {
70− parent.width - dragHandle.edgeDragEvaluator.dragThreshold;
101+ parent.width - dragHandle.edgeDragEvaluator.dragThreshold;
71− }
72 } else {
102 } else {
73 0
103 0
74 }
104 }
@@ -126,13 +156,13 @@ Item {
126 }
156 }
127
157
128 Row {
158 Row {
159+ objectName: "controls"
129 anchors.bottom: parent.bottom
160 anchors.bottom: parent.bottom
130 anchors.left: parent.left
161 anchors.left: parent.left
131 anchors.margins: units.gu(1)
162 anchors.margins: units.gu(1)
132 spacing: units.gu(1)
163 spacing: units.gu(1)
133
164
134 Button {
165 Button {
135− id: stretchButton
136 text: root.stretch ? "stretch" : "move"
166 text: root.stretch ? "stretch" : "move"
137 onClicked: { root.stretch = !root.stretch; }
167 onClicked: { root.stretch = !root.stretch; }
138 }
168 }
@@ -158,5 +188,10 @@ Item {
158 }
188 }
159 }
189 }
160 }
190 }
191+
192+ Button {
193+ text: root.bidirectional ? "bidirectional" : "directional"
194+ onClicked: { root.bidirectional = !root.bidirectional; }
195+ }
161 }
196 }
162}
197}
tests/qmltests/Components/tst_DragHandle/BidirectionalShowable.qmlnew file+69
@@ -0,0 +1,69 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.0
18+import "../../../../qml/Components"
19+import Ubuntu.Components 0.1
20+import Ubuntu.Gestures 0.1
21+
22+Item {
23+ id: root
24+ x: 0
25+ width: parent.width
26+ height: parent.height
27+
28+ property bool shown: true
29+
30+ signal dragHandleRecognizedGesture(var dragHandle)
31+
32+ property bool fullyHidden: x == -width || x == width
33+
34+ function show() {
35+ shown = true;
36+ animation.stop();
37+ animation.to = 0;
38+ animation.start();
39+ }
40+
41+ function hide() {
42+ shown = false;
43+ animation.stop();
44+ animation.to = x > 0 ? width : -width;
45+ animation.start();
46+ }
47+
48+ StandardAnimation {
49+ id: animation
50+ target: root
51+ property: "x"
52+ }
53+
54+ Image { source: "../../UnityLogo.png"; anchors.fill: parent }
55+
56+ DragHandle {
57+ id: dragHandle
58+ anchors.fill: parent
59+ direction: Direction.Horizontal
60+ maxTotalDragDistance: root.parent.width
61+ autoCompleteDragThreshold: parent.width / 3
62+
63+ onStatusChanged: {
64+ if (status === DirectionalDragArea.Recognized) {
65+ dragHandleRecognizedGesture(dragHandle);
66+ }
67+ }
68+ }
69+}
tests/qmltests/Dash/tst_Dash.qml+107−11
@@ -70,17 +70,28 @@ Item {
70 waitForRendering(findChild(dash, "scopeLoader0").item);
70 waitForRendering(findChild(dash, "scopeLoader0").item);
71 }
71 }
72
72
73− function get_scope_data() {
73+ function test_manage_dash_clickscope_unfavoritable() {
74− return [
74+ // Show the manage dash
75− { tag: "MockScope1", visualIndex: 0 },
75+ touchFlick(dash, dash.width / 2, dash.height - 1, dash.width / 2, units.gu(2));
76− { tag: "MockScope2", visualIndex: -1 },
76+ var bottomEdgeController = findInvisibleChild(dash, "bottomEdgeController");
77− { tag: "clickscope", visualIndex: 1 },
77+ tryCompare(bottomEdgeController, "progress", 1);
78− { tag: "MockScope5", visualIndex: 2 },
78+
79− ]
79+ // Make sure stuff is loaded
80− }
80+ var favScopesListCategory = findChild(dash, "scopesListCategoryfavorites");
81+ var favScopesListCategoryList = findChild(favScopesListCategory, "scopesListCategoryInnerList");
82+ tryCompare(favScopesListCategoryList, "currentIndex", 0);
83+
84+ // Click scope star area is not visible (i.e. can't be unfavorited)
85+ var clickScope = findChild(favScopesListCategoryList, "delegateclickscope");
86+ var starArea = findChild(clickScope, "starArea");
87+ compare(starArea.visible, false);
81
88
82− function test_show_scope_on_load_data() {
89+ // Go back
83− return get_scope_data()
90+ var scopesList = findChild(dash, "scopesList");
91+ var scopesListPageHeader = findChild(scopesList, "pageHeader");
92+ var backButton = findChild(findChild(scopesListPageHeader, "innerPageHeader"), "backButton");
93+ mouseClick(backButton, 0, 0);
94+ tryCompare(bottomEdgeController, "progress", 0);
84 }
95 }
85
96
86 function test_manage_dash_select_same_favorite() {
97 function test_manage_dash_select_same_favorite() {
@@ -306,7 +317,7 @@ Item {
306 spy.target = scopesList.scope;
317 spy.target = scopesList.scope;
307 spy.signalName = "performQuery";
318 spy.signalName = "performQuery";
308
319
309− // Do a search
320+ // Click on the store
310 var scopesListPageHeader = findChild(scopesList, "pageHeader");
321 var scopesListPageHeader = findChild(scopesList, "pageHeader");
311 var searchButton = findChild(scopesListPageHeader, "store_header_button");
322 var searchButton = findChild(scopesListPageHeader, "store_header_button");
312 mouseClick(searchButton, 0, 0);
323 mouseClick(searchButton, 0, 0);
@@ -315,5 +326,90 @@ Item {
315 compare(spy.signalArguments[0][0], "scope://com.canonical.scopes.clickstore");
326 compare(spy.signalArguments[0][0], "scope://com.canonical.scopes.clickstore");
316 tryCompare(bottomEdgeController, "progress", 0);
327 tryCompare(bottomEdgeController, "progress", 0);
317 }
328 }
329+
330+ function test_manage_dash_move_current() {
331+ var dashContentList = findChild(dash, "dashContentList");
332+ compare(dashContentList.currentIndex, 0);
333+ compare(dashContentList.currentItem.scopeId, "MockScope1");
334+
335+ // Show the manage dash
336+ touchFlick(dash, dash.width / 2, dash.height - 1, dash.width / 2, units.gu(2));
337+ var bottomEdgeController = findInvisibleChild(dash, "bottomEdgeController");
338+ tryCompare(bottomEdgeController, "progress", 1);
339+
340+ // Make sure stuff is loaded
341+ var favScopesListCategory = findChild(dash, "scopesListCategoryfavorites");
342+ var favScopesListCategoryList = findChild(favScopesListCategory, "scopesListCategoryInnerList");
343+ tryCompare(favScopesListCategoryList, "currentIndex", 0);
344+
345+ // Enter edit mode
346+ var scopesList = findChild(dash, "scopesList");
347+ var clickScope = findChild(favScopesListCategoryList, "delegateclickscope");
348+ mousePress(clickScope, 0, 0);
349+ tryCompare(scopesList, "state", "edit");
350+ mouseRelease(clickScope, 0, 0);
351+
352+ var starArea = findChild(clickScope, "starArea");
353+ touchFlick(starArea, 0, 0, 0, -units.gu(10));
354+
355+ // Exit edit mode and go back
356+ var scopesList = findChild(dash, "scopesList");
357+ var scopesListPageHeader = findChild(scopesList, "pageHeader");
358+ var backButton = findChild(findChild(scopesListPageHeader, "innerPageHeader"), "backButton");
359+ mouseClick(backButton, 0, 0);
360+ mouseClick(backButton, 0, 0);
361+ tryCompare(bottomEdgeController, "progress", 0);
362+
363+ tryCompare(dashContentList, "currentIndex", 0);
364+ compare(dashContentList.currentItem.scopeId, "clickscope");
365+
366+ // Move to second scope
367+ touchFlick(dash, dash.width / 2, units.gu(2), dash.width / 5, units.gu(2));
368+ tryCompare(dashContentList, "currentIndex", 1);
369+ compare(dashContentList.currentItem.scopeId, "MockScope1");
370+ }
371+
372+ function test_manage_dash_move_current_click_other() {
373+ var dashContentList = findChild(dash, "dashContentList");
374+ compare(dashContentList.currentIndex, 0);
375+ compare(dashContentList.currentItem.scopeId, "MockScope1");
376+
377+ // Show the manage dash
378+ touchFlick(dash, dash.width / 2, dash.height - 1, dash.width / 2, units.gu(2));
379+ var bottomEdgeController = findInvisibleChild(dash, "bottomEdgeController");
380+ tryCompare(bottomEdgeController, "progress", 1);
381+
382+ // Make sure stuff is loaded
383+ var favScopesListCategory = findChild(dash, "scopesListCategoryfavorites");
384+ var favScopesListCategoryList = findChild(favScopesListCategory, "scopesListCategoryInnerList");
385+ tryCompare(favScopesListCategoryList, "currentIndex", 0);
386+
387+ // Enter edit mode
388+ var scopesList = findChild(dash, "scopesList");
389+ var clickScope = findChild(favScopesListCategoryList, "delegateclickscope");
390+ mousePress(clickScope, 0, 0);
391+ tryCompare(scopesList, "state", "edit");
392+ mouseRelease(clickScope, 0, 0);
393+
394+ var starArea = findChild(clickScope, "starArea");
395+ touchFlick(starArea, 0, 0, 0, -units.gu(10));
396+
397+ // wait for the animation to settle
398+ tryCompare(clickScope, "height", units.gu(6));
399+
400+ // Exit edit mode
401+ var scopesList = findChild(dash, "scopesList");
402+ var scopesListPageHeader = findChild(scopesList, "pageHeader");
403+ var backButton = findChild(findChild(scopesListPageHeader, "innerPageHeader"), "backButton");
404+ mouseClick(backButton, 0, 0);
405+
406+ // Click on third scope
407+ var mockScope5 = findChild(favScopesListCategoryList, "delegateMockScope5");
408+ waitForRendering(mockScope5)
409+ mouseClick(mockScope5, 0, 0);
410+ tryCompare(bottomEdgeController, "progress", 0);
411+ tryCompare(dashContentList, "currentIndex", 2);
412+ compare(dashContentList.currentItem.scopeId, "MockScope5");
413+ }
318 }
414 }
319}
415}
tests/qmltests/Dash/tst_GenericScopeView.qml+2
@@ -59,6 +59,7 @@ Item {
59 GenericScopeView {
59 GenericScopeView {
60 id: genericScopeView
60 id: genericScopeView
61 anchors.fill: parent
61 anchors.fill: parent
62+ visibleToParent: true
62
63
63 UT.UnityTestCase {
64 UT.UnityTestCase {
64 id: testCase
65 id: testCase
@@ -574,6 +575,7 @@ Item {
574 var innerHeader = findChild(header, "innerPageHeader");
575 var innerHeader = findChild(header, "innerPageHeader");
575 verify(innerHeader, "Could not find the inner header");
576 verify(innerHeader, "Could not find the inner header");
576
577
578+ expectFail("Apps", "Click scope should not have a favorite button");
577 var favoriteAction = findChild(innerHeader, "favorite_header_button");
579 var favoriteAction = findChild(innerHeader, "favorite_header_button");
578 verify(favoriteAction, "Could not find the favorite action.");
580 verify(favoriteAction, "Could not find the favorite action.");
579 mouseClick(favoriteAction, favoriteAction.width / 2, favoriteAction.height / 2);
581 mouseClick(favoriteAction, favoriteAction.width / 2, favoriteAction.height / 2);
tests/qmltests/Greeter/tst_MultiGreeter.qml+15−15
@@ -56,9 +56,9 @@ Item {
56 }
56 }
57
57
58 SignalSpy {
58 SignalSpy {
59− id: teaseSpy
59+ id: tappedSpy
60 target: greeter
60 target: greeter
61− signalName: "tease"
61+ signalName: "tapped"
62 }
62 }
63
63
64 UT.UnityTestCase {
64 UT.UnityTestCase {
@@ -323,18 +323,18 @@ Item {
323 compare(greeter.model.data(index, LightDM.UserRoles.BackgroundPathRole), "")
323 compare(greeter.model.data(index, LightDM.UserRoles.BackgroundPathRole), "")
324 }
324 }
325
325
326− function test_teasingArea_data() {
326+ function test_tappedSignal_data() {
327 return [
327 return [
328− {tag: "left", posX: units.gu(2), leftPressed: true, rightPressed: false},
328+ {tag: "left", posX: units.gu(2)},
329− {tag: "right", posX: greeter.width - units.gu(2), leftPressed: false, rightPressed: true}
329+ {tag: "right", posX: greeter.width - units.gu(2)}
330 ]
330 ]
331 }
331 }
332
332
333− function test_teasingArea(data) {
333+ function test_tappedSignal(data) {
334− teaseSpy.clear()
334+ select_user("no-password");
335+ tappedSpy.clear();
335− mouseClick(greeter, data.posX, greeter.height - units.gu(1))
336+ tap(greeter, data.posX, greeter.height - units.gu(1))
336− teaseSpy.wait()
337− tryCompare(teaseSpy, "count", 1)
337+ tryCompare(tappedSpy, "count", 1)
338 }
338 }
339
339
340 function test_teaseLockedUnlocked_data() {
340 function test_teaseLockedUnlocked_data() {
@@ -345,18 +345,18 @@ Item {
345 }
345 }
346
346
347 function test_teaseLockedUnlocked(data) {
347 function test_teaseLockedUnlocked(data) {
348− teaseSpy.clear()
348+ tappedSpy.clear()
349 greeter.locked = data.locked;
349 greeter.locked = data.locked;
350
350
351− mouseClick(greeter, greeter.width - units.gu(5), greeter.height - units.gu(1));
351+ tap(greeter, greeter.width - units.gu(5), greeter.height - units.gu(1));
352
352
353 if (!data.locked || data.narrow) {
353 if (!data.locked || data.narrow) {
354− teaseSpy.wait()
354+ tappedSpy.wait()
355− tryCompare(teaseSpy, "count", 1);
355+ tryCompare(tappedSpy, "count", 1);
356 } else {
356 } else {
357 // waiting 100ms to make sure nothing happens
357 // waiting 100ms to make sure nothing happens
358 wait(100);
358 wait(100);
359− compare(teaseSpy.count, 0, "Greeter teasing not disabled even though it's locked.");
359+ compare(tappedSpy.count, 0, "Greeter teasing not disabled even though it's locked.");
360 }
360 }
361
361
362 // Reset value
362 // Reset value
tests/qmltests/Greeter/tst_SingleGreeter.qml+104−16
@@ -23,10 +23,20 @@ import LightDM 0.1 as LightDM
23import Ubuntu.Components 0.1
23import Ubuntu.Components 0.1
24import Unity.Test 0.1 as UT
24import Unity.Test 0.1 as UT
25
25
26−Item {
26+Rectangle {
27+ color: "darkblue"
27 width: units.gu(60)
28 width: units.gu(60)
28 height: units.gu(80)
29 height: units.gu(80)
29
30
31+ Button {
32+ anchors.centerIn: parent
33+ text: "Show Greeter"
34+ onClicked: {
35+ if (greeterLoader.item)
36+ greeterLoader.item.show();
37+ }
38+ }
39+
30 Loader {
40 Loader {
31 id: greeterLoader
41 id: greeterLoader
32 anchors.fill: parent
42 anchors.fill: parent
@@ -35,15 +45,8 @@ Item {
35
45
36 sourceComponent: Component {
46 sourceComponent: Component {
37 Greeter {
47 Greeter {
38− anchors.fill: greeterLoader
48+ width: greeterLoader.width
39−
49+ height: greeterLoader.height
40− property int minX: 0
41−
42− onXChanged: {
43− if (x < minX) {
44− minX = x;
45− }
46− }
47
50
48 Component.onDestruction: {
51 Component.onDestruction: {
49 greeterLoader.itemDestroyed = true;
52 greeterLoader.itemDestroyed = true;
@@ -64,9 +67,9 @@ Item {
64 }
67 }
65
68
66 SignalSpy {
69 SignalSpy {
67− id: teaseSpy
70+ id: tappedSpy
68 target: greeterLoader.item
71 target: greeterLoader.item
69− signalName: "tease"
72+ signalName: "tapped"
70 }
73 }
71
74
72 SignalSpy {
75 SignalSpy {
@@ -90,9 +93,11 @@ Item {
90 tryCompare(greeterLoader, "itemDestroyed", true);
93 tryCompare(greeterLoader, "itemDestroyed", true);
91
94
92 unlockSpy.clear();
95 unlockSpy.clear();
93− teaseSpy.clear();
96+ tappedSpy.clear();
94
97
95 greeterLoader.active = true;
98 greeterLoader.active = true;
99+ tryCompare(greeterLoader, "status", Loader.Ready);
100+ removeTimeConstraintsFromDirectionalDragAreas(greeterLoader.item);
96 }
101 }
97
102
98 function test_properties() {
103 function test_properties() {
@@ -108,10 +113,10 @@ Item {
108 }
113 }
109
114
110 function test_teasingArea(data) {
115 function test_teasingArea(data) {
111− teaseSpy.clear()
116+ tappedSpy.clear()
112 tap(greeter, data.posX, greeter.height - units.gu(1))
117 tap(greeter, data.posX, greeter.height - units.gu(1))
113− teaseSpy.wait()
118+ tappedSpy.wait()
114− tryCompare(teaseSpy, "count", 1)
119+ tryCompare(tappedSpy, "count", 1)
115 }
120 }
116
121
117 function test_statsWelcomeScreen() {
122 function test_statsWelcomeScreen() {
@@ -152,5 +157,88 @@ Item {
152
157
153 tryCompare(infographicDataChangedSpy, "count", 1);
158 tryCompare(infographicDataChangedSpy, "count", 1);
154 }
159 }
160+
161+ function test_movesBackIntoPlaceWhenNotDraggedFarEnough() {
162+
163+ var dragEvaluator = findInvisibleChild(greeter, "edgeDragEvaluator");
164+ verify(dragEvaluator);
165+
166+ // Make it easier to get a rejection/rollback. Otherwise would have to inject
167+ // a fake timer into dragEvaluator.
168+ // Afterall, we are testing if the Greeter indeed moves back on a
169+ // rollback decision, not the drag evaluation itself.
170+ dragEvaluator.minDragDistance = dragEvaluator.maxDragDistance / 2;
171+
172+ // it starts as fully shown
173+ compare(greeter.x, 0);
174+
175+ // then we drag it a bit
176+ var startX = greeter.width - 1;
177+ var touchY = greeter.height / 2;
178+ var dragXDelta = -(dragEvaluator.minDragDistance * 0.3);
179+ touchFlick(greeter,
180+ startX , touchY, // start pos
181+ startX + dragXDelta, touchY, // end pos
182+ true /* beginTouch */, false /* endTouch */);
183+
184+ // which should make it move a bit
185+ tryCompareFunction(function(){return greeter.x < 0;}, true);
186+
187+ // then we release it
188+ touchRelease(greeter, startX + dragXDelta, touchY);
189+
190+ // which should make it move back into its original position as it didn't move
191+ // far enough to have it hidden
192+ tryCompare(greeter, "x", 0);
193+ }
194+
195+ function test_dragToHide_data() {
196+ return [
197+ {tag: "left", startX: greeter.width * 0.95, endX: greeter.width * 0.1, hiddenX: -greeter.width},
198+ {tag: "right", startX: greeter.width * 0.1, endX: greeter.width * 0.95, hiddenX: greeter.width},
199+ ];
200+ }
201+ function test_dragToHide(data) {
202+ compare(greeter.x, 0);
203+ compare(greeter.visible, true);
204+ compare(greeter.shown, true);
205+ compare(greeter.showProgress, 1);
206+
207+ touchFlick(greeter,
208+ data.startX, greeter.height / 2, // start pos
209+ data.endX, greeter.height / 2); // end pos
210+
211+ tryCompare(greeter, "x", data.hiddenX);
212+ tryCompare(greeter, "visible", false);
213+ tryCompare(greeter, "shown", false);
214+ tryCompare(greeter, "showProgress", 0);
215+ }
216+
217+ function test_hiddenGreeterRemainsHiddenAfterResize_data() {
218+ return [
219+ {tag: "left", startX: greeter.width * 0.95, endX: greeter.width * 0.1},
220+ {tag: "right", startX: greeter.width * 0.1, endX: greeter.width * 0.95},
221+ ];
222+ }
223+ function test_hiddenGreeterRemainsHiddenAfterResize(data) {
224+ touchFlick(greeter,
225+ data.startX, greeter.height / 2, // start pos
226+ data.endX, greeter.height / 2); // end pos
227+
228+ tryCompare(greeter, "x", data.tag == "left" ? -greeter.width : greeter.width);
229+ tryCompare(greeter, "visible", false);
230+ tryCompare(greeter, "shown", false);
231+ tryCompare(greeter, "showProgress", 0);
232+
233+ // flip dimensions to simulate an orientation change
234+ greeter.width = greeterLoader.height;
235+ greeter.height = greeterLoader.width;
236+
237+ // All properties should remain consistent
238+ tryCompare(greeter, "x", data.tag == "left" ? -greeter.width : greeter.width);
239+ tryCompare(greeter, "visible", false);
240+ tryCompare(greeter, "shown", false);
241+ tryCompare(greeter, "showProgress", 0);
242+ }
155 }
243 }
156}
244}
tests/qmltests/tst_TabletShell.qml+15−12
@@ -74,21 +74,24 @@ Row {
74 Column {
74 Column {
75 anchors { left: parent.left; right: parent.right; top: parent.top; margins: units.gu(1) }
75 anchors { left: parent.left; right: parent.right; top: parent.top; margins: units.gu(1) }
76 spacing: units.gu(1)
76 spacing: units.gu(1)
77− Row {
78− anchors { left: parent.left; right: parent.right }
79− Button {
77+ Button {
80− text: "Show Greeter"
78+ text: "Show Greeter"
81− onClicked: {
79+ onClicked: {
82− if (shellLoader.status !== Loader.Ready)
80+ if (shellLoader.status !== Loader.Ready)
83− return
81+ return
84−
82+
85− var greeter = testCase.findChild(shellLoader.item, "greeter")
83+ var greeter = testCase.findChild(shellLoader.item, "greeter")
86− if (!greeter.shown) {
84+ if (!greeter.shown) {
87− greeter.show()
85+ greeter.show()
88− }
89 }
86 }
90 }
87 }
91 }
88 }
89+ Button {
90+ text: "Demo edges"
91+ onClicked: {
92+ AccountsService.demoEdges = true
93+ }
94+ }
92 }
95 }
93 }
96 }
94
97