on xenial help sign in
Untested merge from trunk
936045aMichael Terry
CMakeLists.txt+13−2
@@ -57,12 +57,24 @@ find_package(Qt5DBus 5.4 REQUIRED)
57find_package(Qt5Concurrent 5.4 REQUIRED)
57find_package(Qt5Concurrent 5.4 REQUIRED)
58find_package(Qt5Sql 5.4 REQUIRED)
58find_package(Qt5Sql 5.4 REQUIRED)
59
59
60−pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=16)
60+pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=17)
61pkg_check_modules(GEONAMES REQUIRED geonames>=0.2)
61pkg_check_modules(GEONAMES REQUIRED geonames>=0.2)
62pkg_check_modules(GIO REQUIRED gio-2.0>=2.32)
62pkg_check_modules(GIO REQUIRED gio-2.0>=2.32)
63pkg_check_modules(GLIB REQUIRED glib-2.0>=2.32)
63pkg_check_modules(GLIB REQUIRED glib-2.0>=2.32)
64pkg_check_modules(QMENUMODEL REQUIRED qmenumodel)
64pkg_check_modules(QMENUMODEL REQUIRED qmenumodel)
65
65
66+pkg_check_modules(UBUNTUGESTURES REQUIRED UbuntuGestures)
67+
68+### Check UbuntuGestures private headers. No pkg-config (.pc) file is provided for them
69+find_path(UBUNTUGESTUREPRIV
70+ NAMES UbuntuGestures/private/damper_p.h UbuntuGestures/private/ucswipearea_p.h UbuntuGestures/private/ucswipearea_p_p.h
71+ PATHS ${UBUNTUGESTURES_INCLUDEDIR}/UbuntuGestures/${UBUNTUGESTURES_VERSION}
72+ NO_DEFAULT_PATH)
73+if (${UBUNTUGESTUREPRIV} STREQUAL UBUNTUGESTUREPRIV-NOTFOUND)
74+ message(FATAL_ERROR "UbuntuGestures private headers not found.")
75+endif()
76+# end of UbuntuGesture private headers check
77+
66# Standard install paths
78# Standard install paths
67include(GNUInstallDirs)
79include(GNUInstallDirs)
68
80
@@ -144,7 +156,6 @@ endif()
144
156
145# add subdirectories to build
157# add subdirectories to build
146add_subdirectory(include)
158add_subdirectory(include)
147−add_subdirectory(libs)
148add_subdirectory(src)
159add_subdirectory(src)
149add_subdirectory(tools)
160add_subdirectory(tools)
150add_subdirectory(qml)
161add_subdirectory(qml)
debian/changelog+85
@@ -1,3 +1,88 @@
1+unity8 (8.12+16.10.20160527-0ubuntu1) yakkety; urgency=medium
2+
3+ [ Albert Astals Cid ]
4+ * Activate on click for SimpleMessages (LP: #1421696)
5+ * Add override
6+ * Change the art back to the cardData value if it changes from broken
7+ to valid image (LP: #1533577)
8+ * Concierge mode generated code optimization
9+ * Don't use context properties but properties of the delegates
10+ * Listen to contentItem::widthChanged instead of
11+ Flickable::contentWidthChanged (LP: #1565763)
12+ * Make some AP code faster
13+ * Make tests a bit more stable
14+ * Make unity8 and unity8-dash handle termination signals
15+ * Remove workaround not needed anymore (LP: #1475643)
16+ * Resolve cardArtStyle on compile time
17+ * Set the theme earlier (LP: #1574048)
18+
19+ [ Albert Astals Cid, Daniel d'Andrada ]
20+ * Remove DirectionalDragArea and libs/UbuntuGestures and port to SDK
21+ equivalents
22+
23+ [ Andrea Cimitan ]
24+ * Hide the preview review input field when a rating is required (LP:
25+ #1541971)
26+
27+ [ CI Train Bot ]
28+ * Resync trunk.
29+
30+ [ Daniel d'Andrada ]
31+ * Fix DragHandle so it works in all directions
32+ * Support animated cursors
33+ * WindowInputMonitor - also map Qt::Key_HomePage to our home key
34+ * plugins/Cursor: properly register to the screen's QPlatformCursor
35+ when screen changes (LP: #1579742)
36+
37+ [ Josh Arenson ]
38+ * Close the PageHeaderExtraPanel when a filter option is selected (LP:
39+ #1569498)
40+ * Wrap primaryFilter in a flickable to make it behave nicely. (LP:
41+ #1569492)
42+
43+ [ Lukáš Tinkl ]
44+ * First snap decision should always be expanded, unless user decides
45+ otherwise (LP: #1580090, #1575045)
46+ * Fullscreen notification bug fixes (LP: #1583944, #1581498, #1422711)
47+ * Implement maximizing windows horizontally/vertically
48+ * Lock the session when putting the laptop into sleep (LP: #1581063)
49+
50+ [ Lukáš Tinkl, Michael Terry ]
51+ * With a maximized window, "dragging" the panel down should restore it
52+
53+ [ Michael Terry ]
54+ * Change some dash button colors from orange to green. (LP: #1581047)
55+ * Use PageHeader instead Ambiance's PageHeadStyle
56+ * Use new setTimeZone method to set user-friendly timezone name in the
57+ wizard. (LP: #1566295)
58+
59+ [ Michael Zanetti ]
60+ * Remove the background dimming when the launcher is revealed by a
61+ drag (LP: #1575137)
62+ * reenable or drop disabled tests
63+
64+ -- Michael Terry <michael.terry@canonical.com> Fri, 27 May 2016 13:54:44 +0000
65+
66+unity8 (8.12+16.10.20160520.1-0ubuntu1) yakkety; urgency=medium
67+
68+ [ Lukáš Tinkl ]
69+ * Don't dim screen when the indicators are open (LP: #1564342)
70+ * Fix upcoming alarms ETA labels (LP: #1576741)
71+ * Stabilize flaky wizard tests (LP: #1582994)
72+
73+ [ Michael Zanetti ]
74+ * fix the SIM PIN darkening after it got removed accidentally (LP:
75+ #1577147)
76+
77+ [ Michał Sawicz, Nick Dedekind ]
78+ * Fixed saving current stage and loss of surface focus when switching
79+ stages
80+
81+ [ Nick Dedekind ]
82+ * Fixed incorrect osk surface item resizing the surface.
83+
84+ -- Michał Sawicz <michal.sawicz@canonical.com> Fri, 20 May 2016 08:44:19 +0000
85+
1unity8 (8.12+16.04.20160518.1-0ubuntu1) xenial; urgency=medium
86unity8 (8.12+16.04.20160518.1-0ubuntu1) xenial; urgency=medium
2
87
3 [ CI Train Bot ]
88 [ CI Train Bot ]
debian/control+5−3
@@ -30,8 +30,10 @@ Build-Depends: cmake,
30 libqt5svg5-dev,
30 libqt5svg5-dev,
31 libqt5xmlpatterns5-dev,
31 libqt5xmlpatterns5-dev,
32 libsystemsettings-dev,
32 libsystemsettings-dev,
33+ libubuntugestures5-dev,
34+ libubuntugestures5-private-dev,
33 libudev-dev,
35 libudev-dev,
34− libunity-api-dev (>= 7.112),
36+ libunity-api-dev (>= 7.113),
35 libusermetricsoutput1-dev,
37 libusermetricsoutput1-dev,
36# Need those X11 libs touch emulation from mouse events in manual QML tests on a X11 desktop
38# Need those X11 libs touch emulation from mouse events in manual QML tests on a X11 desktop
37 libx11-dev[!armhf],
39 libx11-dev[!armhf],
@@ -108,7 +110,7 @@ Depends: dmz-cursor-theme,
108 qtdeclarative5-qtmir-plugin (>= 0.4.8),
110 qtdeclarative5-qtmir-plugin (>= 0.4.8),
109 qtdeclarative5-ubuntu-telephony0.1,
111 qtdeclarative5-ubuntu-telephony0.1,
110 qtdeclarative5-ubuntu-web-plugin,
112 qtdeclarative5-ubuntu-web-plugin,
111− ubuntu-system-settings,
113+ ubuntu-system-settings (>= 0.4),
112 unity-launcher-impl-7,
114 unity-launcher-impl-7,
113 unity8-common (= ${source:Version}),
115 unity8-common (= ${source:Version}),
114 unity8-private (= ${binary:Version}),
116 unity8-private (= ${binary:Version}),
@@ -135,7 +137,7 @@ Depends: qml-module-qtquick-layouts,
135 qtdeclarative5-ubuntu-ui-toolkit-plugin (>= 1.3.1845) | qtdeclarative5-ubuntu-ui-toolkit-plugin-gles (>= 1.3.1845),
137 qtdeclarative5-ubuntu-ui-toolkit-plugin (>= 1.3.1845) | qtdeclarative5-ubuntu-ui-toolkit-plugin-gles (>= 1.3.1845),
136 qtdeclarative5-unity-notifications-plugin (>= 0.1.2) | unity-notifications-impl,
138 qtdeclarative5-unity-notifications-plugin (>= 0.1.2) | unity-notifications-impl,
137 ubuntu-thumbnailer-impl-0,
139 ubuntu-thumbnailer-impl-0,
138− unity-application-impl-16,
140+ unity-application-impl-17,
139 unity-notifications-impl-3,
141 unity-notifications-impl-3,
140 unity-plugin-scopes | unity-scopes-impl,
142 unity-plugin-scopes | unity-scopes-impl,
141 unity-scopes-impl-12,
143 unity-scopes-impl-12,
debian/unity8-private.install−1
@@ -1,5 +1,4 @@
1usr/lib/*/libunity8-private.*
1usr/lib/*/libunity8-private.*
2−usr/lib/*/unity8/libUbuntuGestures*
3usr/lib/*/unity8/qml/AccountsService
2usr/lib/*/unity8/qml/AccountsService
4usr/lib/*/unity8/qml/Cursor
3usr/lib/*/unity8/qml/Cursor
5usr/lib/*/unity8/qml/Dash
4usr/lib/*/unity8/qml/Dash
libs/CMakeLists.txtdeleted−1
@@ -1 +0,0 @@
1−add_subdirectory(UbuntuGestures)
libs/UbuntuGestures/CMakeLists.txtdeleted−41
@@ -1,41 +0,0 @@
1−# in order to include Qt's private headers
2−remove_definitions(-DQT_NO_KEYWORDS)
3−
4−set(UbuntuGestures_SOURCES
5− CandidateInactivityTimer.cpp
6− DebugHelpers.cpp
7− Timer.cpp
8− TimeSource.cpp
9− TouchOwnershipEvent.cpp
10− TouchRegistry.cpp
11− UnownedTouchEvent.cpp
12−)
13−
14−add_definitions(-DUBUNTUGESTURES_LIBRARY)
15−
16−add_library(UbuntuGestures SHARED ${UbuntuGestures_SOURCES})
17−
18−qt5_use_modules(UbuntuGestures Core Quick)
19−
20−# So that Foo.cpp can #include "Foo.moc"
21−include_directories(${CMAKE_CURRENT_BINARY_DIR})
22−
23−install(TARGETS UbuntuGestures
24− DESTINATION ${SHELL_PRIVATE_LIBDIR})
25−
26−
27−# There's no cmake var for v8 include path :-/ so create one
28−LIST(GET Qt5Core_INCLUDE_DIRS 0 QtCoreDir0)
29−if(${Qt5Core_VERSION_STRING} VERSION_LESS "5.1.0")
30− SET(Qt5V8_PRIVATE_INCLUDE_DIR ${QtCoreDir0}/../QtV8/${Qt5Core_VERSION_STRING}/QtV8)
31−else()
32− SET(Qt5V8_PRIVATE_INCLUDE_DIR ${QtCoreDir0}/QtV8/${Qt5Core_VERSION_STRING}/QtV8)
33−endif()
34−
35−# DANGER! DANGER! Using Qt's private API!
36−include_directories(
37− ${Qt5Qml_PRIVATE_INCLUDE_DIRS}
38− ${Qt5Quick_INCLUDE_DIRS}
39− ${Qt5Quick_PRIVATE_INCLUDE_DIRS}
40− ${Qt5V8_PRIVATE_INCLUDE_DIR}
41−)
libs/UbuntuGestures/CandidateInactivityTimer.cppdeleted−46
@@ -1,46 +0,0 @@
1−/*
2− * Copyright (C) 2014 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#include "CandidateInactivityTimer.h"
18−
19−namespace UbuntuGestures {
20−
21−CandidateInactivityTimer::CandidateInactivityTimer(int touchId, QQuickItem *candidate,
22− AbstractTimer *timer, QObject *parent)
23− : QObject(parent)
24− , m_timer(timer)
25− , m_touchId(touchId)
26− , m_candidate(candidate)
27−{
28− connect(m_timer, &AbstractTimer::timeout,
29− this, &CandidateInactivityTimer::onTimeout);
30− m_timer->setInterval(durationMs);
31− m_timer->setSingleShot(true);
32− m_timer->start();
33−}
34−
35−CandidateInactivityTimer::~CandidateInactivityTimer()
36−{
37− delete m_timer;
38−}
39−
40−void CandidateInactivityTimer::onTimeout()
41−{
42− qWarning("[TouchRegistry] Candidate for touch %d defaulted!", m_touchId);
43− Q_EMIT candidateDefaulted(m_touchId, m_candidate);
44−}
45−
46−} // namespace UbuntuGestures
libs/UbuntuGestures/CandidateInactivityTimer.hdeleted−51
@@ -1,51 +0,0 @@
1−/*
2− * Copyright (C) 2014 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#ifndef UBUNTUGESTURES_CANDIDATE_INACTIVITY_TIMER_H
18−#define UBUNTUGESTURES_CANDIDATE_INACTIVITY_TIMER_H
19−
20−#include <QObject>
21−
22−class QQuickItem;
23−
24−#include "Timer.h"
25−
26−namespace UbuntuGestures {
27−
28−class UBUNTUGESTURES_EXPORT CandidateInactivityTimer : public QObject {
29− Q_OBJECT
30−public:
31− CandidateInactivityTimer(int touchId, QQuickItem *candidate,
32− AbstractTimer *timer,
33− QObject *parent = nullptr);
34−
35− virtual ~CandidateInactivityTimer();
36−
37− const int durationMs = 1000;
38−
39−Q_SIGNALS:
40− void candidateDefaulted(int touchId, QQuickItem *candidate);
41−private Q_SLOTS:
42− void onTimeout();
43−private:
44− AbstractTimer *m_timer;
45− int m_touchId;
46− QQuickItem *m_candidate;
47−};
48−
49−} // namespace UbuntuGestures
50−
51−#endif // UBUNTUGESTURES_CANDIDATE_INACTIVITY_TIMER_H
libs/UbuntuGestures/DebugHelpers.cppdeleted−95
@@ -1,95 +0,0 @@
1−/*
2− * Copyright (C) 2014 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#include "DebugHelpers.h"
18−#include <QTouchEvent>
19−#include <QMouseEvent>
20−
21−QString touchPointStateToString(Qt::TouchPointState state)
22−{
23− switch (state) {
24− case Qt::TouchPointPressed:
25− return QStringLiteral("pressed");
26− case Qt::TouchPointMoved:
27− return QStringLiteral("moved");
28− case Qt::TouchPointStationary:
29− return QStringLiteral("stationary");
30− case Qt::TouchPointReleased:
31− return QStringLiteral("released");
32− default:
33− return QStringLiteral("INVALID_STATE");
34− }
35−}
36−
37−QString touchEventToString(const QTouchEvent *ev)
38−{
39− QString message;
40−
41− switch (ev->type()) {
42− case QEvent::TouchBegin:
43− message.append("TouchBegin ");
44− break;
45− case QEvent::TouchUpdate:
46− message.append("TouchUpdate ");
47− break;
48− case QEvent::TouchEnd:
49− message.append("TouchEnd ");
50− break;
51− case QEvent::TouchCancel:
52− message.append("TouchCancel ");
53− break;
54− default:
55− message.append("INVALID_TOUCH_EVENT_TYPE ");
56− }
57−
58− foreach(const QTouchEvent::TouchPoint& touchPoint, ev->touchPoints()) {
59− message.append(
60− QStringLiteral("(id:%1, state:%2, scenePos:(%3,%4)) ")
61− .arg(touchPoint.id())
62− .arg(touchPointStateToString(touchPoint.state()))
63− .arg(touchPoint.scenePos().x())
64− .arg(touchPoint.scenePos().y())
65− );
66− }
67−
68− return message;
69−}
70−
71−QString mouseEventToString(const QMouseEvent *ev)
72−{
73− QString message;
74−
75− switch (ev->type()) {
76− case QEvent::MouseButtonPress:
77− message.append("MouseButtonPress ");
78− break;
79− case QEvent::MouseButtonRelease:
80− message.append("MouseButtonRelease ");
81− break;
82− case QEvent::MouseButtonDblClick:
83− message.append("MouseButtonDblClick ");
84− break;
85− case QEvent::MouseMove:
86− message.append("MouseMove ");
87− break;
88− default:
89− message.append("INVALID_MOUSE_EVENT_TYPE ");
90− }
91−
92− message.append(QStringLiteral("pos(%1, %2)").arg(ev->x()).arg(ev->y()));
93−
94− return message;
95−}
libs/UbuntuGestures/DebugHelpers.hdeleted−31
@@ -1,31 +0,0 @@
1−/*
2− * Copyright (C) 2014 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#ifndef UBUNTUGESTURES_DEBUG_HELPER_H
18−#define UBUNTUGESTURES_DEBUG_HELPER_H
19−
20−#include <QString>
21−
22−#include "UbuntuGesturesGlobal.h"
23−
24−class QMouseEvent;
25−class QTouchEvent;
26−
27−UBUNTUGESTURES_EXPORT QString touchPointStateToString(Qt::TouchPointState state);
28−UBUNTUGESTURES_EXPORT QString touchEventToString(const QTouchEvent *ev);
29−UBUNTUGESTURES_EXPORT QString mouseEventToString(const QMouseEvent *ev);
30−
31−#endif // UBUNTUGESTURES_DEBUG_HELPER_H
libs/UbuntuGestures/Pool.hdeleted−124
@@ -1,124 +0,0 @@
1−/*
2− * Copyright (C) 2014 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#ifndef UBUNTUGESTURES_POOL_H
18−#define UBUNTUGESTURES_POOL_H
19−
20−#include <QVector>
21−
22−#include "UbuntuGesturesGlobal.h"
23−
24−/*
25− An object pool.
26− Avoids unnecessary creations/initializations and deletions/destructions of items. Useful
27− in a scenario where items are created and destroyed very frequently but the total number
28− of items at any given time remains small. They're stored in a unordered fashion.
29−
30− To be used in Pool, ItemType needs to have the following methods:
31−
32− - ItemType();
33−
34− A constructor that takes no parameters. An object contructed with it must return false if
35− isValid() is called.
36−
37− - bool isValid() const;
38−
39− Returns wheter the object holds a valid , "filled" state or is empty.
40− Used by Pool to check if the slot occupied by this object is actually available.
41−
42− - void reset();
43−
44− Resets the object to its initial, empty, state. After calling this method, isValid() must
45− return false.
46− */
47−template <class ItemType> class Pool
48−{
49−public:
50− Pool() : m_lastUsedIndex(-1) {
51− }
52−
53− class Iterator {
54− public:
55− Iterator() : index(-1), item(nullptr) {}
56− Iterator(int index, ItemType *item)
57− : index(index), item(item) {}
58−
59− ItemType *operator->() const { return item; }
60− ItemType &operator*() const { return *item; }
61− ItemType &value() const { return *item; }
62−
63− operator bool() const { return item != nullptr; }
64−
65− int index;
66− ItemType *item;
67− };
68−
69− ItemType &getEmptySlot() {
70− Q_ASSERT(m_lastUsedIndex < m_slots.size());
71−
72− // Look for an in-between vacancy first
73− for (int i = 0; i < m_lastUsedIndex; ++i) {
74− ItemType &item = m_slots[i];
75− if (!item.isValid()) {
76− return item;
77− }
78− }
79−
80− ++m_lastUsedIndex;
81− if (m_lastUsedIndex >= m_slots.size()) {
82− m_slots.resize(m_lastUsedIndex + 1);
83− }
84−
85− return m_slots[m_lastUsedIndex];
86− }
87−
88− void freeSlot(Iterator &iterator) {
89− m_slots[iterator.index].reset();
90− if (iterator.index == m_lastUsedIndex) {
91− do {
92− --m_lastUsedIndex;
93− } while (m_lastUsedIndex >= 0 && !m_slots.at(m_lastUsedIndex).isValid());
94− }
95− }
96−
97− // Iterates through all valid items (i.e. the occupied slots)
98− // calling the given function, with the option of ending the loop early.
99− //
100− // bool Func(Iterator& item)
101− //
102− // Returning true means it wants to continue the "for" loop, false
103− // terminates the loop.
104− template<typename Func> void forEach(Func func) {
105− Iterator it;
106− for (it.index = 0; it.index <= m_lastUsedIndex; ++it.index) {
107− it.item = &m_slots[it.index];
108− if (!it.item->isValid())
109− continue;
110−
111− if (!func(it))
112− break;
113− }
114− }
115−
116− bool isEmpty() const { return m_lastUsedIndex == -1; }
117−
118−
119−private:
120− QVector<ItemType> m_slots;
121− int m_lastUsedIndex;
122−};
123−
124−#endif // UBUNTUGESTURES_POOL_H
libs/UbuntuGestures/TimeSource.cppdeleted−49
@@ -1,49 +0,0 @@
1−/*
2− * Copyright (C) 2013 - Canonical Ltd.
3− *
4− * This program is free software: you can redistribute it and/or modify it
5− * under the terms of the GNU Lesser General Public License, as
6− * published by the Free Software Foundation; either version 2.1 or 3.0
7− * of the License.
8− *
9− * This program is distributed in the hope that it will be useful, but
10− * WITHOUT ANY WARRANTY; without even the implied warranties of
11− * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
12− * PURPOSE. See the applicable version of the GNU Lesser General Public
13− * License for more details.
14− *
15− * You should have received a copy of both the GNU Lesser General Public
16− * License along with this program. If not, see <http://www.gnu.org/licenses/>
17− *
18− * Authored by: Daniel d'Andrada <daniel.dandrada@canonical.com>
19− */
20−
21−#include "TimeSource.h"
22−
23−#include <QElapsedTimer>
24−
25−namespace UbuntuGestures {
26−class RealTimeSourcePrivate {
27−public:
28− QElapsedTimer timer;
29−};
30−}
31−
32−using namespace UbuntuGestures;
33−
34−RealTimeSource::RealTimeSource()
35− : UbuntuGestures::TimeSource()
36− , d(new RealTimeSourcePrivate)
37−{
38− d->timer.start();
39−}
40−
41−RealTimeSource::~RealTimeSource()
42−{
43− delete d;
44−}
45−
46−qint64 RealTimeSource::msecsSinceReference()
47−{
48− return d->timer.elapsed();
49−}
libs/UbuntuGestures/TimeSource.hdeleted−64
@@ -1,64 +0,0 @@
1−/*
2− * Copyright (C) 2013,2015 Canonical Ltd.
3− *
4− * This program is free software: you can redistribute it and/or modify it
5− * under the terms of the GNU Lesser General Public License, as
6− * published by the Free Software Foundation; either version 2.1 or 3.0
7− * of the License.
8− *
9− * This program is distributed in the hope that it will be useful, but
10− * WITHOUT ANY WARRANTY; without even the implied warranties of
11− * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
12− * PURPOSE. See the applicable version of the GNU Lesser General Public
13− * License for more details.
14− *
15− * You should have received a copy of both the GNU Lesser General Public
16− * License along with this program. If not, see <http://www.gnu.org/licenses/>
17− *
18− * Authored by: Daniel d'Andrada <daniel.dandrada@canonical.com>
19− */
20−
21−#ifndef UBUNTUGESTURES_TIMESOURCE_H
22−#define UBUNTUGESTURES_TIMESOURCE_H
23−
24−#include "UbuntuGesturesGlobal.h"
25−#include <QSharedPointer>
26−
27−namespace UbuntuGestures {
28−/*
29− Interface for a time source.
30− */
31−class UBUNTUGESTURES_EXPORT TimeSource {
32−public:
33− virtual ~TimeSource() {}
34− /* Returns the current time in milliseconds since some reference time in the past. */
35− virtual qint64 msecsSinceReference() = 0;
36−};
37−typedef QSharedPointer<TimeSource> SharedTimeSource;
38−
39−/*
40− Implementation of a time source
41− */
42−class RealTimeSourcePrivate;
43−class UBUNTUGESTURES_EXPORT RealTimeSource : public TimeSource {
44−public:
45− RealTimeSource();
46− virtual ~RealTimeSource();
47− qint64 msecsSinceReference() override;
48−private:
49− RealTimeSourcePrivate *d;
50−};
51−
52−/*
53− A fake time source, useful for tests
54− */
55−class FakeTimeSource : public TimeSource {
56−public:
57− FakeTimeSource() { m_msecsSinceReference = 0; }
58− qint64 msecsSinceReference() override { return m_msecsSinceReference; }
59− qint64 m_msecsSinceReference;
60−};
61−
62−} // namespace UbuntuGestures
63−
64−#endif // UBUNTUGESTURES_TIMESOURCE_H
libs/UbuntuGestures/Timer.cppdeleted−152
@@ -1,152 +0,0 @@
1−/*
2− * Copyright (C) 2014-2015 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#include "Timer.h"
18−
19−namespace UbuntuGestures {
20−
21−Timer::Timer(QObject *parent) : AbstractTimer(parent)
22−{
23− m_timer.setSingleShot(false);
24− connect(&m_timer, &QTimer::timeout, this, &AbstractTimer::timeout);
25−}
26−
27−int Timer::interval() const
28−{
29− return m_timer.interval();
30−}
31−
32−void Timer::setInterval(int msecs)
33−{
34− m_timer.setInterval(msecs);
35−}
36−
37−void Timer::start()
38−{
39− m_timer.start();
40− AbstractTimer::start();
41−}
42−
43−void Timer::stop()
44−{
45− m_timer.stop();
46− AbstractTimer::stop();
47−}
48−
49−bool Timer::isSingleShot() const
50−{
51− return m_timer.isSingleShot();
52−}
53−
54−void Timer::setSingleShot(bool value)
55−{
56− m_timer.setSingleShot(value);
57−}
58−
59−/////////////////////////////////// FakeTimer //////////////////////////////////
60−
61−FakeTimer::FakeTimer(const SharedTimeSource &timeSource, QObject *parent)
62− : UbuntuGestures::AbstractTimer(parent)
63− , m_interval(0)
64− , m_singleShot(false)
65− , m_timeSource(timeSource)
66−{
67−}
68−
69−void FakeTimer::update()
70−{
71− if (!isRunning()) {
72− return;
73− }
74−
75− if (m_nextTimeoutTime <= m_timeSource->msecsSinceReference()) {
76− if (isSingleShot()) {
77− stop();
78− } else {
79− m_nextTimeoutTime += interval();
80− }
81− Q_EMIT timeout();
82− }
83−}
84−
85−void FakeTimer::start()
86−{
87− AbstractTimer::start();
88− m_nextTimeoutTime = m_timeSource->msecsSinceReference() + (qint64)interval();
89−}
90−
91−int FakeTimer::interval() const
92−{
93− return m_interval;
94−}
95−
96−void FakeTimer::setInterval(int msecs)
97−{
98− m_interval = msecs;
99−}
100−
101−bool FakeTimer::isSingleShot() const
102−{
103− return m_singleShot;
104−}
105−
106−void FakeTimer::setSingleShot(bool value)
107−{
108− m_singleShot = value;
109−}
110−
111−/////////////////////////////////// FakeTimerFactory //////////////////////////////////
112−
113−FakeTimerFactory::FakeTimerFactory()
114−{
115− m_timeSource.reset(new FakeTimeSource);
116−}
117−
118−void FakeTimerFactory::updateTime(qint64 targetTime)
119−{
120− qint64 minTimeoutTime = targetTime;
121−
122− for (int i = 0; i < timers.count(); ++i) {
123− FakeTimer *timer = timers[i].data();
124− if (timer && timer->isRunning() && timer->nextTimeoutTime() < minTimeoutTime) {
125− minTimeoutTime = timer->nextTimeoutTime();
126− }
127− }
128−
129− m_timeSource->m_msecsSinceReference = minTimeoutTime;
130−
131− for (int i = 0; i < timers.count(); ++i) {
132− FakeTimer *timer = timers[i].data();
133− if (timer) {
134− timer->update();
135− }
136− }
137−
138− if (m_timeSource->msecsSinceReference() < targetTime) {
139− updateTime(targetTime);
140− }
141−}
142−
143−AbstractTimer *FakeTimerFactory::createTimer(QObject *parent)
144−{
145− FakeTimer *fakeTimer = new FakeTimer(m_timeSource, parent);
146−
147− timers.append(fakeTimer);
148−
149− return fakeTimer;
150−}
151−
152−} // namespace UbuntuGestures
libs/UbuntuGestures/Timer.hdeleted−122
@@ -1,122 +0,0 @@
1−/*
2− * Copyright (C) 2014 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#ifndef UBUNTUGESTURES_TIMER_H
18−#define UBUNTUGESTURES_TIMER_H
19−
20−#include "UbuntuGesturesGlobal.h"
21−#include "TimeSource.h"
22−
23−#include <QObject>
24−#include <QPointer>
25−#include <QTimer>
26−
27−namespace UbuntuGestures {
28−
29−/* Defines an interface for a Timer. Useful for tests. */
30−class UBUNTUGESTURES_EXPORT AbstractTimer : public QObject
31−{
32− Q_OBJECT
33−public:
34− AbstractTimer(QObject *parent) : QObject(parent), m_isRunning(false) {}
35− virtual int interval() const = 0;
36− virtual void setInterval(int msecs) = 0;
37− virtual void start() { m_isRunning = true; }
38− virtual void start(int msecs)
39− {
40− setInterval(msecs);
41− start();
42− }
43− virtual void stop() { m_isRunning = false; }
44− bool isRunning() const { return m_isRunning; }
45− virtual bool isSingleShot() const = 0;
46− virtual void setSingleShot(bool value) = 0;
47−Q_SIGNALS:
48− void timeout();
49−private:
50− bool m_isRunning;
51−};
52−
53−/* Essentially a QTimer wrapper */
54−class UBUNTUGESTURES_EXPORT Timer : public AbstractTimer
55−{
56− Q_OBJECT
57−public:
58− Timer(QObject *parent = nullptr);
59−
60− int interval() const override;
61− void setInterval(int msecs) override;
62− void start() override;
63− void stop() override;
64− bool isSingleShot() const override;
65− void setSingleShot(bool value) override;
66−private:
67− QTimer m_timer;
68−};
69−
70−/* For tests */
71−class UBUNTUGESTURES_EXPORT FakeTimer : public AbstractTimer
72−{
73− Q_OBJECT
74−public:
75− FakeTimer(const SharedTimeSource &timeSource, QObject *parent = nullptr);
76−
77− void update();
78− qint64 nextTimeoutTime() const { return m_nextTimeoutTime; }
79−
80− int interval() const override;
81− void setInterval(int msecs) override;
82− void start() override;
83− bool isSingleShot() const override;
84− void setSingleShot(bool value) override;
85−private:
86− int m_interval;
87− bool m_singleShot;
88− SharedTimeSource m_timeSource;
89− qint64 m_nextTimeoutTime;
90−};
91−
92−class UBUNTUGESTURES_EXPORT AbstractTimerFactory
93−{
94−public:
95− virtual ~AbstractTimerFactory() {}
96− virtual AbstractTimer *createTimer(QObject *parent = nullptr) = 0;
97−};
98−
99−class UBUNTUGESTURES_EXPORT TimerFactory : public AbstractTimerFactory
100−{
101−public:
102− AbstractTimer *createTimer(QObject *parent = nullptr) override { return new Timer(parent); }
103−};
104−
105−class UBUNTUGESTURES_EXPORT FakeTimerFactory : public AbstractTimerFactory
106−{
107−public:
108− FakeTimerFactory();
109− virtual ~FakeTimerFactory() {}
110−
111− void updateTime(qint64 msecsSinceReference);
112− QSharedPointer<TimeSource> timeSource() { return m_timeSource; }
113−
114− AbstractTimer *createTimer(QObject *parent = nullptr) override;
115− QList<QPointer<FakeTimer>> timers;
116−private:
117− QSharedPointer<FakeTimeSource> m_timeSource;
118−};
119−
120−} // namespace UbuntuGestures
121−
122−#endif // UBUNTUGESTURES_TIMER_H
libs/UbuntuGestures/TouchOwnershipEvent.cppdeleted−35
@@ -1,35 +0,0 @@
1−/*
2− * Copyright (C) 2014 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#include "TouchOwnershipEvent.h"
18−
19−QEvent::Type TouchOwnershipEvent::m_touchOwnershipType = (QEvent::Type)-1;
20−
21−TouchOwnershipEvent::TouchOwnershipEvent(int touchId, bool gained)
22− : QEvent(touchOwnershipEventType())
23− , m_touchId(touchId)
24− , m_gained(gained)
25−{
26−}
27−
28−QEvent::Type TouchOwnershipEvent::touchOwnershipEventType()
29−{
30− if (m_touchOwnershipType == (QEvent::Type)-1) {
31− m_touchOwnershipType = (QEvent::Type)registerEventType();
32− }
33−
34− return m_touchOwnershipType;
35−}
libs/UbuntuGestures/TouchOwnershipEvent.hdeleted−50
@@ -1,50 +0,0 @@
1−/*
2− * Copyright (C) 2014 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#ifndef UBUNTU_TOUCHOWNERSHIPEVENT_H
18−#define UBUNTU_TOUCHOWNERSHIPEVENT_H
19−
20−#include <QEvent>
21−#include "UbuntuGesturesGlobal.h"
22−
23−/*
24− When an item get an ownership event for a touch it can grab/steal that touch
25− with a clean conscience.
26− */
27−class UBUNTUGESTURES_EXPORT TouchOwnershipEvent : public QEvent
28−{
29−public:
30− TouchOwnershipEvent(int touchId, bool gained);
31−
32− static Type touchOwnershipEventType();
33−
34− /*
35− Whether ownership was gained (true) or lost (false)
36− */
37− bool gained() const { return m_gained; }
38−
39− /*
40− Id of the touch whose ownership was granted.
41− */
42− int touchId() const { return m_touchId; }
43−
44−private:
45− static Type m_touchOwnershipType;
46− int m_touchId;
47− bool m_gained;
48−};
49−
50−#endif // UBUNTU_TOUCHOWNERSHIPEVENT_H
libs/UbuntuGestures/TouchRegistry.cppdeleted−553
@@ -1,553 +0,0 @@
1−/*
2− * Copyright (C) 2014-2015 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#include "TouchRegistry.h"
18−
19−#include <QCoreApplication>
20−#include <QDebug>
21−
22−#pragma GCC diagnostic push
23−#pragma GCC diagnostic ignored "-pedantic"
24−#include <private/qquickitem_p.h>
25−#pragma GCC diagnostic pop
26−
27−#include "CandidateInactivityTimer.h"
28−#include "Timer.h"
29−#include "TouchOwnershipEvent.h"
30−#include "UnownedTouchEvent.h"
31−
32−#define TOUCHREGISTRY_DEBUG 0
33−
34−#if TOUCHREGISTRY_DEBUG
35− #include "DebugHelpers.h"
36− #define UG_DEBUG qDebug() << "[TouchRegistry]"
37−#endif // TOUCHREGISTRY_DEBUG
38−
39−using namespace UbuntuGestures;
40−
41−TouchRegistry *TouchRegistry::m_instance = nullptr;
42−
43−TouchRegistry::TouchRegistry(QObject *parent)
44− : QObject(parent)
45− , m_inDispatchLoop(false)
46− , m_timerFactory(new TimerFactory)
47−{
48−}
49−
50−TouchRegistry::~TouchRegistry()
51−{
52− Q_ASSERT(m_instance != nullptr);
53− m_instance = nullptr;
54− delete m_timerFactory;
55−}
56−
57−TouchRegistry *TouchRegistry::instance()
58−{
59− if (m_instance == nullptr) {
60− m_instance = new TouchRegistry;
61− }
62− return m_instance;
63−}
64−
65−void TouchRegistry::setTimerFactory(AbstractTimerFactory *timerFactory)
66−{
67− delete m_timerFactory;
68− m_timerFactory = timerFactory;
69−}
70−
71−void TouchRegistry::update(const QTouchEvent *event)
72−{
73− #if TOUCHREGISTRY_DEBUG
74− UG_DEBUG << "got" << qPrintable(touchEventToString(event));
75− #endif
76−
77− const QList<QTouchEvent::TouchPoint> &touchPoints = event->touchPoints();
78− for (int i = 0; i < touchPoints.count(); ++i) {
79− const QTouchEvent::TouchPoint &touchPoint = touchPoints.at(i);
80− if (touchPoint.state() == Qt::TouchPointPressed) {
81− TouchInfo &touchInfo = m_touchInfoPool.getEmptySlot();
82− touchInfo.init(touchPoint.id());
83− } else if (touchPoint.state() == Qt::TouchPointReleased) {
84− Pool<TouchInfo>::Iterator touchInfo = findTouchInfo(touchPoint.id());
85−
86− touchInfo->physicallyEnded = true;
87− }
88− }
89−
90− deliverTouchUpdatesToUndecidedCandidatesAndWatchers(event);
91−
92− freeEndedTouchInfos();
93−}
94−
95−void TouchRegistry::deliverTouchUpdatesToUndecidedCandidatesAndWatchers(const QTouchEvent *event)
96−{
97− // TODO: Look into how we could optimize this whole thing.
98− // Although it's not really a problem as we should have at most two candidates
99− // for each point and there should not be many active points at any given moment.
100− // But having three nested for-loops does scare.
101−
102− const QList<QTouchEvent::TouchPoint> &updatedTouchPoints = event->touchPoints();
103−
104− // Maps an item to the touches in this event he should be informed about.
105− // E.g.: a QTouchEvent might have three touches but a given item might be interested in only
106− // one of them. So he will get a UnownedTouchEvent from this QTouchEvent containing only that
107− // touch point.
108− QHash<QQuickItem*, QList<int>> touchIdsForItems;
109−
110− // Build touchIdsForItems
111− m_touchInfoPool.forEach([&](Pool<TouchInfo>::Iterator &touchInfo) {
112− if (touchInfo->isOwned() && touchInfo->watchers.isEmpty())
113− return true;
114−
115− for (int j = 0; j < updatedTouchPoints.count(); ++j) {
116− if (updatedTouchPoints[j].id() == touchInfo->id) {
117− if (!touchInfo->isOwned()) {
118− for (int i = 0; i < touchInfo->candidates.count(); ++i) {
119− CandidateInfo &candidate = touchInfo->candidates[i];
120− Q_ASSERT(!candidate.item.isNull());
121− if (candidate.state != CandidateInfo::InterimOwner) {
122− touchIdsForItems[candidate.item.data()].append(touchInfo->id);
123− }
124− }
125− }
126−
127− const QList<QPointer<QQuickItem>> &watchers = touchInfo->watchers;
128− for (int i = 0; i < watchers.count(); ++i) {
129− if (!watchers[i].isNull()) {
130− touchIdsForItems[watchers[i].data()].append(touchInfo->id);
131− }
132− }
133−
134− return true;
135− }
136− }
137−
138− return true;
139− });
140−
141− // TODO: Consider what happens if an item calls any of TouchRegistry's public methods
142− // from the event handler callback.
143− m_inDispatchLoop = true;
144− auto it = touchIdsForItems.constBegin();
145− while (it != touchIdsForItems.constEnd()) {
146− QQuickItem *item = it.key();
147− const QList<int> &touchIds = it.value();
148− dispatchPointsToItem(event, touchIds, item);
149− ++it;
150− };
151− m_inDispatchLoop = false;
152−}
153−
154−void TouchRegistry::freeEndedTouchInfos()
155−{
156− m_touchInfoPool.forEach([&](Pool<TouchInfo>::Iterator &touchInfo) {
157− if (touchInfo->ended()) {
158− m_touchInfoPool.freeSlot(touchInfo);
159− }
160− return true;
161− });
162−}
163−
164−/*
165− Extracts the touches with the given touchIds from event and send them in a
166− UnownedTouchEvent to the given item
167− */
168−void TouchRegistry::dispatchPointsToItem(const QTouchEvent *event, const QList<int> &touchIds,
169− QQuickItem *item)
170−{
171− Qt::TouchPointStates touchPointStates = 0;
172− QList<QTouchEvent::TouchPoint> touchPoints;
173−
174− const QList<QTouchEvent::TouchPoint> &allTouchPoints = event->touchPoints();
175−
176− QTransform windowToCandidateTransform = QQuickItemPrivate::get(item)->windowToItemTransform();
177− QMatrix4x4 windowToCandidateMatrix(windowToCandidateTransform);
178−
179− for (int i = 0; i < allTouchPoints.count(); ++i) {
180− const QTouchEvent::TouchPoint &originalTouchPoint = allTouchPoints[i];
181− if (touchIds.contains(originalTouchPoint.id())) {
182− QTouchEvent::TouchPoint touchPoint = originalTouchPoint;
183−
184− translateTouchPointFromScreenToWindowCoords(touchPoint);
185−
186− // Set the point's local coordinates to that of the item
187− touchPoint.setRect(windowToCandidateTransform.mapRect(touchPoint.sceneRect()));
188− touchPoint.setStartPos(windowToCandidateTransform.map(touchPoint.startScenePos()));
189− touchPoint.setLastPos(windowToCandidateTransform.map(touchPoint.lastScenePos()));
190− touchPoint.setVelocity(windowToCandidateMatrix.mapVector(touchPoint.velocity()).toVector2D());
191−
192− touchPoints.append(touchPoint);
193− touchPointStates |= touchPoint.state();
194− }
195− }
196−
197− QTouchEvent *eventForItem = new QTouchEvent(event->type(),
198− event->device(),
199− event->modifiers(),
200− touchPointStates,
201− touchPoints);
202− eventForItem->setWindow(event->window());
203− eventForItem->setTimestamp(event->timestamp());
204− eventForItem->setTarget(event->target());
205−
206− UnownedTouchEvent unownedTouchEvent(eventForItem);
207−
208− #if TOUCHREGISTRY_DEBUG
209− UG_DEBUG << "Sending unowned" << qPrintable(touchEventToString(eventForItem))
210− << "to" << item;
211− #endif
212−
213− QCoreApplication::sendEvent(item, &unownedTouchEvent);
214−}
215−
216−void TouchRegistry::translateTouchPointFromScreenToWindowCoords(QTouchEvent::TouchPoint &touchPoint)
217−{
218− touchPoint.setScreenRect(touchPoint.sceneRect());
219− touchPoint.setStartScreenPos(touchPoint.startScenePos());
220− touchPoint.setLastScreenPos(touchPoint.lastScenePos());
221−
222− touchPoint.setSceneRect(touchPoint.rect());
223− touchPoint.setStartScenePos(touchPoint.startPos());
224− touchPoint.setLastScenePos(touchPoint.lastPos());
225−}
226−
227−bool TouchRegistry::eventFilter(QObject *watched, QEvent *event)
228−{
229− Q_UNUSED(watched);
230−
231− switch (event->type()) {
232− case QEvent::TouchBegin:
233− case QEvent::TouchUpdate:
234− case QEvent::TouchEnd:
235− case QEvent::TouchCancel:
236− update(static_cast<QTouchEvent*>(event));
237− break;
238− default:
239− // do nothing
240− break;
241− }
242−
243− // Do not filter out the event. i.e., let it be handled further as
244− // we're just monitoring events
245− return false;
246−}
247−
248−void TouchRegistry::addCandidateOwnerForTouch(int id, QQuickItem *candidate)
249−{
250− #if TOUCHREGISTRY_DEBUG
251− UG_DEBUG << "addCandidateOwnerForTouch id" << id << "candidate" << candidate;
252− #endif
253−
254− Pool<TouchInfo>::Iterator touchInfo = findTouchInfo(id);
255− if (!touchInfo) { qFatal("TouchRegistry: Failed to find TouchInfo"); }
256−
257− if (touchInfo->isOwned()) {
258− qWarning("TouchRegistry: trying to add candidate owner for a touch that's already owned");
259− return;
260− }
261−
262− // TODO: Check if candidate already exists
263−
264− CandidateInfo candidateInfo;
265− candidateInfo.state = CandidateInfo::Undecided;
266− candidateInfo.item = candidate;
267− candidateInfo.inactivityTimer = new CandidateInactivityTimer(id, candidate,
268− m_timerFactory->createTimer(),
269− this);
270− connect(candidateInfo.inactivityTimer, &CandidateInactivityTimer::candidateDefaulted,
271− this, &TouchRegistry::rejectCandidateOwnerForTouch);
272−
273− touchInfo->candidates.append(candidateInfo);
274−
275− connect(candidate, &QObject::destroyed, this, [=](){ pruneNullCandidatesForTouch(id); });
276−}
277−
278−void TouchRegistry::addTouchWatcher(int touchId, QQuickItem *watcher)
279−{
280− #if TOUCHREGISTRY_DEBUG
281− UG_DEBUG << "addTouchWatcher id" << touchId << "watcher" << watcher;
282− #endif
283−
284− Pool<TouchInfo>::Iterator touchInfo = findTouchInfo(touchId);
285− if (!touchInfo) { qFatal("TouchRegistry: Failed to find TouchInfo"); }
286−
287− // TODO: Check if watcher already exists
288−
289− touchInfo->watchers.append(watcher);
290−}
291−
292−void TouchRegistry::removeCandidateOwnerForTouch(int id, QQuickItem *candidate)
293−{
294− #if TOUCHREGISTRY_DEBUG
295− UG_DEBUG << "removeCandidateOwnerForTouch id" << id << "candidate" << candidate;
296− #endif
297−
298− Pool<TouchInfo>::Iterator touchInfo = findTouchInfo(id);
299− if (!touchInfo) { qFatal("TouchRegistry: Failed to find TouchInfo"); }
300−
301−
302− // TODO: check if the candidate is in fact the owner of the touch
303−
304− bool removed = false;
305− for (int i = 0; i < touchInfo->candidates.count() && !removed; ++i) {
306− if (touchInfo->candidates[i].item == candidate) {
307− removeCandidateOwnerForTouchByIndex(touchInfo, i);
308− removed = true;
309− }
310− }
311−}
312−
313−void TouchRegistry::pruneNullCandidatesForTouch(int touchId)
314−{
315− #if TOUCHREGISTRY_DEBUG
316− UG_DEBUG << "pruneNullCandidatesForTouch touchId" << touchId;
317− #endif
318−
319− Pool<TouchInfo>::Iterator touchInfo = findTouchInfo(touchId);
320− if (!touchInfo) {
321− // doesn't matter as touch is already gone.
322− return;
323− }
324−
325− int i = 0;
326− while (i < touchInfo->candidates.count()) {
327− if (touchInfo->candidates[i].item.isNull()) {
328− removeCandidateOwnerForTouchByIndex(touchInfo, i);
329− } else {
330− ++i;
331− }
332− }
333−}
334−
335−void TouchRegistry::removeCandidateOwnerForTouchByIndex(Pool<TouchRegistry::TouchInfo>::Iterator &touchInfo,
336− int candidateIndex)
337−{
338− // TODO: check if the candidate is in fact the owner of the touch
339−
340− Q_ASSERT(candidateIndex < touchInfo->candidates.count());
341−
342− if (candidateIndex == 0 && touchInfo->candidates[candidateIndex].state != CandidateInfo::Undecided) {
343− qCritical("TouchRegistry: touch owner is being removed.");
344− }
345− removeCandidateHelper(touchInfo, candidateIndex);
346−
347− if (candidateIndex == 0) {
348− // the top candidate has been removed. if the new top candidate
349− // wants the touch let him know he's now the owner.
350− if (touchInfo->isOwned()) {
351− touchInfo->notifyCandidatesOfOwnershipResolution();
352− }
353− }
354−
355− if (!m_inDispatchLoop && touchInfo->ended()) {
356− m_touchInfoPool.freeSlot(touchInfo);
357− }
358−}
359−
360−void TouchRegistry::requestTouchOwnership(int id, QQuickItem *candidate)
361−{
362− Pool<TouchInfo>::Iterator touchInfo = findTouchInfo(id);
363− if (!touchInfo) { qFatal("TouchRegistry: Failed to find TouchInfo"); }
364−
365− Q_ASSERT(!touchInfo->isOwned());
366−
367− int candidateIndex = -1;
368− for (int i = 0; i < touchInfo->candidates.count(); ++i) {
369− CandidateInfo &candidateInfo = touchInfo->candidates[i];
370− if (candidateInfo.item == candidate) {
371− candidateInfo.state = CandidateInfo::Requested;
372− delete candidateInfo.inactivityTimer;
373− candidateInfo.inactivityTimer = nullptr;
374− candidateIndex = i;
375− break;
376− }
377− }
378− #if TOUCHREGISTRY_DEBUG
379− UG_DEBUG << "requestTouchOwnership id " << id << "candidate" << candidate << "index: " << candidateIndex;
380− #endif
381−
382− // add it as a candidate if not present yet
383− if (candidateIndex < 0) {
384− CandidateInfo candidateInfo;
385− candidateInfo.state = CandidateInfo::InterimOwner;
386− candidateInfo.item = candidate;
387− candidateInfo.inactivityTimer = nullptr;
388− touchInfo->candidates.append(candidateInfo);
389− // it's the last one
390− candidateIndex = touchInfo->candidates.count() - 1;
391− connect(candidate, &QObject::destroyed, this, [=](){ pruneNullCandidatesForTouch(id); });
392− }
393−
394− // If it's the top candidate it means it's now the owner. Let
395− // it know about it.
396− if (candidateIndex == 0) {
397− touchInfo->notifyCandidatesOfOwnershipResolution();
398− }
399−}
400−
401−Pool<TouchRegistry::TouchInfo>::Iterator TouchRegistry::findTouchInfo(int id)
402−{
403− Pool<TouchInfo>::Iterator touchInfo;
404−
405− m_touchInfoPool.forEach([&](Pool<TouchInfo>::Iterator &someTouchInfo) -> bool {
406− if (someTouchInfo->id == id) {
407− touchInfo = someTouchInfo;
408− return false;
409− } else {
410− return true;
411− }
412− });
413−
414− return touchInfo;
415−}
416−
417−
418−void TouchRegistry::rejectCandidateOwnerForTouch(int id, QQuickItem *candidate)
419−{
420− // NB: It's technically possible that candidate is a dangling pointer at this point.
421− // Although that would most likely be due to a bug in our code.
422− // In any case, only dereference it after it's confirmed that it indeed exists.
423−
424− #if TOUCHREGISTRY_DEBUG
425− UG_DEBUG << "rejectCandidateOwnerForTouch id" << id << "candidate" << (void*)candidate;
426− #endif
427−
428− Pool<TouchInfo>::Iterator touchInfo = findTouchInfo(id);
429− if (!touchInfo) {
430− #if TOUCHREGISTRY_DEBUG
431− UG_DEBUG << "Failed to find TouchInfo for id" << id;
432− #endif
433− return;
434− }
435−
436− int rejectedCandidateIndex = -1;
437−
438− // Check if the given candidate is valid and still undecided
439− for (int i = 0; i < touchInfo->candidates.count() && rejectedCandidateIndex == -1; ++i) {
440− CandidateInfo &candidateInfo = touchInfo->candidates[i];
441− if (candidateInfo.item == candidate) {
442− Q_ASSERT(i > 0 || candidateInfo.state == CandidateInfo::Undecided);
443− if (i == 0 && candidateInfo.state != CandidateInfo::Undecided) {
444− qCritical() << "TouchRegistry: Can't reject item (" << (void*)candidate
445− << ") as it already owns touch" << id;
446− return;
447− } else {
448− // we found the guy and it's all fine.
449− rejectedCandidateIndex = i;
450− }
451− }
452− }
453−
454− // If we reached this point it's because the given candidate exists and is indeed undecided.
455−
456− Q_ASSERT(rejectedCandidateIndex >= 0 && rejectedCandidateIndex < touchInfo->candidates.size());
457−
458− {
459− TouchOwnershipEvent lostOwnershipEvent(id, false /*gained*/);
460− QCoreApplication::sendEvent(candidate, &lostOwnershipEvent);
461− }
462−
463− removeCandidateHelper(touchInfo, rejectedCandidateIndex);
464−
465− if (rejectedCandidateIndex == 0) {
466− // the top candidate has been removed. if the new top candidate
467− // wants the touch let him know he's now the owner.
468− if (touchInfo->isOwned()) {
469− touchInfo->notifyCandidatesOfOwnershipResolution();
470− }
471− }
472−}
473−
474−void TouchRegistry::removeCandidateHelper(Pool<TouchInfo>::Iterator &touchInfo, int candidateIndex)
475−{
476− {
477− CandidateInfo &candidateInfo = touchInfo->candidates[candidateIndex];
478−
479− delete candidateInfo.inactivityTimer;
480− candidateInfo.inactivityTimer = nullptr;
481−
482− if (candidateInfo.item) {
483− disconnect(candidateInfo.item.data(), nullptr, this, nullptr);
484− }
485− }
486− touchInfo->candidates.removeAt(candidateIndex);
487−}
488−
489−////////////////////////////////////// TouchRegistry::TouchInfo ////////////////////////////////////
490−
491−TouchRegistry::TouchInfo::TouchInfo(int id)
492−{
493− init(id);
494−}
495−
496−void TouchRegistry::TouchInfo::reset()
497−{
498− id = -1;
499−
500− for (int i = 0; i < candidates.count(); ++i) {
501− CandidateInfo &candidate = candidates[i];
502− delete candidate.inactivityTimer;
503− candidate.inactivityTimer.clear(); // shoundn't be needed but anyway...
504− }
505−}
506−
507−void TouchRegistry::TouchInfo::init(int id)
508−{
509− this->id = id;
510− physicallyEnded = false;
511− candidates.clear();
512− watchers.clear();
513−}
514−
515−bool TouchRegistry::TouchInfo::isOwned() const
516−{
517− return !candidates.isEmpty() && candidates.first().state != CandidateInfo::Undecided;
518−}
519−
520−bool TouchRegistry::TouchInfo::ended() const
521−{
522− Q_ASSERT(isValid());
523− return physicallyEnded && (isOwned() || candidates.isEmpty());
524−}
525−
526−void TouchRegistry::TouchInfo::notifyCandidatesOfOwnershipResolution()
527−{
528− Q_ASSERT(isOwned());
529−
530− #if TOUCHREGISTRY_DEBUG
531− UG_DEBUG << "sending TouchOwnershipEvent(id =" << id
532− << " gained) to candidate" << candidates[0].item;
533− #endif
534−
535− // need to take a copy of the item list in case
536− // we call back in to remove candidate during the lost ownership event.
537− QList<QPointer<QQuickItem>> items;
538− Q_FOREACH(const CandidateInfo& info, candidates) {
539− items << info.item;
540− }
541−
542− TouchOwnershipEvent gainedOwnershipEvent(id, true /*gained*/);
543− QCoreApplication::sendEvent(items[0], &gainedOwnershipEvent);
544−
545− TouchOwnershipEvent lostOwnershipEvent(id, false /*gained*/);
546− for (int i = 1; i < items.count(); ++i) {
547− #if TOUCHREGISTRY_DEBUG
548− UG_DEBUG << "sending TouchOwnershipEvent(id =" << id << " lost) to candidate"
549− << items[i];
550− #endif
551− QCoreApplication::sendEvent(items[i], &lostOwnershipEvent);
552− }
553−}
libs/UbuntuGestures/TouchRegistry.hdeleted−201
@@ -1,201 +0,0 @@
1−/*
2− * Copyright (C) 2014 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#ifndef UNITY_TOUCHREGISTRY_H
18−#define UNITY_TOUCHREGISTRY_H
19−
20−#include <QQuickItem>
21−#include <QObject>
22−#include <QPointer>
23−#include <QTouchEvent>
24−#include <QVector>
25−
26−#include "UbuntuGesturesGlobal.h"
27−#include "CandidateInactivityTimer.h"
28−#include "Timer.h"
29−#include "Pool.h"
30−
31−namespace UbuntuGestures {
32− class AbstractTimerFactory;
33−}
34−
35−/*
36− Where the ownership of touches is registered.
37−
38− Singleton used for adding a touch point ownership model analogous to the one
39− described in the XInput 2.2 protocol[1] on top of the existing input dispatch logic in QQuickWindow.
40−
41− It provides a much more flexible and powerful way of dealing with pointer ownership than the existing
42− mechanisms in Qt. Namely QQuickItem::grabTouchPoints, QuickItem::keepTouchGrab,
43− QQuickItem::setFiltersChildMouseEvents, QQuickItem::ungrabTouchPoints and QQuickItem::touchUngrabEvent.
44−
45− Usage:
46−
47− 1- An item receives a a new touch point. If he's not sure whether he wants it yet, he calls:
48− TouchRegistry::instance()->addCandidateOwnerForTouch(touchId, this);
49− touchEvent->ignore();
50− Ignoring the event is crucial so that it can be seen by other interested parties, which will
51− behave similarly.
52−
53− 2- That item will then start receiving UnownedTouchEvents for that touch from step 1. Once he's
54− made a decision he calls either:
55− TouchRegistry::instance()->requestTouchOwnership(touchId, this);
56− If he wants the touch point or:
57− TouchRegistry::instance()->removeCandidateOwnerForTouch(touchId, this);
58−  if he does not want it.
59−
60− Candidates are put in a priority queue. The first one to call addCandidateOwnerForTouch() will
61− take precedence over the others for receiving ownership over the touch point (from now on called
62− simply top-candidate).
63−
64− If the top-candidate calls requestTouchOwnership() he will immediately receive a
65− TouchOwnershipEvent(gained=true) for that touch point. He can then safely call
66− QQuickItem::grabTouchPoints to actually get the owned touch points. The other candidates
67− will receive TouchOwnershipEvent(gained=false) and will no longer receive UnownedTouchEvents
68− for that touch point. They will have to undo whatever action they were performing with that
69− touch point.
70−
71− But if the top-candidate calls removeCandidateOwnerForTouch() instead, he's popped from the
72− candidacy queue and ownership is given to the new top-most candidate if he has already
73− made his decision, that is.
74−
75− The TouchRegistry cannot enforce the results of this pointer ownership negotiation (i.e.,
76− who gets to grab the touch points) as that would clash with QQuickWindow's input event
77− dispatching logic. The candidates have to respect the decision and grab the touch points
78− themselves.
79−
80− If an item wants ownership over touches as soon as he receives the TouchBegin for them, his step 1
81− would be instead:
82− TouchRegistry::instance()->requestTouchOwnership(touchId, this);
83− touchEvent->accept();
84− He won't get any UnownedTouchEvent for that touch as he is already the interim owner (ie, QQuickWindow
85− will keep sending touch updates to him already). Eventually he will be notified once ownership has
86− been granted to him (from TouchRegistry perspective), from which point onwards he could safely assume
87− other TouchRegistry users wouldn't snatch this touch away from him.
88−
89− Items oblivious to TouchRegistry will lose their touch points without warning, just like in plain Qt.
90−
91− [1] - http://www.x.org/releases/X11R7.7/doc/inputproto/XI2proto.txt (see multitouch-ownership)
92− */
93−class UBUNTUGESTURES_EXPORT TouchRegistry : public QObject
94−{
95− Q_OBJECT
96−public:
97− virtual ~TouchRegistry();
98−
99− // Returns a pointer to the application's TouchRegistry instance.
100− static TouchRegistry *instance();
101−
102− void update(const QTouchEvent *event);
103−
104− // Calls update() if the given event is a QTouchEvent
105− bool eventFilter(QObject *watched, QEvent *event) override;
106−
107− // An item that might later request ownership over the given touch point.
108− // He will be kept informed about that touch point through UnownedTouchEvents
109− // All candidates must eventually decide whether they want to own the touch point
110− // or not. That decision is informed through requestTouchOwnership() or
111− // removeCandidateOwnerForTouch()
112− void addCandidateOwnerForTouch(int id, QQuickItem *candidate);
113−
114− // The same as rejecting ownership of a touch
115− void removeCandidateOwnerForTouch(int id, QQuickItem *candidate);
116−
117− // The candidate object wants to be the owner of the touch with the given id.
118− // If he's currently the oldest/top-most candidate, he will get an ownership
119− // event immediately. If not, he will get ownership if (or once) he becomes the
120− // top-most candidate.
121− void requestTouchOwnership(int id, QQuickItem *candidate);
122−
123− // An item that has no interest (effective or potential) in owning a touch point
124− // but would nonetheless like to be kept up-to-date on its state.
125− void addTouchWatcher(int touchId, QQuickItem *watcherItem);
126−
127− // Useful for tests, where you should use fake timers
128− void setTimerFactory(UbuntuGestures::AbstractTimerFactory *timerFactory);
129−
130−private Q_SLOTS:
131− void rejectCandidateOwnerForTouch(int id, QQuickItem *candidate);
132−
133−private:
134− // Only instance() can cronstruct one
135− TouchRegistry(QObject *parent = nullptr);
136−
137− class CandidateInfo {
138− public:
139− enum {
140− // A candidate owner that doesn't yet know for sure whether he wants the touch point
141− // (gesture recognition is stilll going on)
142− Undecided = 0,
143− // A candidate owner that wants the touch but hasn't been granted it yet,
144− // most likely because there's an undecided candidate with higher priority
145− Requested = 1,
146− // An item that is the interim owner of the touch, receiving QTouchEvents of it
147− // from QQuickWindow. Ie, it's the actual touch owner from Qt's point of view.
148− // It wants to keep its touch ownership but hasn't been granted it by TouchRegistry
149− // yet because of undecided candidates higher up.
150− InterimOwner = 2
151− } state;
152− QPointer<QQuickItem> item;
153− QPointer<UbuntuGestures::CandidateInactivityTimer> inactivityTimer;
154− };
155−
156− class TouchInfo {
157− public:
158− TouchInfo() : id(-1) {}
159− TouchInfo(int id);
160− bool isValid() const { return id >= 0; }
161− void reset();
162− void init(int id);
163− int id;
164− bool physicallyEnded;
165− bool isOwned() const;
166− bool ended() const;
167− void notifyCandidatesOfOwnershipResolution();
168−
169− // TODO optimize storage (s/QList/Pool)
170− QList<CandidateInfo> candidates;
171− QList<QPointer<QQuickItem>> watchers;
172− };
173−
174− void pruneNullCandidatesForTouch(int touchId);
175− void removeCandidateOwnerForTouchByIndex(Pool<TouchInfo>::Iterator &touchInfo, int candidateIndex);
176− void removeCandidateHelper(Pool<TouchInfo>::Iterator &touchInfo, int candidateIndex);
177−
178− Pool<TouchInfo>::Iterator findTouchInfo(int id);
179−
180− void deliverTouchUpdatesToUndecidedCandidatesAndWatchers(const QTouchEvent *event);
181−
182− static void translateTouchPointFromScreenToWindowCoords(QTouchEvent::TouchPoint &touchPoint);
183−
184− static void dispatchPointsToItem(const QTouchEvent *event, const QList<int> &touchIds,
185− QQuickItem *item);
186− void freeEndedTouchInfos();
187−
188− Pool<TouchInfo> m_touchInfoPool;
189−
190− // the singleton instance
191− static TouchRegistry *m_instance;
192−
193− bool m_inDispatchLoop;
194−
195− UbuntuGestures::AbstractTimerFactory *m_timerFactory;
196−
197− friend class tst_TouchRegistry;
198− friend class tst_DirectionalDragArea;
199−};
200−
201−#endif // UNITY_TOUCHREGISTRY_H
libs/UbuntuGestures/UbuntuGesturesGlobal.hdeleted−23
@@ -1,23 +0,0 @@
1−/*
2− * Copyright (C) 2014 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#include <QtCore/QtGlobal>
18−
19−#if defined(UBUNTUGESTURES_LIBRARY)
20−# define UBUNTUGESTURES_EXPORT Q_DECL_EXPORT
21−#else
22−# define UBUNTUGESTURES_EXPORT Q_DECL_IMPORT
23−#endif
libs/UbuntuGestures/UnownedTouchEvent.cppdeleted−39
@@ -1,39 +0,0 @@
1−/*
2− * Copyright (C) 2014 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#include "UnownedTouchEvent.h"
18−
19−QEvent::Type UnownedTouchEvent::m_unownedTouchEventType = (QEvent::Type)-1;
20−
21−UnownedTouchEvent::UnownedTouchEvent(QTouchEvent *touchEvent)
22− : QEvent(unownedTouchEventType())
23− , m_touchEvent(touchEvent)
24−{
25−}
26−
27−QEvent::Type UnownedTouchEvent::unownedTouchEventType()
28−{
29− if (m_unownedTouchEventType == (QEvent::Type)-1) {
30− m_unownedTouchEventType = (QEvent::Type)registerEventType();
31− }
32−
33− return m_unownedTouchEventType;
34−}
35−
36−QTouchEvent *UnownedTouchEvent::touchEvent()
37−{
38− return m_touchEvent.data();
39−}
libs/UbuntuGestures/UnownedTouchEvent.hdeleted−45
@@ -1,45 +0,0 @@
1−/*
2− * Copyright (C) 2014 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#ifndef UBUNTU_UNOWNEDTOUCHEVENT_H
18−#define UBUNTU_UNOWNEDTOUCHEVENT_H
19−
20−#include <QTouchEvent>
21−#include <QScopedPointer>
22−#include "UbuntuGesturesGlobal.h"
23−
24−/*
25− A touch event with touch points that do not belong the item receiving it.
26−
27− See TouchRegistry::addCandidateOwnerForTouch and TouchRegistry::addTouchWatcher
28− */
29−class UBUNTUGESTURES_EXPORT UnownedTouchEvent : public QEvent
30−{
31−public:
32− UnownedTouchEvent(QTouchEvent *touchEvent);
33− static Type unownedTouchEventType();
34−
35− // TODO: It might be cleaner to store the information directly in UnownedTouchEvent
36− // instead of carrying around a synthesized QTouchEvent. But the latter option
37− // is very convenient.
38− QTouchEvent *touchEvent();
39−
40−private:
41− static Type m_unownedTouchEventType;
42− QScopedPointer<QTouchEvent> m_touchEvent;
43−};
44−
45−#endif // UBUNTU_UNOWNEDTOUCHEVENT_H
plugins/Cursor/CMakeLists.txt+2−1
@@ -8,8 +8,9 @@ include_directories(
8
8
9set(QMLPLUGIN_SRC
9set(QMLPLUGIN_SRC
10 plugin.cpp
10 plugin.cpp
11− MousePointer.cpp
11+ CursorImageInfo.cpp
12 CursorImageProvider.cpp
12 CursorImageProvider.cpp
13+ MousePointer.cpp
13 # We need to run moc on this header
14 # We need to run moc on this header
14 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirMousePointerInterface.h
15 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirMousePointerInterface.h
15 )
16 )
plugins/Cursor/Cursor.qml+21−5
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2015 Canonical, Ltd.
2+ * Copyright (C) 2015-2016 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
@@ -15,14 +15,30 @@
15 */
15 */
16
16
17import QtQuick 2.4
17import QtQuick 2.4
18−import Cursor 1.0 // For MousePointer
18+import Cursor 1.1
19
19
20MousePointer {
20MousePointer {
21 id: mousePointer
21 id: mousePointer
22
22
23− Image {
23+ CursorImageInfo {
24− x: -mousePointer.hotspotX
24+ id: imageInfo
25− y: -mousePointer.hotspotY
25+ themeName: mousePointer.themeName
26+ cursorName: mousePointer.cursorName
27+ }
28+
29+ AnimatedSprite {
30+ x: -imageInfo.hotspot.x
31+ y: -imageInfo.hotspot.y
26 source: "image://cursor/" + mousePointer.themeName + "/" + mousePointer.cursorName
32 source: "image://cursor/" + mousePointer.themeName + "/" + mousePointer.cursorName
33+
34+ interpolate: false
35+
36+ width: imageInfo.frameWidth
37+ height: imageInfo.frameHeight
38+
39+ frameCount: imageInfo.frameCount
40+ frameDuration: imageInfo.frameDuration
41+ frameWidth: imageInfo.frameWidth
42+ frameHeight: imageInfo.frameHeight
27 }
43 }
28}
44}
plugins/Cursor/Cursor.qmltypesdeleted−78
@@ -1,78 +0,0 @@
1−import QtQuick.tooling 1.1
2−
3−// This file describes the plugin-supplied types contained in the library.
4−// It is used for QML tooling purposes only.
5−//
6−// This file was auto-generated by:
7−// 'qmlplugindump -notrelocatable Cursor 1.0 plugins'
8−
9−Module {
10− Component {
11− name: "MirMousePointerInterface"
12− defaultProperty: "data"
13− prototype: "QQuickItem"
14− Property { name: "cursorName"; type: "string"; isReadonly: true }
15− Property { name: "themeName"; type: "string"; isReadonly: true }
16− Property { name: "hotspotX"; type: "double"; isReadonly: true }
17− Property { name: "hotspotY"; type: "double"; isReadonly: true }
18− Signal {
19− name: "cursorNameChanged"
20− Parameter { name: "name"; type: "string" }
21− }
22− Signal {
23− name: "themeNameChanged"
24− Parameter { name: "name"; type: "string" }
25− }
26− Signal {
27− name: "hotspotXChanged"
28− Parameter { name: "value"; type: "double" }
29− }
30− Signal {
31− name: "hotspotYChanged"
32− Parameter { name: "value"; type: "double" }
33− }
34− Method {
35− name: "handleMouseEvent"
36− Parameter { name: "timestamp"; type: "ulong" }
37− Parameter { name: "movement"; type: "QPointF" }
38− Parameter { name: "buttons"; type: "Qt::MouseButtons" }
39− Parameter { name: "modifiers"; type: "Qt::KeyboardModifiers" }
40− }
41− Method {
42− name: "handleWheelEvent"
43− Parameter { name: "timestamp"; type: "ulong" }
44− Parameter { name: "angleDelta"; type: "QPoint" }
45− Parameter { name: "modifiers"; type: "Qt::KeyboardModifiers" }
46− }
47− }
48− Component {
49− name: "MousePointer"
50− defaultProperty: "data"
51− prototype: "MirMousePointerInterface"
52− exports: ["Cursor/MousePointer 1.0"]
53− exportMetaObjectRevisions: [0]
54− Signal {
55− name: "pushedLeftBoundary"
56− Parameter { name: "amount"; type: "double" }
57− Parameter { name: "buttons"; type: "Qt::MouseButtons" }
58− }
59− Signal {
60− name: "pushedRightBoundary"
61− Parameter { name: "amount"; type: "double" }
62− Parameter { name: "buttons"; type: "Qt::MouseButtons" }
63− }
64− Method {
65− name: "handleMouseEvent"
66− Parameter { name: "timestamp"; type: "ulong" }
67− Parameter { name: "movement"; type: "QPointF" }
68− Parameter { name: "buttons"; type: "Qt::MouseButtons" }
69− Parameter { name: "modifiers"; type: "Qt::KeyboardModifiers" }
70− }
71− Method {
72− name: "handleWheelEvent"
73− Parameter { name: "timestamp"; type: "ulong" }
74− Parameter { name: "angleDelta"; type: "QPoint" }
75− Parameter { name: "modifiers"; type: "Qt::KeyboardModifiers" }
76− }
77− }
78−}
plugins/Cursor/CursorImageInfo.cppnew file+106
@@ -0,0 +1,106 @@
1+/*
2+ * Copyright (C) 2016 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include "CursorImageInfo.h"
18+
19+CursorImageInfo::CursorImageInfo(QObject *parent)
20+ : QObject(parent)
21+{
22+ m_updateTimer.setInterval(0);
23+ m_updateTimer.setSingleShot(true);
24+ connect(&m_updateTimer, &QTimer::timeout, this, &CursorImageInfo::update);
25+}
26+
27+void CursorImageInfo::setCursorName(const QString &cursorName)
28+{
29+ if (cursorName != m_cursorName) {
30+ m_cursorName = cursorName;
31+ Q_EMIT cursorNameChanged();
32+ scheduleUpdate();
33+ }
34+}
35+
36+void CursorImageInfo::setThemeName(const QString &themeName)
37+{
38+ if (m_themeName != themeName) {
39+ m_themeName = themeName;
40+ Q_EMIT themeNameChanged();
41+ scheduleUpdate();
42+ }
43+}
44+
45+void CursorImageInfo::scheduleUpdate()
46+{
47+ if (!m_updateTimer.isActive()) {
48+ m_updateTimer.start();
49+ }
50+}
51+
52+void CursorImageInfo::update()
53+{
54+ m_cursorImage = CursorImageProvider::instance()->fetchCursor(m_themeName, m_cursorName);
55+
56+ Q_EMIT hotspotChanged();
57+ Q_EMIT frameWidthChanged();
58+ Q_EMIT frameHeightChanged();
59+ Q_EMIT frameCountChanged();
60+ Q_EMIT frameDurationChanged();
61+}
62+
63+QPoint CursorImageInfo::hotspot() const
64+{
65+ if (m_cursorImage) {
66+ return m_cursorImage->hotspot;
67+ } else {
68+ return QPoint();
69+ }
70+}
71+
72+qreal CursorImageInfo::frameWidth() const
73+{
74+ if (m_cursorImage) {
75+ return m_cursorImage->frameWidth;
76+ } else {
77+ return 0;
78+ }
79+}
80+
81+qreal CursorImageInfo::frameHeight() const
82+{
83+ if (m_cursorImage) {
84+ return m_cursorImage->frameHeight;
85+ } else {
86+ return 0;
87+ }
88+}
89+
90+int CursorImageInfo::frameCount() const
91+{
92+ if (m_cursorImage) {
93+ return m_cursorImage->frameCount;
94+ } else {
95+ return 0;
96+ }
97+}
98+
99+int CursorImageInfo::frameDuration() const
100+{
101+ if (m_cursorImage) {
102+ return m_cursorImage->frameDuration;
103+ } else {
104+ return 0;
105+ }
106+}
plugins/Cursor/CursorImageInfo.hnew file+76
@@ -0,0 +1,76 @@
1+/*
2+ * Copyright (C) 2016 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#ifndef CURSOR_IMAGE_INFO_H
18+#define CURSOR_IMAGE_INFO_H
19+
20+#include "CursorImageProvider.h"
21+
22+#include <QObject>
23+#include <QString>
24+#include <QTimer>
25+
26+class CursorImageInfo : public QObject
27+{
28+ Q_OBJECT
29+
30+ Q_PROPERTY(QString themeName READ themeName WRITE setThemeName NOTIFY themeNameChanged)
31+ Q_PROPERTY(QString cursorName READ cursorName WRITE setCursorName NOTIFY cursorNameChanged)
32+
33+ Q_PROPERTY(QPoint hotspot READ hotspot NOTIFY hotspotChanged)
34+ Q_PROPERTY(qreal frameWidth READ frameWidth NOTIFY frameWidthChanged)
35+ Q_PROPERTY(qreal frameHeight READ frameHeight NOTIFY frameHeightChanged)
36+ Q_PROPERTY(int frameCount READ frameCount NOTIFY frameCountChanged)
37+ Q_PROPERTY(int frameDuration READ frameDuration NOTIFY frameDurationChanged)
38+
39+public:
40+ CursorImageInfo(QObject *parent = nullptr);
41+
42+ QString themeName() const { return m_themeName; }
43+ void setThemeName(const QString &);
44+
45+ QString cursorName() const { return m_cursorName; }
46+ void setCursorName(const QString &);
47+
48+ QPoint hotspot() const;
49+ qreal frameWidth() const;
50+ qreal frameHeight() const;
51+ int frameCount() const;
52+ int frameDuration() const;
53+
54+Q_SIGNALS:
55+ void themeNameChanged();
56+ void cursorNameChanged();
57+ void hotspotChanged();
58+ void frameWidthChanged();
59+ void frameHeightChanged();
60+ void frameCountChanged();
61+ void frameDurationChanged();
62+
63+private Q_SLOTS:
64+ void update();
65+
66+private:
67+ void scheduleUpdate();
68+ QTimer m_updateTimer;
69+
70+ QString m_themeName;
71+ QString m_cursorName;
72+
73+ CursorImage *m_cursorImage{nullptr};
74+};
75+
76+#endif // CURSOR_IMAGE_INFO_H
plugins/Cursor/CursorImageProvider.cpp+50−21
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2015 Canonical, Ltd.
2+ * Copyright (C) 2015-2016 Canonical, Ltd.
3 *
3 *
4 * This program is free software: you can redistribute it and/or modify it under
4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU Lesser General Public License version 3, as published by
5 * the terms of the GNU Lesser General Public License version 3, as published by
@@ -46,6 +46,9 @@ BuiltInCursorImage::BuiltInCursorImage()
46 qimage.fill(Qt::transparent);
46 qimage.fill(Qt::transparent);
47 QPainter imagePainter(&qimage);
47 QPainter imagePainter(&qimage);
48
48
49+ frameWidth = qimage.width();
50+ frameHeight = qimage.height();
51+
49 QSvgRenderer *svgRenderer = new QSvgRenderer(QByteArray(svgString));
52 QSvgRenderer *svgRenderer = new QSvgRenderer(QByteArray(svgString));
50 svgRenderer->render(&imagePainter);
53 svgRenderer->render(&imagePainter);
51 delete svgRenderer;
54 delete svgRenderer;
@@ -59,6 +62,8 @@ BlankCursorImage::BlankCursorImage()
59{
62{
60 qimage = QImage(1, 1, QImage::Format_ARGB32);
63 qimage = QImage(1, 1, QImage::Format_ARGB32);
61 qimage.fill(Qt::transparent);
64 qimage.fill(Qt::transparent);
65+ frameWidth = qimage.width();
66+ frameHeight = qimage.height();
62}
67}
63
68
64/////
69/////
@@ -69,40 +74,74 @@ CustomCursorImage::CustomCursorImage(const QCursor &cursor)
69{
74{
70 qimage = cursor.pixmap().toImage();
75 qimage = cursor.pixmap().toImage();
71 hotspot = cursor.hotSpot();
76 hotspot = cursor.hotSpot();
77+ frameWidth = qimage.width();
78+ frameHeight = qimage.height();
72}
79}
73
80
74/////
81/////
75// XCursorImage
82// XCursorImage
76
83
77XCursorImage::XCursorImage(const QString &theme, const QString &file)
84XCursorImage::XCursorImage(const QString &theme, const QString &file)
78− : xcursorImages(nullptr)
79{
85{
80 // TODO: Consider grid unit value
86 // TODO: Consider grid unit value
81 // Hardcoding to a medium size for now
87 // Hardcoding to a medium size for now
82 int preferredCursorHeightPx = 32;
88 int preferredCursorHeightPx = 32;
83
89
84− xcursorImages = XcursorLibraryLoadImages(QFile::encodeName(file), QFile::encodeName(theme),
90+ XcursorImages *xcursorImages = XcursorLibraryLoadImages(QFile::encodeName(file), QFile::encodeName(theme),
85 preferredCursorHeightPx);
91 preferredCursorHeightPx);
86− if (!xcursorImages) {
92+ if (!xcursorImages || xcursorImages->nimage == 0) {
87 return;
93 return;
88 }
94 }
89
95
90− // Just take the first one. It will have multiple images in case of an animated cursor.
96+ frameCount = xcursorImages->nimage;
91− // TODO: Support animated cursors
92− if ( xcursorImages->nimage > 0) {
93− XcursorImage *xcursorImage = xcursorImages->images[0];
94
97
95− qimage = QImage((uchar*)xcursorImage->pixels,
98+ for (int i = 0; i < xcursorImages->nimage; ++i) {
96− xcursorImage->width, xcursorImage->height, QImage::Format_ARGB32);
99+ XcursorImage *xcursorImage = xcursorImages->images[0];
100+ if (frameWidth < (int)xcursorImage->width) {
101+ frameWidth = xcursorImage->width;
102+ }
103+ if (frameHeight < (int)xcursorImage->height) {
104+ frameHeight = xcursorImage->height;
105+ }
106+ if (i == 0) {
107+ frameDuration = (int)xcursorImage->delay;
108+ } else {
109+ if (frameDuration != (int)xcursorImage->delay) {
110+ qWarning().nospace() << "CursorImageProvider: XCursorImage("<<theme<<","<<file<<") has"
111+ " varying delays in its animation. Animation won't look right.";
112+ }
113+ }
114+ }
97
115
116+ {
117+ // Assume that the hotspot position does not animate
118+ XcursorImage *xcursorImage = xcursorImages->images[0];
98 hotspot.setX(xcursorImage->xhot);
119 hotspot.setX(xcursorImage->xhot);
99 hotspot.setY(xcursorImage->yhot);
120 hotspot.setY(xcursorImage->yhot);
100 }
121 }
122+
123+ // Build the sprite as a single row of frames
124+ qimage = QImage(frameWidth*frameCount, frameHeight, QImage::Format_ARGB32);
125+ qimage.fill(Qt::transparent);
126+
127+ {
128+ QPainter painter(&qimage);
129+
130+ for (int i = 0; i < xcursorImages->nimage; ++i) {
131+ XcursorImage *xcursorImage = xcursorImages->images[i];
132+
133+ auto frameImage = QImage((uchar*)xcursorImage->pixels,
134+ xcursorImage->width, xcursorImage->height, QImage::Format_ARGB32);
135+
136+ painter.drawImage(QPoint(i*frameWidth, 0), frameImage);
137+ }
138+ }
139+
140+ XcursorImagesDestroy(xcursorImages);
101}
141}
102
142
103XCursorImage::~XCursorImage()
143XCursorImage::~XCursorImage()
104{
144{
105− XcursorImagesDestroy(xcursorImages);
106}
145}
107
146
108/////
147/////
@@ -205,16 +244,6 @@ QImage CursorImageProvider::requestImage(const QString &cursorThemeAndName, QSiz
205 return cursorImage->qimage;
244 return cursorImage->qimage;
206}
245}
207
246
208−QPoint CursorImageProvider::hotspot(const QString &themeName, const QString &cursorName)
209−{
210− CursorImage *cursorImage = fetchCursor(themeName, cursorName);
211− if (cursorImage) {
212− return cursorImage->hotspot;
213− } else {
214− return QPoint(0,0);
215− }
216−}
217−
218CursorImage *CursorImageProvider::fetchCursor(const QString &cursorThemeAndName)
247CursorImage *CursorImageProvider::fetchCursor(const QString &cursorThemeAndName)
219{
248{
220 QString themeName;
249 QString themeName;
plugins/Cursor/CursorImageProvider.h+12−4
@@ -31,15 +31,23 @@ public:
31 virtual ~CursorImage() {}
31 virtual ~CursorImage() {}
32
32
33 QImage qimage;
33 QImage qimage;
34+
35+ // TODO: consider if there's a need to animate the hotspot
36+ // ie, if there's a need to make it an array of points, one for each frame.
37+ // Maybe no single xcursor (or at least the ones we know of or use)
38+ // vary its hotspot position through its animation.
34 QPoint hotspot;
39 QPoint hotspot;
40+
41+ int frameWidth{0};
42+ int frameHeight{0};
43+ int frameCount{1};
44+ int frameDuration{40};
35};
45};
36
46
37class XCursorImage : public CursorImage {
47class XCursorImage : public CursorImage {
38public:
48public:
39 XCursorImage(const QString &theme, const QString &file);
49 XCursorImage(const QString &theme, const QString &file);
40 virtual ~XCursorImage();
50 virtual ~XCursorImage();
41−
42− XcursorImages *xcursorImages;
43};
51};
44
52
45class BuiltInCursorImage : public CursorImage {
53class BuiltInCursorImage : public CursorImage {
@@ -68,16 +76,16 @@ public:
68
76
69 QImage requestImage(const QString &cursorName, QSize *size, const QSize &requestedSize) override;
77 QImage requestImage(const QString &cursorName, QSize *size, const QSize &requestedSize) override;
70
78
71− QPoint hotspot(const QString &themeName, const QString &cursorName);
79+ CursorImage *fetchCursor(const QString &themeName, const QString &cursorName);
72
80
73 void setCustomCursor(const QCursor &customCursor);
81 void setCustomCursor(const QCursor &customCursor);
74
82
75private:
83private:
76 CursorImage *fetchCursor(const QString &cursorThemeAndName);
84 CursorImage *fetchCursor(const QString &cursorThemeAndName);
77− CursorImage *fetchCursor(const QString &themeName, const QString &cursorName);
78 CursorImage *fetchCursorHelper(const QString &themeName, const QString &cursorName);
85 CursorImage *fetchCursorHelper(const QString &themeName, const QString &cursorName);
79
86
80 // themeName -> (cursorName -> cursorImage)
87 // themeName -> (cursorName -> cursorImage)
88+ // TODO: discard old, unused, cursors
81 QMap<QString, QMap<QString, CursorImage*> > m_cursors;
89 QMap<QString, QMap<QString, CursorImage*> > m_cursors;
82
90
83 QScopedPointer<CursorImage> m_builtInCursorImage;
91 QScopedPointer<CursorImage> m_builtInCursorImage;
plugins/Cursor/MousePointer.cpp+29−24
@@ -29,10 +29,7 @@ MousePointer::MousePointer(QQuickItem *parent)
29 : MirMousePointerInterface(parent)
29 : MirMousePointerInterface(parent)
30 , m_cursorName(QStringLiteral("left_ptr"))
30 , m_cursorName(QStringLiteral("left_ptr"))
31 , m_themeName(QStringLiteral("default"))
31 , m_themeName(QStringLiteral("default"))
32− , m_hotspotX(0)
33− , m_hotspotY(0)
34{
32{
35− updateHotspot();
36}
33}
37
34
38void MousePointer::handleMouseEvent(ulong timestamp, QPointF movement, Qt::MouseButtons buttons,
35void MousePointer::handleMouseEvent(ulong timestamp, QPointF movement, Qt::MouseButtons buttons,
@@ -89,8 +86,32 @@ void MousePointer::itemChange(ItemChange change, const ItemChangeData &value)
89
86
90void MousePointer::registerWindow(QWindow *window)
87void MousePointer::registerWindow(QWindow *window)
91{
88{
89+ if (window == m_registeredWindow) {
90+ return;
91+ }
92+
93+ if (m_registeredWindow) {
94+ m_registeredWindow->disconnect(this);
95+ }
96+
92− if (m_registeredWindow && window != m_registeredWindow) {
97+ m_registeredWindow = window;
98+
99+ if (m_registeredWindow) {
100+ connect(window, &QWindow::screenChanged, this, &MousePointer::registerScreen);
101+ registerScreen(window->screen());
102+ } else {
103+ registerScreen(nullptr);
104+ }
105+}
106+
107+void MousePointer::registerScreen(QScreen *screen)
108+{
109+ if (m_registeredScreen == screen) {
110+ return;
111+ }
112+
113+ if (m_registeredScreen) {
93− auto previousCursor = dynamic_cast<MirPlatformCursor*>(m_registeredWindow->screen()->handle()->cursor());
114+ auto previousCursor = dynamic_cast<MirPlatformCursor*>(m_registeredScreen->handle()->cursor());
94 if (previousCursor) {
115 if (previousCursor) {
95 previousCursor->setMousePointer(nullptr);
116 previousCursor->setMousePointer(nullptr);
96 } else {
117 } else {
@@ -98,10 +119,10 @@ void MousePointer::registerWindow(QWindow *window)
98 }
119 }
99 }
120 }
100
121
101− m_registeredWindow = window;
122+ m_registeredScreen = screen;
102
123
103− if (m_registeredWindow) {
124+ if (m_registeredScreen) {
104− auto cursor = dynamic_cast<MirPlatformCursor*>(window->screen()->handle()->cursor());
125+ auto cursor = dynamic_cast<MirPlatformCursor*>(m_registeredScreen->handle()->cursor());
105 if (cursor) {
126 if (cursor) {
106 cursor->setMousePointer(this);
127 cursor->setMousePointer(this);
107 } else {
128 } else {
@@ -115,22 +136,6 @@ void MousePointer::setCursorName(const QString &cursorName)
115 if (cursorName != m_cursorName) {
136 if (cursorName != m_cursorName) {
116 m_cursorName = cursorName;
137 m_cursorName = cursorName;
117 Q_EMIT cursorNameChanged(m_cursorName);
138 Q_EMIT cursorNameChanged(m_cursorName);
118− updateHotspot();
119− }
120−}
121−
122−void MousePointer::updateHotspot()
123−{
124− QPoint newHotspot = CursorImageProvider::instance()->hotspot(m_themeName, m_cursorName);
125−
126− if (m_hotspotX != newHotspot.x()) {
127− m_hotspotX = newHotspot.x();
128− Q_EMIT hotspotXChanged(m_hotspotX);
129− }
130−
131− if (m_hotspotY != newHotspot.y()) {
132− m_hotspotY = newHotspot.y();
133− Q_EMIT hotspotYChanged(m_hotspotY);
134 }
139 }
135}
140}
136
141
plugins/Cursor/MousePointer.h+5−6
@@ -20,6 +20,7 @@
20// Qt
20// Qt
21#include <QPointer>
21#include <QPointer>
22#include <QWindow>
22#include <QWindow>
23+#include <QScreen>
23
24
24// Unity API
25// Unity API
25#include <unity/shell/application/MirMousePointerInterface.h>
26#include <unity/shell/application/MirMousePointerInterface.h>
@@ -35,9 +36,6 @@ public:
35 void setThemeName(const QString &themeName) override;
36 void setThemeName(const QString &themeName) override;
36 QString themeName() const override { return m_themeName; }
37 QString themeName() const override { return m_themeName; }
37
38
38− qreal hotspotX() const override { return m_hotspotX; }
39− qreal hotspotY() const override { return m_hotspotY; }
40−
41 void setCustomCursor(const QCursor &) override;
39 void setCustomCursor(const QCursor &) override;
42
40
43public Q_SLOTS:
41public Q_SLOTS:
@@ -53,15 +51,16 @@ Q_SIGNALS:
53protected:
51protected:
54 void itemChange(ItemChange change, const ItemChangeData &value) override;
52 void itemChange(ItemChange change, const ItemChangeData &value) override;
55
53
54+private Q_SLOTS:
55+ void registerScreen(QScreen *screen);
56+
56private:
57private:
57 void registerWindow(QWindow *window);
58 void registerWindow(QWindow *window);
58− void updateHotspot();
59
59
60 QPointer<QWindow> m_registeredWindow;
60 QPointer<QWindow> m_registeredWindow;
61+ QPointer<QScreen> m_registeredScreen;
61 QString m_cursorName;
62 QString m_cursorName;
62 QString m_themeName;
63 QString m_themeName;
63− int m_hotspotX;
64− int m_hotspotY;
65};
64};
66
65
67#endif // MOUSEPOINTER_H
66#endif // MOUSEPOINTER_H
plugins/Cursor/plugin.cpp+4−2
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2015 Canonical, Ltd.
2+ * Copyright (C) 2015-2016 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
@@ -22,13 +22,15 @@
22#include "plugin.h"
22#include "plugin.h"
23
23
24// local
24// local
25+#include "CursorImageInfo.h"
25#include "CursorImageProvider.h"
26#include "CursorImageProvider.h"
26#include "MousePointer.h"
27#include "MousePointer.h"
27
28
28void CursorPlugin::registerTypes(const char *uri)
29void CursorPlugin::registerTypes(const char *uri)
29{
30{
30 Q_ASSERT(uri == QLatin1String("Cursor"));
31 Q_ASSERT(uri == QLatin1String("Cursor"));
32+ qmlRegisterType<CursorImageInfo>(uri, 1, 1, "CursorImageInfo");
31− qmlRegisterType<MousePointer>(uri, 1, 0, "MousePointer");
33+ qmlRegisterType<MousePointer>(uri, 1, 1, "MousePointer");
32}
34}
33
35
34void CursorPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
36void CursorPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
plugins/Cursor/qmldir+1−1
@@ -1,3 +1,3 @@
1module Cursor
1module Cursor
2plugin Cursor-qml
2plugin Cursor-qml
3−Cursor 1.0 Cursor.qml
3+Cursor 1.1 Cursor.qml
plugins/Dash/AudioProgressBar.qml+1−1
@@ -49,6 +49,6 @@ Item {
49 rightMargin: maxWidth - (maxWidth * root.progress)
49 rightMargin: maxWidth - (maxWidth * root.progress)
50 }
50 }
51 height: units.dp(2)
51 height: units.dp(2)
52− backgroundColor: UbuntuColors.orange
52+ backgroundColor: theme.palette.normal.activity
53 }
53 }
54}
54}
plugins/Dash/CardCreator.js+64−48
@@ -59,14 +59,30 @@ var kBackgroundLoaderCode = 'Loader {\n\
59 } \n\
59 } \n\
60 }\n';
60 }\n';
61
61
62+// %1 is the aspect of the UbuntuShape
63+var kArtUbuntuShapeCode = 'UbuntuShape { \n\
64+ anchors.fill: parent; \n\
65+ source: artImage; \n\
66+ sourceFillMode: UbuntuShape.PreserveAspectCrop; \n\
67+ radius: "medium"; \n\
68+ aspect: %1; \n\
69+ }';
70+
71+var kArtProportionalShapeCode = 'ProportionalShape { \n\
72+ anchors.fill: parent; \n\
73+ source: artImage; \n\
74+ aspect: UbuntuShape.DropShadow; \n\
75+ }';
76+
62// %1 is used as anchors of artShapeHolder
77// %1 is used as anchors of artShapeHolder
63// %2 is used as image width
78// %2 is used as image width
64// %3 is used as image height
79// %3 is used as image height
65−// %4 is whether the image or the Loader with the UbuntuShape/ProportionalShape should be visible
80+// %4 is whether the image should be visible
66// %5 is used as aspect ratio fallback
81// %5 is used as aspect ratio fallback
67// %6 is whether the loader should be asynchronous or not
82// %6 is whether the loader should be asynchronous or not
83+// %7 is the shape code we want to use
68−// %7 is injected as code to artImage
84+// %8 is injected as code to artImage
69−// %8 is used as image fallback
85+// %9 is used as image fallback
70var kArtShapeHolderCode = 'Item { \n\
86var kArtShapeHolderCode = 'Item { \n\
71 id: artShapeHolder; \n\
87 id: artShapeHolder; \n\
72 height: root.fixedArtShapeSize.height > 0 ? root.fixedArtShapeSize.height : artShapeLoader.height; \n\
88 height: root.fixedArtShapeSize.height > 0 ? root.fixedArtShapeSize.height : artShapeLoader.height; \n\
@@ -75,7 +91,8 @@ var kArtShapeHolderCode = 'Item { \n\
75 Loader { \n\
91 Loader { \n\
76 id: artShapeLoader; \n\
92 id: artShapeLoader; \n\
77 objectName: "artShapeLoader"; \n\
93 objectName: "artShapeLoader"; \n\
78− readonly property string cardArt: cardData && cardData["art"] || %8; \n\
94+ readonly property string cardArt: cardData && cardData["art"] || %9; \n\
95+ onCardArtChanged: { if (item) { item.image.source = cardArt; } } \n\
79 active: cardArt != ""; \n\
96 active: cardArt != ""; \n\
80 asynchronous: %6; \n\
97 asynchronous: %6; \n\
81 visible: status == Loader.Ready; \n\
98 visible: status == Loader.Ready; \n\
@@ -84,31 +101,7 @@ var kArtShapeHolderCode = 'Item { \n\
84 objectName: "artShape"; \n\
101 objectName: "artShape"; \n\
85 visible: image.status == Image.Ready; \n\
102 visible: image.status == Image.Ready; \n\
86 readonly property alias image: artImage; \n\
103 readonly property alias image: artImage; \n\
87− Loader { \n\
88− anchors.fill: parent; \n\
89− visible: %4; \n\
90− sourceComponent: root.artShapeStyle === "icon" ? artShapeIconComponent : artShapeShapeComponent; \n\
91− Component { \n\
92− id: artShapeShapeComponent; \n\
93− UbuntuShape { \n\
94− source: artImage; \n\
95− sourceFillMode: UbuntuShape.PreserveAspectCrop; \n\
96− radius: "medium"; \n\
97− aspect: { \n\
98− switch (root.artShapeStyle) { \n\
99− case "inset": return UbuntuShape.Inset; \n\
100− case "shadow": return UbuntuShape.DropShadow; \n\
101− default: \n\
102− case "flat": return UbuntuShape.Flat; \n\
103− } \n\
104− } \n\
105− } \n\
106− } \n\
107− Component { \n\
108− id: artShapeIconComponent; \n\
109− ProportionalShape { source: artImage; aspect: UbuntuShape.DropShadow; } \n\
110− } \n\
111− } \n\
104+ %7 \n\
112 readonly property real fixedArtShapeSizeAspect: (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) ? root.fixedArtShapeSize.width / root.fixedArtShapeSize.height : -1; \n\
105 readonly property real fixedArtShapeSizeAspect: (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) ? root.fixedArtShapeSize.width / root.fixedArtShapeSize.height : -1; \n\
113 readonly property real aspect: fixedArtShapeSizeAspect > 0 ? fixedArtShapeSizeAspect : %5; \n\
106 readonly property real aspect: fixedArtShapeSizeAspect > 0 ? fixedArtShapeSizeAspect : %5; \n\
114 Component.onCompleted: { updateWidthHeightBindings(); } \n\
107 Component.onCompleted: { updateWidthHeightBindings(); } \n\
@@ -127,10 +120,10 @@ var kArtShapeHolderCode = 'Item { \n\
127 objectName: "artImage"; \n\
120 objectName: "artImage"; \n\
128 source: artShapeLoader.cardArt; \n\
121 source: artShapeLoader.cardArt; \n\
129 asynchronous: %6; \n\
122 asynchronous: %6; \n\
130− visible: !%4; \n\
123+ visible: %4; \n\
131 width: %2; \n\
124 width: %2; \n\
132 height: %3; \n\
125 height: %3; \n\
133− %7 \n\
126+ %8 \n\
134 } \n\
127 } \n\
135 } \n\
128 } \n\
136 } \n\
129 } \n\
@@ -318,7 +311,7 @@ var kTouchdownCode = 'UbuntuShape { \n\
318 id: touchdown; \n\
311 id: touchdown; \n\
319 objectName: "touchdown"; \n\
312 objectName: "touchdown"; \n\
320 anchors { %1 } \n\
313 anchors { %1 } \n\
321− visible: root.artShapeStyle != "shadow" && root.artShapeStyle != "icon" && root.pressed; \n\
314+ visible: root.pressed; \n\
322 radius: "medium"; \n\
315 radius: "medium"; \n\
323 borderSource: "radius_pressed.sci" \n\
316 borderSource: "radius_pressed.sci" \n\
324 }\n';
317 }\n';
@@ -412,7 +405,7 @@ function sanitizeColor(colorString) {
412 return colorString;
405 return colorString;
413}
406}
414
407
415−function cardString(template, components, isCardTool) {
408+function cardString(template, components, isCardTool, artShapeStyle) {
416 var code;
409 var code;
417
410
418 var templateInteractive = (template == null ? true : (template["non-interactive"] !== undefined ? !template["non-interactive"] : true)) ? "true" : "false";
411 var templateInteractive = (template == null ? true : (template["non-interactive"] !== undefined ? !template["non-interactive"] : true)) ? "true" : "false";
@@ -420,7 +413,6 @@ function cardString(template, components, isCardTool) {
420 code = 'AbstractButton { \n\
413 code = 'AbstractButton { \n\
421 id: root; \n\
414 id: root; \n\
422 property var cardData; \n\
415 property var cardData; \n\
423− property string artShapeStyle: "inset"; \n\
424 property string backgroundShapeStyle: "inset"; \n\
416 property string backgroundShapeStyle: "inset"; \n\
425 property real fontScale: 1.0; \n\
417 property real fontScale: 1.0; \n\
426 property var scopeStyle: null; \n\
418 property var scopeStyle: null; \n\
@@ -519,17 +511,35 @@ function cardString(template, components, isCardTool) {
519 var fallbackStatusCode = "";
511 var fallbackStatusCode = "";
520 var fallbackURICode = '""';
512 var fallbackURICode = '""';
521 if (fallback !== "") {
513 if (fallback !== "") {
522− // fallbackStatusCode has %6 in it because we want to substitute it for fallbackURICode
514+ // fallbackStatusCode has %9 in it because we want to substitute it for fallbackURICode
523− // which in kArtShapeHolderCode is %8
515+ // which in kArtShapeHolderCode is %9
524− fallbackStatusCode += 'onStatusChanged: if (status === Image.Error) source = %8;';
516+ fallbackStatusCode += 'onStatusChanged: if (status === Image.Error) source = %9;';
525 fallbackURICode = 'decodeURI("%1")'.arg(fallback);
517 fallbackURICode = 'decodeURI("%1")'.arg(fallback);
526 }
518 }
519+ var artShapeHolderShapeCode;
520+ if (!isConciergeMode) {
521+ if (artShapeStyle === "icon") {
522+ artShapeHolderShapeCode = kArtProportionalShapeCode;
523+ } else {
524+ var artShapeHolderShapeAspect;
525+ switch (artShapeStyle) {
526+ case "inset": artShapeHolderShapeAspect = "UbuntuShape.Inset"; break;
527+ case "shadow": artShapeHolderShapeAspect = "UbuntuShape.DropShadow"; break;
528+ default:
529+ case "flat": artShapeHolderShapeAspect = "UbuntuShape.Flat"; break;
530+ }
531+ artShapeHolderShapeCode = kArtUbuntuShapeCode.arg(artShapeHolderShapeAspect);
532+ }
533+ } else {
534+ artShapeHolderShapeCode = "";
535+ }
527 code += kArtShapeHolderCode.arg(artAnchors)
536 code += kArtShapeHolderCode.arg(artAnchors)
528 .arg(widthCode)
537 .arg(widthCode)
529 .arg(heightCode)
538 .arg(heightCode)
530− .arg(isConciergeMode ? "false" : "true")
539+ .arg(isConciergeMode ? "true" : "false")
531 .arg(aspectRatio)
540 .arg(aspectRatio)
532 .arg(asynchronous)
541 .arg(asynchronous)
542+ .arg(artShapeHolderShapeCode)
533 .arg(fallbackStatusCode)
543 .arg(fallbackStatusCode)
534 .arg(fallbackURICode);
544 .arg(fallbackURICode);
535 } else {
545 } else {
@@ -854,6 +864,10 @@ function cardString(template, components, isCardTool) {
854 code += kSummaryLabelCode.arg(summaryTopAnchor).arg(summaryTopMargin).arg(summaryColor);
864 code += kSummaryLabelCode.arg(summaryTopAnchor).arg(summaryTopMargin).arg(summaryColor);
855 }
865 }
856
866
867+// <<<<<<< TREE
868+// if (artShapeStyle != "shadow" && artShapeStyle != "icon") {
869+// var touchdownAnchors;
870+// =======
857 if (hasSocialActions) {
871 if (hasSocialActions) {
858 var socialAnchors;
872 var socialAnchors;
859 var socialTopAnchor;
873 var socialTopAnchor;
@@ -882,15 +896,17 @@ function cardString(template, components, isCardTool) {
882 code += kSocialActionsRowCode.arg(socialAnchors).arg(socialColor);
896 code += kSocialActionsRowCode.arg(socialAnchors).arg(socialColor);
883 }
897 }
884
898
899+ if (artShapeStyle != "shadow" && artShapeStyle != "icon") {
885− var touchdownAnchors;
900+ var touchdownAnchors;
886− if (hasBackground) {
901+ if (hasBackground) {
887− touchdownAnchors = 'fill: backgroundLoader';
902+ touchdownAnchors = 'fill: backgroundLoader';
888− } else if (touchdownOnArtShape) {
903+ } else if (touchdownOnArtShape) {
889− touchdownAnchors = 'fill: artShapeHolder';
904+ touchdownAnchors = 'fill: artShapeHolder';
890− } else {
905+ } else {
891− touchdownAnchors = 'fill: root'
906+ touchdownAnchors = 'fill: root'
907+ }
908+ code += kTouchdownCode.arg(touchdownAnchors);
892 }
909 }
893− code += kTouchdownCode.arg(touchdownAnchors);
894
910
895 var implicitHeight = 'implicitHeight: ';
911 var implicitHeight = 'implicitHeight: ';
896 if (hasSocialActions) {
912 if (hasSocialActions) {
@@ -925,13 +941,13 @@ function cardString(template, components, isCardTool) {
925 return code;
941 return code;
926}
942}
927
943
928−function createCardComponent(parent, template, components, isCardTool, identifier) {
944+function createCardComponent(parent, template, components, isCardTool, artShapeStyle, identifier) {
929 var imports = 'import QtQuick 2.4; \n\
945 var imports = 'import QtQuick 2.4; \n\
930 import Ubuntu.Components 1.3; \n\
946 import Ubuntu.Components 1.3; \n\
931 import Ubuntu.Settings.Components 0.1; \n\
947 import Ubuntu.Settings.Components 0.1; \n\
932 import Dash 0.1;\n\
948 import Dash 0.1;\n\
933 import Utils 0.1;\n';
949 import Utils 0.1;\n';
934− var card = cardString(template, components, isCardTool);
950+ var card = cardString(template, components, isCardTool, artShapeStyle);
935 var code = imports + 'Component {\n' + card + '}\n';
951 var code = imports + 'Component {\n' + card + '}\n';
936
952
937 try {
953 try {
plugins/Dash/CardCreatorCache.qml+2−2
@@ -23,7 +23,7 @@ QtObject {
23
23
24 property var cache: new Object();
24 property var cache: new Object();
25
25
26− function getCardComponent(template, components, isCardTool) {
26+ function getCardComponent(template, components, isCardTool, artShapeStyle) {
27 if (template === undefined || components === undefined)
27 if (template === undefined || components === undefined)
28 return undefined;
28 return undefined;
29
29
@@ -32,7 +32,7 @@ QtObject {
32 var allString = tString + cString + isCardTool;
32 var allString = tString + cString + isCardTool;
33 var component = cache[allString];
33 var component = cache[allString];
34 if (component === undefined) {
34 if (component === undefined) {
35− component = CardCreator.createCardComponent(root, template, components, isCardTool, allString);
35+ component = CardCreator.createCardComponent(root, template, components, isCardTool, artShapeStyle, allString);
36 cache[allString] = component;
36 cache[allString] = component;
37 }
37 }
38 return component;
38 return component;
plugins/Dash/ScopeStyle.qml+1−1
@@ -70,7 +70,7 @@ QtObject {
70 readonly property url navigationBackground: "navigation-background" in d.headerStyle ? d.headerStyle["navigation-background"] : "color:///#f5f5f5"
70 readonly property url navigationBackground: "navigation-background" in d.headerStyle ? d.headerStyle["navigation-background"] : "color:///#f5f5f5"
71
71
72 /// Color of the primary preview button
72 /// Color of the primary preview button
73− readonly property color previewButtonColor: "preview-button-color" in style ? style["preview-button-color"] : UbuntuColors.orange
73+ readonly property color previewButtonColor: "preview-button-color" in style ? style["preview-button-color"] : theme.palette.normal.positive
74
74
75 //! @cond
75 //! @cond
76 property var d: QtObject {
76 property var d: QtObject {
plugins/Dash/listviewwithpageheader.cpp+14−17
@@ -97,6 +97,7 @@
97#include <qqmlengine.h>
97#include <qqmlengine.h>
98#pragma GCC diagnostic push
98#pragma GCC diagnostic push
99#pragma GCC diagnostic ignored "-pedantic"
99#pragma GCC diagnostic ignored "-pedantic"
100+#include <private/qqmlcontext_p.h>
100#include <private/qqmldelegatemodel_p.h>
101#include <private/qqmldelegatemodel_p.h>
101#include <private/qqmlglobal_p.h>
102#include <private/qqmlglobal_p.h>
102#include <private/qquickitem_p.h>
103#include <private/qquickitem_p.h>
@@ -168,7 +169,7 @@ ListViewWithPageHeader::ListViewWithPageHeader()
168 m_contentYAnimation->setDuration(200);
169 m_contentYAnimation->setDuration(200);
169 m_contentYAnimation->setTargetObject(this);
170 m_contentYAnimation->setTargetObject(this);
170
171
171− connect(this, &ListViewWithPageHeader::contentWidthChanged, this, &ListViewWithPageHeader::onContentWidthChanged);
172+ connect(contentItem(), &QQuickItem::widthChanged, this, &ListViewWithPageHeader::onContentWidthChanged);
172 connect(this, &ListViewWithPageHeader::contentHeightChanged, this, &ListViewWithPageHeader::onContentHeightChanged);
173 connect(this, &ListViewWithPageHeader::contentHeightChanged, this, &ListViewWithPageHeader::onContentHeightChanged);
173 connect(this, &ListViewWithPageHeader::heightChanged, this, &ListViewWithPageHeader::onHeightChanged);
174 connect(this, &ListViewWithPageHeader::heightChanged, this, &ListViewWithPageHeader::onHeightChanged);
174 connect(m_contentYAnimation, &QQuickNumberAnimation::runningChanged, this, &ListViewWithPageHeader::contentYAnimationRunningChanged);
175 connect(m_contentYAnimation, &QQuickNumberAnimation::runningChanged, this, &ListViewWithPageHeader::contentYAnimationRunningChanged);
@@ -757,8 +758,6 @@ QQuickItem *ListViewWithPageHeader::getSectionItem(const QString &sectionText, b
757
758
758 QQmlContext *creationContext = m_sectionDelegate->creationContext();
759 QQmlContext *creationContext = m_sectionDelegate->creationContext();
759 QQmlContext *context = new QQmlContext(creationContext ? creationContext : qmlContext(this));
760 QQmlContext *context = new QQmlContext(creationContext ? creationContext : qmlContext(this));
760− context->setContextProperty(QStringLiteral("section"), sectionText);
761− context->setContextProperty(QStringLiteral("delegateIndex"), -1);
762 QObject *nobj = m_sectionDelegate->beginCreate(context);
761 QObject *nobj = m_sectionDelegate->beginCreate(context);
763 if (nobj) {
762 if (nobj) {
764 QQml_setParent_noEvent(context, nobj);
763 QQml_setParent_noEvent(context, nobj);
@@ -766,6 +765,8 @@ QQuickItem *ListViewWithPageHeader::getSectionItem(const QString &sectionText, b
766 if (!sectionItem) {
765 if (!sectionItem) {
767 delete nobj;
766 delete nobj;
768 } else {
767 } else {
768+ sectionItem->setProperty("text", sectionText);
769+ sectionItem->setProperty("delegateIndex", -1);
769 sectionItem->setZ(2);
770 sectionItem->setZ(2);
770 QQml_setParent_noEvent(sectionItem, m_clipItem);
771 QQml_setParent_noEvent(sectionItem, m_clipItem);
771 sectionItem->setParentItem(m_clipItem);
772 sectionItem->setParentItem(m_clipItem);
@@ -801,8 +802,7 @@ void ListViewWithPageHeader::updateSectionItem(int modelIndex)
801 if (!item->sectionItem()) {
802 if (!item->sectionItem()) {
802 item->setSectionItem(getSectionItem(sectionText));
803 item->setSectionItem(getSectionItem(sectionText));
803 } else {
804 } else {
804− QQmlContext *context = QQmlEngine::contextForObject(item->sectionItem())->parentContext();
805+ item->sectionItem()->setProperty("text", sectionText);
805− context->setContextProperty(QStringLiteral("section"), sectionText);
806 }
806 }
807 } else {
807 } else {
808 if (item->sectionItem()) {
808 if (item->sectionItem()) {
@@ -923,8 +923,7 @@ ListViewWithPageHeader::ListItem *ListViewWithPageHeader::createItem(int modelIn
923 polish();
923 polish();
924 }
924 }
925 if (listItem->sectionItem()) {
925 if (listItem->sectionItem()) {
926− QQmlContext *context = QQmlEngine::contextForObject(listItem->sectionItem())->parentContext();
927− context->setContextProperty(QStringLiteral("delegateIndex"), modelIndex);
926+ listItem->sectionItem()->setProperty("delegateIndex", modelIndex);
928 }
927 }
929 adjustMinYExtent();
928 adjustMinYExtent();
930 m_contentHeightDirty = true;
929 m_contentHeightDirty = true;
@@ -948,9 +947,10 @@ void ListViewWithPageHeader::itemCreated(int modelIndex, QObject *object)
948 return;
947 return;
949
948
950 item->setParentItem(m_clipItem);
949 item->setParentItem(m_clipItem);
950+ // FIXME Why do we need the refreshExpressions call?
951 QQmlContext *context = QQmlEngine::contextForObject(item)->parentContext();
951 QQmlContext *context = QQmlEngine::contextForObject(item)->parentContext();
952− context->setContextProperty(QStringLiteral("ListViewWithPageHeader"), this);
952+ QQmlContextPrivate::get(context)->data->refreshExpressions();
953− context->setContextProperty(QStringLiteral("heightToClip"), QVariant::fromValue<int>(0));
953+ item->setProperty("heightToClip", QVariant::fromValue<int>(0));
954 if (modelIndex == m_asyncRequestedIndex) {
954 if (modelIndex == m_asyncRequestedIndex) {
955 createItem(modelIndex, false);
955 createItem(modelIndex, false);
956 refill();
956 refill();
@@ -1116,8 +1116,7 @@ void ListViewWithPageHeader::onModelUpdated(const QQmlChangeSet &changeSet, bool
1116 for (int i = 0; i < m_visibleItems.count(); ++i) {
1116 for (int i = 0; i < m_visibleItems.count(); ++i) {
1117 ListItem *item = m_visibleItems[i];
1117 ListItem *item = m_visibleItems[i];
1118 if (item->sectionItem()) {
1118 if (item->sectionItem()) {
1119− QQmlContext *context = QQmlEngine::contextForObject(item->sectionItem())->parentContext();
1120− context->setContextProperty(QStringLiteral("delegateIndex"), m_firstVisibleIndex + i);
1119+ item->sectionItem()->setProperty("delegateIndex", m_firstVisibleIndex + i);
1121 }
1120 }
1122 }
1121 }
1123
1122
@@ -1287,8 +1286,7 @@ void ListViewWithPageHeader::layout()
1287 } else {
1286 } else {
1288 // Update the top sticky section header
1287 // Update the top sticky section header
1289 const QString section = m_delegateModel->stringValue(modelIndex, m_sectionProperty);
1288 const QString section = m_delegateModel->stringValue(modelIndex, m_sectionProperty);
1290− QQmlContext *context = QQmlEngine::contextForObject(m_topSectionItem)->parentContext();
1289+ m_topSectionItem->setProperty("text", section);
1291− context->setContextProperty(QStringLiteral("section"), section);
1292
1290
1293 QQuickItemPrivate::get(m_topSectionItem)->setCulled(false);
1291 QQuickItemPrivate::get(m_topSectionItem)->setCulled(false);
1294 m_topSectionItem->setY(topSectionStickPos);
1292 m_topSectionItem->setY(topSectionStickPos);
@@ -1300,19 +1298,18 @@ void ListViewWithPageHeader::layout()
1300 break;
1298 break;
1301 delegateIndex--;
1299 delegateIndex--;
1302 }
1300 }
1303− context->setContextProperty(QStringLiteral("delegateIndex"), delegateIndex);
1301+ m_topSectionItem->setProperty("delegateIndex", delegateIndex);
1304 if (item->sectionItem()) {
1302 if (item->sectionItem()) {
1305 QQuickItemPrivate::get(item->sectionItem())->setCulled(true);
1303 QQuickItemPrivate::get(item->sectionItem())->setCulled(true);
1306 }
1304 }
1307 }
1305 }
1308 }
1306 }
1309 }
1307 }
1310− QQmlContext *context = QQmlEngine::contextForObject(item->m_item)->parentContext();
1311 const qreal clipFrom = visibleFrom + (!item->sectionItem() && m_topSectionItem && !QQuickItemPrivate::get(m_topSectionItem)->culled ? m_topSectionItem->height() : 0);
1308 const qreal clipFrom = visibleFrom + (!item->sectionItem() && m_topSectionItem && !QQuickItemPrivate::get(m_topSectionItem)->culled ? m_topSectionItem->height() : 0);
1312 if (!cull && pos < clipFrom) {
1309 if (!cull && pos < clipFrom) {
1313− context->setContextProperty(QStringLiteral("heightToClip"), clipFrom - pos);
1310+ item->m_item->setProperty("heightToClip", clipFrom - pos);
1314 } else {
1311 } else {
1315− context->setContextProperty(QStringLiteral("heightToClip"), QVariant::fromValue<int>(0));
1312+ item->m_item->setProperty("heightToClip", QVariant::fromValue<int>(0));
1316 }
1313 }
1317// qDebug() << "ListViewWithPageHeader::layout" << item->m_item;
1314// qDebug() << "ListViewWithPageHeader::layout" << item->m_item;
1318 pos += item->height();
1315 pos += item->height();
plugins/Ubuntu/Gestures/AxisVelocityCalculator.h+1−1
@@ -24,7 +24,7 @@
24#include "UbuntuGesturesQmlGlobal.h"
24#include "UbuntuGesturesQmlGlobal.h"
25#include <stdint.h>
25#include <stdint.h>
26#include <QtCore/QObject>
26#include <QtCore/QObject>
27−#include "TimeSource.h"
27+#include <TimeSource>
28
28
29/*
29/*
30 Estimates the current velocity of a finger based on recent movement along an axis
30 Estimates the current velocity of a finger based on recent movement along an axis
plugins/Ubuntu/Gestures/CMakeLists.txt+9−4
@@ -4,27 +4,32 @@ remove_definitions(-DQT_NO_KEYWORDS)
4set(UbuntuGesturesQml_SOURCES
4set(UbuntuGesturesQml_SOURCES
5 plugin.cpp
5 plugin.cpp
6 AxisVelocityCalculator.cpp
6 AxisVelocityCalculator.cpp
7− Damper.cpp
8 Direction.cpp
7 Direction.cpp
9− DirectionalDragArea.cpp
8+ MouseEventGenerator.cpp
10− FloatingFlickable.cpp
11 PressedOutsideNotifier.cpp
9 PressedOutsideNotifier.cpp
12 TouchDispatcher.cpp
10 TouchDispatcher.cpp
13 TouchGate.cpp
11 TouchGate.cpp
14 TouchGestureArea.cpp
12 TouchGestureArea.cpp
15)
13)
16
14
15+pkg_check_modules(UBUNTUGESTURES REQUIRED UbuntuGestures)
16+
17add_definitions(-DUBUNTUGESTURESQML_LIBRARY)
17add_definitions(-DUBUNTUGESTURESQML_LIBRARY)
18
18
19+<<<<<<< TREE
19add_library(UbuntuGesturesQml SHARED ${UbuntuGesturesQml_SOURCES})
20add_library(UbuntuGesturesQml SHARED ${UbuntuGesturesQml_SOURCES})
20target_link_libraries(UbuntuGesturesQml UbuntuGestures)
21target_link_libraries(UbuntuGesturesQml UbuntuGestures)
22+=======
23+add_library(UbuntuGesturesQml MODULE ${UbuntuGesturesQml_SOURCES})
24+target_link_libraries(UbuntuGesturesQml ${UBUNTUGESTURES_LIBRARIES})
25+>>>>>>> MERGE-SOURCE
21
26
22qt5_use_modules(UbuntuGesturesQml Core Quick)
27qt5_use_modules(UbuntuGesturesQml Core Quick)
23
28
24# So that Foo.cpp can #include "Foo.moc"
29# So that Foo.cpp can #include "Foo.moc"
25include_directories(${CMAKE_CURRENT_BINARY_DIR})
30include_directories(${CMAKE_CURRENT_BINARY_DIR})
26
31
27−include_directories(${CMAKE_SOURCE_DIR}/libs/UbuntuGestures)
32+include_directories(${UBUNTUGESTURES_INCLUDE_DIRS})
28
33
29# There's no cmake var for v8 include path :-/ so create one
34# There's no cmake var for v8 include path :-/ so create one
30LIST(GET Qt5Core_INCLUDE_DIRS 0 QtCoreDir0)
35LIST(GET Qt5Core_INCLUDE_DIRS 0 QtCoreDir0)
plugins/Ubuntu/Gestures/Damper.cppdeleted−24
@@ -1,24 +0,0 @@
1−/*
2− * Copyright (C) 2015 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#include "Damper.h"
18−#include <QDebug>
19−
20−QDebug operator<<(QDebug dbg, const DampedPointF &p)
21−{
22− dbg.nospace() << "(" << p.x() << ", " << p.y() << ")";
23− return dbg.space();
24−}
plugins/Ubuntu/Gestures/Damper.hdeleted−89
@@ -1,89 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#ifndef UBUNTU_GESTURES_DAMPER_H
18−#define UBUNTU_GESTURES_DAMPER_H
19−
20−#include <QtCore/QPointF>
21−
22−/*
23− Decreases the oscillations of a value along an axis.
24− */
25−template <class Type> class Damper {
26−public:
27− Damper() : m_value(0), m_maxDelta(0) { }
28−
29− // Maximum delta between the raw value and its dampened counterpart.
30− void setMaxDelta(Type maxDelta) {
31− if (maxDelta < 0) qFatal("Damper::maxDelta must be a positive number.");
32− m_maxDelta = maxDelta;
33− }
34− Type maxDelta() const { return m_maxDelta; }
35−
36− void reset(Type value) {
37− m_value = value;
38− }
39−
40− Type update(Type value) {
41− Type delta = value - m_value;
42− if (delta > 0 && delta > m_maxDelta) {
43− m_value += delta - m_maxDelta;
44− } else if (delta < 0 && delta < -m_maxDelta) {
45− m_value += delta + m_maxDelta;
46− }
47−
48− return m_value;
49− }
50−
51− Type value() const { return m_value; }
52−
53−private:
54− Type m_value;
55− Type m_maxDelta;
56−};
57−
58−/*
59− A point that has its movement dampened.
60− */
61−class DampedPointF {
62−public:
63− void setMaxDelta(qreal maxDelta) {
64− m_x.setMaxDelta(maxDelta);
65− m_y.setMaxDelta(maxDelta);
66− }
67−
68− qreal maxDelta() const { return m_x.maxDelta(); }
69−
70− void reset(const QPointF point) {
71− m_x.reset(point.x());
72− m_y.reset(point.y());
73− }
74−
75− void update(const QPointF point) {
76− m_x.update(point.x());
77− m_y.update(point.y());
78− }
79−
80− qreal x() const { return m_x.value(); }
81− qreal y() const { return m_y.value(); }
82−private:
83− Damper<qreal> m_x;
84− Damper<qreal> m_y;
85−};
86−
87−QDebug operator<<(QDebug dbg, const DampedPointF &p);
88−
89−#endif // UBUNTU_GESTURES_DAMPER_H
plugins/Ubuntu/Gestures/Direction.h+1
@@ -29,6 +29,7 @@ class UBUNTUGESTURESQML_EXPORT Direction : public QObject {
29 Q_ENUMS(Type)
29 Q_ENUMS(Type)
30
30
31public:
31public:
32+ // Make sure it is kept synchronized with SDK UCSwipeArea::Direction
32 enum Type {
33 enum Type {
33 Rightwards, // Along the positive direction of the X axis
34 Rightwards, // Along the positive direction of the X axis
34 Leftwards, // Along the negative direction of the X axis
35 Leftwards, // Along the negative direction of the X axis
plugins/Ubuntu/Gestures/DirectionalDragArea.cppdeleted−932
@@ -1,932 +0,0 @@
1−/*
2− * Copyright (C) 2013-2015 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−#define ACTIVETOUCHESINFO_DEBUG 0
18−#define DIRECTIONALDRAGAREA_DEBUG 0
19−
20−#include "DirectionalDragArea.h"
21−
22−#include <QQuickWindow>
23−#include <QtCore/qmath.h>
24−#include <QScreen>
25−#include <QDebug>
26−
27−#pragma GCC diagnostic push
28−#pragma GCC diagnostic ignored "-pedantic"
29−#include <private/qquickwindow_p.h>
30−#pragma GCC diagnostic pop
31−
32−// local
33−#include "TouchOwnershipEvent.h"
34−#include "TouchRegistry.h"
35−#include "UnownedTouchEvent.h"
36−
37−#include "DirectionalDragArea_p.h"
38−
39−using namespace UbuntuGestures;
40−
41−#if DIRECTIONALDRAGAREA_DEBUG
42−#define ddaDebug(params) qDebug().nospace() << "[DDA(" << qPrintable(objectName()) << ")] " << params
43−#include "DebugHelpers.h"
44−
45−namespace {
46−const char *statusToString(DirectionalDragAreaPrivate::Status status)
47−{
48− if (status == DirectionalDragAreaPrivate::WaitingForTouch) {
49− return "WaitingForTouch";
50− } else if (status == DirectionalDragAreaPrivate::Undecided) {
51− return "Undecided";
52− } else {
53− return "Recognized";
54− }
55−}
56−
57−} // namespace {
58−#else // DIRECTIONALDRAGAREA_DEBUG
59−#define ddaDebug(params) ((void)0)
60−#endif // DIRECTIONALDRAGAREA_DEBUG
61−
62−DirectionalDragArea::DirectionalDragArea(QQuickItem *parent)
63− : QQuickItem(parent)
64− , d(new DirectionalDragAreaPrivate(this))
65−{
66− d->setRecognitionTimer(new Timer(this));
67− d->recognitionTimer->setInterval(d->maxTime);
68− d->recognitionTimer->setSingleShot(true);
69−
70− connect(this, &QQuickItem::enabledChanged, d, &DirectionalDragAreaPrivate::giveUpIfDisabledOrInvisible);
71− connect(this, &QQuickItem::visibleChanged, d, &DirectionalDragAreaPrivate::giveUpIfDisabledOrInvisible);
72−}
73−
74−Direction::Type DirectionalDragArea::direction() const
75−{
76− return d->direction;
77−}
78−
79−void DirectionalDragArea::setDirection(Direction::Type direction)
80−{
81− if (direction != d->direction) {
82− d->direction = direction;
83− Q_EMIT directionChanged(d->direction);
84− }
85−}
86−
87−void DirectionalDragAreaPrivate::setDistanceThreshold(qreal value)
88−{
89− if (distanceThreshold != value) {
90− distanceThreshold = value;
91− distanceThresholdSquared = distanceThreshold * distanceThreshold;
92− }
93−}
94−
95−void DirectionalDragAreaPrivate::setMaxTime(int value)
96−{
97− if (maxTime != value) {
98− maxTime = value;
99− recognitionTimer->setInterval(maxTime);
100− }
101−}
102−
103−void DirectionalDragAreaPrivate::setRecognitionTimer(UbuntuGestures::AbstractTimer *timer)
104−{
105− int interval = 0;
106− bool timerWasRunning = false;
107− bool wasSingleShot = false;
108−
109− // can be null when called from the constructor
110− if (recognitionTimer) {
111− interval = recognitionTimer->interval();
112− timerWasRunning = recognitionTimer->isRunning();
113− if (recognitionTimer->parent() == this) {
114− delete recognitionTimer;
115− }
116− }
117−
118− recognitionTimer = timer;
119− timer->setInterval(interval);
120− timer->setSingleShot(wasSingleShot);
121− connect(timer, &UbuntuGestures::AbstractTimer::timeout,
122− this, &DirectionalDragAreaPrivate::rejectGesture);
123− if (timerWasRunning) {
124− recognitionTimer->start();
125− }
126−}
127−
128−void DirectionalDragAreaPrivate::setTimeSource(const SharedTimeSource &timeSource)
129−{
130− this->timeSource = timeSource;
131− activeTouches.m_timeSource = timeSource;
132−}
133−
134−qreal DirectionalDragArea::distance() const
135−{
136− if (Direction::isHorizontal(d->direction)) {
137− return d->publicPos.x() - d->startPos.x();
138− } else {
139− return d->publicPos.y() - d->startPos.y();
140− }
141−}
142−
143−void DirectionalDragAreaPrivate::updateSceneDistance()
144−{
145− QPointF totalMovement = publicScenePos - startScenePos;
146− sceneDistance = projectOntoDirectionVector(totalMovement);
147−}
148−
149−qreal DirectionalDragArea::sceneDistance() const
150−{
151− return d->sceneDistance;
152−}
153−
154−qreal DirectionalDragArea::touchX() const
155−{
156− return d->publicPos.x();
157−}
158−
159−qreal DirectionalDragArea::touchY() const
160−{
161− return d->publicPos.y();
162−}
163−
164−qreal DirectionalDragArea::touchSceneX() const
165−{
166− return d->publicScenePos.x();
167−}
168−
169−qreal DirectionalDragArea::touchSceneY() const
170−{
171− return d->publicScenePos.y();
172−}
173−
174−bool DirectionalDragArea::dragging() const
175−{
176− return d->status == DirectionalDragAreaPrivate::Recognized;
177−}
178−
179−bool DirectionalDragArea::pressed() const
180−{
181− return d->status != DirectionalDragAreaPrivate::WaitingForTouch;
182−}
183−
184−bool DirectionalDragArea::immediateRecognition() const
185−{
186− return d->immediateRecognition;
187−}
188−
189−void DirectionalDragArea::setImmediateRecognition(bool enabled)
190−{
191− if (d->immediateRecognition != enabled) {
192− d->immediateRecognition = enabled;
193− Q_EMIT immediateRecognitionChanged(enabled);
194− }
195−}
196−
197−bool DirectionalDragArea::monitorOnly() const
198−{
199− return d->monitorOnly;
200−}
201−
202−void DirectionalDragArea::setMonitorOnly(bool monitorOnly)
203−{
204− if (d->monitorOnly != monitorOnly) {
205− d->monitorOnly = monitorOnly;
206−
207− if (monitorOnly && d->status == DirectionalDragAreaPrivate::Undecided) {
208− TouchRegistry::instance()->removeCandidateOwnerForTouch(d->touchId, this);
209− // We still wanna know when it ends for keeping the composition time window up-to-date
210− TouchRegistry::instance()->addTouchWatcher(d->touchId, this);
211− }
212−
213− Q_EMIT monitorOnlyChanged(monitorOnly);
214− }
215−}
216−
217−void DirectionalDragArea::removeTimeConstraints()
218−{
219− d->setMaxTime(60 * 60 * 1000);
220− d->compositionTime = 0;
221− ddaDebug("removed time constraints");
222−}
223−
224−bool DirectionalDragArea::event(QEvent *event)
225−{
226− if (event->type() == TouchOwnershipEvent::touchOwnershipEventType()) {
227− d->touchOwnershipEvent(static_cast<TouchOwnershipEvent *>(event));
228− return true;
229− } else if (event->type() == UnownedTouchEvent::unownedTouchEventType()) {
230− d->unownedTouchEvent(static_cast<UnownedTouchEvent *>(event));
231− return true;
232− } else {
233− return QQuickItem::event(event);
234− }
235−}
236−
237−void DirectionalDragAreaPrivate::touchOwnershipEvent(TouchOwnershipEvent *event)
238−{
239− if (event->gained()) {
240− QVector<int> ids;
241− ids.append(event->touchId());
242− ddaDebug("grabbing touch");
243− q->grabTouchPoints(ids);
244−
245− // Work around for Qt bug. If we grab a touch that is being used for mouse pointer
246− // emulation it will cause the emulation logic to go nuts.
247− // Thus we have to also grab the mouse in this case.
248− //
249− // The fix for this bug has landed in Qt 5.4 (https://codereview.qt-project.org/96887)
250− // TODO: Remove this workaround once we start using Qt 5.4
251− if (q->window()) {
252− QQuickWindowPrivate *windowPrivate = QQuickWindowPrivate::get(q->window());
253− if (windowPrivate->touchMouseId == event->touchId() && q->window()->mouseGrabberItem()) {
254− ddaDebug("removing mouse grabber");
255− q->window()->mouseGrabberItem()->ungrabMouse();
256− }
257− }
258− } else {
259− // We still wanna know when it ends for keeping the composition time window up-to-date
260− TouchRegistry::instance()->addTouchWatcher(touchId, q);
261−
262− setStatus(WaitingForTouch);
263− }
264−}
265−
266−void DirectionalDragAreaPrivate::unownedTouchEvent(UnownedTouchEvent *unownedTouchEvent)
267−{
268− QTouchEvent *event = unownedTouchEvent->touchEvent();
269−
270− Q_ASSERT(!event->touchPointStates().testFlag(Qt::TouchPointPressed));
271−
272− ddaDebug("Unowned " << timeSource->msecsSinceReference() << " " << qPrintable(touchEventToString(event)));
273−
274− switch (status) {
275− case WaitingForTouch:
276− // do nothing
277− break;
278− case Undecided:
279− Q_ASSERT(q->isEnabled() && q->isVisible());
280− unownedTouchEvent_undecided(unownedTouchEvent);
281− break;
282− default: // Recognized:
283− if (monitorOnly) {
284− // Treat unowned event as if we owned it, but we are really just watching it
285− touchEvent_recognized(event);
286− }
287− break;
288− }
289−
290− activeTouches.update(event);
291−}
292−
293−void DirectionalDragAreaPrivate::unownedTouchEvent_undecided(UnownedTouchEvent *unownedTouchEvent)
294−{
295− const QTouchEvent::TouchPoint *touchPoint = fetchTargetTouchPoint(unownedTouchEvent->touchEvent());
296− if (!touchPoint) {
297− qCritical() << "DirectionalDragArea[status=Undecided]: touch " << touchId
298− << "missing from UnownedTouchEvent without first reaching state Qt::TouchPointReleased. "
299− "Considering it as released.";
300−
301− TouchRegistry::instance()->removeCandidateOwnerForTouch(touchId, q);
302− setStatus(WaitingForTouch);
303− return;
304− }
305−
306− const QPointF &touchScenePos = touchPoint->scenePos();
307−
308− if (touchPoint->state() == Qt::TouchPointReleased) {
309− // touch has ended before recognition concluded
310− ddaDebug("Touch has ended before recognition concluded");
311− TouchRegistry::instance()->removeCandidateOwnerForTouch(touchId, q);
312− setStatus(WaitingForTouch);
313− return;
314− }
315−
316− previousDampedScenePos.setX(dampedScenePos.x());
317− previousDampedScenePos.setY(dampedScenePos.y());
318− dampedScenePos.update(touchScenePos);
319−
320− if (!movingInRightDirection()) {
321− ddaDebug("Rejecting gesture because touch point is moving in the wrong direction.");
322− TouchRegistry::instance()->removeCandidateOwnerForTouch(touchId, q);
323− // We still wanna know when it ends for keeping the composition time window up-to-date
324− TouchRegistry::instance()->addTouchWatcher(touchId, q);
325− setStatus(WaitingForTouch);
326− return;
327− }
328−
329− if (isWithinTouchCompositionWindow()) {
330− // There's still time for some new touch to appear and ruin our party as it would be combined
331− // with our touchId one and therefore deny the possibility of a single-finger gesture.
332− ddaDebug("Sill within composition window. Let's wait more.");
333− return;
334− }
335−
336− if (movedFarEnoughAlongGestureAxis()) {
337− if (!monitorOnly) {
338− TouchRegistry::instance()->requestTouchOwnership(touchId, q);
339− }
340− setStatus(Recognized);
341− setPublicPos(touchPoint->pos());
342− setPublicScenePos(touchScenePos);
343− } else if (isPastMaxDistance()) {
344− ddaDebug("Rejecting gesture because it went farther than maxDistance without getting recognized.");
345− TouchRegistry::instance()->removeCandidateOwnerForTouch(touchId, q);
346− // We still wanna know when it ends for keeping the composition time window up-to-date
347− TouchRegistry::instance()->addTouchWatcher(touchId, q);
348− setStatus(WaitingForTouch);
349− } else {
350− ddaDebug("Didn't move far enough yet. Let's wait more.");
351− }
352−}
353−
354−void DirectionalDragArea::touchEvent(QTouchEvent *event)
355−{
356− // TODO: Consider when more than one touch starts in the same event (although it's not possible
357− // with Mir's android-input). Have to track them all. Consider it a plus/bonus.
358−
359− ddaDebug(d->timeSource->msecsSinceReference() << " " << qPrintable(touchEventToString(event)));
360−
361− if (!isEnabled() || !isVisible()) {
362− QQuickItem::touchEvent(event);
363− return;
364− }
365−
366− switch (d->status) {
367− case DirectionalDragAreaPrivate::WaitingForTouch:
368− d->touchEvent_absent(event);
369− break;
370− case DirectionalDragAreaPrivate::Undecided:
371− d->touchEvent_undecided(event);
372− break;
373− default: // Recognized:
374− d->touchEvent_recognized(event);
375− break;
376− }
377−
378− d->activeTouches.update(event);
379−}
380−
381−void DirectionalDragAreaPrivate::touchEvent_absent(QTouchEvent *event)
382−{
383− // TODO: accept/reject is for the whole event, not per touch id. See how that affects us.
384−
385− if (!event->touchPointStates().testFlag(Qt::TouchPointPressed)) {
386− // Nothing to see here. No touch starting in this event.
387− return;
388− }
389−
390− // to be proven wrong, if that's the case
391− bool allGood = true;
392−
393− if (isWithinTouchCompositionWindow()) {
394− // too close to the last touch start. So we consider them as starting roughly at the same time.
395− // Can't be a single-touch gesture.
396− ddaDebug("A new touch point came in but we're still within time composition window. Ignoring it.");
397− allGood = false;
398− }
399−
400− const QList<QTouchEvent::TouchPoint> &touchPoints = event->touchPoints();
401−
402− const QTouchEvent::TouchPoint *newTouchPoint = nullptr;
403− for (int i = 0; i < touchPoints.count() && allGood; ++i) {
404− const QTouchEvent::TouchPoint &touchPoint = touchPoints.at(i);
405− if (touchPoint.state() == Qt::TouchPointPressed) {
406− if (newTouchPoint) {
407− // more than one touch starting in this QTouchEvent. Can't be a single-touch gesture
408− allGood = false;
409− } else {
410− // that's our candidate
411− newTouchPoint = &touchPoint;
412− }
413− }
414− }
415−
416− if (allGood) {
417− allGood = sanityCheckRecognitionProperties();
418− if (!allGood) {
419− qWarning("DirectionalDragArea: recognition properties are wrongly set. Gesture recognition"
420− " is impossible");
421− }
422− }
423−
424− if (allGood) {
425− Q_ASSERT(newTouchPoint);
426−
427− startPos = newTouchPoint->pos();
428− startScenePos = newTouchPoint->scenePos();
429− touchId = newTouchPoint->id();
430− dampedScenePos.reset(startScenePos);
431− setPublicPos(startPos);
432−
433− setPublicScenePos(startScenePos);
434− updateSceneDirectionVector();
435−
436− if (recognitionIsDisabled()) {
437− // Behave like a dumb TouchArea
438− ddaDebug("Gesture recognition is disabled. Requesting touch ownership immediately.");
439− setStatus(Recognized);
440− if (monitorOnly) {
441− watchPressedTouchPoints(touchPoints);
442− event->ignore();
443− } else {
444− TouchRegistry::instance()->requestTouchOwnership(touchId, q);
445− event->accept();
446− }
447− } else {
448− // just monitor the touch points for now.
449− if (monitorOnly) {
450− watchPressedTouchPoints(touchPoints);
451− } else {
452− TouchRegistry::instance()->addCandidateOwnerForTouch(touchId, q);
453− }
454−
455− setStatus(Undecided);
456− // Let the item below have it. We will monitor it and grab it later if a gesture
457− // gets recognized.
458− event->ignore();
459− }
460− } else {
461− watchPressedTouchPoints(touchPoints);
462− event->ignore();
463− }
464−}
465−
466−void DirectionalDragAreaPrivate::touchEvent_undecided(QTouchEvent *event)
467−{
468− Q_ASSERT(fetchTargetTouchPoint(event) == nullptr);
469−
470− // We're not interested in new touch points. We already have our candidate (touchId).
471− // But we do want to know when those new touches end for keeping the composition time
472− // window up-to-date
473− event->ignore();
474− watchPressedTouchPoints(event->touchPoints());
475−
476− if (event->touchPointStates().testFlag(Qt::TouchPointPressed) && isWithinTouchCompositionWindow()) {
477− // multi-finger drags are not accepted
478− ddaDebug("Multi-finger drags are not accepted");
479−
480− TouchRegistry::instance()->removeCandidateOwnerForTouch(touchId, q);
481− // We still wanna know when it ends for keeping the composition time window up-to-date
482− TouchRegistry::instance()->addTouchWatcher(touchId, q);
483−
484− setStatus(WaitingForTouch);
485− }
486−}
487−
488−void DirectionalDragAreaPrivate::touchEvent_recognized(QTouchEvent *event)
489−{
490− const QTouchEvent::TouchPoint *touchPoint = fetchTargetTouchPoint(event);
491−
492− if (!touchPoint) {
493− qCritical() << "DirectionalDragArea[status=Recognized]: touch " << touchId
494− << "missing from QTouchEvent without first reaching state Qt::TouchPointReleased. "
495− "Considering it as released.";
496− setStatus(WaitingForTouch);
497− } else {
498− setPublicPos(touchPoint->pos());
499− setPublicScenePos(touchPoint->scenePos());
500−
501− if (touchPoint->state() == Qt::TouchPointReleased) {
502− setStatus(WaitingForTouch);
503− }
504− }
505−}
506−
507−void DirectionalDragAreaPrivate::watchPressedTouchPoints(const QList<QTouchEvent::TouchPoint> &touchPoints)
508−{
509− for (int i = 0; i < touchPoints.count(); ++i) {
510− const QTouchEvent::TouchPoint &touchPoint = touchPoints.at(i);
511− if (touchPoint.state() == Qt::TouchPointPressed) {
512− TouchRegistry::instance()->addTouchWatcher(touchPoint.id(), q);
513− }
514− }
515−}
516−
517−bool DirectionalDragAreaPrivate::recognitionIsDisabled() const
518−{
519− return immediateRecognition || (distanceThreshold <= 0 && compositionTime <= 0);
520−}
521−
522−bool DirectionalDragAreaPrivate::sanityCheckRecognitionProperties()
523−{
524− return recognitionIsDisabled()
525− || (distanceThreshold < maxDistance && compositionTime < maxTime);
526−}
527−
528−const QTouchEvent::TouchPoint *DirectionalDragAreaPrivate::fetchTargetTouchPoint(QTouchEvent *event)
529−{
530− const QList<QTouchEvent::TouchPoint> &touchPoints = event->touchPoints();
531− const QTouchEvent::TouchPoint *touchPoint = 0;
532− for (int i = 0; i < touchPoints.size(); ++i) {
533− if (touchPoints.at(i).id() == touchId) {
534− touchPoint = &touchPoints.at(i);
535− break;
536− }
537− }
538− return touchPoint;
539−}
540−
541−bool DirectionalDragAreaPrivate::movingInRightDirection() const
542−{
543− if (direction == Direction::Horizontal || direction == Direction::Vertical) {
544− return true;
545− } else {
546− QPointF movementVector(dampedScenePos.x() - previousDampedScenePos.x(),
547− dampedScenePos.y() - previousDampedScenePos.y());
548−
549− qreal scalarProjection = projectOntoDirectionVector(movementVector);
550−
551− return scalarProjection >= 0.;
552− }
553−}
554−
555−bool DirectionalDragAreaPrivate::movedFarEnoughAlongGestureAxis() const
556−{
557− if (distanceThreshold <= 0.) {
558− // distance threshold check is disabled
559− return true;
560− } else {
561− QPointF totalMovement(dampedScenePos.x() - startScenePos.x(),
562− dampedScenePos.y() - startScenePos.y());
563−
564− qreal scalarProjection = projectOntoDirectionVector(totalMovement);
565−
566− ddaDebug(" movedFarEnoughAlongGestureAxis: scalarProjection=" << scalarProjection
567− << ", distanceThreshold=" << distanceThreshold);
568−
569− if (direction == Direction::Horizontal || direction == Direction::Vertical) {
570− return qAbs(scalarProjection) > distanceThreshold;
571− } else {
572− return scalarProjection > distanceThreshold;
573− }
574− }
575−}
576−
577−bool DirectionalDragAreaPrivate::isPastMaxDistance() const
578−{
579− QPointF totalMovement(dampedScenePos.x() - startScenePos.x(),
580− dampedScenePos.y() - startScenePos.y());
581−
582− qreal squaredDistance = totalMovement.x()*totalMovement.x() + totalMovement.y()*totalMovement.y();
583− return squaredDistance > maxDistance*maxDistance;
584−}
585−
586−void DirectionalDragAreaPrivate::giveUpIfDisabledOrInvisible()
587−{
588− if (!q->isEnabled() || !q->isVisible()) {
589− if (status == Undecided) {
590− TouchRegistry::instance()->removeCandidateOwnerForTouch(touchId, q);
591− // We still wanna know when it ends for keeping the composition time window up-to-date
592− TouchRegistry::instance()->addTouchWatcher(touchId, q);
593− }
594−
595− if (status != WaitingForTouch) {
596− ddaDebug("Resetting status because got disabled or made invisible");
597− setStatus(WaitingForTouch);
598− }
599− }
600−}
601−
602−void DirectionalDragAreaPrivate::rejectGesture()
603−{
604− if (status == Undecided) {
605− ddaDebug("Rejecting gesture because it's taking too long to drag beyond the threshold.");
606−
607− TouchRegistry::instance()->removeCandidateOwnerForTouch(touchId, q);
608− // We still wanna know when it ends for keeping the composition time window up-to-date
609− TouchRegistry::instance()->addTouchWatcher(touchId, q);
610−
611− setStatus(WaitingForTouch);
612− }
613−}
614−
615−void DirectionalDragAreaPrivate::setStatus(Status newStatus)
616−{
617− if (newStatus == status)
618− return;
619−
620− Status oldStatus = status;
621−
622− if (oldStatus == Undecided) {
623− recognitionTimer->stop();
624− }
625−
626− status = newStatus;
627− Q_EMIT statusChanged(status);
628−
629− ddaDebug(statusToString(oldStatus) << " -> " << statusToString(newStatus));
630−
631− switch (newStatus) {
632− case WaitingForTouch:
633− if (oldStatus == Recognized) {
634− Q_EMIT q->draggingChanged(false);
635− }
636− Q_EMIT q->pressedChanged(false);
637− break;
638− case Undecided:
639− recognitionTimer->start();
640− Q_EMIT q->pressedChanged(true);
641− break;
642− case Recognized:
643− if (oldStatus == WaitingForTouch) { // for immediate recognition
644− Q_EMIT q->pressedChanged(true);
645− }
646− Q_EMIT q->draggingChanged(true);
647− break;
648− default:
649− // no-op
650− break;
651− }
652−}
653−
654−void DirectionalDragAreaPrivate::setPublicPos(const QPointF point)
655−{
656− bool xChanged = publicPos.x() != point.x();
657− bool yChanged = publicPos.y() != point.y();
658−
659− // Public position should not get updated while the gesture is still being recognized
660− // (ie, Undecided status).
661− Q_ASSERT(status == WaitingForTouch || status == Recognized);
662−
663− if (status == Recognized && !recognitionIsDisabled()) {
664− // When the gesture finally gets recognized, the finger will likely be
665− // reasonably far from the edge. If we made the contentX immediately
666− // follow the finger position it would be visually unpleasant as it
667− // would appear right next to the user's finger out of nowhere (ie,
668− // it would jump). Instead, we make contentX go towards the user's
669− // finger in several steps. ie., in an animated way.
670− QPointF delta = point - publicPos;
671− // the trick is not to go all the way (1.0) as it would cause a sudden jump
672− publicPos.rx() += 0.4 * delta.x();
673− publicPos.ry() += 0.4 * delta.y();
674− } else {
675− // no smoothing when initializing or if gesture recognition was immediate as there will
676− // be no jump.
677− publicPos = point;
678− }
679−
680− if (xChanged) {
681− Q_EMIT q->touchXChanged(publicPos.x());
682− if (Direction::isHorizontal(direction))
683− Q_EMIT q->distanceChanged(q->distance());
684− }
685−
686− if (yChanged) {
687− Q_EMIT q->touchYChanged(publicPos.y());
688− if (Direction::isVertical(direction))
689− Q_EMIT q->distanceChanged(q->distance());
690− }
691−}
692−
693−void DirectionalDragAreaPrivate::setPublicScenePos(const QPointF point)
694−{
695− bool xChanged = publicScenePos.x() != point.x();
696− bool yChanged = publicScenePos.y() != point.y();
697−
698− if (!xChanged && !yChanged)
699− return;
700−
701− // Public position should not get updated while the gesture is still being recognized
702− // (ie, Undecided status).
703− Q_ASSERT(status == WaitingForTouch || status == Recognized);
704−
705− qreal oldSceneDistance = sceneDistance;
706−
707− if (status == Recognized && !recognitionIsDisabled()) {
708− // When the gesture finally gets recognized, the finger will likely be
709− // reasonably far from the edge. If we made the contentX immediately
710− // follow the finger position it would be visually unpleasant as it
711− // would appear right next to the user's finger out of nowhere (ie,
712− // it would jump). Instead, we make contentX go towards the user's
713− // finger in several steps. ie., in an animated way.
714− QPointF delta = point - publicScenePos;
715− // the trick is not to go all the way (1.0) as it would cause a sudden jump
716− publicScenePos.rx() += 0.4 * delta.x();
717− publicScenePos.ry() += 0.4 * delta.y();
718− } else {
719− // no smoothing when initializing or if gesture recognition was immediate as there will
720− // be no jump.
721− publicScenePos = point;
722− }
723−
724− updateSceneDistance();
725−
726− if (oldSceneDistance != sceneDistance) {
727− Q_EMIT q->sceneDistanceChanged(sceneDistance);
728− }
729−
730− if (xChanged) {
731− Q_EMIT q->touchSceneXChanged(publicScenePos.x());
732− }
733−
734− if (yChanged) {
735− Q_EMIT q->touchSceneYChanged(publicScenePos.y());
736− }
737−}
738−
739−bool DirectionalDragAreaPrivate::isWithinTouchCompositionWindow()
740−{
741− return
742− compositionTime > 0 &&
743− !activeTouches.isEmpty() &&
744− timeSource->msecsSinceReference() <=
745− activeTouches.mostRecentStartTime() + (qint64)compositionTime;
746−}
747−
748−void DirectionalDragArea::itemChange(ItemChange change, const ItemChangeData &value)
749−{
750− if (change == QQuickItem::ItemSceneChange) {
751− if (value.window != nullptr) {
752− value.window->installEventFilter(TouchRegistry::instance());
753−
754− // TODO: Handle window->screen() changes (ie window changing screens)
755−
756− qreal pixelsPerInch = value.window->screen()->physicalDotsPerInch();
757− if (pixelsPerInch < 0) {
758− // It can return garbage when run in a XVFB server (Virtual Framebuffer 'fake' X server)
759− pixelsPerInch = 72;
760− }
761−
762− d->setPixelsPerMm(pixelsPerInch / 25.4);
763− }
764− }
765−}
766−
767−void DirectionalDragAreaPrivate::setPixelsPerMm(qreal pixelsPerMm)
768−{
769− dampedScenePos.setMaxDelta(1. * pixelsPerMm);
770− setDistanceThreshold(4. * pixelsPerMm);
771− maxDistance = 10. * pixelsPerMm;
772−}
773−
774−//************************** ActiveTouchesInfo **************************
775−
776−ActiveTouchesInfo::ActiveTouchesInfo(const SharedTimeSource &timeSource)
777− : m_timeSource(timeSource)
778−{
779−}
780−
781−void ActiveTouchesInfo::update(QTouchEvent *event)
782−{
783− if (!(event->touchPointStates() & (Qt::TouchPointPressed | Qt::TouchPointReleased))) {
784− // nothing to update
785− #if ACTIVETOUCHESINFO_DEBUG
786− qDebug("[DDA::ActiveTouchesInfo] Nothing to Update");
787− #endif
788− return;
789− }
790−
791− const QList<QTouchEvent::TouchPoint> &touchPoints = event->touchPoints();
792− for (int i = 0; i < touchPoints.count(); ++i) {
793− const QTouchEvent::TouchPoint &touchPoint = touchPoints.at(i);
794− if (touchPoint.state() == Qt::TouchPointPressed) {
795− addTouchPoint(touchPoint.id());
796− } else if (touchPoint.state() == Qt::TouchPointReleased) {
797− removeTouchPoint(touchPoint.id());
798− }
799− }
800−}
801−
802−#if ACTIVETOUCHESINFO_DEBUG
803−QString ActiveTouchesInfo::toString()
804−{
805− QString string = "(";
806−
807− {
808− QTextStream stream(&string);
809− m_touchInfoPool.forEach([&](Pool<ActiveTouchInfo>::Iterator &touchInfo) {
810− stream << "(id=" << touchInfo->id << ",startTime=" << touchInfo->startTime << ")";
811− return true;
812− });
813− }
814−
815− string.append(")");
816−
817− return string;
818−}
819−#endif // ACTIVETOUCHESINFO_DEBUG
820−
821−void ActiveTouchesInfo::addTouchPoint(int touchId)
822−{
823− ActiveTouchInfo &activeTouchInfo = m_touchInfoPool.getEmptySlot();
824− activeTouchInfo.id = touchId;
825− activeTouchInfo.startTime = m_timeSource->msecsSinceReference();
826−
827− #if ACTIVETOUCHESINFO_DEBUG
828− qDebug() << "[DDA::ActiveTouchesInfo]" << qPrintable(toString());
829− #endif
830−}
831−
832−qint64 ActiveTouchesInfo::touchStartTime(int touchId)
833−{
834− qint64 result = -1;
835−
836− m_touchInfoPool.forEach([&](Pool<ActiveTouchInfo>::Iterator &touchInfo) {
837− if (touchId == touchInfo->id) {
838− result = touchInfo->startTime;
839− return false;
840− } else {
841− return true;
842− }
843− });
844−
845− Q_ASSERT(result != -1);
846− return result;
847−}
848−
849−void ActiveTouchesInfo::removeTouchPoint(int touchId)
850−{
851− m_touchInfoPool.forEach([&](Pool<ActiveTouchInfo>::Iterator &touchInfo) {
852− if (touchId == touchInfo->id) {
853− m_touchInfoPool.freeSlot(touchInfo);
854− return false;
855− } else {
856− return true;
857− }
858− });
859−
860− #if ACTIVETOUCHESINFO_DEBUG
861− qDebug() << "[DDA::ActiveTouchesInfo]" << qPrintable(toString());
862− #endif
863−}
864−
865−qint64 ActiveTouchesInfo::mostRecentStartTime()
866−{
867− Q_ASSERT(!m_touchInfoPool.isEmpty());
868−
869− qint64 highestStartTime = -1;
870−
871− m_touchInfoPool.forEach([&](Pool<ActiveTouchInfo>::Iterator &activeTouchInfo) {
872− if (activeTouchInfo->startTime > highestStartTime) {
873− highestStartTime = activeTouchInfo->startTime;
874− }
875− return true;
876− });
877−
878− return highestStartTime;
879−}
880−
881−void DirectionalDragAreaPrivate::updateSceneDirectionVector()
882−{
883− QPointF localOrigin(0., 0.);
884− QPointF localDirection;
885− switch (direction) {
886− case Direction::Upwards:
887− localDirection.rx() = 0.;
888− localDirection.ry() = -1.;
889− break;
890− case Direction::Downwards:
891− case Direction::Vertical:
892− localDirection.rx() = 0.;
893− localDirection.ry() = 1;
894− break;
895− case Direction::Leftwards:
896− localDirection.rx() = -1.;
897− localDirection.ry() = 0.;
898− break;
899− default: // Direction::Rightwards || Direction.Horizontal
900− localDirection.rx() = 1.;
901− localDirection.ry() = 0.;
902− break;
903− }
904− QPointF sceneOrigin = q->mapToScene(localOrigin);
905− QPointF sceneDirection = q->mapToScene(localDirection);
906− sceneDirectionVector = sceneDirection - sceneOrigin;
907−}
908−
909−qreal DirectionalDragAreaPrivate::projectOntoDirectionVector(const QPointF sceneVector) const
910−{
911− // same as dot product as sceneDirectionVector is a unit vector
912− return sceneVector.x() * sceneDirectionVector.x() +
913− sceneVector.y() * sceneDirectionVector.y();
914−}
915−
916−DirectionalDragAreaPrivate::DirectionalDragAreaPrivate(DirectionalDragArea *q)
917− : q(q)
918− , status(WaitingForTouch)
919− , sceneDistance(0)
920− , touchId(-1)
921− , direction(Direction::Rightwards)
922− , distanceThreshold(0)
923− , distanceThresholdSquared(0.)
924− , maxTime(400)
925− , compositionTime(60)
926− , immediateRecognition(false)
927− , recognitionTimer(nullptr)
928− , timeSource(new RealTimeSource)
929− , activeTouches(timeSource)
930− , monitorOnly(false)
931−{
932−}
plugins/Ubuntu/Gestures/DirectionalDragArea.hdeleted−143
@@ -1,143 +0,0 @@
1−/*
2− * Copyright (C) 2013,2014 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#ifndef DIRECTIONAL_DRAG_AREA_H
18−#define DIRECTIONAL_DRAG_AREA_H
19−
20−#include <QtQuick/QQuickItem>
21−#include "UbuntuGesturesQmlGlobal.h"
22−#include "Damper.h"
23−#include "Direction.h"
24−
25−// lib UbuntuGestures
26−#include <Pool.h>
27−#include <Timer.h>
28−
29−class TouchOwnershipEvent;
30−class UnownedTouchEvent;
31−class DirectionalDragAreaPrivate;
32−
33−/*
34− An area that detects axis-aligned single-finger drag gestures
35−
36− If a drag deviates too much from the components' direction recognition will
37− fail. It will also fail if the drag or flick is too short. E.g. a noisy or
38− fidgety click
39−
40− See doc/DirectionalDragArea.svg
41− */
42−class UBUNTUGESTURESQML_EXPORT DirectionalDragArea : public QQuickItem {
43− Q_OBJECT
44−
45− // The direction in which the gesture should move in order to be recognized.
46− Q_PROPERTY(Direction::Type direction READ direction WRITE setDirection NOTIFY directionChanged)
47−
48− // The distance travelled by the finger along the axis specified by
49− // DirectionalDragArea's direction.
50− Q_PROPERTY(qreal distance READ distance NOTIFY distanceChanged)
51−
52− // The distance travelled by the finger along the axis specified by
53− // DirectionalDragArea's direction in scene coordinates
54− Q_PROPERTY(qreal sceneDistance READ sceneDistance NOTIFY sceneDistanceChanged)
55−
56− // Position of the touch point performing the drag relative to this item.
57− Q_PROPERTY(qreal touchX READ touchX NOTIFY touchXChanged)
58− Q_PROPERTY(qreal touchY READ touchY NOTIFY touchYChanged)
59−
60− // Position of the touch point performing the drag, in scene's coordinate system
61− Q_PROPERTY(qreal touchSceneX READ touchSceneX NOTIFY touchSceneXChanged)
62− Q_PROPERTY(qreal touchSceneY READ touchSceneY NOTIFY touchSceneYChanged)
63−
64− // Whether a drag gesture is taking place
65− Q_PROPERTY(bool dragging READ dragging NOTIFY draggingChanged)
66−
67− // Whether the drag area is pressed.
68− Q_PROPERTY(bool pressed READ pressed NOTIFY pressedChanged)
69−
70− // Whether a gesture should be Recognized as soon a touch lands on the area.
71− // With this property enabled it will work pretty much like a MultiPointTouchArea,
72− // just with a different API.
73− //
74− // It's false by default. In most cases you will not want that enabled.
75− Q_PROPERTY(bool immediateRecognition
76− READ immediateRecognition
77− WRITE setImmediateRecognition
78− NOTIFY immediateRecognitionChanged)
79−
80− // Whether we are merely monitoring touch events (in which case, we don't
81− // claim ownership of the touch).
82− Q_PROPERTY(bool monitorOnly READ monitorOnly WRITE setMonitorOnly NOTIFY monitorOnlyChanged)
83−
84− Q_ENUMS(Direction)
85−public:
86− DirectionalDragArea(QQuickItem *parent = 0);
87−
88− Direction::Type direction() const;
89− void setDirection(Direction::Type);
90−
91− qreal distance() const;
92− qreal sceneDistance() const;
93−
94− qreal touchX() const;
95− qreal touchY() const;
96−
97− qreal touchSceneX() const;
98− qreal touchSceneY() const;
99−
100− bool dragging() const;
101−
102− bool pressed() const;
103−
104− bool immediateRecognition() const;
105− void setImmediateRecognition(bool enabled);
106−
107− bool monitorOnly() const;
108− void setMonitorOnly(bool monitorOnly);
109−
110− bool event(QEvent *e) override;
111−
112− /*
113− In qmltests, sequences of touch events are sent all at once, unlike in "real life".
114− Also qmltests might run really slowly, e.g. when run from inside virtual machines.
115− Thus to remove a variable that qmltests cannot really control, namely time, this
116− function removes all constraints that are sensible to elapsed time.
117−
118− This effectively makes the DirectionalDragArea easier to fool.
119− */
120− Q_INVOKABLE void removeTimeConstraints();
121−
122−Q_SIGNALS:
123− void directionChanged(Direction::Type direction);
124− void draggingChanged(bool value);
125− void pressedChanged(bool value);
126− void distanceChanged(qreal value);
127− void sceneDistanceChanged(qreal value);
128− void touchXChanged(qreal value);
129− void touchYChanged(qreal value);
130− void touchSceneXChanged(qreal value);
131− void touchSceneYChanged(qreal value);
132− void immediateRecognitionChanged(bool value);
133− void monitorOnlyChanged(bool value);
134−
135−protected:
136− void touchEvent(QTouchEvent *event) override;
137− void itemChange(ItemChange change, const ItemChangeData &value) override;
138−
139−public: // so tests can access it
140− DirectionalDragAreaPrivate *d;
141−};
142−
143−#endif // DIRECTIONAL_DRAG_AREA_H
plugins/Ubuntu/Gestures/DirectionalDragArea_p.hdeleted−169
@@ -1,169 +0,0 @@
1−/*
2− * Copyright (C) 2015 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#ifndef DIRECTIONAL_DRAG_AREA_PRIV_H
18−#define DIRECTIONAL_DRAG_AREA_PRIV_H
19−
20−// Information about an active touch point
21−struct UBUNTUGESTURESQML_EXPORT ActiveTouchInfo {
22− ActiveTouchInfo() : id(-1), startTime(-1) {}
23− bool isValid() const { return id != -1; }
24− void reset() { id = -1; }
25− int id;
26− qint64 startTime;
27−};
28−class UBUNTUGESTURESQML_EXPORT ActiveTouchesInfo {
29−public:
30− ActiveTouchesInfo(const UbuntuGestures::SharedTimeSource &timeSource);
31− void update(QTouchEvent *event);
32− qint64 touchStartTime(int id);
33− bool isEmpty() const { return m_touchInfoPool.isEmpty(); }
34− qint64 mostRecentStartTime();
35− UbuntuGestures::SharedTimeSource m_timeSource;
36−private:
37− void addTouchPoint(int touchId);
38− void removeTouchPoint(int touchId);
39− #if ACTIVETOUCHESINFO_DEBUG
40− QString toString();
41− #endif
42−
43− Pool<ActiveTouchInfo> m_touchInfoPool;
44−};
45−
46−class UBUNTUGESTURESQML_EXPORT DirectionalDragAreaPrivate : public QObject {
47− Q_OBJECT
48−
49− Q_ENUMS(Status)
50−public:
51− DirectionalDragAreaPrivate(DirectionalDragArea *q);
52−
53−public Q_SLOTS:
54− void giveUpIfDisabledOrInvisible();
55− void rejectGesture();
56−
57−public:
58− // Describes the state of the directional drag gesture.
59− enum Status {
60− // Waiting for a new touch point to land on this area. No gesture is being processed
61− // or tracked.
62− WaitingForTouch,
63−
64− // A touch point has landed on this area but it's not know yet whether it is
65− // performing a drag in the correct direction.
66− // If it's decided that the touch point is not performing a directional drag gesture,
67− // it will be rejected/ignored and status will return to WaitingForTouch.
68− Undecided, //Recognizing,
69−
70− // There's a touch point in this area and it performed a drag in the correct
71− // direction.
72− //
73− // Once recognized, the gesture state will move back to WaitingForTouch only once
74− // that touch point ends. The gesture will remain in the Recognized state even if
75− // the touch point starts moving in other directions or halts.
76− Recognized,
77− };
78−
79− void touchEvent_absent(QTouchEvent *event);
80− void touchEvent_undecided(QTouchEvent *event);
81− void touchEvent_recognized(QTouchEvent *event);
82− bool movingInRightDirection() const;
83− bool movedFarEnoughAlongGestureAxis() const;
84− bool isPastMaxDistance() const;
85− const QTouchEvent::TouchPoint *fetchTargetTouchPoint(QTouchEvent *event);
86− void setStatus(Status newStatus);
87− void setPublicPos(const QPointF point);
88− void setPublicScenePos(const QPointF point);
89− bool isWithinTouchCompositionWindow();
90− void updateSceneDirectionVector();
91− // returns the scalar projection between the given vector (in scene coordinates)
92− // and m_sceneDirectionVector
93− qreal projectOntoDirectionVector(const QPointF sceneVector) const;
94− void touchOwnershipEvent(TouchOwnershipEvent *event);
95− void unownedTouchEvent(UnownedTouchEvent *event);
96− void unownedTouchEvent_undecided(UnownedTouchEvent *unownedTouchEvent);
97− void watchPressedTouchPoints(const QList<QTouchEvent::TouchPoint> &touchPoints);
98− bool recognitionIsDisabled() const;
99− bool sanityCheckRecognitionProperties();
100− void updateSceneDistance();
101− void setMaxTime(int value);
102− void setDistanceThreshold(qreal value);
103− void setPixelsPerMm(qreal pixelsPerMm);
104− QString objectName() const { return q->objectName(); }
105−
106− // Replaces the existing Timer with the given one.
107− //
108− // Useful for providing a fake timer when testing.
109− void setRecognitionTimer(UbuntuGestures::AbstractTimer *timer);
110−
111− // Useful for testing, where a fake time source can be supplied
112− void setTimeSource(const UbuntuGestures::SharedTimeSource &timeSource);
113−
114− DirectionalDragArea *q;
115−
116− // The current status of the directional drag gesture area.
117− Status status;
118−
119− QPointF startPos;
120− QPointF startScenePos;
121− qreal sceneDistance;
122− int touchId;
123−
124− // The touch position exposed in the public API.
125− // It only starts to move once the gesture gets recognized.
126− QPointF publicPos;
127− QPointF publicScenePos;
128−
129− // A movement damper is used in some of the gesture recognition calculations
130− // to get rid of noise or small oscillations in the touch position.
131− DampedPointF dampedScenePos;
132− QPointF previousDampedScenePos;
133−
134− // Unit vector in scene coordinates describing the direction of the gesture recognition
135− QPointF sceneDirectionVector;
136−
137− Direction::Type direction;
138−
139− // How far a touch point has to move from its initial position along the gesture axis in order
140− // for it to be recognized as a directional drag.
141− qreal distanceThreshold;
142− qreal distanceThresholdSquared; // it's pow(distanceThreshold, 2)
143−
144− // Maximum time (in milliseconds) the gesture can take to go beyond the distance threshold
145− int maxTime;
146−
147− // Maximum distance the gesture can go without crossing the axis-aligned distance threshold
148− qreal maxDistance;
149−
150− // Maximum time (in milliseconds) after the start of a given touch point where
151− // subsequent touch starts are grouped with the first one into an N-touches gesture
152− // (e.g. a two-fingers tap or drag).
153− int compositionTime;
154−
155− bool immediateRecognition;
156−
157− UbuntuGestures::AbstractTimer *recognitionTimer;
158−
159− UbuntuGestures::SharedTimeSource timeSource;
160−
161− ActiveTouchesInfo activeTouches;
162−
163− bool monitorOnly;
164−
165−Q_SIGNALS:
166− void statusChanged(Status value);
167−};
168−
169−#endif // DIRECTIONAL_DRAG_AREA_PRIV_H
plugins/Ubuntu/Gestures/FloatingFlickable.cppdeleted−150
@@ -1,150 +0,0 @@
1−/*
2− * Copyright (C) 2015 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#include "FloatingFlickable.h"
18−
19−#include <private/qquickflickable_p.h>
20−#include "DirectionalDragArea.h"
21−
22−#include <QDebug>
23−
24−FloatingFlickable::FloatingFlickable(QQuickItem *parent)
25− : QQuickItem(parent)
26− , m_mousePressed(false)
27−{
28− m_dragArea = new DirectionalDragArea(this);
29− m_dragArea->setWidth(width());
30− m_dragArea->setHeight(height());
31− m_dragArea->setDirection(Direction::Horizontal);
32− connect(m_dragArea, &DirectionalDragArea::touchXChanged,
33− this, &FloatingFlickable::onDragAreaTouchPosChanged);
34− connect(m_dragArea, &DirectionalDragArea::touchYChanged,
35− this, &FloatingFlickable::onDragAreaTouchPosChanged);
36− connect(m_dragArea, &DirectionalDragArea::draggingChanged,
37− this, &FloatingFlickable::onDragAreaDraggingChanged);
38− connect(m_dragArea, &DirectionalDragArea::directionChanged, this, &FloatingFlickable::directionChanged);
39−
40− m_flickable = new QQuickFlickable(this);
41− m_flickable->setEnabled(false);
42− m_flickable->setWidth(width());
43− m_flickable->setHeight(height());
44− connect(m_flickable, &QQuickFlickable::contentWidthChanged, this, &FloatingFlickable::contentWidthChanged);
45− connect(m_flickable, &QQuickFlickable::contentHeightChanged, this, &FloatingFlickable::contentHeightChanged);
46− connect(m_flickable, &QQuickFlickable::contentXChanged, this, &FloatingFlickable::contentXChanged);
47− connect(m_flickable, &QQuickFlickable::contentYChanged, this, &FloatingFlickable::contentYChanged);
48−
49− connect(this, &QQuickItem::widthChanged, this, &FloatingFlickable::updateChildrenWidth);
50− connect(this, &QQuickItem::heightChanged, this, &FloatingFlickable::updateChildrenHeight);
51−}
52−
53−qreal FloatingFlickable::contentWidth() const
54−{
55− return m_flickable->contentWidth();
56−}
57−
58−void FloatingFlickable::setContentWidth(qreal contentWidth)
59−{
60− m_flickable->setContentWidth(contentWidth);
61−}
62−
63−qreal FloatingFlickable::contentHeight() const
64−{
65− return m_flickable->contentHeight();
66−}
67−
68−void FloatingFlickable::setContentHeight(qreal contentHeight)
69−{
70− m_flickable->setContentHeight(contentHeight);
71−}
72−
73−qreal FloatingFlickable::contentX() const
74−{
75− return m_flickable->contentX();
76−}
77−
78−void FloatingFlickable::setContentX(qreal contentX)
79−{
80− m_flickable->setContentX(contentX);
81−}
82−
83−qreal FloatingFlickable::contentY() const
84−{
85− return m_flickable->contentY();
86−}
87−
88−void FloatingFlickable::setContentY(qreal contentY)
89−{
90− m_flickable->setContentY(contentY);
91−}
92−
93−Direction::Type FloatingFlickable::direction() const
94−{
95− return m_dragArea->direction();
96−}
97−
98−void FloatingFlickable::setDirection(Direction::Type direction)
99−{
100− m_dragArea->setDirection(direction);
101− if (Direction::isHorizontal(direction)) {
102− m_flickable->setFlickableDirection(QQuickFlickable::HorizontalFlick);
103− } else {
104− m_flickable->setFlickableDirection(QQuickFlickable::VerticalFlick);
105− }
106−}
107−
108−void FloatingFlickable::updateChildrenWidth()
109−{
110− m_dragArea->setWidth(width());
111− m_flickable->setWidth(width());
112−}
113−
114−void FloatingFlickable::updateChildrenHeight()
115−{
116− m_dragArea->setHeight(height());
117− m_flickable->setHeight(height());
118−}
119−
120−void FloatingFlickable::onDragAreaTouchPosChanged(qreal)
121−{
122− if (m_mousePressed) {
123− QMouseEvent mouseEvent(QEvent::MouseMove,
124− QPointF(m_dragArea->touchX(),m_dragArea->touchY()),
125− Qt::NoButton, Qt::LeftButton, Qt::NoModifier);
126−
127− QCoreApplication::sendEvent(m_flickable, &mouseEvent);
128−
129− }
130−}
131−
132−void FloatingFlickable::onDragAreaDraggingChanged(bool dragging)
133−{
134− if (dragging && !m_mousePressed) {
135− QMouseEvent mouseEvent(QEvent::MouseButtonPress,
136− QPointF(m_dragArea->touchX(),m_dragArea->touchY()),
137− Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
138−
139− QCoreApplication::sendEvent(m_flickable, &mouseEvent);
140− m_mousePressed = true;
141−
142− } else if (!dragging && m_mousePressed) {
143− QMouseEvent mouseEvent(QEvent::MouseButtonRelease,
144− QPointF(m_dragArea->touchX(),m_dragArea->touchY()),
145− Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
146−
147− QCoreApplication::sendEvent(m_flickable, &mouseEvent);
148− m_mousePressed = false;
149− }
150−}
plugins/Ubuntu/Gestures/FloatingFlickable.hdeleted−86
@@ -1,86 +0,0 @@
1−/*
2− * Copyright (C) 2015 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#ifndef FLOATING_FLICKABLE_H
18−#define FLOATING_FLICKABLE_H
19−
20−#include <QQuickItem>
21−#include "UbuntuGesturesQmlGlobal.h"
22−#include "Direction.h"
23−
24−class DirectionalDragArea;
25−class QQuickFlickable;
26−
27−/*
28− A Flickable that can be put in front of the item to be flicked and
29− still have the item-to-be-flicked receive input events that are not flicks.
30−
31− Ie, it's a Flickable that, input-wise, is transparent to non-flick gestures.
32−
33− With a regular Flickable you would have to make the item-to-be-flicked a child
34− of Flicakble to achieve the same result. FloatingFlickable has no such requirement
35− or limitation.
36− */
37−class UBUNTUGESTURESQML_EXPORT FloatingFlickable : public QQuickItem {
38− Q_OBJECT
39−
40− Q_PROPERTY(qreal contentWidth READ contentWidth WRITE setContentWidth NOTIFY contentWidthChanged)
41− Q_PROPERTY(qreal contentHeight READ contentHeight WRITE setContentHeight NOTIFY contentHeightChanged)
42− Q_PROPERTY(qreal contentX READ contentX WRITE setContentX NOTIFY contentXChanged)
43− Q_PROPERTY(qreal contentY READ contentY WRITE setContentY NOTIFY contentYChanged)
44−
45− Q_PROPERTY(Direction::Type direction READ direction WRITE setDirection NOTIFY directionChanged)
46−
47−Q_SIGNALS:
48− void contentWidthChanged();
49− void contentHeightChanged();
50− void contentXChanged();
51− void contentYChanged();
52− void directionChanged();
53−
54−public:
55− FloatingFlickable(QQuickItem *parent = nullptr);
56−
57− qreal contentWidth() const;
58− void setContentWidth(qreal contentWidth);
59−
60− qreal contentHeight() const;
61− void setContentHeight(qreal contentHeight);
62−
63− qreal contentX() const;
64− void setContentX(qreal contentX);
65−
66− qreal contentY() const;
67− void setContentY(qreal contentY);
68−
69− Direction::Type direction() const;
70− void setDirection(Direction::Type);
71−
72−private Q_SLOTS:
73− void updateChildrenWidth();
74− void updateChildrenHeight();
75− void onDragAreaTouchPosChanged(qreal);
76− void onDragAreaDraggingChanged(bool value);
77−
78−private:
79− DirectionalDragArea *m_dragArea;
80− QQuickFlickable *m_flickable;
81− bool m_mousePressed;
82−
83− friend class tst_FloatingFlickable;
84−};
85−
86−#endif // FLOATING_FLICKABLE_H
plugins/Ubuntu/Gestures/Gestures.qmltypes−132
@@ -54,88 +54,6 @@ Module {
54 Parameter { name: "type"; type: "Direction::Type" }
54 Parameter { name: "type"; type: "Direction::Type" }
55 }
55 }
56 }
56 }
57− Component {
58− name: "DirectionalDragArea"
59− defaultProperty: "data"
60− prototype: "QQuickItem"
61− exports: ["Ubuntu.Gestures/DirectionalDragArea 0.1"]
62− exportMetaObjectRevisions: [0]
63− Property { name: "direction"; type: "Direction::Type" }
64− Property { name: "distance"; type: "double"; isReadonly: true }
65− Property { name: "sceneDistance"; type: "double"; isReadonly: true }
66− Property { name: "touchX"; type: "double"; isReadonly: true }
67− Property { name: "touchY"; type: "double"; isReadonly: true }
68− Property { name: "touchSceneX"; type: "double"; isReadonly: true }
69− Property { name: "touchSceneY"; type: "double"; isReadonly: true }
70− Property { name: "dragging"; type: "bool"; isReadonly: true }
71− Property { name: "pressed"; type: "bool"; isReadonly: true }
72− Property { name: "immediateRecognition"; type: "bool" }
73− Signal {
74− name: "directionChanged"
75− Parameter { name: "direction"; type: "Direction::Type" }
76− }
77− Signal {
78− name: "draggingChanged"
79− Parameter { name: "value"; type: "bool" }
80− }
81− Signal {
82− name: "pressedChanged"
83− Parameter { name: "value"; type: "bool" }
84− }
85− Signal {
86− name: "distanceChanged"
87− Parameter { name: "value"; type: "double" }
88− }
89− Signal {
90− name: "sceneDistanceChanged"
91− Parameter { name: "value"; type: "double" }
92− }
93− Signal {
94− name: "touchXChanged"
95− Parameter { name: "value"; type: "double" }
96− }
97− Signal {
98− name: "touchYChanged"
99− Parameter { name: "value"; type: "double" }
100− }
101− Signal {
102− name: "touchSceneXChanged"
103− Parameter { name: "value"; type: "double" }
104− }
105− Signal {
106− name: "touchSceneYChanged"
107− Parameter { name: "value"; type: "double" }
108− }
109− Signal {
110− name: "immediateRecognitionChanged"
111− Parameter { name: "value"; type: "bool" }
112− }
113− Method { name: "removeTimeConstraints" }
114− }
115− Component {
116− name: "FloatingFlickable"
117− defaultProperty: "data"
118− prototype: "QQuickItem"
119− exports: ["Ubuntu.Gestures/FloatingFlickable 0.1"]
120− exportMetaObjectRevisions: [0]
121− Property { name: "contentWidth"; type: "double" }
122− Property { name: "contentHeight"; type: "double" }
123− Property { name: "contentX"; type: "double" }
124− Property { name: "contentY"; type: "double" }
125− Property { name: "direction"; type: "Direction::Type" }
126− }
127− Component {
128− name: "GestureTouchPoint"
129− prototype: "QObject"
130− exports: ["Ubuntu.Gestures/GestureTouchPoint 0.1"]
131− isCreatable: false
132− exportMetaObjectRevisions: [0]
133− Property { name: "pointId"; type: "int"; isReadonly: true }
134− Property { name: "pressed"; type: "bool"; isReadonly: true }
135− Property { name: "x"; type: "double"; isReadonly: true }
136− Property { name: "y"; type: "double"; isReadonly: true }
137− Property { name: "dragging"; type: "bool"; isReadonly: true }
138− }
139 Component {
57 Component {
140 name: "PressedOutsideNotifier"
58 name: "PressedOutsideNotifier"
141 defaultProperty: "data"
59 defaultProperty: "data"
@@ -156,54 +74,4 @@ Module {
156 Parameter { name: "item"; type: "QQuickItem"; isPointer: true }
74 Parameter { name: "item"; type: "QQuickItem"; isPointer: true }
157 }
75 }
158 }
76 }
159− Component {
160− name: "TouchGestureArea"
161− defaultProperty: "data"
162− prototype: "QQuickItem"
163− exports: ["Ubuntu.Gestures/TouchGestureArea 0.1"]
164− exportMetaObjectRevisions: [0]
165− Enum {
166− name: "Status"
167− values: {
168− "WaitingForTouch": 0,
169− "Undecided": 1,
170− "Recognized": 2,
171− "Rejected": 3
172− }
173− }
174− Property { name: "touchPoints"; type: "GestureTouchPoint"; isList: true; isReadonly: true }
175− Property { name: "dragging"; type: "bool"; isReadonly: true }
176− Property { name: "minimumTouchPoints"; type: "int" }
177− Property { name: "maximumTouchPoints"; type: "int" }
178− Signal {
179− name: "statusChanged"
180− Parameter { name: "status"; type: "Status" }
181− }
182− Signal { name: "touchPointsUpdated" }
183− Signal {
184− name: "draggingChanged"
185− Parameter { name: "dragging"; type: "bool" }
186− }
187− Signal {
188− name: "minimumTouchPointsChanged"
189− Parameter { name: "value"; type: "bool" }
190− }
191− Signal {
192− name: "maximumTouchPointsChanged"
193− Parameter { name: "value"; type: "bool" }
194− }
195− Signal {
196− name: "pressed"
197− Parameter { name: "points"; type: "QList<QObject*>" }
198− }
199− Signal {
200− name: "released"
201− Parameter { name: "points"; type: "QList<QObject*>" }
202− }
203− Signal {
204− name: "updated"
205− Parameter { name: "points"; type: "QList<QObject*>" }
206− }
207− Signal { name: "clicked" }
208− }
209}
77}
plugins/Ubuntu/Gestures/MouseEventGenerator.cppnew file+64
@@ -0,0 +1,64 @@
1+/*
2+ * Copyright (C) 2015-2016 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include "MouseEventGenerator.h"
18+
19+#include <QCoreApplication>
20+#include <QMouseEvent>
21+#include <QQuickItem>
22+
23+MouseEventGenerator::MouseEventGenerator(QObject *parent)
24+ : QObject(parent)
25+{
26+}
27+
28+void MouseEventGenerator::move(const QPointF position)
29+{
30+ if (!m_mousePressed || !m_targetItem) {
31+ return;
32+ }
33+
34+ QMouseEvent mouseEvent(QEvent::MouseMove,
35+ QPointF(position.x(), position.y()), Qt::NoButton, Qt::LeftButton, Qt::NoModifier);
36+
37+ QCoreApplication::sendEvent(m_targetItem, &mouseEvent);
38+}
39+
40+void MouseEventGenerator::press(const QPointF position)
41+{
42+ if (m_mousePressed || !m_targetItem) {
43+ return;
44+ }
45+
46+ QMouseEvent mouseEvent(QEvent::MouseButtonPress,
47+ QPointF(position.x(), position.y()), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
48+
49+ QCoreApplication::sendEvent(m_targetItem, &mouseEvent);
50+ m_mousePressed = true;
51+}
52+
53+void MouseEventGenerator::release(const QPointF position)
54+{
55+ if (!m_mousePressed || !m_targetItem) {
56+ return;
57+ }
58+
59+ QMouseEvent mouseEvent(QEvent::MouseButtonRelease,
60+ QPointF(position.x(), position.y()), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
61+
62+ QCoreApplication::sendEvent(m_targetItem, &mouseEvent);
63+ m_mousePressed = false;
64+}
plugins/Ubuntu/Gestures/MouseEventGenerator.hnew file+48
@@ -0,0 +1,48 @@
1+/*
2+ * Copyright (C) 2015-2016 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#ifndef MOUSEEVENTGENERATOR_H
18+#define MOUSEEVENTGENERATOR_H
19+
20+#include <QObject>
21+#include <QPointF>
22+
23+#include "UbuntuGesturesQmlGlobal.h"
24+
25+class QQuickItem;
26+
27+class UBUNTUGESTURESQML_EXPORT MouseEventGenerator : public QObject {
28+ Q_OBJECT
29+ Q_PROPERTY(QQuickItem* targetItem MEMBER m_targetItem NOTIFY targetItemChanged)
30+
31+public:
32+ MouseEventGenerator(QObject *parent = nullptr);
33+
34+ Q_INVOKABLE void move(const QPointF position);
35+ Q_INVOKABLE void press(const QPointF position);
36+ Q_INVOKABLE void release(const QPointF position);
37+
38+Q_SIGNALS:
39+ void targetItemChanged(QQuickItem *);
40+
41+private:
42+ bool m_mousePressed {false};
43+ QQuickItem *m_targetItem {nullptr};
44+
45+ friend class tst_FloatingFlickable;
46+};
47+
48+#endif // MOUSEEVENTGENERATOR_H
plugins/Ubuntu/Gestures/PressedOutsideNotifier.h+1−1
@@ -23,7 +23,7 @@
23#include <QPointer>
23#include <QPointer>
24#include <QTimer>
24#include <QTimer>
25
25
26−#include "UbuntuGesturesGlobal.h"
26+#include <ubuntugesturesglobal.h>
27
27
28/*
28/*
29 Notifies when a point, mouse or touch, is pressed outside its area.
29 Notifies when a point, mouse or touch, is pressed outside its area.
plugins/Ubuntu/Gestures/TouchGate.cpp+2−2
@@ -20,8 +20,8 @@
20#include <QDebug>
20#include <QDebug>
21#include <QQuickWindow>
21#include <QQuickWindow>
22
22
23−#include <TouchOwnershipEvent.h>
23+#include <TouchOwnershipEvent>
24−#include <TouchRegistry.h>
24+#include <TouchRegistry>
25
25
26#if TOUCHGATE_DEBUG
26#if TOUCHGATE_DEBUG
27#define ugDebug(params) qDebug().nospace() << "[TouchGate(" << (void*)this << ")] " << params
27#define ugDebug(params) qDebug().nospace() << "[TouchGate(" << (void*)this << ")] " << params
plugins/Ubuntu/Gestures/TouchGestureArea.cpp+9−6
@@ -16,10 +16,11 @@
16
16
17#include "TouchGestureArea.h"
17#include "TouchGestureArea.h"
18
18
19−// local
20−#include "TouchOwnershipEvent.h"
19+#include <UbuntuGestures/TouchOwnershipEvent>
20+#include <UbuntuGestures/TouchRegistry>
21+#include <UbuntuGestures/UnownedTouchEvent>
21−#include "TouchRegistry.h"
22+// #include "TouchRegistry.h"
22−#include "UnownedTouchEvent.h"
23+// #include "UnownedTouchEvent.h"
23
24
24#include <QGuiApplication>
25#include <QGuiApplication>
25#include <QStyleHints>
26#include <QStyleHints>
@@ -588,13 +589,15 @@ void TouchGestureArea::setInternalStatus(uint newStatus)
588 resyncCachedTouchPoints();
589 resyncCachedTouchPoints();
589 break;
590 break;
590 case InternalStatus::WaitingForMoreTouches:
591 case InternalStatus::WaitingForMoreTouches:
591− m_recognitionTimer->start(m_recognitionPeriod);
592+ m_recognitionTimer->setInterval(m_recognitionPeriod);
593+ m_recognitionTimer->start();
592 break;
594 break;
593 case InternalStatus::Recognized:
595 case InternalStatus::Recognized:
594 resyncCachedTouchPoints();
596 resyncCachedTouchPoints();
595 break;
597 break;
596 case InternalStatus::WaitingForRejection:
598 case InternalStatus::WaitingForRejection:
597− m_recognitionTimer->start(m_releaseRejectPeriod);
599+ m_recognitionTimer->setInterval(m_releaseRejectPeriod);
600+ m_recognitionTimer->start();
598 break;
601 break;
599 case InternalStatus::Rejected:
602 case InternalStatus::Rejected:
600 resyncCachedTouchPoints();
603 resyncCachedTouchPoints();
plugins/Ubuntu/Gestures/TouchGestureArea.h+2−3
@@ -21,8 +21,7 @@
21
21
22#include <QQuickItem>
22#include <QQuickItem>
23
23
24−// lib UbuntuGestures
25−#include <Timer.h>
24+#include <UbuntuGestures/Timer>
26
25
27class TouchOwnershipEvent;
26class TouchOwnershipEvent;
28class UnownedTouchEvent;
27class UnownedTouchEvent;
@@ -176,7 +175,7 @@ Q_SIGNALS:
176 void clicked();
175 void clicked();
177
176
178protected:
177protected:
179− void itemChange(ItemChange change, const ItemChangeData &value);
178+ void itemChange(ItemChange change, const ItemChangeData &value) override;
180
179
181private Q_SLOTS:
180private Q_SLOTS:
182 void rejectGesture();
181 void rejectGesture();
plugins/Ubuntu/Gestures/plugin.cpp+3−5
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2013,2015 Canonical, Ltd.
2+ * Copyright (C) 2013,2015,2016 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
@@ -17,8 +17,7 @@
17#include "plugin.h"
17#include "plugin.h"
18#include "AxisVelocityCalculator.h"
18#include "AxisVelocityCalculator.h"
19#include "Direction.h"
19#include "Direction.h"
20−#include "DirectionalDragArea.h"
20+#include "MouseEventGenerator.h"
21−#include "FloatingFlickable.h"
22#include "PressedOutsideNotifier.h"
21#include "PressedOutsideNotifier.h"
23#include "TouchGate.h"
22#include "TouchGate.h"
24#include "TouchGestureArea.h"
23#include "TouchGestureArea.h"
@@ -34,9 +33,8 @@ static QObject* directionSingleton(QQmlEngine* engine, QJSEngine* scriptEngine)
34void UbuntuGesturesQmlPlugin::registerTypes(const char *uri)
33void UbuntuGesturesQmlPlugin::registerTypes(const char *uri)
35{
34{
36 qmlRegisterSingletonType<Direction>(uri, 0, 1, "Direction", directionSingleton);
35 qmlRegisterSingletonType<Direction>(uri, 0, 1, "Direction", directionSingleton);
37− qmlRegisterType<DirectionalDragArea>(uri, 0, 1, "DirectionalDragArea");
38 qmlRegisterType<AxisVelocityCalculator>(uri, 0, 1, "AxisVelocityCalculator");
36 qmlRegisterType<AxisVelocityCalculator>(uri, 0, 1, "AxisVelocityCalculator");
39− qmlRegisterType<FloatingFlickable>(uri, 0, 1, "FloatingFlickable");
37+ qmlRegisterType<MouseEventGenerator>(uri, 0, 1, "MouseEventGenerator");
40 qmlRegisterType<PressedOutsideNotifier>(uri, 0, 1, "PressedOutsideNotifier");
38 qmlRegisterType<PressedOutsideNotifier>(uri, 0, 1, "PressedOutsideNotifier");
41 qmlRegisterType<TouchGate>(uri, 0, 1, "TouchGate");
39 qmlRegisterType<TouchGate>(uri, 0, 1, "TouchGate");
42 qmlRegisterType<TouchGestureArea>(uri, 0, 1, "TouchGestureArea");
40 qmlRegisterType<TouchGestureArea>(uri, 0, 1, "TouchGestureArea");
plugins/Unity/InputInfo/plugin.h+1−1
@@ -24,7 +24,7 @@ class InputInfoPlugin : public QQmlExtensionPlugin
24 Q_OBJECT
24 Q_OBJECT
25 Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
25 Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
26public:
26public:
27− void registerTypes(const char *uri);
27+ void registerTypes(const char *uri) override;
28};
28};
29
29
30#endif // INPUTINFO_PLUGIN_H
30#endif // INPUTINFO_PLUGIN_H
plugins/Unity/InputInfo/qdeclarativeinputdevicemodel_p.h+3−3
@@ -69,8 +69,8 @@ public:
69 explicit QDeclarativeInputDeviceModel(QObject *parent = 0);
69 explicit QDeclarativeInputDeviceModel(QObject *parent = 0);
70 virtual ~QDeclarativeInputDeviceModel();
70 virtual ~QDeclarativeInputDeviceModel();
71
71
72− QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
72+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
73− int rowCount(const QModelIndex &parent = QModelIndex()) const;
73+ int rowCount(const QModelIndex &parent = QModelIndex()) const override;
74
74
75 void setDeviceFilter(QInputDevice::InputType filter);
75 void setDeviceFilter(QInputDevice::InputType filter);
76 QInputDevice::InputType deviceFilter();
76 QInputDevice::InputType deviceFilter();
@@ -78,7 +78,7 @@ public:
78 Q_INVOKABLE int indexOf(const QString &devicePath) const;
78 Q_INVOKABLE int indexOf(const QString &devicePath) const;
79
79
80 Q_INVOKABLE QInputDevice *get(int index) const;
80 Q_INVOKABLE QInputDevice *get(int index) const;
81− QHash<int, QByteArray> roleNames() const;
81+ QHash<int, QByteArray> roleNames() const override;
82
82
83Q_SIGNALS:
83Q_SIGNALS:
84 void deviceAdded(const QString &devicePath);
84 void deviceAdded(const QString &devicePath);
plugins/Unity/Session/dbusunitysessionservice.cpp+7
@@ -227,11 +227,14 @@ private Q_SLOTS:
227 {
227 {
228 if (!active) {
228 if (!active) {
229 setupSystemdInhibition();
229 setupSystemdInhibition();
230+ } else {
231+ Q_EMIT prepareForSleep();
230 }
232 }
231 }
233 }
232
234
233Q_SIGNALS:
235Q_SIGNALS:
234 void screensaverActiveChanged(bool active);
236 void screensaverActiveChanged(bool active);
237+ void prepareForSleep();
235};
238};
236
239
237Q_GLOBAL_STATIC(DBusUnitySessionServicePrivate, d)
240Q_GLOBAL_STATIC(DBusUnitySessionServicePrivate, d)
@@ -245,6 +248,7 @@ DBusUnitySessionService::DBusUnitySessionService()
245 // ... and our Unlocked() signal to the logind's session Unlock() signal
248 // ... and our Unlocked() signal to the logind's session Unlock() signal
246 // (lightdm handles the unlocking by calling logind's Unlock method which in turn emits this signal we connect to)
249 // (lightdm handles the unlocking by calling logind's Unlock method which in turn emits this signal we connect to)
247 QDBusConnection::systemBus().connect(LOGIN1_SERVICE, d->logindSessionPath, LOGIN1_SESSION_IFACE, QStringLiteral("Unlock"), this, SIGNAL(Unlocked()));
250 QDBusConnection::systemBus().connect(LOGIN1_SERVICE, d->logindSessionPath, LOGIN1_SESSION_IFACE, QStringLiteral("Unlock"), this, SIGNAL(Unlocked()));
251+ connect(d, &DBusUnitySessionServicePrivate::prepareForSleep, this, &DBusUnitySessionService::PromptLock);
248 } else {
252 } else {
249 qWarning() << "Failed to connect to logind's session Lock/Unlock signals";
253 qWarning() << "Failed to connect to logind's session Lock/Unlock signals";
250 }
254 }
@@ -390,16 +394,19 @@ void DBusUnitySessionService::Shutdown()
390
394
391void DBusUnitySessionService::Suspend()
395void DBusUnitySessionService::Suspend()
392{
396{
397+ PromptLock();
393 d->makeLogin1Call(QStringLiteral("Suspend"), {false});
398 d->makeLogin1Call(QStringLiteral("Suspend"), {false});
394}
399}
395
400
396void DBusUnitySessionService::Hibernate()
401void DBusUnitySessionService::Hibernate()
397{
402{
403+ PromptLock();
398 d->makeLogin1Call(QStringLiteral("Hibernate"), {false});
404 d->makeLogin1Call(QStringLiteral("Hibernate"), {false});
399}
405}
400
406
401void DBusUnitySessionService::HybridSleep()
407void DBusUnitySessionService::HybridSleep()
402{
408{
409+ PromptLock();
403 d->makeLogin1Call(QStringLiteral("HybridSleep"), {false});
410 d->makeLogin1Call(QStringLiteral("HybridSleep"), {false});
404}
411}
405
412
plugins/Utils/WindowInputMonitor.cpp+8−8
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2015 Canonical, Ltd.
2+ * Copyright (C) 2015-2016 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
@@ -30,7 +30,6 @@ WindowInputMonitor::WindowInputMonitor(UnityUtil::AbstractTimer *timer,
30 QQuickItem *parent)
30 QQuickItem *parent)
31 : QQuickItem(parent)
31 : QQuickItem(parent)
32 , m_windowBeingTouched(false)
32 , m_windowBeingTouched(false)
33− , m_homeKeyPressed(false)
34 , m_windowLastTouchedTimer(elapsedTimer)
33 , m_windowLastTouchedTimer(elapsedTimer)
35 , m_activationTimer(timer)
34 , m_activationTimer(timer)
36{
35{
@@ -42,6 +41,7 @@ WindowInputMonitor::WindowInputMonitor(UnityUtil::AbstractTimer *timer,
42 connect(m_activationTimer, &UnityUtil::AbstractTimer::timeout,
41 connect(m_activationTimer, &UnityUtil::AbstractTimer::timeout,
43 this, &WindowInputMonitor::emitActivatedIfNoTouchesAround);
42 this, &WindowInputMonitor::emitActivatedIfNoTouchesAround);
44 m_activationTimer->setInterval(msecsWithoutTouches);
43 m_activationTimer->setInterval(msecsWithoutTouches);
44+ m_activationTimer->setSingleShot(true);
45}
45}
46
46
47WindowInputMonitor::~WindowInputMonitor()
47WindowInputMonitor::~WindowInputMonitor()
@@ -67,19 +67,19 @@ void WindowInputMonitor::update(QEvent *event)
67 if (event->type() == QEvent::KeyPress) {
67 if (event->type() == QEvent::KeyPress) {
68 QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
68 QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
69
69
70− m_homeKeyPressed = true;
70+ if (m_pressedHomeKey == 0 && m_homeKeys.contains(keyEvent->key()) && !keyEvent->isAutoRepeat()
71−
71+ && !m_activationTimer->isRunning()
72− if (keyEvent->key() == Qt::Key_Super_L && !keyEvent->isAutoRepeat()
73 && !m_windowBeingTouched
72 && !m_windowBeingTouched
74 && m_windowLastTouchedTimer->elapsed() >= msecsWithoutTouches) {
73 && m_windowLastTouchedTimer->elapsed() >= msecsWithoutTouches) {
74+ m_pressedHomeKey = keyEvent->key();
75 m_activationTimer->start();
75 m_activationTimer->start();
76 }
76 }
77
77
78 } else if (event->type() == QEvent::KeyRelease) {
78 } else if (event->type() == QEvent::KeyRelease) {
79 QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
79 QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
80
80
81− if (keyEvent->key() == Qt::Key_Super_L) {
81+ if (keyEvent->key() == m_pressedHomeKey) {
82− m_homeKeyPressed = false;
82+ m_pressedHomeKey = 0;
83 }
83 }
84
84
85 } else if (event->type() == QEvent::TouchBegin) {
85 } else if (event->type() == QEvent::TouchBegin) {
@@ -116,7 +116,7 @@ void WindowInputMonitor::setupFilterOnWindow(QQuickWindow *window)
116
116
117void WindowInputMonitor::emitActivatedIfNoTouchesAround()
117void WindowInputMonitor::emitActivatedIfNoTouchesAround()
118{
118{
119− if (!m_homeKeyPressed && !m_windowBeingTouched &&
119+ if (m_pressedHomeKey == 0 && !m_windowBeingTouched &&
120 (m_windowLastTouchedTimer->elapsed() > msecsWithoutTouches)) {
120 (m_windowLastTouchedTimer->elapsed() > msecsWithoutTouches)) {
121 Q_EMIT homeKeyActivated();
121 Q_EMIT homeKeyActivated();
122 }
122 }
plugins/Utils/WindowInputMonitor.h+8−2
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2015 Canonical, Ltd.
2+ * Copyright (C) 2015-2016 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
@@ -18,6 +18,7 @@
18#define UNITY_WINDOWINPUTMONITOR_H
18#define UNITY_WINDOWINPUTMONITOR_H
19
19
20#include <QQuickItem>
20#include <QQuickItem>
21+#include <QList>
21#include <QPointer>
22#include <QPointer>
22
23
23#include "Timer.h"
24#include "Timer.h"
@@ -83,9 +84,14 @@ private Q_SLOTS:
83private:
84private:
84 QPointer<QQuickWindow> m_filteredWindow;
85 QPointer<QQuickWindow> m_filteredWindow;
85 bool m_windowBeingTouched;
86 bool m_windowBeingTouched;
86− bool m_homeKeyPressed;
87 UnityUtil::AbstractElapsedTimer *m_windowLastTouchedTimer;
87 UnityUtil::AbstractElapsedTimer *m_windowLastTouchedTimer;
88 UnityUtil::AbstractTimer *m_activationTimer;
88 UnityUtil::AbstractTimer *m_activationTimer;
89+
90+ // Qt::Keys that are mapped to our "home" key.
91+ QList<int> m_homeKeys{Qt::Key_Super_L, Qt::Key_HomePage};
92+ // Which Qt::Key from m_homeKeys is currently pressed.
93+ // 0 if none
94+ int m_pressedHomeKey{0};
89};
95};
90
96
91#endif // UNITY_WINDOWINPUTMONITOR_H
97#endif // UNITY_WINDOWINPUTMONITOR_H
plugins/Utils/windowstatestorage.h+13−3
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright 2015 Canonical Ltd.
2+ * Copyright 2015-2016 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 Lesser General Public License as published by
5 * it under the terms of the GNU Lesser General Public License as published by
@@ -25,9 +25,19 @@ class WindowStateStorage: public QObject
25 Q_ENUMS(WindowState)
25 Q_ENUMS(WindowState)
26public:
26public:
27 enum WindowState {
27 enum WindowState {
28− WindowStateNormal,
28+ WindowStateNormal = 1 << 0,
29− WindowStateMaximized
29+ WindowStateMaximized = 1 << 1,
30+ WindowStateMinimized = 1 << 2,
31+ WindowStateFullscreen = 1 << 3,
32+ WindowStateMaximizedLeft = 1 << 4,
33+ WindowStateMaximizedRight = 1 << 5,
34+ WindowStateMaximizedHorizontally = 1 << 6,
35+ WindowStateMaximizedVertically = 1 << 7
30 };
36 };
37+ Q_DECLARE_FLAGS(WindowStates, WindowState)
38+#if (QT_VERSION >= QT_VERSION_CHECK(5, 5, 0))
39+ Q_FLAG(WindowStates)
40+#endif
31
41
32 WindowStateStorage(QObject *parent = 0);
42 WindowStateStorage(QObject *parent = 0);
33 virtual ~WindowStateStorage();
43 virtual ~WindowStateStorage();
po/aa.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2016-02-12 10:18+0000\n"
11"PO-Revision-Date: 2016-02-12 10:18+0000\n"
12"Last-Translator: Charif AYFARAH <ayfarah@ymail.com>\n"
12"Last-Translator: Charif AYFARAH <ayfarah@ymail.com>\n"
13"Language-Team: Afar <aa@li.org>\n"
13"Language-Team: Afar <aa@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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: 2016-05-19 05:49+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:08+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -256,7 +256,7 @@ msgstr "Dabqi"
256msgid "Also installed"
256msgid "Also installed"
257msgstr ""
257msgstr ""
258
258
259−#: qml/DisabledScreenNotice.qml:104
259+#: qml/DisabledScreenNotice.qml:109
260msgid ""
260msgid ""
261"Your device is now connected to an external display. Use this screen as a "
261"Your device is now connected to an external display. Use this screen as a "
262"touch pad to interact with the pointer."
262"touch pad to interact with the pointer."
po/am.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2016-03-24 19:07+0000\n"
11"PO-Revision-Date: 2016-03-24 19:07+0000\n"
12"Last-Translator: samson <Unknown>\n"
12"Last-Translator: samson <Unknown>\n"
13"Language-Team: Amharic <am@li.org>\n"
13"Language-Team: Amharic <am@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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: 2016-05-19 05:49+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:08+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -258,7 +258,7 @@ msgstr "ቤት"
258msgid "Also installed"
258msgid "Also installed"
259msgstr "እንዲሁም የተገጠሙ"
259msgstr "እንዲሁም የተገጠሙ"
260
260
261−#: qml/DisabledScreenNotice.qml:104
261+#: qml/DisabledScreenNotice.qml:109
262msgid ""
262msgid ""
263"Your device is now connected to an external display. Use this screen as a "
263"Your device is now connected to an external display. Use this screen as a "
264"touch pad to interact with the pointer."
264"touch pad to interact with the pointer."
po/ar.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2015-07-29 09:41+0000\n"
11"PO-Revision-Date: 2015-07-29 09:41+0000\n"
12"Last-Translator: Ibrahim Saed <ibraheem5000@gmail.com>\n"
12"Last-Translator: Ibrahim Saed <ibraheem5000@gmail.com>\n"
13"Language-Team: Arabic <ar@li.org>\n"
13"Language-Team: Arabic <ar@li.org>\n"
@@ -16,8 +16,8 @@ msgstr ""
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n % 100 >= "
17"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n % 100 >= "
18"3 && n % 100 <= 10 ? 3 : n % 100 >= 11 && n % 100 <= 99 ? 4 : 5;\n"
18"3 && n % 100 <= 10 ? 3 : n % 100 >= 11 && n % 100 <= 99 ? 4 : 5;\n"
19−"X-Launchpad-Export-Date: 2016-05-19 05:49+0000\n"
19+"X-Launchpad-Export-Date: 2016-05-25 06:08+0000\n"
20−"X-Generator: Launchpad (build 18025)\n"
20+"X-Generator: Launchpad (build 18053)\n"
21
21
22#: plugins/IntegratedLightDM/Greeter.cpp:112
22#: plugins/IntegratedLightDM/Greeter.cpp:112
23msgid "Password: "
23msgid "Password: "
@@ -265,7 +265,7 @@ msgstr "الرئيسية"
265msgid "Also installed"
265msgid "Also installed"
266msgstr "أيضا تم تثبيت"
266msgstr "أيضا تم تثبيت"
267
267
268−#: qml/DisabledScreenNotice.qml:104
268+#: qml/DisabledScreenNotice.qml:109
269msgid ""
269msgid ""
270"Your device is now connected to an external display. Use this screen as a "
270"Your device is now connected to an external display. Use this screen as a "
271"touch pad to interact with the pointer."
271"touch pad to interact with the pointer."
po/ast.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2016-05-16 14:07+0000\n"
11"PO-Revision-Date: 2016-05-16 14:07+0000\n"
12"Last-Translator: Xuacu Saturio <xuacusk8@gmail.com>\n"
12"Last-Translator: Xuacu Saturio <xuacusk8@gmail.com>\n"
13"Language-Team: Asturian <ast@li.org>\n"
13"Language-Team: Asturian <ast@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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: 2016-05-19 05:49+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:08+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -259,7 +259,7 @@ msgstr "Aniciu"
259msgid "Also installed"
259msgid "Also installed"
260msgstr "Tamién instalaos"
260msgstr "Tamién instalaos"
261
261
262−#: qml/DisabledScreenNotice.qml:104
262+#: qml/DisabledScreenNotice.qml:109
263msgid ""
263msgid ""
264"Your device is now connected to an external display. Use this screen as a "
264"Your device is now connected to an external display. Use this screen as a "
265"touch pad to interact with the pointer."
265"touch pad to interact with the pointer."
po/az.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2014-09-03 16:39+0000\n"
11"PO-Revision-Date: 2014-09-03 16:39+0000\n"
12"Last-Translator: Nicat Məmmədov <n1c4t97@gmail.com>\n"
12"Last-Translator: Nicat Məmmədov <n1c4t97@gmail.com>\n"
13"Language-Team: Azerbaijani <az@li.org>\n"
13"Language-Team: Azerbaijani <az@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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: 2016-05-19 05:49+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:08+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -256,7 +256,7 @@ msgstr ""
256msgid "Also installed"
256msgid "Also installed"
257msgstr ""
257msgstr ""
258
258
259−#: qml/DisabledScreenNotice.qml:104
259+#: qml/DisabledScreenNotice.qml:109
260msgid ""
260msgid ""
261"Your device is now connected to an external display. Use this screen as a "
261"Your device is now connected to an external display. Use this screen as a "
262"touch pad to interact with the pointer."
262"touch pad to interact with the pointer."
po/be.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2015-12-13 13:12+0000\n"
11"PO-Revision-Date: 2015-12-13 13:12+0000\n"
12"Last-Translator: Mikhail_SaTuRn <mikhail_saturn@tut.by>\n"
12"Last-Translator: Mikhail_SaTuRn <mikhail_saturn@tut.by>\n"
13"Language-Team: Belarusian <be@li.org>\n"
13"Language-Team: Belarusian <be@li.org>\n"
@@ -16,8 +16,8 @@ msgstr ""
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
17"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
18"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
18"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
19−"X-Launchpad-Export-Date: 2016-05-19 05:49+0000\n"
19+"X-Launchpad-Export-Date: 2016-05-25 06:08+0000\n"
20−"X-Generator: Launchpad (build 18025)\n"
20+"X-Generator: Launchpad (build 18053)\n"
21
21
22#: plugins/IntegratedLightDM/Greeter.cpp:112
22#: plugins/IntegratedLightDM/Greeter.cpp:112
23msgid "Password: "
23msgid "Password: "
@@ -263,7 +263,7 @@ msgstr "Хатняя папка"
263msgid "Also installed"
263msgid "Also installed"
264msgstr "Таксама ўсталявана"
264msgstr "Таксама ўсталявана"
265
265
266−#: qml/DisabledScreenNotice.qml:104
266+#: qml/DisabledScreenNotice.qml:109
267msgid ""
267msgid ""
268"Your device is now connected to an external display. Use this screen as a "
268"Your device is now connected to an external display. Use this screen as a "
269"touch pad to interact with the pointer."
269"touch pad to interact with the pointer."
po/bg.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2015-04-12 14:43+0000\n"
11"PO-Revision-Date: 2015-04-12 14:43+0000\n"
12"Last-Translator: George Karavasilev <kokoto-java@ubuntu.com>\n"
12"Last-Translator: George Karavasilev <kokoto-java@ubuntu.com>\n"
13"Language-Team: Bulgarian <bg@li.org>\n"
13"Language-Team: Bulgarian <bg@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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: 2016-05-19 05:49+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:08+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -258,7 +258,7 @@ msgstr ""
258msgid "Also installed"
258msgid "Also installed"
259msgstr ""
259msgstr ""
260
260
261−#: qml/DisabledScreenNotice.qml:104
261+#: qml/DisabledScreenNotice.qml:109
262msgid ""
262msgid ""
263"Your device is now connected to an external display. Use this screen as a "
263"Your device is now connected to an external display. Use this screen as a "
264"touch pad to interact with the pointer."
264"touch pad to interact with the pointer."
po/bn.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2015-11-27 19:38+0000\n"
11"PO-Revision-Date: 2015-11-27 19:38+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Bengali <bn@li.org>\n"
13"Language-Team: Bengali <bn@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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: 2016-05-19 05:49+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:08+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -258,7 +258,7 @@ msgstr ""
258msgid "Also installed"
258msgid "Also installed"
259msgstr "আরও ইন্সটল করা রয়েছে..."
259msgstr "আরও ইন্সটল করা রয়েছে..."
260
260
261−#: qml/DisabledScreenNotice.qml:104
261+#: qml/DisabledScreenNotice.qml:109
262msgid ""
262msgid ""
263"Your device is now connected to an external display. Use this screen as a "
263"Your device is now connected to an external display. Use this screen as a "
264"touch pad to interact with the pointer."
264"touch pad to interact with the pointer."
po/br.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2016-04-27 12:20+0000\n"
11"PO-Revision-Date: 2016-04-27 12:20+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"
@@ -15,8 +15,8 @@ msgstr ""
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: 2016-05-19 05:49+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:08+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -265,7 +265,7 @@ msgstr "Er gêr"
265msgid "Also installed"
265msgid "Also installed"
266msgstr "Staliet ivez"
266msgstr "Staliet ivez"
267
267
268−#: qml/DisabledScreenNotice.qml:104
268+#: qml/DisabledScreenNotice.qml:109
269msgid ""
269msgid ""
270"Your device is now connected to an external display. Use this screen as a "
270"Your device is now connected to an external display. Use this screen as a "
271"touch pad to interact with the pointer."
271"touch pad to interact with the pointer."
po/bs.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2015-12-01 20:06+0000\n"
11"PO-Revision-Date: 2015-12-01 20:06+0000\n"
12"Last-Translator: Kenan Gutić <Unknown>\n"
12"Last-Translator: Kenan Gutić <Unknown>\n"
13"Language-Team: Bosnian <bs@li.org>\n"
13"Language-Team: Bosnian <bs@li.org>\n"
@@ -16,8 +16,8 @@ msgstr ""
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
17"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
18"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
18"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
19−"X-Launchpad-Export-Date: 2016-05-19 05:49+0000\n"
19+"X-Launchpad-Export-Date: 2016-05-25 06:08+0000\n"
20−"X-Generator: Launchpad (build 18025)\n"
20+"X-Generator: Launchpad (build 18053)\n"
21
21
22#: plugins/IntegratedLightDM/Greeter.cpp:112
22#: plugins/IntegratedLightDM/Greeter.cpp:112
23msgid "Password: "
23msgid "Password: "
@@ -262,7 +262,7 @@ msgstr "Početna"
262msgid "Also installed"
262msgid "Also installed"
263msgstr "Također instalirano"
263msgstr "Također instalirano"
264
264
265−#: qml/DisabledScreenNotice.qml:104
265+#: qml/DisabledScreenNotice.qml:109
266msgid ""
266msgid ""
267"Your device is now connected to an external display. Use this screen as a "
267"Your device is now connected to an external display. Use this screen as a "
268"touch pad to interact with the pointer."
268"touch pad to interact with the pointer."
po/ca.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2015-07-04 09:48+0000\n"
11"PO-Revision-Date: 2015-07-04 09:48+0000\n"
12"Last-Translator: David Planella <david.planella@ubuntu.com>\n"
12"Last-Translator: David Planella <david.planella@ubuntu.com>\n"
13"Language-Team: Catalan <ca@li.org>\n"
13"Language-Team: Catalan <ca@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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: 2016-05-19 05:49+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:08+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -262,7 +262,7 @@ msgstr "Inici"
262msgid "Also installed"
262msgid "Also installed"
263msgstr "També instal·lat"
263msgstr "També instal·lat"
264
264
265−#: qml/DisabledScreenNotice.qml:104
265+#: qml/DisabledScreenNotice.qml:109
266msgid ""
266msgid ""
267"Your device is now connected to an external display. Use this screen as a "
267"Your device is now connected to an external display. Use this screen as a "
268"touch pad to interact with the pointer."
268"touch pad to interact with the pointer."
po/ca@valencia.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2015-02-22 15:22+0000\n"
11"PO-Revision-Date: 2015-02-22 15:22+0000\n"
12"Last-Translator: David Planella <david.planella@ubuntu.com>\n"
12"Last-Translator: David Planella <david.planella@ubuntu.com>\n"
13"Language-Team: Catalan <ca@li.org>\n"
13"Language-Team: Catalan <ca@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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: 2016-05-19 05:50+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -262,7 +262,7 @@ msgstr "Inici"
262msgid "Also installed"
262msgid "Also installed"
263msgstr "També instal·lat"
263msgstr "També instal·lat"
264
264
265−#: qml/DisabledScreenNotice.qml:104
265+#: qml/DisabledScreenNotice.qml:109
266msgid ""
266msgid ""
267"Your device is now connected to an external display. Use this screen as a "
267"Your device is now connected to an external display. Use this screen as a "
268"touch pad to interact with the pointer."
268"touch pad to interact with the pointer."
po/ce.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2015-02-15 04:01+0000\n"
11"PO-Revision-Date: 2015-02-15 04:01+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Chechen <ce@li.org>\n"
13"Language-Team: Chechen <ce@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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: 2016-05-19 05:49+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:08+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -256,7 +256,7 @@ msgstr ""
256msgid "Also installed"
256msgid "Also installed"
257msgstr ""
257msgstr ""
258
258
259−#: qml/DisabledScreenNotice.qml:104
259+#: qml/DisabledScreenNotice.qml:109
260msgid ""
260msgid ""
261"Your device is now connected to an external display. Use this screen as a "
261"Your device is now connected to an external display. Use this screen as a "
262"touch pad to interact with the pointer."
262"touch pad to interact with the pointer."
po/ckb.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2014-01-21 11:05+0000\n"
11"PO-Revision-Date: 2014-01-21 11:05+0000\n"
12"Last-Translator: Aras <aras.noori@gmail.com>\n"
12"Last-Translator: Aras <aras.noori@gmail.com>\n"
13"Language-Team: Kurdish (Sorani) <ckb@li.org>\n"
13"Language-Team: Kurdish (Sorani) <ckb@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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: 2016-05-19 05:50+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -256,7 +256,7 @@ msgstr ""
256msgid "Also installed"
256msgid "Also installed"
257msgstr ""
257msgstr ""
258
258
259−#: qml/DisabledScreenNotice.qml:104
259+#: qml/DisabledScreenNotice.qml:109
260msgid ""
260msgid ""
261"Your device is now connected to an external display. Use this screen as a "
261"Your device is now connected to an external display. Use this screen as a "
262"touch pad to interact with the pointer."
262"touch pad to interact with the pointer."
po/co.ponew file+736
@@ -0,0 +1,736 @@
1+# Corsican translation for unity8
2+# Copyright (c) 2016 Rosetta Contributors and Canonical Ltd 2016
3+# This file is distributed under the same license as the unity8 package.
4+# FIRST AUTHOR <EMAIL@ADDRESS>, 2016.
5+#
6+msgid ""
7+msgstr ""
8+"Project-Id-Version: unity8\n"
9+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11+"PO-Revision-Date: 2016-05-24 10:40+0000\n"
12+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13+"Language-Team: Corsican <co@li.org>\n"
14+"MIME-Version: 1.0\n"
15+"Content-Type: text/plain; charset=UTF-8\n"
16+"Content-Transfer-Encoding: 8bit\n"
17+"Plural-Forms: nplurals=2; plural=n != 1;\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:08+0000\n"
19+"X-Generator: Launchpad (build 18053)\n"
20+
21+#: plugins/IntegratedLightDM/Greeter.cpp:112
22+msgid "Password: "
23+msgstr ""
24+
25+#: plugins/Unity/Launcher/launcheritem.cpp:48
26+#: plugins/Unity/Launcher/launcheritem.cpp:107
27+msgid "Pin shortcut"
28+msgstr ""
29+
30+#: plugins/Unity/Launcher/launcheritem.cpp:53
31+msgid "Quit"
32+msgstr ""
33+
34+#: plugins/Unity/Launcher/launcheritem.cpp:107
35+msgid "Unpin shortcut"
36+msgstr ""
37+
38+#: qml/Components/DelayedLockscreen.qml:49
39+msgid "Device Locked"
40+msgstr ""
41+
42+#: qml/Components/DelayedLockscreen.qml:64
43+msgid "You have been locked out due to too many failed passphrase attempts."
44+msgstr ""
45+
46+#: qml/Components/DelayedLockscreen.qml:65
47+msgid "You have been locked out due to too many failed passcode attempts."
48+msgstr ""
49+
50+#: qml/Components/DelayedLockscreen.qml:74
51+#, qt-format
52+msgid "Please wait %1 minute and then try again…"
53+msgid_plural "Please wait %1 minutes and then try again…"
54+msgstr[0] ""
55+msgstr[1] ""
56+
57+#: qml/Components/Dialogs.qml:144
58+msgctxt "Title: Lock/Log out dialog"
59+msgid "Log out"
60+msgstr ""
61+
62+#: qml/Components/Dialogs.qml:145
63+msgid "Are you sure you want to log out?"
64+msgstr ""
65+
66+#: qml/Components/Dialogs.qml:147
67+msgctxt "Button: Lock the system"
68+msgid "Lock"
69+msgstr ""
70+
71+#: qml/Components/Dialogs.qml:154
72+msgctxt "Button: Log out from the system"
73+msgid "Log Out"
74+msgstr ""
75+
76+#: qml/Components/Dialogs.qml:161 qml/Components/Dialogs.qml:217
77+#: qml/Dash/DashPageHeader.qml:298 qml/Wizard/Pages/passcode-confirm.qml:32
78+#: qml/Wizard/Pages/passcode-set.qml:32
79+msgid "Cancel"
80+msgstr ""
81+
82+#: qml/Components/Dialogs.qml:173
83+msgctxt "Title: Reboot dialog"
84+msgid "Reboot"
85+msgstr ""
86+
87+#: qml/Components/Dialogs.qml:174
88+msgid "Are you sure you want to reboot?"
89+msgstr ""
90+
91+#: qml/Components/Dialogs.qml:176
92+msgid "No"
93+msgstr ""
94+
95+#: qml/Components/Dialogs.qml:182
96+msgid "Yes"
97+msgstr ""
98+
99+#: qml/Components/Dialogs.qml:197
100+msgctxt "Title: Power off/Restart dialog"
101+msgid "Power"
102+msgstr ""
103+
104+#: qml/Components/Dialogs.qml:198
105+msgid ""
106+"Are you sure you would like\n"
107+"to power off?"
108+msgstr ""
109+
110+#: qml/Components/Dialogs.qml:200
111+msgctxt "Button: Power off the system"
112+msgid "Power off"
113+msgstr ""
114+
115+#: qml/Components/Dialogs.qml:209
116+msgctxt "Button: Restart the system"
117+msgid "Restart"
118+msgstr ""
119+
120+#: qml/Components/Lockscreen.qml:231
121+msgid "Return to Call"
122+msgstr ""
123+
124+#: qml/Components/Lockscreen.qml:231
125+msgid "Emergency Call"
126+msgstr ""
127+
128+#: qml/Components/Lockscreen.qml:263
129+msgid "OK"
130+msgstr ""
131+
132+#: qml/Components/ModeSwitchWarningDialog.qml:32
133+msgid "Apps may have unsaved data:"
134+msgstr ""
135+
136+#: qml/Components/ModeSwitchWarningDialog.qml:57
137+msgctxt ""
138+"Re-dock means connect the device again to an external screen/mouse/keyboard"
139+msgid "Re-dock, save your work and close these apps to continue."
140+msgstr ""
141+
142+#: qml/Components/ModeSwitchWarningDialog.qml:63
143+msgid "Or force close now (unsaved data will be lost)."
144+msgstr ""
145+
146+#: qml/Components/ModeSwitchWarningDialog.qml:75
147+msgid "OK, I will reconnect"
148+msgstr ""
149+
150+#: qml/Components/ModeSwitchWarningDialog.qml:76
151+msgid "Reconnect now!"
152+msgstr ""
153+
154+#: qml/Components/ModeSwitchWarningDialog.qml:88
155+msgid "Close all"
156+msgstr ""
157+
158+#: qml/Dash/DashPageHeader.qml:337
159+msgctxt "Button: Open the Ubuntu Store"
160+msgid "Store"
161+msgstr ""
162+
163+#: qml/Dash/DashPageHeader.qml:344
164+msgctxt "Button: Start a search in the current dash scope"
165+msgid "Search"
166+msgstr ""
167+
168+#: qml/Dash/DashPageHeader.qml:354
169+msgctxt "Button: Show the current dash scope settings"
170+msgid "Settings"
171+msgstr ""
172+
173+#: qml/Dash/DashPageHeader.qml:361
174+msgid "Remove from Favorites"
175+msgstr ""
176+
177+#: qml/Dash/DashPageHeader.qml:361
178+msgid "Add to Favorites"
179+msgstr ""
180+
181+#: qml/Dash/FiltersPopover.qml:60
182+msgid "Refine your results"
183+msgstr ""
184+
185+#: qml/Dash/FiltersPopover.qml:69
186+msgid "Reset"
187+msgstr ""
188+
189+#: qml/Dash/GenericScopeView.qml:579 qml/Dash/GenericScopeView.qml:764
190+msgid "Show less"
191+msgstr ""
192+
193+#: qml/Dash/GenericScopeView.qml:579
194+msgid "Show all"
195+msgstr ""
196+
197+#: qml/Dash/GenericScopeView.qml:636
198+msgctxt "Label: Hint for dash search line edit"
199+msgid "Search"
200+msgstr ""
201+
202+#: qml/Dash/PageHeaderExtraPanel.qml:55
203+msgid "Recent Searches"
204+msgstr ""
205+
206+#: qml/Dash/PageHeaderExtraPanel.qml:66
207+msgid "Clear All"
208+msgstr ""
209+
210+#: qml/Dash/Previews/PreviewActionCombo.qml:35
211+msgid "More..."
212+msgstr ""
213+
214+#: qml/Dash/Previews/PreviewActionCombo.qml:35
215+msgid "Less..."
216+msgstr ""
217+
218+#: qml/Dash/Previews/PreviewCommentInput.qml:68
219+#: qml/Dash/Previews/PreviewRatingInput.qml:174
220+msgid "Send"
221+msgstr ""
222+
223+#: qml/Dash/Previews/PreviewRatingInput.qml:84
224+msgid "Rate this"
225+msgstr ""
226+
227+#: qml/Dash/Previews/PreviewRatingInput.qml:129
228+msgid "Add a review"
229+msgstr ""
230+
231+#: qml/Dash/Previews/PreviewSharing.qml:66
232+msgid "Preview Share Item"
233+msgstr ""
234+
235+#: qml/Dash/PullToRefreshScopeStyle.qml:55
236+msgid "Pull to refresh…"
237+msgstr ""
238+
239+#: qml/Dash/PullToRefreshScopeStyle.qml:60
240+msgid "Release to refresh…"
241+msgstr ""
242+
243+#: qml/Dash/ScopeSettings/ScopeSettingBoolean.qml:43
244+msgid "Enable location data"
245+msgstr ""
246+
247+#: qml/Dash/ScopesList.qml:67
248+msgid "Manage"
249+msgstr ""
250+
251+#: qml/Dash/ScopesList.qml:113
252+msgid "Home"
253+msgstr ""
254+
255+#: qml/Dash/ScopesList.qml:114
256+msgid "Also installed"
257+msgstr ""
258+
259+#: qml/DisabledScreenNotice.qml:109
260+msgid ""
261+"Your device is now connected to an external display. Use this screen as a "
262+"touch pad to interact with the pointer."
263+msgstr ""
264+
265+#: qml/Greeter/CoverPage.qml:118
266+msgid "Unlock"
267+msgstr ""
268+
269+#: qml/Greeter/LoginList.qml:239
270+msgid "Retry"
271+msgstr ""
272+
273+#: qml/Greeter/LoginList.qml:240
274+msgid "Tap to unlock"
275+msgstr ""
276+
277+#: qml/Greeter/NarrowView.qml:54
278+msgid "Sorry, incorrect passphrase."
279+msgstr ""
280+
281+#: qml/Greeter/NarrowView.qml:55
282+msgid "Sorry, incorrect passcode."
283+msgstr ""
284+
285+#: qml/Greeter/NarrowView.qml:56
286+msgid "This will be your last attempt."
287+msgstr ""
288+
289+#: qml/Greeter/NarrowView.qml:58
290+msgid ""
291+"If passphrase is entered incorrectly, your phone will conduct a factory "
292+"reset and all personal data will be deleted."
293+msgstr ""
294+
295+#: qml/Greeter/NarrowView.qml:59
296+msgid ""
297+"If passcode is entered incorrectly, your phone will conduct a factory reset "
298+"and all personal data will be deleted."
299+msgstr ""
300+
301+#: qml/Greeter/NarrowView.qml:116
302+#, qt-format
303+msgid "Enter %1"
304+msgstr ""
305+
306+#: qml/Greeter/NarrowView.qml:117
307+msgid "Enter passphrase"
308+msgstr ""
309+
310+#: qml/Greeter/NarrowView.qml:118
311+msgid "Enter passcode"
312+msgstr ""
313+
314+#: qml/Greeter/NarrowView.qml:119
315+#, qt-format
316+msgid "Sorry, incorrect %1"
317+msgstr ""
318+
319+#: qml/Greeter/NarrowView.qml:120
320+msgid "Sorry, incorrect passphrase"
321+msgstr ""
322+
323+#: qml/Greeter/NarrowView.qml:121
324+msgctxt "passphrase"
325+msgid "Please re-enter"
326+msgstr ""
327+
328+#: qml/Greeter/NarrowView.qml:122
329+msgid "Sorry, incorrect passcode"
330+msgstr ""
331+
332+#: qml/Notifications/NotificationMenuItemFactory.qml:124
333+msgid "Show password"
334+msgstr ""
335+
336+#: qml/Panel/ActiveCallHint.qml:79
337+msgid "Tap to return to call..."
338+msgstr ""
339+
340+#: qml/Panel/ActiveCallHint.qml:92
341+msgid "Conference"
342+msgstr ""
343+
344+#: qml/Panel/Indicators/MenuItemFactory.qml:762
345+msgid "Nothing is playing"
346+msgstr ""
347+
348+#: qml/Panel/Indicators/MenuItemFactory.qml:891
349+#, qt-format
350+msgid "%1 hour"
351+msgid_plural "%1 hours"
352+msgstr[0] ""
353+msgstr[1] ""
354+
355+#: qml/Panel/Indicators/MenuItemFactory.qml:895
356+#, qt-format
357+msgid "%1 minute"
358+msgid_plural "%1 minutes"
359+msgstr[0] ""
360+msgstr[1] ""
361+
362+#: qml/Panel/Indicators/MenuItemFactory.qml:900
363+#, qt-format
364+msgid "%1 second"
365+msgid_plural "%1 seconds"
366+msgstr[0] ""
367+msgstr[1] ""
368+
369+#: qml/Panel/Indicators/MenuItemFactory.qml:903
370+msgid "0 seconds"
371+msgstr ""
372+
373+#. Translators: String like "1 hour, 2 minutes, 3 seconds remaining"
374+#: qml/Panel/Indicators/MenuItemFactory.qml:905
375+#, qt-format
376+msgid "%1 remaining"
377+msgstr ""
378+
379+#: qml/Panel/Indicators/MenuItemFactory.qml:911
380+msgid "In queue…"
381+msgstr ""
382+
383+#: qml/Panel/Indicators/MenuItemFactory.qml:915
384+msgid "Downloading"
385+msgstr ""
386+
387+#: qml/Panel/Indicators/MenuItemFactory.qml:917
388+msgid "Paused, tap to resume"
389+msgstr ""
390+
391+#: qml/Panel/Indicators/MenuItemFactory.qml:919
392+msgid "Canceled"
393+msgstr ""
394+
395+#: qml/Panel/Indicators/MenuItemFactory.qml:921
396+msgid "Finished"
397+msgstr ""
398+
399+#: qml/Panel/Indicators/MenuItemFactory.qml:923
400+msgid "Failed, tap to retry"
401+msgstr ""
402+
403+#: qml/Panel/Indicators/MessageMenuItemFactory.qml:155
404+#: qml/Panel/Indicators/MessageMenuItemFactory.qml:214
405+msgctxt "Button: Send a reply message"
406+msgid "Send"
407+msgstr ""
408+
409+#: qml/Panel/Indicators/MessageMenuItemFactory.qml:156
410+msgctxt "Label: Hint in message indicator line edit"
411+msgid "Reply"
412+msgstr ""
413+
414+#: qml/Panel/Indicators/MessageMenuItemFactory.qml:213
415+msgctxt "Button: Call back on phone"
416+msgid "Call back"
417+msgstr ""
418+
419+#: qml/Stages/SideStage.qml:76
420+msgid "Drag using 3 fingers any application from one window to the other"
421+msgstr ""
422+
423+#: qml/Tutorial/TutorialBottom.qml:78
424+msgid "Swipe up to add a contact"
425+msgstr ""
426+
427+#: qml/Tutorial/TutorialBottom.qml:80
428+msgid "Swipe up for favorite calculations"
429+msgstr ""
430+
431+#: qml/Tutorial/TutorialBottom.qml:82
432+msgid "Swipe up for recent calls"
433+msgstr ""
434+
435+#: qml/Tutorial/TutorialBottom.qml:84
436+msgid "Swipe up to create a message"
437+msgstr ""
438+
439+#: qml/Tutorial/TutorialBottom.qml:85
440+msgid "Swipe up to manage the app"
441+msgstr ""
442+
443+#: qml/Tutorial/TutorialLeftLong.qml:47
444+msgid "Long swipe from the left edge to open the Today scope"
445+msgstr ""
446+
447+#: qml/Tutorial/TutorialLeft.qml:47
448+msgid "Swipe from the left edge to open the launcher"
449+msgstr ""
450+
451+#: qml/Tutorial/TutorialRight.qml:55
452+msgid "Push your mouse against the right edge to view your open apps"
453+msgstr ""
454+
455+#: qml/Tutorial/TutorialRight.qml:56
456+msgid "Short or long swipe from the right edge to view your open apps"
457+msgstr ""
458+
459+#: qml/Tutorial/TutorialTop.qml:53
460+msgid "Swipe from the top right edge to open the notification bar"
461+msgstr ""
462+
463+#: qml/Tutorial/TutorialTop.qml:54
464+msgid "Swipe from the top edge to open the notification bar"
465+msgstr ""
466+
467+#: qml/Wizard/Page.qml:54
468+msgctxt "Button: Go back one page in the Wizard"
469+msgid "Back"
470+msgstr ""
471+
472+#: qml/Wizard/Pages/10-welcome.qml:27
473+msgid "Language"
474+msgstr ""
475+
476+#: qml/Wizard/Pages/10-welcome.qml:156 qml/Wizard/Pages/30-wifi.qml:206
477+#: qml/Wizard/Pages/40-location.qml:271 qml/Wizard/Pages/50-timezone.qml:267
478+#: qml/Wizard/Pages/60-account.qml:65 qml/Wizard/Pages/70-passwd-type.qml:144
479+#: qml/Wizard/Pages/75-report-check.qml:84
480+#: qml/Wizard/Pages/passcode-desktop.qml:124
481+#: qml/Wizard/Pages/password-set.qml:141
482+msgid "Next"
483+msgstr ""
484+
485+#: qml/Wizard/Pages/30-wifi.qml:29
486+msgid "Connect to Wi‑Fi"
487+msgstr ""
488+
489+#: qml/Wizard/Pages/30-wifi.qml:130
490+msgid "Connected"
491+msgstr ""
492+
493+#: qml/Wizard/Pages/30-wifi.qml:163
494+msgid "Available Wi-Fi networks"
495+msgstr ""
496+
497+#: qml/Wizard/Pages/30-wifi.qml:164
498+msgid "No available Wi-Fi networks"
499+msgstr ""
500+
501+#: qml/Wizard/Pages/30-wifi.qml:206 qml/Wizard/Pages/60-account.qml:65
502+#: qml/Wizard/Pages/sim.qml:101
503+msgid "Skip"
504+msgstr ""
505+
506+#: qml/Wizard/Pages/40-location.qml:27
507+msgid "Location Services"
508+msgstr ""
509+
510+#: qml/Wizard/Pages/40-location.qml:83
511+msgid ""
512+"Use GPS, Wi-Fi hotspots and mobile network anonymously to detect location "
513+"(recommended)"
514+msgstr ""
515+
516+#: qml/Wizard/Pages/40-location.qml:105
517+#, qt-format
518+msgid "By selecting this option you agree to the Nokia HERE %1."
519+msgstr ""
520+
521+#: qml/Wizard/Pages/40-location.qml:106
522+msgctxt "part of: Nokia HERE terms and conditions"
523+msgid "terms and conditions"
524+msgstr ""
525+
526+#: qml/Wizard/Pages/40-location.qml:160
527+msgid "GPS only"
528+msgstr ""
529+
530+#: qml/Wizard/Pages/40-location.qml:214
531+msgid "Don't use my location"
532+msgstr ""
533+
534+#: qml/Wizard/Pages/40-location.qml:260
535+msgid "You can change it later in System Settings."
536+msgstr ""
537+
538+#: qml/Wizard/Pages/50-timezone.qml:29
539+msgid "Time Zone"
540+msgstr ""
541+
542+#: qml/Wizard/Pages/50-timezone.qml:178
543+msgid "Enter your city"
544+msgstr ""
545+
546+#: qml/Wizard/Pages/60-account.qml:24
547+msgid "Personalize Your Device"
548+msgstr ""
549+
550+#: qml/Wizard/Pages/60-account.qml:48
551+msgid "Preferred Name"
552+msgstr ""
553+
554+#: qml/Wizard/Pages/70-passwd-type.qml:39
555+msgid "Lock Screen"
556+msgstr ""
557+
558+#: qml/Wizard/Pages/70-passwd-type.qml:101
559+msgctxt "Label: Type of security method"
560+msgid "Create new password"
561+msgstr ""
562+
563+#: qml/Wizard/Pages/70-passwd-type.qml:103
564+msgctxt "Label: Type of security method"
565+msgid "Create passcode (numbers only)"
566+msgstr ""
567+
568+#: qml/Wizard/Pages/70-passwd-type.qml:105
569+msgctxt "Label: Type of security method"
570+msgid "No lock code"
571+msgstr ""
572+
573+#: qml/Wizard/Pages/75-report-check.qml:26 qml/Wizard/Pages/here-terms.qml:108
574+msgid "Privacy Policy"
575+msgstr ""
576+
577+#: qml/Wizard/Pages/75-report-check.qml:26
578+msgid "Help Us Improve"
579+msgstr ""
580+
581+#: qml/Wizard/Pages/75-report-check.qml:59
582+msgid "Improve system performance by sending us crashes and error reports."
583+msgstr ""
584+
585+#: qml/Wizard/Pages/75-report-check.qml:60
586+msgid "Privacy policy"
587+msgstr ""
588+
589+#: qml/Wizard/Pages/80-finished.qml:89
590+msgid "Welcome to Ubuntu"
591+msgstr ""
592+
593+#: qml/Wizard/Pages/80-finished.qml:104
594+msgid "You are ready to use your device now"
595+msgstr ""
596+
597+#: qml/Wizard/Pages/80-finished.qml:124
598+msgid "Get Started"
599+msgstr ""
600+
601+#: qml/Wizard/Pages/here-terms.qml:25
602+msgid "Terms & Conditions"
603+msgstr ""
604+
605+#: qml/Wizard/Pages/here-terms.qml:69
606+msgid "Your device uses positioning technologies provided by HERE."
607+msgstr ""
608+
609+#: qml/Wizard/Pages/here-terms.qml:81
610+msgid ""
611+"To provide you with positioning services and to improve their quality, HERE "
612+"collects information about nearby cell towers and Wi-Fi hotspots around your "
613+"current location whenever your position is being found."
614+msgstr ""
615+
616+#: qml/Wizard/Pages/here-terms.qml:93
617+msgid ""
618+"The information collected is used to analyze the service and to improve the "
619+"use of service, but not to identify you personally."
620+msgstr ""
621+
622+#: qml/Wizard/Pages/here-terms.qml:106
623+#, qt-format
624+msgid "By continuing, you agree to the HERE platform %1 and %2."
625+msgstr ""
626+
627+#: qml/Wizard/Pages/here-terms.qml:107
628+msgid "Service Terms"
629+msgstr ""
630+
631+#: qml/Wizard/Pages/passcode-confirm.qml:43
632+#: qml/Wizard/Pages/passcode-desktop.qml:80
633+msgid "Confirm passcode"
634+msgstr ""
635+
636+#: qml/Wizard/Pages/passcode-confirm.qml:45
637+msgid "Incorrect passcode."
638+msgstr ""
639+
640+#: qml/Wizard/Pages/passcode-confirm.qml:45
641+msgctxt "Enter the passcode again"
642+msgid "Please re-enter."
643+msgstr ""
644+
645+#: qml/Wizard/Pages/passcode-desktop.qml:30
646+msgid "Lock Screen Passcode"
647+msgstr ""
648+
649+#: qml/Wizard/Pages/passcode-desktop.qml:56
650+msgid "Enter 4 numbers to setup your passcode"
651+msgstr ""
652+
653+#: qml/Wizard/Pages/passcode-desktop.qml:65
654+#: qml/Wizard/Pages/passcode-set.qml:54
655+msgid "Choose passcode"
656+msgstr ""
657+
658+#: qml/Wizard/Pages/passcode-desktop.qml:105
659+msgid "Passcode too short"
660+msgstr ""
661+
662+#: qml/Wizard/Pages/passcode-desktop.qml:107
663+msgid "Passcodes match"
664+msgstr ""
665+
666+#: qml/Wizard/Pages/passcode-desktop.qml:109
667+msgid "Passcodes do not match"
668+msgstr ""
669+
670+#: qml/Wizard/Pages/passcode-set.qml:62
671+msgid "Passcode must be 4 characters long"
672+msgstr ""
673+
674+#: qml/Wizard/Pages/password-set.qml:30
675+msgid "Lock Screen Password"
676+msgstr ""
677+
678+#: qml/Wizard/Pages/password-set.qml:61
679+msgid "Enter at least 8 characters"
680+msgstr ""
681+
682+#: qml/Wizard/Pages/password-set.qml:73
683+msgid "Choose password"
684+msgstr ""
685+
686+#: qml/Wizard/Pages/password-set.qml:103
687+msgid "Confirm password"
688+msgstr ""
689+
690+#: qml/Wizard/Pages/sim.qml:27
691+msgid "No SIM card installed"
692+msgstr ""
693+
694+#: qml/Wizard/Pages/sim.qml:54
695+msgid "SIM card added"
696+msgstr ""
697+
698+#: qml/Wizard/Pages/sim.qml:55
699+msgid "You must restart the device to access the mobile network."
700+msgstr ""
701+
702+#: qml/Wizard/Pages/sim.qml:59
703+msgid "Restart"
704+msgstr ""
705+
706+#: qml/Wizard/Pages/sim.qml:78
707+msgid "You won’t be able to make calls or use text messaging without a SIM."
708+msgstr ""
709+
710+#: qml/Wizard/Pages/sim.qml:90
711+msgid "To proceed with no SIM tap Skip."
712+msgstr ""
713+
714+#: qml/Wizard/PasswordMeter.qml:87
715+msgid "Passwords match"
716+msgstr ""
717+
718+#: qml/Wizard/PasswordMeter.qml:89
719+msgid "Passwords do not match"
720+msgstr ""
721+
722+#: qml/Wizard/PasswordMeter.qml:93
723+msgid "Strong password"
724+msgstr ""
725+
726+#: qml/Wizard/PasswordMeter.qml:95
727+msgid "Fair password"
728+msgstr ""
729+
730+#: qml/Wizard/PasswordMeter.qml:97
731+msgid "Weak password"
732+msgstr ""
733+
734+#: qml/Wizard/PasswordMeter.qml:99
735+msgid "Very weak password"
736+msgstr ""
po/cs.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2015-07-07 10:44+0000\n"
11"PO-Revision-Date: 2015-07-07 10:44+0000\n"
12"Last-Translator: Vojtěch Daněk <vdanek@outlook.com>\n"
12"Last-Translator: Vojtěch Daněk <vdanek@outlook.com>\n"
13"Language-Team: Czech <cs@li.org>\n"
13"Language-Team: Czech <cs@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
17"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
18−"X-Launchpad-Export-Date: 2016-05-19 05:49+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:08+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20"Language: cs\n"
20"Language: cs\n"
21
21
22#: plugins/IntegratedLightDM/Greeter.cpp:112
22#: plugins/IntegratedLightDM/Greeter.cpp:112
@@ -262,7 +262,7 @@ msgstr "Domů"
262msgid "Also installed"
262msgid "Also installed"
263msgstr "Také nainstalováno"
263msgstr "Také nainstalováno"
264
264
265−#: qml/DisabledScreenNotice.qml:104
265+#: qml/DisabledScreenNotice.qml:109
266msgid ""
266msgid ""
267"Your device is now connected to an external display. Use this screen as a "
267"Your device is now connected to an external display. Use this screen as a "
268"touch pad to interact with the pointer."
268"touch pad to interact with the pointer."
po/cy.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2015-07-31 13:21+0000\n"
11"PO-Revision-Date: 2015-07-31 13:21+0000\n"
12"Last-Translator: Owen Llywelyn <owen.llywelyn@gmail.com>\n"
12"Last-Translator: Owen Llywelyn <owen.llywelyn@gmail.com>\n"
13"Language-Team: Welsh <cy@li.org>\n"
13"Language-Team: Welsh <cy@li.org>\n"
@@ -16,8 +16,8 @@ msgstr ""
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=4; plural=n==1 ? 0 : n==2 ? 1 : (n != 8 && n != 11) ? "
17"Plural-Forms: nplurals=4; plural=n==1 ? 0 : n==2 ? 1 : (n != 8 && n != 11) ? "
18"2 : 3;\n"
18"2 : 3;\n"
19−"X-Launchpad-Export-Date: 2016-05-19 05:50+0000\n"
19+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
20−"X-Generator: Launchpad (build 18025)\n"
20+"X-Generator: Launchpad (build 18053)\n"
21
21
22#: plugins/IntegratedLightDM/Greeter.cpp:112
22#: plugins/IntegratedLightDM/Greeter.cpp:112
23msgid "Password: "
23msgid "Password: "
@@ -263,7 +263,7 @@ msgstr "Cartref"
263msgid "Also installed"
263msgid "Also installed"
264msgstr "Hefyd wedi gosod"
264msgstr "Hefyd wedi gosod"
265
265
266−#: qml/DisabledScreenNotice.qml:104
266+#: qml/DisabledScreenNotice.qml:109
267msgid ""
267msgid ""
268"Your device is now connected to an external display. Use this screen as a "
268"Your device is now connected to an external display. Use this screen as a "
269"touch pad to interact with the pointer."
269"touch pad to interact with the pointer."
po/da.po+4−4
@@ -8,7 +8,7 @@ msgid ""
8msgstr ""
8msgstr ""
9"Project-Id-Version: unity8\n"
9"Project-Id-Version: unity8\n"
10"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
11−"POT-Creation-Date: 2016-05-18 11:19+0000\n"
11+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
12"PO-Revision-Date: 2015-07-06 12:05+0000\n"
12"PO-Revision-Date: 2015-07-06 12:05+0000\n"
13"Last-Translator: Folmer Fredslund <Unknown>\n"
13"Last-Translator: Folmer Fredslund <Unknown>\n"
14"Language-Team: Danish <dansk@dansk-gruppen.dk>\n"
14"Language-Team: Danish <dansk@dansk-gruppen.dk>\n"
@@ -16,8 +16,8 @@ msgstr ""
16"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Type: text/plain; charset=UTF-8\n"
17"Content-Transfer-Encoding: 8bit\n"
17"Content-Transfer-Encoding: 8bit\n"
18"Plural-Forms: nplurals=2; plural=n != 1;\n"
18"Plural-Forms: nplurals=2; plural=n != 1;\n"
19−"X-Launchpad-Export-Date: 2016-05-19 05:49+0000\n"
19+"X-Launchpad-Export-Date: 2016-05-25 06:08+0000\n"
20−"X-Generator: Launchpad (build 18025)\n"
20+"X-Generator: Launchpad (build 18053)\n"
21
21
22#: plugins/IntegratedLightDM/Greeter.cpp:112
22#: plugins/IntegratedLightDM/Greeter.cpp:112
23msgid "Password: "
23msgid "Password: "
@@ -263,7 +263,7 @@ msgstr "Hjem"
263msgid "Also installed"
263msgid "Also installed"
264msgstr "Også installeret"
264msgstr "Også installeret"
265
265
266−#: qml/DisabledScreenNotice.qml:104
266+#: qml/DisabledScreenNotice.qml:109
267msgid ""
267msgid ""
268"Your device is now connected to an external display. Use this screen as a "
268"Your device is now connected to an external display. Use this screen as a "
269"touch pad to interact with the pointer."
269"touch pad to interact with the pointer."
po/de.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2016-05-10 19:23+0000\n"
11"PO-Revision-Date: 2016-05-10 19:23+0000\n"
12"Last-Translator: Torsten Franz <Unknown>\n"
12"Last-Translator: Torsten Franz <Unknown>\n"
13"Language-Team: German <de@li.org>\n"
13"Language-Team: German <de@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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: 2016-05-19 05:49+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -264,7 +264,7 @@ msgstr "Startseite"
264msgid "Also installed"
264msgid "Also installed"
265msgstr "Ebenfalls installiert"
265msgstr "Ebenfalls installiert"
266
266
267−#: qml/DisabledScreenNotice.qml:104
267+#: qml/DisabledScreenNotice.qml:109
268msgid ""
268msgid ""
269"Your device is now connected to an external display. Use this screen as a "
269"Your device is now connected to an external display. Use this screen as a "
270"touch pad to interact with the pointer."
270"touch pad to interact with the pointer."
po/el.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2016-04-25 16:24+0000\n"
11"PO-Revision-Date: 2016-04-25 16:24+0000\n"
12"Last-Translator: Aggelos Arnaoutis <angelosarn@hotmail.com>\n"
12"Last-Translator: Aggelos Arnaoutis <angelosarn@hotmail.com>\n"
13"Language-Team: Greek <el@li.org>\n"
13"Language-Team: Greek <el@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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: 2016-05-19 05:49+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -264,7 +264,7 @@ msgstr "Αρχή"
264msgid "Also installed"
264msgid "Also installed"
265msgstr "Επίσης εγκατεστημένα"
265msgstr "Επίσης εγκατεστημένα"
266
266
267−#: qml/DisabledScreenNotice.qml:104
267+#: qml/DisabledScreenNotice.qml:109
268msgid ""
268msgid ""
269"Your device is now connected to an external display. Use this screen as a "
269"Your device is now connected to an external display. Use this screen as a "
270"touch pad to interact with the pointer."
270"touch pad to interact with the pointer."
po/en_AU.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2016-03-27 10:09+0000\n"
11"PO-Revision-Date: 2016-03-27 10:09+0000\n"
12"Last-Translator: Jared Norris <jarednorris@ubuntu.com>\n"
12"Last-Translator: Jared Norris <jarednorris@ubuntu.com>\n"
13"Language-Team: English (Australia) <en_AU@li.org>\n"
13"Language-Team: English (Australia) <en_AU@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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: 2016-05-19 05:50+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -258,7 +258,7 @@ msgstr "Home"
258msgid "Also installed"
258msgid "Also installed"
259msgstr "Also installed"
259msgstr "Also installed"
260
260
261−#: qml/DisabledScreenNotice.qml:104
261+#: qml/DisabledScreenNotice.qml:109
262msgid ""
262msgid ""
263"Your device is now connected to an external display. Use this screen as a "
263"Your device is now connected to an external display. Use this screen as a "
264"touch pad to interact with the pointer."
264"touch pad to interact with the pointer."
po/en_GB.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2016-05-10 10:10+0000\n"
11"PO-Revision-Date: 2016-05-10 10:10+0000\n"
12"Last-Translator: Andi Chandler <Unknown>\n"
12"Last-Translator: Andi Chandler <Unknown>\n"
13"Language-Team: English (United Kingdom) <en_GB@li.org>\n"
13"Language-Team: English (United Kingdom) <en_GB@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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: 2016-05-19 05:50+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -258,7 +258,7 @@ msgstr "Home"
258msgid "Also installed"
258msgid "Also installed"
259msgstr "Also installed"
259msgstr "Also installed"
260
260
261−#: qml/DisabledScreenNotice.qml:104
261+#: qml/DisabledScreenNotice.qml:109
262msgid ""
262msgid ""
263"Your device is now connected to an external display. Use this screen as a "
263"Your device is now connected to an external display. Use this screen as a "
264"touch pad to interact with the pointer."
264"touch pad to interact with the pointer."
po/eo.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2015-06-06 23:37+0000\n"
11"PO-Revision-Date: 2015-06-06 23:37+0000\n"
12"Last-Translator: Eliovir <Unknown>\n"
12"Last-Translator: Eliovir <Unknown>\n"
13"Language-Team: Esperanto <eo@li.org>\n"
13"Language-Team: Esperanto <eo@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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: 2016-05-19 05:49+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:08+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -256,7 +256,7 @@ msgstr "Hejmo"
256msgid "Also installed"
256msgid "Also installed"
257msgstr ""
257msgstr ""
258
258
259−#: qml/DisabledScreenNotice.qml:104
259+#: qml/DisabledScreenNotice.qml:109
260msgid ""
260msgid ""
261"Your device is now connected to an external display. Use this screen as a "
261"Your device is now connected to an external display. Use this screen as a "
262"touch pad to interact with the pointer."
262"touch pad to interact with the pointer."
po/es.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2016-03-25 12:02+0000\n"
11"PO-Revision-Date: 2016-03-25 12:02+0000\n"
12"Last-Translator: Adolfo Jayme <fitoschido@gmail.com>\n"
12"Last-Translator: Adolfo Jayme <fitoschido@gmail.com>\n"
13"Language-Team: Spanish <es@li.org>\n"
13"Language-Team: Spanish <es@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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: 2016-05-19 05:50+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -263,7 +263,7 @@ msgstr "Inicio"
263msgid "Also installed"
263msgid "Also installed"
264msgstr "También instalados"
264msgstr "También instalados"
265
265
266−#: qml/DisabledScreenNotice.qml:104
266+#: qml/DisabledScreenNotice.qml:109
267msgid ""
267msgid ""
268"Your device is now connected to an external display. Use this screen as a "
268"Your device is now connected to an external display. Use this screen as a "
269"touch pad to interact with the pointer."
269"touch pad to interact with the pointer."
po/eu.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2015-07-13 23:29+0000\n"
11"PO-Revision-Date: 2015-07-13 23:29+0000\n"
12"Last-Translator: Ibai Oihanguren Sala <Unknown>\n"
12"Last-Translator: Ibai Oihanguren Sala <Unknown>\n"
13"Language-Team: Basque <eu@li.org>\n"
13"Language-Team: Basque <eu@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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: 2016-05-19 05:49+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:08+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -259,7 +259,7 @@ msgstr "Hasiera"
259msgid "Also installed"
259msgid "Also installed"
260msgstr "Hau ere instalatuta"
260msgstr "Hau ere instalatuta"
261
261
262−#: qml/DisabledScreenNotice.qml:104
262+#: qml/DisabledScreenNotice.qml:109
263msgid ""
263msgid ""
264"Your device is now connected to an external display. Use this screen as a "
264"Your device is now connected to an external display. Use this screen as a "
265"touch pad to interact with the pointer."
265"touch pad to interact with the pointer."
po/fa.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2016-03-30 14:29+0000\n"
11"PO-Revision-Date: 2016-03-30 14:29+0000\n"
12"Last-Translator: Danial Behzadi <dani.behzi@gmail.com>\n"
12"Last-Translator: Danial Behzadi <dani.behzi@gmail.com>\n"
13"Language-Team: Persian <fa@li.org>\n"
13"Language-Team: Persian <fa@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2016-05-19 05:50+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -259,7 +259,7 @@ msgstr "خانه"
259msgid "Also installed"
259msgid "Also installed"
260msgstr "هم‌چنین نصب شده"
260msgstr "هم‌چنین نصب شده"
261
261
262−#: qml/DisabledScreenNotice.qml:104
262+#: qml/DisabledScreenNotice.qml:109
263msgid ""
263msgid ""
264"Your device is now connected to an external display. Use this screen as a "
264"Your device is now connected to an external display. Use this screen as a "
265"touch pad to interact with the pointer."
265"touch pad to interact with the pointer."
po/fi.po+8−6
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2015-07-04 18:32+0000\n"
11"PO-Revision-Date: 2015-07-04 18:32+0000\n"
12"Last-Translator: Jiri Grönroos <Unknown>\n"
12"Last-Translator: Jiri Grönroos <Unknown>\n"
13"Language-Team: Finnish <fi@li.org>\n"
13"Language-Team: Finnish <fi@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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: 2016-05-19 05:49+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:08+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -194,11 +194,11 @@ msgstr "Palauta"
194
194
195#: qml/Dash/GenericScopeView.qml:579 qml/Dash/GenericScopeView.qml:764
195#: qml/Dash/GenericScopeView.qml:579 qml/Dash/GenericScopeView.qml:764
196msgid "Show less"
196msgid "Show less"
197−msgstr ""
197+msgstr "Näytä vähemmän"
198
198
199#: qml/Dash/GenericScopeView.qml:579
199#: qml/Dash/GenericScopeView.qml:579
200msgid "Show all"
200msgid "Show all"
201−msgstr ""
201+msgstr "Näytä kaikki"
202
202
203#: qml/Dash/GenericScopeView.qml:636
203#: qml/Dash/GenericScopeView.qml:636
204msgctxt "Label: Hint for dash search line edit"
204msgctxt "Label: Hint for dash search line edit"
@@ -262,7 +262,7 @@ msgstr "Koti"
262msgid "Also installed"
262msgid "Also installed"
263msgstr "Myös asennettu"
263msgstr "Myös asennettu"
264
264
265−#: qml/DisabledScreenNotice.qml:104
265+#: qml/DisabledScreenNotice.qml:109
266msgid ""
266msgid ""
267"Your device is now connected to an external display. Use this screen as a "
267"Your device is now connected to an external display. Use this screen as a "
268"touch pad to interact with the pointer."
268"touch pad to interact with the pointer."
@@ -463,6 +463,8 @@ msgstr "Vedä vasemmasta reunasta avataksesi käynnistimen"
463#: qml/Tutorial/TutorialRight.qml:55
463#: qml/Tutorial/TutorialRight.qml:55
464msgid "Push your mouse against the right edge to view your open apps"
464msgid "Push your mouse against the right edge to view your open apps"
465msgstr ""
465msgstr ""
466+"Työnnä oikeaa reunaa hiiren osoittimella nähdäksesi avoinna olevat "
467+"sovellukset"
466
468
467#: qml/Tutorial/TutorialRight.qml:56
469#: qml/Tutorial/TutorialRight.qml:56
468msgid "Short or long swipe from the right edge to view your open apps"
470msgid "Short or long swipe from the right edge to view your open apps"
po/fo.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2014-01-14 20:08+0000\n"
11"PO-Revision-Date: 2014-01-14 20:08+0000\n"
12"Last-Translator: Jógvan Olsen <jeggy@jebster.net>\n"
12"Last-Translator: Jógvan Olsen <jeggy@jebster.net>\n"
13"Language-Team: Faroese <fo@li.org>\n"
13"Language-Team: Faroese <fo@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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: 2016-05-19 05:49+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:08+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -256,7 +256,7 @@ msgstr ""
256msgid "Also installed"
256msgid "Also installed"
257msgstr ""
257msgstr ""
258
258
259−#: qml/DisabledScreenNotice.qml:104
259+#: qml/DisabledScreenNotice.qml:109
260msgid ""
260msgid ""
261"Your device is now connected to an external display. Use this screen as a "
261"Your device is now connected to an external display. Use this screen as a "
262"touch pad to interact with the pointer."
262"touch pad to interact with the pointer."
po/fr.po+9−9
@@ -7,16 +7,16 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11−"PO-Revision-Date: 2016-05-01 09:09+0000\n"
11+"PO-Revision-Date: 2016-05-19 21:22+0000\n"
12−"Last-Translator: Anne <anneonyme017@gmail.com>\n"
12+"Last-Translator: Ubuntu-QC-1 <Unknown>\n"
13"Language-Team: French <fr@li.org>\n"
13"Language-Team: French <fr@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n > 1;\n"
17"Plural-Forms: nplurals=2; plural=n > 1;\n"
18−"X-Launchpad-Export-Date: 2016-05-19 05:49+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:08+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -37,13 +37,13 @@ msgstr "Détacher le raccourci"
37
37
38#: qml/Components/DelayedLockscreen.qml:49
38#: qml/Components/DelayedLockscreen.qml:49
39msgid "Device Locked"
39msgid "Device Locked"
40−msgstr "Périphérique verrouillé"
40+msgstr "Appareil verrouillé"
41
41
42#: qml/Components/DelayedLockscreen.qml:64
42#: qml/Components/DelayedLockscreen.qml:64
43msgid "You have been locked out due to too many failed passphrase attempts."
43msgid "You have been locked out due to too many failed passphrase attempts."
44msgstr ""
44msgstr ""
45−"Vous avez été bloqué suite à un trop grand nombre de tentatives de saisie "
45+"L'appareil a été verrouillé suite à un trop grand nombre de tentatives de "
46−"d'une phrase de passe erronée."
46+"saisie d'une phrase de passe erronée."
47
47
48#: qml/Components/DelayedLockscreen.qml:65
48#: qml/Components/DelayedLockscreen.qml:65
49msgid "You have been locked out due to too many failed passcode attempts."
49msgid "You have been locked out due to too many failed passcode attempts."
@@ -266,7 +266,7 @@ msgstr "Accueil"
266msgid "Also installed"
266msgid "Also installed"
267msgstr "Également installées"
267msgstr "Également installées"
268
268
269−#: qml/DisabledScreenNotice.qml:104
269+#: qml/DisabledScreenNotice.qml:109
270msgid ""
270msgid ""
271"Your device is now connected to an external display. Use this screen as a "
271"Your device is now connected to an external display. Use this screen as a "
272"touch pad to interact with the pointer."
272"touch pad to interact with the pointer."
po/ga.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2016-01-25 11:33+0000\n"
11"PO-Revision-Date: 2016-01-25 11:33+0000\n"
12"Last-Translator: Joshua Kiley <Unknown>\n"
12"Last-Translator: Joshua Kiley <Unknown>\n"
13"Language-Team: Irish <ga@li.org>\n"
13"Language-Team: Irish <ga@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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=3; plural=n==1 ? 0 : n==2 ? 1 : 2;\n"
17"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n==2 ? 1 : 2;\n"
18−"X-Launchpad-Export-Date: 2016-05-19 05:49+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -257,7 +257,7 @@ msgstr "Baile"
257msgid "Also installed"
257msgid "Also installed"
258msgstr ""
258msgstr ""
259
259
260−#: qml/DisabledScreenNotice.qml:104
260+#: qml/DisabledScreenNotice.qml:109
261msgid ""
261msgid ""
262"Your device is now connected to an external display. Use this screen as a "
262"Your device is now connected to an external display. Use this screen as a "
263"touch pad to interact with the pointer."
263"touch pad to interact with the pointer."
po/gd.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2016-04-08 18:34+0000\n"
11"PO-Revision-Date: 2016-04-08 18:34+0000\n"
12"Last-Translator: Akerbeltz <fios@akerbeltz.org>\n"
12"Last-Translator: Akerbeltz <fios@akerbeltz.org>\n"
13"Language-Team: Fòram na Gàidhlig\n"
13"Language-Team: Fòram na Gàidhlig\n"
@@ -16,8 +16,8 @@ msgstr ""
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=4; plural=(n==1 || n==11) ? 0 : (n==2 || n==12) ? 1 : "
17"Plural-Forms: nplurals=4; plural=(n==1 || n==11) ? 0 : (n==2 || n==12) ? 1 : "
18"(n > 2 && n < 20) ? 2 : 3;\n"
18"(n > 2 && n < 20) ? 2 : 3;\n"
19−"X-Launchpad-Export-Date: 2016-05-19 05:49+0000\n"
19+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
20−"X-Generator: Launchpad (build 18025)\n"
20+"X-Generator: Launchpad (build 18053)\n"
21"Language: gd\n"
21"Language: gd\n"
22
22
23#: plugins/IntegratedLightDM/Greeter.cpp:112
23#: plugins/IntegratedLightDM/Greeter.cpp:112
@@ -268,7 +268,7 @@ msgstr "Dhachaigh"
268msgid "Also installed"
268msgid "Also installed"
269msgstr "Air a stàladh cuideachd"
269msgstr "Air a stàladh cuideachd"
270
270
271−#: qml/DisabledScreenNotice.qml:104
271+#: qml/DisabledScreenNotice.qml:109
272msgid ""
272msgid ""
273"Your device is now connected to an external display. Use this screen as a "
273"Your device is now connected to an external display. Use this screen as a "
274"touch pad to interact with the pointer."
274"touch pad to interact with the pointer."
po/gl.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2016-01-15 14:56+0000\n"
11"PO-Revision-Date: 2016-01-15 14:56+0000\n"
12"Last-Translator: Marcos Lans <Unknown>\n"
12"Last-Translator: Marcos Lans <Unknown>\n"
13"Language-Team: Galician <gl@li.org>\n"
13"Language-Team: Galician <gl@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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: 2016-05-19 05:49+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -258,7 +258,7 @@ msgstr "Persoal"
258msgid "Also installed"
258msgid "Also installed"
259msgstr "Tamén instalado"
259msgstr "Tamén instalado"
260
260
261−#: qml/DisabledScreenNotice.qml:104
261+#: qml/DisabledScreenNotice.qml:109
262msgid ""
262msgid ""
263"Your device is now connected to an external display. Use this screen as a "
263"Your device is now connected to an external display. Use this screen as a "
264"touch pad to interact with the pointer."
264"touch pad to interact with the pointer."
po/gv.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2015-04-02 14:24+0000\n"
11"PO-Revision-Date: 2015-04-02 14:24+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Manx <gv@li.org>\n"
13"Language-Team: Manx <gv@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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=3; plural=n == 1 ? 0 : (n == 2 ? 1 : 2);\n"
17"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : (n == 2 ? 1 : 2);\n"
18−"X-Launchpad-Export-Date: 2016-05-19 05:49+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -263,7 +263,7 @@ msgstr "Balley"
263msgid "Also installed"
263msgid "Also installed"
264msgstr ""
264msgstr ""
265
265
266−#: qml/DisabledScreenNotice.qml:104
266+#: qml/DisabledScreenNotice.qml:109
267msgid ""
267msgid ""
268"Your device is now connected to an external display. Use this screen as a "
268"Your device is now connected to an external display. Use this screen as a "
269"touch pad to interact with the pointer."
269"touch pad to interact with the pointer."
po/he.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2015-07-12 08:47+0000\n"
11"PO-Revision-Date: 2015-07-12 08:47+0000\n"
12"Last-Translator: Yaron <sh.yaron@gmail.com>\n"
12"Last-Translator: Yaron <sh.yaron@gmail.com>\n"
13"Language-Team: Hebrew <he@li.org>\n"
13"Language-Team: Hebrew <he@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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: 2016-05-19 05:49+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -256,7 +256,7 @@ msgstr "בית"
256msgid "Also installed"
256msgid "Also installed"
257msgstr ""
257msgstr ""
258
258
259−#: qml/DisabledScreenNotice.qml:104
259+#: qml/DisabledScreenNotice.qml:109
260msgid ""
260msgid ""
261"Your device is now connected to an external display. Use this screen as a "
261"Your device is now connected to an external display. Use this screen as a "
262"touch pad to interact with the pointer."
262"touch pad to interact with the pointer."
po/hi.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2014-01-15 01:49+0000\n"
11"PO-Revision-Date: 2014-01-15 01:49+0000\n"
12"Last-Translator: Siddhanathan Shanmugam <Unknown>\n"
12"Last-Translator: Siddhanathan Shanmugam <Unknown>\n"
13"Language-Team: Hindi <hi@li.org>\n"
13"Language-Team: Hindi <hi@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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: 2016-05-19 05:49+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -256,7 +256,7 @@ msgstr ""
256msgid "Also installed"
256msgid "Also installed"
257msgstr ""
257msgstr ""
258
258
259−#: qml/DisabledScreenNotice.qml:104
259+#: qml/DisabledScreenNotice.qml:109
260msgid ""
260msgid ""
261"Your device is now connected to an external display. Use this screen as a "
261"Your device is now connected to an external display. Use this screen as a "
262"touch pad to interact with the pointer."
262"touch pad to interact with the pointer."
po/hr.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2016-05-04 17:52+0000\n"
11"PO-Revision-Date: 2016-05-04 17:52+0000\n"
12"Last-Translator: gogo <trebelnik2@gmail.com>\n"
12"Last-Translator: gogo <trebelnik2@gmail.com>\n"
13"Language-Team: Croatian <hr@li.org>\n"
13"Language-Team: Croatian <hr@li.org>\n"
@@ -16,8 +16,8 @@ msgstr ""
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
17"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
18"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
18"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
19−"X-Launchpad-Export-Date: 2016-05-19 05:50+0000\n"
19+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
20−"X-Generator: Launchpad (build 18025)\n"
20+"X-Generator: Launchpad (build 18053)\n"
21
21
22#: plugins/IntegratedLightDM/Greeter.cpp:112
22#: plugins/IntegratedLightDM/Greeter.cpp:112
23msgid "Password: "
23msgid "Password: "
@@ -262,7 +262,7 @@ msgstr "Naslovnica"
262msgid "Also installed"
262msgid "Also installed"
263msgstr "Također instalirano"
263msgstr "Također instalirano"
264
264
265−#: qml/DisabledScreenNotice.qml:104
265+#: qml/DisabledScreenNotice.qml:109
266msgid ""
266msgid ""
267"Your device is now connected to an external display. Use this screen as a "
267"Your device is now connected to an external display. Use this screen as a "
268"touch pad to interact with the pointer."
268"touch pad to interact with the pointer."
po/hu.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2016-03-24 09:19+0000\n"
11"PO-Revision-Date: 2016-03-24 09:19+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"
@@ -15,8 +15,8 @@ msgstr ""
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: 2016-05-19 05:49+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -260,7 +260,7 @@ msgstr "Kezdőlapon"
260msgid "Also installed"
260msgid "Also installed"
261msgstr "Telepítve"
261msgstr "Telepítve"
262
262
263−#: qml/DisabledScreenNotice.qml:104
263+#: qml/DisabledScreenNotice.qml:109
264msgid ""
264msgid ""
265"Your device is now connected to an external display. Use this screen as a "
265"Your device is now connected to an external display. Use this screen as a "
266"touch pad to interact with the pointer."
266"touch pad to interact with the pointer."
po/hy.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2014-10-28 06:34+0000\n"
11"PO-Revision-Date: 2014-10-28 06:34+0000\n"
12"Last-Translator: Vahan Harutyunyan <Unknown>\n"
12"Last-Translator: Vahan Harutyunyan <Unknown>\n"
13"Language-Team: Armenian <hy@li.org>\n"
13"Language-Team: Armenian <hy@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2016-05-19 05:49+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:08+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -260,7 +260,7 @@ msgstr ""
260msgid "Also installed"
260msgid "Also installed"
261msgstr ""
261msgstr ""
262
262
263−#: qml/DisabledScreenNotice.qml:104
263+#: qml/DisabledScreenNotice.qml:109
264msgid ""
264msgid ""
265"Your device is now connected to an external display. Use this screen as a "
265"Your device is now connected to an external display. Use this screen as a "
266"touch pad to interact with the pointer."
266"touch pad to interact with the pointer."
po/ia.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2015-08-25 19:31+0000\n"
11"PO-Revision-Date: 2015-08-25 19:31+0000\n"
12"Last-Translator: karm <melo@carmu.com>\n"
12"Last-Translator: karm <melo@carmu.com>\n"
13"Language-Team: Interlingua <ia@li.org>\n"
13"Language-Team: Interlingua <ia@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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: 2016-05-19 05:49+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -260,7 +260,7 @@ msgstr "A domo"
260msgid "Also installed"
260msgid "Also installed"
261msgstr "Ja installate"
261msgstr "Ja installate"
262
262
263−#: qml/DisabledScreenNotice.qml:104
263+#: qml/DisabledScreenNotice.qml:109
264msgid ""
264msgid ""
265"Your device is now connected to an external display. Use this screen as a "
265"Your device is now connected to an external display. Use this screen as a "
266"touch pad to interact with the pointer."
266"touch pad to interact with the pointer."
po/id.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2013-06-26 22:35+0000\n"
11"PO-Revision-Date: 2013-06-26 22:35+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Indonesian <id@li.org>\n"
13"Language-Team: Indonesian <id@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2016-05-19 05:49+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -259,7 +259,7 @@ msgstr "Beranda"
259msgid "Also installed"
259msgid "Also installed"
260msgstr "Juga terpasang"
260msgstr "Juga terpasang"
261
261
262−#: qml/DisabledScreenNotice.qml:104
262+#: qml/DisabledScreenNotice.qml:109
263msgid ""
263msgid ""
264"Your device is now connected to an external display. Use this screen as a "
264"Your device is now connected to an external display. Use this screen as a "
265"touch pad to interact with the pointer."
265"touch pad to interact with the pointer."
po/is.po+4−4
@@ -9,7 +9,7 @@ msgid ""
9msgstr ""
9msgstr ""
10"Project-Id-Version: po_unity8-is\n"
10"Project-Id-Version: po_unity8-is\n"
11"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
11"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
12−"POT-Creation-Date: 2016-05-18 11:19+0000\n"
12+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
13"PO-Revision-Date: 2014-11-13 09:32+0000\n"
13"PO-Revision-Date: 2014-11-13 09:32+0000\n"
14"Last-Translator: Sveinn í Felli <sv1@fellsnet.is>\n"
14"Last-Translator: Sveinn í Felli <sv1@fellsnet.is>\n"
15"Language-Team: Icelandic <translation-team-is@lists.sourceforge.net>\n"
15"Language-Team: Icelandic <translation-team-is@lists.sourceforge.net>\n"
@@ -17,8 +17,8 @@ msgstr ""
17"Content-Type: text/plain; charset=UTF-8\n"
17"Content-Type: text/plain; charset=UTF-8\n"
18"Content-Transfer-Encoding: 8bit\n"
18"Content-Transfer-Encoding: 8bit\n"
19"Plural-Forms: nplurals=2; plural=n != 1;\n"
19"Plural-Forms: nplurals=2; plural=n != 1;\n"
20−"X-Launchpad-Export-Date: 2016-05-19 05:49+0000\n"
20+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
21−"X-Generator: Launchpad (build 18025)\n"
21+"X-Generator: Launchpad (build 18053)\n"
22"Language: is\n"
22"Language: is\n"
23
23
24#: plugins/IntegratedLightDM/Greeter.cpp:112
24#: plugins/IntegratedLightDM/Greeter.cpp:112
@@ -265,7 +265,7 @@ msgstr ""
265msgid "Also installed"
265msgid "Also installed"
266msgstr ""
266msgstr ""
267
267
268−#: qml/DisabledScreenNotice.qml:104
268+#: qml/DisabledScreenNotice.qml:109
269msgid ""
269msgid ""
270"Your device is now connected to an external display. Use this screen as a "
270"Your device is now connected to an external display. Use this screen as a "
271"touch pad to interact with the pointer."
271"touch pad to interact with the pointer."
po/it.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2016-04-03 16:08+0000\n"
11"PO-Revision-Date: 2016-04-03 16:08+0000\n"
12"Last-Translator: Milo Casagrande <milo.casagrande@gmail.com>\n"
12"Last-Translator: Milo Casagrande <milo.casagrande@gmail.com>\n"
13"Language-Team: Italian <it@li.org>\n"
13"Language-Team: Italian <it@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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: 2016-05-19 05:49+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -264,7 +264,7 @@ msgstr "Home"
264msgid "Also installed"
264msgid "Also installed"
265msgstr "Installato anche"
265msgstr "Installato anche"
266
266
267−#: qml/DisabledScreenNotice.qml:104
267+#: qml/DisabledScreenNotice.qml:109
268msgid ""
268msgid ""
269"Your device is now connected to an external display. Use this screen as a "
269"Your device is now connected to an external display. Use this screen as a "
270"touch pad to interact with the pointer."
270"touch pad to interact with the pointer."
po/ja.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2015-10-05 10:05+0000\n"
11"PO-Revision-Date: 2015-10-05 10:05+0000\n"
12"Last-Translator: Kentaro Kazuhama <Unknown>\n"
12"Last-Translator: Kentaro Kazuhama <Unknown>\n"
13"Language-Team: Japanese <ja@li.org>\n"
13"Language-Team: Japanese <ja@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2016-05-19 05:49+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -255,7 +255,7 @@ msgstr ""
255msgid "Also installed"
255msgid "Also installed"
256msgstr ""
256msgstr ""
257
257
258−#: qml/DisabledScreenNotice.qml:104
258+#: qml/DisabledScreenNotice.qml:109
259msgid ""
259msgid ""
260"Your device is now connected to an external display. Use this screen as a "
260"Your device is now connected to an external display. Use this screen as a "
261"touch pad to interact with the pointer."
261"touch pad to interact with the pointer."
po/km.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2014-08-20 02:48+0000\n"
11"PO-Revision-Date: 2014-08-20 02:48+0000\n"
12"Last-Translator: Sophea Sok <sksophea@gmail.com>\n"
12"Last-Translator: Sophea Sok <sksophea@gmail.com>\n"
13"Language-Team: Khmer <km@li.org>\n"
13"Language-Team: Khmer <km@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2016-05-19 05:49+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -258,7 +258,7 @@ msgstr "ផ្ទះ"
258msgid "Also installed"
258msgid "Also installed"
259msgstr ""
259msgstr ""
260
260
261−#: qml/DisabledScreenNotice.qml:104
261+#: qml/DisabledScreenNotice.qml:109
262msgid ""
262msgid ""
263"Your device is now connected to an external display. Use this screen as a "
263"Your device is now connected to an external display. Use this screen as a "
264"touch pad to interact with the pointer."
264"touch pad to interact with the pointer."
po/kn.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2013-06-27 05:43+0000\n"
11"PO-Revision-Date: 2013-06-27 05:43+0000\n"
12"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
12"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
13"Language-Team: Kannada <kn@li.org>\n"
13"Language-Team: Kannada <kn@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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: 2016-05-19 05:49+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -256,7 +256,7 @@ msgstr ""
256msgid "Also installed"
256msgid "Also installed"
257msgstr ""
257msgstr ""
258
258
259−#: qml/DisabledScreenNotice.qml:104
259+#: qml/DisabledScreenNotice.qml:109
260msgid ""
260msgid ""
261"Your device is now connected to an external display. Use this screen as a "
261"Your device is now connected to an external display. Use this screen as a "
262"touch pad to interact with the pointer."
262"touch pad to interact with the pointer."
po/ko.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2014-08-19 13:02+0000\n"
11"PO-Revision-Date: 2014-08-19 13:02+0000\n"
12"Last-Translator: MinSik CHO <Unknown>\n"
12"Last-Translator: MinSik CHO <Unknown>\n"
13"Language-Team: Korean <ko@li.org>\n"
13"Language-Team: Korean <ko@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2016-05-19 05:49+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -255,7 +255,7 @@ msgstr "홈"
255msgid "Also installed"
255msgid "Also installed"
256msgstr "설치함"
256msgstr "설치함"
257
257
258−#: qml/DisabledScreenNotice.qml:104
258+#: qml/DisabledScreenNotice.qml:109
259msgid ""
259msgid ""
260"Your device is now connected to an external display. Use this screen as a "
260"Your device is now connected to an external display. Use this screen as a "
261"touch pad to interact with the pointer."
261"touch pad to interact with the pointer."
po/ku.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2014-09-10 13:14+0000\n"
11"PO-Revision-Date: 2014-09-10 13:14+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Kurdish <ku@li.org>\n"
13"Language-Team: Kurdish <ku@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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: 2016-05-19 05:49+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -258,7 +258,7 @@ msgstr ""
258msgid "Also installed"
258msgid "Also installed"
259msgstr ""
259msgstr ""
260
260
261−#: qml/DisabledScreenNotice.qml:104
261+#: qml/DisabledScreenNotice.qml:109
262msgid ""
262msgid ""
263"Your device is now connected to an external display. Use this screen as a "
263"Your device is now connected to an external display. Use this screen as a "
264"touch pad to interact with the pointer."
264"touch pad to interact with the pointer."
po/ky.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2013-06-27 06:17+0000\n"
11"PO-Revision-Date: 2013-06-27 06:17+0000\n"
12"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
12"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
13"Language-Team: Kirghiz <ky@li.org>\n"
13"Language-Team: Kirghiz <ky@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2016-05-19 05:49+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -256,7 +256,7 @@ msgstr ""
256msgid "Also installed"
256msgid "Also installed"
257msgstr ""
257msgstr ""
258
258
259−#: qml/DisabledScreenNotice.qml:104
259+#: qml/DisabledScreenNotice.qml:109
260msgid ""
260msgid ""
261"Your device is now connected to an external display. Use this screen as a "
261"Your device is now connected to an external display. Use this screen as a "
262"touch pad to interact with the pointer."
262"touch pad to interact with the pointer."
po/lo.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2013-10-02 10:00+0000\n"
11"PO-Revision-Date: 2013-10-02 10:00+0000\n"
12"Last-Translator: Anousak <anousak@gmail.com>\n"
12"Last-Translator: Anousak <anousak@gmail.com>\n"
13"Language-Team: Lao <lo@li.org>\n"
13"Language-Team: Lao <lo@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2016-05-19 05:49+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -256,7 +256,7 @@ msgstr ""
256msgid "Also installed"
256msgid "Also installed"
257msgstr ""
257msgstr ""
258
258
259−#: qml/DisabledScreenNotice.qml:104
259+#: qml/DisabledScreenNotice.qml:109
260msgid ""
260msgid ""
261"Your device is now connected to an external display. Use this screen as a "
261"Your device is now connected to an external display. Use this screen as a "
262"touch pad to interact with the pointer."
262"touch pad to interact with the pointer."
po/lt.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2014-05-19 17:15+0000\n"
11"PO-Revision-Date: 2014-05-19 17:15+0000\n"
12"Last-Translator: Mantas Kriaučiūnas <mantas@akl.lt>\n"
12"Last-Translator: Mantas Kriaučiūnas <mantas@akl.lt>\n"
13"Language-Team: Lithuanian <lt@li.org>\n"
13"Language-Team: Lithuanian <lt@li.org>\n"
@@ -16,8 +16,8 @@ msgstr ""
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
17"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
18"(n%100<10 || n%100>=20) ? 1 : 2;\n"
18"(n%100<10 || n%100>=20) ? 1 : 2;\n"
19−"X-Launchpad-Export-Date: 2016-05-19 05:49+0000\n"
19+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
20−"X-Generator: Launchpad (build 18025)\n"
20+"X-Generator: Launchpad (build 18053)\n"
21
21
22#: plugins/IntegratedLightDM/Greeter.cpp:112
22#: plugins/IntegratedLightDM/Greeter.cpp:112
23msgid "Password: "
23msgid "Password: "
@@ -257,7 +257,7 @@ msgstr ""
257msgid "Also installed"
257msgid "Also installed"
258msgstr ""
258msgstr ""
259
259
260−#: qml/DisabledScreenNotice.qml:104
260+#: qml/DisabledScreenNotice.qml:109
261msgid ""
261msgid ""
262"Your device is now connected to an external display. Use this screen as a "
262"Your device is now connected to an external display. Use this screen as a "
263"touch pad to interact with the pointer."
263"touch pad to interact with the pointer."
po/lv.po+4−4
@@ -8,7 +8,7 @@ msgid ""
8msgstr ""
8msgstr ""
9"Project-Id-Version: unity\n"
9"Project-Id-Version: unity\n"
10"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
11−"POT-Creation-Date: 2016-05-18 11:19+0000\n"
11+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
12"PO-Revision-Date: 2015-11-22 19:13+0000\n"
12"PO-Revision-Date: 2015-11-22 19:13+0000\n"
13"Last-Translator: Klavs Anson <anson.klavs@gmail.com>\n"
13"Last-Translator: Klavs Anson <anson.klavs@gmail.com>\n"
14"Language-Team: Latvian <lata-l10n@googlegroups.com>\n"
14"Language-Team: Latvian <lata-l10n@googlegroups.com>\n"
@@ -16,8 +16,8 @@ msgstr ""
16"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Type: text/plain; charset=UTF-8\n"
17"Content-Transfer-Encoding: 8bit\n"
17"Content-Transfer-Encoding: 8bit\n"
18"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2;\n"
18"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2;\n"
19−"X-Launchpad-Export-Date: 2016-05-19 05:49+0000\n"
19+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
20−"X-Generator: Launchpad (build 18025)\n"
20+"X-Generator: Launchpad (build 18053)\n"
21"Language: lv\n"
21"Language: lv\n"
22
22
23#: plugins/IntegratedLightDM/Greeter.cpp:112
23#: plugins/IntegratedLightDM/Greeter.cpp:112
@@ -261,7 +261,7 @@ msgstr "Mājas"
261msgid "Also installed"
261msgid "Also installed"
262msgstr "Arī instalēja"
262msgstr "Arī instalēja"
263
263
264−#: qml/DisabledScreenNotice.qml:104
264+#: qml/DisabledScreenNotice.qml:109
265msgid ""
265msgid ""
266"Your device is now connected to an external display. Use this screen as a "
266"Your device is now connected to an external display. Use this screen as a "
267"touch pad to interact with the pointer."
267"touch pad to interact with the pointer."
po/ml.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2013-11-23 11:44+0000\n"
11"PO-Revision-Date: 2013-11-23 11:44+0000\n"
12"Last-Translator: ST Alfas <Unknown>\n"
12"Last-Translator: ST Alfas <Unknown>\n"
13"Language-Team: Malayalam <ml@li.org>\n"
13"Language-Team: Malayalam <ml@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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: 2016-05-19 05:49+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -256,7 +256,7 @@ msgstr ""
256msgid "Also installed"
256msgid "Also installed"
257msgstr ""
257msgstr ""
258
258
259−#: qml/DisabledScreenNotice.qml:104
259+#: qml/DisabledScreenNotice.qml:109
260msgid ""
260msgid ""
261"Your device is now connected to an external display. Use this screen as a "
261"Your device is now connected to an external display. Use this screen as a "
262"touch pad to interact with the pointer."
262"touch pad to interact with the pointer."
po/mr.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2014-01-14 19:54+0000\n"
11"PO-Revision-Date: 2014-01-14 19:54+0000\n"
12"Last-Translator: Rohan Deshmukh <Unknown>\n"
12"Last-Translator: Rohan Deshmukh <Unknown>\n"
13"Language-Team: Marathi <mr@li.org>\n"
13"Language-Team: Marathi <mr@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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: 2016-05-19 05:49+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -256,7 +256,7 @@ msgstr ""
256msgid "Also installed"
256msgid "Also installed"
257msgstr ""
257msgstr ""
258
258
259−#: qml/DisabledScreenNotice.qml:104
259+#: qml/DisabledScreenNotice.qml:109
260msgid ""
260msgid ""
261"Your device is now connected to an external display. Use this screen as a "
261"Your device is now connected to an external display. Use this screen as a "
262"touch pad to interact with the pointer."
262"touch pad to interact with the pointer."
po/ms.po+94−73
@@ -7,16 +7,16 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11−"PO-Revision-Date: 2014-01-17 09:05+0000\n"
11+"PO-Revision-Date: 2016-05-24 01:36+0000\n"
12"Last-Translator: abuyop <Unknown>\n"
12"Last-Translator: abuyop <Unknown>\n"
13"Language-Team: Malay <ms@li.org>\n"
13"Language-Team: Malay <ms@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: 2016-05-19 05:49+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -125,7 +125,7 @@ msgstr "Kembali ke Panggilan"
125
125
126#: qml/Components/Lockscreen.qml:231
126#: qml/Components/Lockscreen.qml:231
127msgid "Emergency Call"
127msgid "Emergency Call"
128−msgstr "panggilan Kecemasan"
128+msgstr "Panggilan Kecemasan"
129
129
130#: qml/Components/Lockscreen.qml:263
130#: qml/Components/Lockscreen.qml:263
131msgid "OK"
131msgid "OK"
@@ -139,7 +139,7 @@ msgstr "Apl mungkin mempunyai data tidak disimpan:"
139msgctxt ""
139msgctxt ""
140"Re-dock means connect the device again to an external screen/mouse/keyboard"
140"Re-dock means connect the device again to an external screen/mouse/keyboard"
141msgid "Re-dock, save your work and close these apps to continue."
141msgid "Re-dock, save your work and close these apps to continue."
142−msgstr ""
142+msgstr "Labuh-semula, simpan kerja anda dan tutup apl ini untuk teruskan."
143
143
144#: qml/Components/ModeSwitchWarningDialog.qml:63
144#: qml/Components/ModeSwitchWarningDialog.qml:63
145msgid "Or force close now (unsaved data will be lost)."
145msgid "Or force close now (unsaved data will be lost)."
@@ -182,19 +182,19 @@ msgstr "Tambah ke Kegemaran"
182
182
183#: qml/Dash/FiltersPopover.qml:60
183#: qml/Dash/FiltersPopover.qml:60
184msgid "Refine your results"
184msgid "Refine your results"
185−msgstr ""
185+msgstr "Takrif keputusan anda"
186
186
187#: qml/Dash/FiltersPopover.qml:69
187#: qml/Dash/FiltersPopover.qml:69
188msgid "Reset"
188msgid "Reset"
189−msgstr ""
189+msgstr "Tetap Semula"
190
190
191#: qml/Dash/GenericScopeView.qml:579 qml/Dash/GenericScopeView.qml:764
191#: qml/Dash/GenericScopeView.qml:579 qml/Dash/GenericScopeView.qml:764
192msgid "Show less"
192msgid "Show less"
193−msgstr ""
193+msgstr "Tunjuk sedikit"
194
194
195#: qml/Dash/GenericScopeView.qml:579
195#: qml/Dash/GenericScopeView.qml:579
196msgid "Show all"
196msgid "Show all"
197−msgstr ""
197+msgstr "Tunjuk semua"
198
198
199#: qml/Dash/GenericScopeView.qml:636
199#: qml/Dash/GenericScopeView.qml:636
200msgctxt "Label: Hint for dash search line edit"
200msgctxt "Label: Hint for dash search line edit"
@@ -203,11 +203,11 @@ msgstr "Gelintar"
203
203
204#: qml/Dash/PageHeaderExtraPanel.qml:55
204#: qml/Dash/PageHeaderExtraPanel.qml:55
205msgid "Recent Searches"
205msgid "Recent Searches"
206−msgstr ""
206+msgstr "Gelintar Baru-baru Ini"
207
207
208#: qml/Dash/PageHeaderExtraPanel.qml:66
208#: qml/Dash/PageHeaderExtraPanel.qml:66
209msgid "Clear All"
209msgid "Clear All"
210−msgstr ""
210+msgstr "Kosongkan Semua"
211
211
212#: qml/Dash/Previews/PreviewActionCombo.qml:35
212#: qml/Dash/Previews/PreviewActionCombo.qml:35
213msgid "More..."
213msgid "More..."
@@ -258,11 +258,13 @@ msgstr "Rumah"
258msgid "Also installed"
258msgid "Also installed"
259msgstr "Juga dipasang"
259msgstr "Juga dipasang"
260
260
261−#: qml/DisabledScreenNotice.qml:104
261+#: qml/DisabledScreenNotice.qml:109
262msgid ""
262msgid ""
263"Your device is now connected to an external display. Use this screen as a "
263"Your device is now connected to an external display. Use this screen as a "
264"touch pad to interact with the pointer."
264"touch pad to interact with the pointer."
265msgstr ""
265msgstr ""
266+"Peranti anda kini bersambung dengan paparan luar. Guna skrin ini sebagai pad "
267+"sentuh untuk berinteraksi dengan penuding."
266
268
267#: qml/Greeter/CoverPage.qml:118
269#: qml/Greeter/CoverPage.qml:118
268msgid "Unlock"
270msgid "Unlock"
@@ -392,7 +394,7 @@ msgstr "Memuat turun"
392
394
393#: qml/Panel/Indicators/MenuItemFactory.qml:917
395#: qml/Panel/Indicators/MenuItemFactory.qml:917
394msgid "Paused, tap to resume"
396msgid "Paused, tap to resume"
395−msgstr "Dijeda, ketuk untuk sambung semula"
397+msgstr "Dijeda, ketik untuk sambung semula"
396
398
397#: qml/Panel/Indicators/MenuItemFactory.qml:919
399#: qml/Panel/Indicators/MenuItemFactory.qml:919
398msgid "Canceled"
400msgid "Canceled"
@@ -404,7 +406,7 @@ msgstr "Selesai"
404
406
405#: qml/Panel/Indicators/MenuItemFactory.qml:923
407#: qml/Panel/Indicators/MenuItemFactory.qml:923
406msgid "Failed, tap to retry"
408msgid "Failed, tap to retry"
407−msgstr "Gagal, ketuk untuk cuba lagi"
409+msgstr "Gagal, ketik untuk cuba lagi"
408
410
409#: qml/Panel/Indicators/MessageMenuItemFactory.qml:155
411#: qml/Panel/Indicators/MessageMenuItemFactory.qml:155
410#: qml/Panel/Indicators/MessageMenuItemFactory.qml:214
412#: qml/Panel/Indicators/MessageMenuItemFactory.qml:214
@@ -425,50 +427,56 @@ msgstr "Panggilan semula"
425#: qml/Stages/SideStage.qml:76
427#: qml/Stages/SideStage.qml:76
426msgid "Drag using 3 fingers any application from one window to the other"
428msgid "Drag using 3 fingers any application from one window to the other"
427msgstr ""
429msgstr ""
430+"Seret menggunakan 3 jari pada mana-mana aplik dari satu tetingkap ke "
431+"tetingkap yang lain"
428
432
429#: qml/Tutorial/TutorialBottom.qml:78
433#: qml/Tutorial/TutorialBottom.qml:78
430msgid "Swipe up to add a contact"
434msgid "Swipe up to add a contact"
431−msgstr ""
435+msgstr "Leret ke atas untuk menambah kenalan"
432
436
433#: qml/Tutorial/TutorialBottom.qml:80
437#: qml/Tutorial/TutorialBottom.qml:80
434msgid "Swipe up for favorite calculations"
438msgid "Swipe up for favorite calculations"
435−msgstr ""
439+msgstr "Leret ke atas untuk pengiraan kegemaran"
436
440
437#: qml/Tutorial/TutorialBottom.qml:82
441#: qml/Tutorial/TutorialBottom.qml:82
438msgid "Swipe up for recent calls"
442msgid "Swipe up for recent calls"
439−msgstr ""
443+msgstr "Leret ke atas untuk panggilan baru-baru ini"
440
444
441#: qml/Tutorial/TutorialBottom.qml:84
445#: qml/Tutorial/TutorialBottom.qml:84
442msgid "Swipe up to create a message"
446msgid "Swipe up to create a message"
443−msgstr ""
447+msgstr "Leret ke atas untuk cipta satu mesej"
444
448
445#: qml/Tutorial/TutorialBottom.qml:85
449#: qml/Tutorial/TutorialBottom.qml:85
446msgid "Swipe up to manage the app"
450msgid "Swipe up to manage the app"
447−msgstr ""
451+msgstr "Leret ke atas untuk mengurus apl"
448
452
449#: qml/Tutorial/TutorialLeftLong.qml:47
453#: qml/Tutorial/TutorialLeftLong.qml:47
450msgid "Long swipe from the left edge to open the Today scope"
454msgid "Long swipe from the left edge to open the Today scope"
451−msgstr ""
455+msgstr "Leret panjang dari pinggir kiri untuk membuka skop Hari Ini"
452
456
453#: qml/Tutorial/TutorialLeft.qml:47
457#: qml/Tutorial/TutorialLeft.qml:47
454msgid "Swipe from the left edge to open the launcher"
458msgid "Swipe from the left edge to open the launcher"
455−msgstr ""
459+msgstr "Leret dari pinggir kiri untuk membuka pelancar"
456
460
457#: qml/Tutorial/TutorialRight.qml:55
461#: qml/Tutorial/TutorialRight.qml:55
458msgid "Push your mouse against the right edge to view your open apps"
462msgid "Push your mouse against the right edge to view your open apps"
459msgstr ""
463msgstr ""
464+"Tolak penuding tetikus anda ke pinggir kanan untuk melihat apl yang telah "
465+"dibuka"
460
466
461#: qml/Tutorial/TutorialRight.qml:56
467#: qml/Tutorial/TutorialRight.qml:56
462msgid "Short or long swipe from the right edge to view your open apps"
468msgid "Short or long swipe from the right edge to view your open apps"
463msgstr ""
469msgstr ""
470+"Leret pendek atau panjang dari pinggir kanan untuk melihat apl yang telah "
471+"dibuka"
464
472
465#: qml/Tutorial/TutorialTop.qml:53
473#: qml/Tutorial/TutorialTop.qml:53
466msgid "Swipe from the top right edge to open the notification bar"
474msgid "Swipe from the top right edge to open the notification bar"
467−msgstr ""
475+msgstr "Leret dari pinggir kanan atas untuk membuka palang pemberitahuan"
468
476
469#: qml/Tutorial/TutorialTop.qml:54
477#: qml/Tutorial/TutorialTop.qml:54
470msgid "Swipe from the top edge to open the notification bar"
478msgid "Swipe from the top edge to open the notification bar"
471−msgstr ""
479+msgstr "Leret dari pinggir atas untuk membuka palang pemberitahuan"
472
480
473#: qml/Wizard/Page.qml:54
481#: qml/Wizard/Page.qml:54
474msgctxt "Button: Go back one page in the Wizard"
482msgctxt "Button: Go back one page in the Wizard"
@@ -477,7 +485,7 @@ msgstr "Kembali"
477
485
478#: qml/Wizard/Pages/10-welcome.qml:27
486#: qml/Wizard/Pages/10-welcome.qml:27
479msgid "Language"
487msgid "Language"
480−msgstr ""
488+msgstr "Bahasa"
481
489
482#: qml/Wizard/Pages/10-welcome.qml:156 qml/Wizard/Pages/30-wifi.qml:206
490#: qml/Wizard/Pages/10-welcome.qml:156 qml/Wizard/Pages/30-wifi.qml:206
483#: qml/Wizard/Pages/40-location.qml:271 qml/Wizard/Pages/50-timezone.qml:267
491#: qml/Wizard/Pages/40-location.qml:271 qml/Wizard/Pages/50-timezone.qml:267
@@ -486,7 +494,7 @@ msgstr ""
486#: qml/Wizard/Pages/passcode-desktop.qml:124
494#: qml/Wizard/Pages/passcode-desktop.qml:124
487#: qml/Wizard/Pages/password-set.qml:141
495#: qml/Wizard/Pages/password-set.qml:141
488msgid "Next"
496msgid "Next"
489−msgstr ""
497+msgstr "Berikutnya"
490
498
491#: qml/Wizard/Pages/30-wifi.qml:29
499#: qml/Wizard/Pages/30-wifi.qml:29
492msgid "Connect to Wi‑Fi"
500msgid "Connect to Wi‑Fi"
@@ -494,15 +502,15 @@ msgstr "Sambung ke Wi-Fi"
494
502
495#: qml/Wizard/Pages/30-wifi.qml:130
503#: qml/Wizard/Pages/30-wifi.qml:130
496msgid "Connected"
504msgid "Connected"
497−msgstr ""
505+msgstr "Bersambung"
498
506
499#: qml/Wizard/Pages/30-wifi.qml:163
507#: qml/Wizard/Pages/30-wifi.qml:163
500msgid "Available Wi-Fi networks"
508msgid "Available Wi-Fi networks"
501−msgstr ""
509+msgstr "Rangkaian Wi-Fi tersedia"
502
510
503#: qml/Wizard/Pages/30-wifi.qml:164
511#: qml/Wizard/Pages/30-wifi.qml:164
504msgid "No available Wi-Fi networks"
512msgid "No available Wi-Fi networks"
505−msgstr ""
513+msgstr "Tiada rangkaian Wi-Fi tersedia"
506
514
507#: qml/Wizard/Pages/30-wifi.qml:206 qml/Wizard/Pages/60-account.qml:65
515#: qml/Wizard/Pages/30-wifi.qml:206 qml/Wizard/Pages/60-account.qml:65
508#: qml/Wizard/Pages/sim.qml:101
516#: qml/Wizard/Pages/sim.qml:101
@@ -511,98 +519,101 @@ msgstr "Langkau"
511
519
512#: qml/Wizard/Pages/40-location.qml:27
520#: qml/Wizard/Pages/40-location.qml:27
513msgid "Location Services"
521msgid "Location Services"
514−msgstr ""
522+msgstr "Perkhidmatan Lokasi"
515
523
516#: qml/Wizard/Pages/40-location.qml:83
524#: qml/Wizard/Pages/40-location.qml:83
517msgid ""
525msgid ""
518"Use GPS, Wi-Fi hotspots and mobile network anonymously to detect location "
526"Use GPS, Wi-Fi hotspots and mobile network anonymously to detect location "
519"(recommended)"
527"(recommended)"
520msgstr ""
528msgstr ""
529+"Guna GPS, hotspot Wi-Fi dan rangkaian mudah alih secara awanama untuk "
530+"mengesan lokasi (disarankan)"
521
531
522#: qml/Wizard/Pages/40-location.qml:105
532#: qml/Wizard/Pages/40-location.qml:105
523#, qt-format
533#, qt-format
524msgid "By selecting this option you agree to the Nokia HERE %1."
534msgid "By selecting this option you agree to the Nokia HERE %1."
525−msgstr ""
535+msgstr "Dengan memilih pilihan ini anda bersetuju dengan Nokia HERE %1."
526
536
527#: qml/Wizard/Pages/40-location.qml:106
537#: qml/Wizard/Pages/40-location.qml:106
528msgctxt "part of: Nokia HERE terms and conditions"
538msgctxt "part of: Nokia HERE terms and conditions"
529msgid "terms and conditions"
539msgid "terms and conditions"
530−msgstr ""
540+msgstr "terma dan syarat"
531
541
532#: qml/Wizard/Pages/40-location.qml:160
542#: qml/Wizard/Pages/40-location.qml:160
533msgid "GPS only"
543msgid "GPS only"
534−msgstr ""
544+msgstr "GPS sahaja"
535
545
536#: qml/Wizard/Pages/40-location.qml:214
546#: qml/Wizard/Pages/40-location.qml:214
537msgid "Don't use my location"
547msgid "Don't use my location"
538−msgstr ""
548+msgstr "Jangan guna lokasi saya"
539
549
540#: qml/Wizard/Pages/40-location.qml:260
550#: qml/Wizard/Pages/40-location.qml:260
541msgid "You can change it later in System Settings."
551msgid "You can change it later in System Settings."
542−msgstr ""
552+msgstr "Anda boleh mengubahnya kemudian di dalam Tetapan Sistem."
543
553
544#: qml/Wizard/Pages/50-timezone.qml:29
554#: qml/Wizard/Pages/50-timezone.qml:29
545msgid "Time Zone"
555msgid "Time Zone"
546−msgstr ""
556+msgstr "Zon Waktu"
547
557
548#: qml/Wizard/Pages/50-timezone.qml:178
558#: qml/Wizard/Pages/50-timezone.qml:178
549msgid "Enter your city"
559msgid "Enter your city"
550−msgstr ""
560+msgstr "Masukkan bandar anda"
551
561
552#: qml/Wizard/Pages/60-account.qml:24
562#: qml/Wizard/Pages/60-account.qml:24
553msgid "Personalize Your Device"
563msgid "Personalize Your Device"
554−msgstr ""
564+msgstr "Peribadikan Peranti Anda"
555
565
556#: qml/Wizard/Pages/60-account.qml:48
566#: qml/Wizard/Pages/60-account.qml:48
557msgid "Preferred Name"
567msgid "Preferred Name"
558−msgstr ""
568+msgstr "Nama Digemari"
559
569
560#: qml/Wizard/Pages/70-passwd-type.qml:39
570#: qml/Wizard/Pages/70-passwd-type.qml:39
561msgid "Lock Screen"
571msgid "Lock Screen"
562−msgstr ""
572+msgstr "Skrin Kunci"
563
573
564#: qml/Wizard/Pages/70-passwd-type.qml:101
574#: qml/Wizard/Pages/70-passwd-type.qml:101
565msgctxt "Label: Type of security method"
575msgctxt "Label: Type of security method"
566msgid "Create new password"
576msgid "Create new password"
567−msgstr ""
577+msgstr "Cipta kata laluan baharu"
568
578
569#: qml/Wizard/Pages/70-passwd-type.qml:103
579#: qml/Wizard/Pages/70-passwd-type.qml:103
570msgctxt "Label: Type of security method"
580msgctxt "Label: Type of security method"
571msgid "Create passcode (numbers only)"
581msgid "Create passcode (numbers only)"
572−msgstr ""
582+msgstr "Cipta kod laluan (nombor sahaja)"
573
583
574#: qml/Wizard/Pages/70-passwd-type.qml:105
584#: qml/Wizard/Pages/70-passwd-type.qml:105
575msgctxt "Label: Type of security method"
585msgctxt "Label: Type of security method"
576msgid "No lock code"
586msgid "No lock code"
577−msgstr ""
587+msgstr "Tiada kod kunci"
578
588
579#: qml/Wizard/Pages/75-report-check.qml:26 qml/Wizard/Pages/here-terms.qml:108
589#: qml/Wizard/Pages/75-report-check.qml:26 qml/Wizard/Pages/here-terms.qml:108
580msgid "Privacy Policy"
590msgid "Privacy Policy"
581−msgstr ""
591+msgstr "Dasar Kerahsiaan"
582
592
583#: qml/Wizard/Pages/75-report-check.qml:26
593#: qml/Wizard/Pages/75-report-check.qml:26
584msgid "Help Us Improve"
594msgid "Help Us Improve"
585−msgstr ""
595+msgstr "Bantu Kami"
586
596
587#: qml/Wizard/Pages/75-report-check.qml:59
597#: qml/Wizard/Pages/75-report-check.qml:59
588msgid "Improve system performance by sending us crashes and error reports."
598msgid "Improve system performance by sending us crashes and error reports."
589msgstr ""
599msgstr ""
600+"Tambah baik prestasi sistem dengan menghantar laporan kerosakan dan ralat."
590
601
591#: qml/Wizard/Pages/75-report-check.qml:60
602#: qml/Wizard/Pages/75-report-check.qml:60
592msgid "Privacy policy"
603msgid "Privacy policy"
593−msgstr ""
604+msgstr "Dasar kerahsiaan"
594
605
595#: qml/Wizard/Pages/80-finished.qml:89
606#: qml/Wizard/Pages/80-finished.qml:89
596msgid "Welcome to Ubuntu"
607msgid "Welcome to Ubuntu"
597−msgstr ""
608+msgstr "Selamat datang ke Ubuntu"
598
609
599#: qml/Wizard/Pages/80-finished.qml:104
610#: qml/Wizard/Pages/80-finished.qml:104
600msgid "You are ready to use your device now"
611msgid "You are ready to use your device now"
601−msgstr ""
612+msgstr "Anda boleh gunakan peranti sekarang"
602
613
603#: qml/Wizard/Pages/80-finished.qml:124
614#: qml/Wizard/Pages/80-finished.qml:124
604msgid "Get Started"
615msgid "Get Started"
605−msgstr ""
616+msgstr "Membiasakan Diri"
606
617
607#: qml/Wizard/Pages/here-terms.qml:25
618#: qml/Wizard/Pages/here-terms.qml:25
608msgid "Terms & Conditions"
619msgid "Terms & Conditions"
@@ -611,6 +622,8 @@ msgstr "Terma & Syarat"
611#: qml/Wizard/Pages/here-terms.qml:69
622#: qml/Wizard/Pages/here-terms.qml:69
612msgid "Your device uses positioning technologies provided by HERE."
623msgid "Your device uses positioning technologies provided by HERE."
613msgstr ""
624msgstr ""
625+"Peranti anda menggunakan teknologi menentukan lokasi yang disediakan oleh "
626+"HERE."
614
627
615#: qml/Wizard/Pages/here-terms.qml:81
628#: qml/Wizard/Pages/here-terms.qml:81
616msgid ""
629msgid ""
@@ -618,21 +631,27 @@ msgid ""
618"collects information about nearby cell towers and Wi-Fi hotspots around your "
631"collects information about nearby cell towers and Wi-Fi hotspots around your "
619"current location whenever your position is being found."
632"current location whenever your position is being found."
620msgstr ""
633msgstr ""
634+"Untuk menyediakan perkhidmatan penentuan lokasi dan menambahbaik kualiti, "
635+"HERE mengutip maklumat berkenaan menara telekomunikasi berhampiran dan "
636+"hotspot Wi-Fi disekitar anda bilamana kedudukan anda ditemui."
621
637
622#: qml/Wizard/Pages/here-terms.qml:93
638#: qml/Wizard/Pages/here-terms.qml:93
623msgid ""
639msgid ""
624"The information collected is used to analyze the service and to improve the "
640"The information collected is used to analyze the service and to improve the "
625"use of service, but not to identify you personally."
641"use of service, but not to identify you personally."
626msgstr ""
642msgstr ""
643+"Maklumat tersebut digunakan untuk menganalisis perkhidmatan dan menambahbaik "
644+"penggunaan perkhidmatan, walaubagaimanapun tidak mengenalpasti anda secara "
645+"peribadi."
627
646
628#: qml/Wizard/Pages/here-terms.qml:106
647#: qml/Wizard/Pages/here-terms.qml:106
629#, qt-format
648#, qt-format
630msgid "By continuing, you agree to the HERE platform %1 and %2."
649msgid "By continuing, you agree to the HERE platform %1 and %2."
631−msgstr ""
650+msgstr "Jika diteruskan, anda menyetujui HERE platform %1 dan %2."
632
651
633#: qml/Wizard/Pages/here-terms.qml:107
652#: qml/Wizard/Pages/here-terms.qml:107
634msgid "Service Terms"
653msgid "Service Terms"
635−msgstr ""
654+msgstr "Terma Perkhidmatan"
636
655
637#: qml/Wizard/Pages/passcode-confirm.qml:43
656#: qml/Wizard/Pages/passcode-confirm.qml:43
638#: qml/Wizard/Pages/passcode-desktop.qml:80
657#: qml/Wizard/Pages/passcode-desktop.qml:80
@@ -641,69 +660,70 @@ msgstr "Sahkan kod laluan"
641
660
642#: qml/Wizard/Pages/passcode-confirm.qml:45
661#: qml/Wizard/Pages/passcode-confirm.qml:45
643msgid "Incorrect passcode."
662msgid "Incorrect passcode."
644−msgstr ""
663+msgstr "Kod laluan tidak betul."
645
664
646#: qml/Wizard/Pages/passcode-confirm.qml:45
665#: qml/Wizard/Pages/passcode-confirm.qml:45
647msgctxt "Enter the passcode again"
666msgctxt "Enter the passcode again"
648msgid "Please re-enter."
667msgid "Please re-enter."
649−msgstr ""
668+msgstr "Sila masukkan sekali lagi."
650
669
651#: qml/Wizard/Pages/passcode-desktop.qml:30
670#: qml/Wizard/Pages/passcode-desktop.qml:30
652msgid "Lock Screen Passcode"
671msgid "Lock Screen Passcode"
653−msgstr ""
672+msgstr "Kod Laluan Skrin Kunci"
654
673
655#: qml/Wizard/Pages/passcode-desktop.qml:56
674#: qml/Wizard/Pages/passcode-desktop.qml:56
656msgid "Enter 4 numbers to setup your passcode"
675msgid "Enter 4 numbers to setup your passcode"
657−msgstr ""
676+msgstr "Masukkan 4 nombor untuk persediaan kod laluan anda"
658
677
659#: qml/Wizard/Pages/passcode-desktop.qml:65
678#: qml/Wizard/Pages/passcode-desktop.qml:65
660#: qml/Wizard/Pages/passcode-set.qml:54
679#: qml/Wizard/Pages/passcode-set.qml:54
661msgid "Choose passcode"
680msgid "Choose passcode"
662−msgstr ""
681+msgstr "Pilih kod laluan"
663
682
664#: qml/Wizard/Pages/passcode-desktop.qml:105
683#: qml/Wizard/Pages/passcode-desktop.qml:105
665msgid "Passcode too short"
684msgid "Passcode too short"
666−msgstr ""
685+msgstr "Kod laluan terlalu pendek"
667
686
668#: qml/Wizard/Pages/passcode-desktop.qml:107
687#: qml/Wizard/Pages/passcode-desktop.qml:107
669msgid "Passcodes match"
688msgid "Passcodes match"
670−msgstr ""
689+msgstr "Kod laluan sepadan"
671
690
672#: qml/Wizard/Pages/passcode-desktop.qml:109
691#: qml/Wizard/Pages/passcode-desktop.qml:109
673msgid "Passcodes do not match"
692msgid "Passcodes do not match"
674−msgstr ""
693+msgstr "Kod laluan tidak sepadan"
675
694
676#: qml/Wizard/Pages/passcode-set.qml:62
695#: qml/Wizard/Pages/passcode-set.qml:62
677msgid "Passcode must be 4 characters long"
696msgid "Passcode must be 4 characters long"
678−msgstr ""
697+msgstr "Kod laluan mestilah 4 aksara panjang"
679
698
680#: qml/Wizard/Pages/password-set.qml:30
699#: qml/Wizard/Pages/password-set.qml:30
681msgid "Lock Screen Password"
700msgid "Lock Screen Password"
682−msgstr ""
701+msgstr "Kata Laluan Skrin Kunci"
683
702
684#: qml/Wizard/Pages/password-set.qml:61
703#: qml/Wizard/Pages/password-set.qml:61
685msgid "Enter at least 8 characters"
704msgid "Enter at least 8 characters"
686−msgstr ""
705+msgstr "Masukkan sekurang-kurangnya 8 aksara"
687
706
688#: qml/Wizard/Pages/password-set.qml:73
707#: qml/Wizard/Pages/password-set.qml:73
689msgid "Choose password"
708msgid "Choose password"
690−msgstr ""
709+msgstr "Pilih kata laluan"
691
710
692#: qml/Wizard/Pages/password-set.qml:103
711#: qml/Wizard/Pages/password-set.qml:103
693msgid "Confirm password"
712msgid "Confirm password"
694−msgstr ""
713+msgstr "Sahkan kata laluan"
695
714
696#: qml/Wizard/Pages/sim.qml:27
715#: qml/Wizard/Pages/sim.qml:27
697msgid "No SIM card installed"
716msgid "No SIM card installed"
698−msgstr ""
717+msgstr "Tiada kad SIM terpasang"
699
718
700#: qml/Wizard/Pages/sim.qml:54
719#: qml/Wizard/Pages/sim.qml:54
701msgid "SIM card added"
720msgid "SIM card added"
702−msgstr ""
721+msgstr "Kad SIM ditambah"
703
722
704#: qml/Wizard/Pages/sim.qml:55
723#: qml/Wizard/Pages/sim.qml:55
705msgid "You must restart the device to access the mobile network."
724msgid "You must restart the device to access the mobile network."
706msgstr ""
725msgstr ""
726+"Anda mesti mulakan semula peranti supaya dapat mencapai rangkaian mudah alih."
707
727
708#: qml/Wizard/Pages/sim.qml:59
728#: qml/Wizard/Pages/sim.qml:59
709msgid "Restart"
729msgid "Restart"
@@ -712,34 +732,35 @@ msgstr "Mula Semula"
712#: qml/Wizard/Pages/sim.qml:78
732#: qml/Wizard/Pages/sim.qml:78
713msgid "You won’t be able to make calls or use text messaging without a SIM."
733msgid "You won’t be able to make calls or use text messaging without a SIM."
714msgstr ""
734msgstr ""
735+"Anda tidak dapat membuat panggilan atau guna pemesejan teks tanpa SIM."
715
736
716#: qml/Wizard/Pages/sim.qml:90
737#: qml/Wizard/Pages/sim.qml:90
717msgid "To proceed with no SIM tap Skip."
738msgid "To proceed with no SIM tap Skip."
718−msgstr ""
739+msgstr "Untuk teruskan tanpa SIM ketik Langkau."
719
740
720#: qml/Wizard/PasswordMeter.qml:87
741#: qml/Wizard/PasswordMeter.qml:87
721msgid "Passwords match"
742msgid "Passwords match"
722−msgstr ""
743+msgstr "Kata laluan sepadan"
723
744
724#: qml/Wizard/PasswordMeter.qml:89
745#: qml/Wizard/PasswordMeter.qml:89
725msgid "Passwords do not match"
746msgid "Passwords do not match"
726−msgstr ""
747+msgstr "Kata laluan tidak sepadan"
727
748
728#: qml/Wizard/PasswordMeter.qml:93
749#: qml/Wizard/PasswordMeter.qml:93
729msgid "Strong password"
750msgid "Strong password"
730−msgstr ""
751+msgstr "Kata laluan kuat"
731
752
732#: qml/Wizard/PasswordMeter.qml:95
753#: qml/Wizard/PasswordMeter.qml:95
733msgid "Fair password"
754msgid "Fair password"
734−msgstr ""
755+msgstr "Kata laluan sederhana"
735
756
736#: qml/Wizard/PasswordMeter.qml:97
757#: qml/Wizard/PasswordMeter.qml:97
737msgid "Weak password"
758msgid "Weak password"
738−msgstr ""
759+msgstr "Kata laluan lemah"
739
760
740#: qml/Wizard/PasswordMeter.qml:99
761#: qml/Wizard/PasswordMeter.qml:99
741msgid "Very weak password"
762msgid "Very weak password"
742−msgstr ""
763+msgstr "Kata laluan sangat lemah"
743
764
744#~ msgid "Top edge"
765#~ msgid "Top edge"
745#~ msgstr "Pinggir atas"
766#~ msgstr "Pinggir atas"
po/my.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2013-12-12 11:12+0000\n"
11"PO-Revision-Date: 2013-12-12 11:12+0000\n"
12"Last-Translator: Pyae Sone <Unknown>\n"
12"Last-Translator: Pyae Sone <Unknown>\n"
13"Language-Team: Burmese <my@li.org>\n"
13"Language-Team: Burmese <my@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2016-05-19 05:49+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:08+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -256,7 +256,7 @@ msgstr "ပင်မ"
256msgid "Also installed"
256msgid "Also installed"
257msgstr ""
257msgstr ""
258
258
259−#: qml/DisabledScreenNotice.qml:104
259+#: qml/DisabledScreenNotice.qml:109
260msgid ""
260msgid ""
261"Your device is now connected to an external display. Use this screen as a "
261"Your device is now connected to an external display. Use this screen as a "
262"touch pad to interact with the pointer."
262"touch pad to interact with the pointer."
po/nb.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2016-03-29 08:56+0000\n"
11"PO-Revision-Date: 2016-03-29 08:56+0000\n"
12"Last-Translator: Åka Sikrom <Unknown>\n"
12"Last-Translator: Åka Sikrom <Unknown>\n"
13"Language-Team: Norwegian Bokmal <nb@li.org>\n"
13"Language-Team: Norwegian Bokmal <nb@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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: 2016-05-19 05:49+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -262,7 +262,7 @@ msgstr "Hjem"
262msgid "Also installed"
262msgid "Also installed"
263msgstr "Også installert"
263msgstr "Også installert"
264
264
265−#: qml/DisabledScreenNotice.qml:104
265+#: qml/DisabledScreenNotice.qml:109
266msgid ""
266msgid ""
267"Your device is now connected to an external display. Use this screen as a "
267"Your device is now connected to an external display. Use this screen as a "
268"touch pad to interact with the pointer."
268"touch pad to interact with the pointer."
po/ne.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2015-12-06 15:11+0000\n"
11"PO-Revision-Date: 2015-12-06 15:11+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Nepali <ne@li.org>\n"
13"Language-Team: Nepali <ne@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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: 2016-05-19 05:49+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -256,7 +256,7 @@ msgstr ""
256msgid "Also installed"
256msgid "Also installed"
257msgstr ""
257msgstr ""
258
258
259−#: qml/DisabledScreenNotice.qml:104
259+#: qml/DisabledScreenNotice.qml:109
260msgid ""
260msgid ""
261"Your device is now connected to an external display. Use this screen as a "
261"Your device is now connected to an external display. Use this screen as a "
262"touch pad to interact with the pointer."
262"touch pad to interact with the pointer."
po/nl.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2015-07-07 07:14+0000\n"
11"PO-Revision-Date: 2015-07-07 07:14+0000\n"
12"Last-Translator: Hannie Dumoleyn <Unknown>\n"
12"Last-Translator: Hannie Dumoleyn <Unknown>\n"
13"Language-Team: Dutch <nl@li.org>\n"
13"Language-Team: Dutch <nl@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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: 2016-05-19 05:49+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:08+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -265,7 +265,7 @@ msgstr "Thuis"
265msgid "Also installed"
265msgid "Also installed"
266msgstr "Ook geïnstalleerd"
266msgstr "Ook geïnstalleerd"
267
267
268−#: qml/DisabledScreenNotice.qml:104
268+#: qml/DisabledScreenNotice.qml:109
269msgid ""
269msgid ""
270"Your device is now connected to an external display. Use this screen as a "
270"Your device is now connected to an external display. Use this screen as a "
271"touch pad to interact with the pointer."
271"touch pad to interact with the pointer."
po/nn.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2015-05-12 11:32+0000\n"
11"PO-Revision-Date: 2015-05-12 11:32+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Norwegian Nynorsk <nn@li.org>\n"
13"Language-Team: Norwegian Nynorsk <nn@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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: 2016-05-19 05:49+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -256,7 +256,7 @@ msgstr ""
256msgid "Also installed"
256msgid "Also installed"
257msgstr ""
257msgstr ""
258
258
259−#: qml/DisabledScreenNotice.qml:104
259+#: qml/DisabledScreenNotice.qml:109
260msgid ""
260msgid ""
261"Your device is now connected to an external display. Use this screen as a "
261"Your device is now connected to an external display. Use this screen as a "
262"touch pad to interact with the pointer."
262"touch pad to interact with the pointer."
po/oc.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2015-02-05 20:35+0000\n"
11"PO-Revision-Date: 2015-02-05 20:35+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Occitan (post 1500) <oc@li.org>\n"
13"Language-Team: Occitan (post 1500) <oc@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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: 2016-05-19 05:50+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -265,7 +265,7 @@ msgstr "Acuèlh"
265msgid "Also installed"
265msgid "Also installed"
266msgstr "Tanben installadas"
266msgstr "Tanben installadas"
267
267
268−#: qml/DisabledScreenNotice.qml:104
268+#: qml/DisabledScreenNotice.qml:109
269msgid ""
269msgid ""
270"Your device is now connected to an external display. Use this screen as a "
270"Your device is now connected to an external display. Use this screen as a "
271"touch pad to interact with the pointer."
271"touch pad to interact with the pointer."
po/or.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2015-03-21 05:28+0000\n"
11"PO-Revision-Date: 2015-03-21 05:28+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Oriya <or@li.org>\n"
13"Language-Team: Oriya <or@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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: 2016-05-19 05:50+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -256,7 +256,7 @@ msgstr ""
256msgid "Also installed"
256msgid "Also installed"
257msgstr ""
257msgstr ""
258
258
259−#: qml/DisabledScreenNotice.qml:104
259+#: qml/DisabledScreenNotice.qml:109
260msgid ""
260msgid ""
261"Your device is now connected to an external display. Use this screen as a "
261"Your device is now connected to an external display. Use this screen as a "
262"touch pad to interact with the pointer."
262"touch pad to interact with the pointer."
po/pa.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2015-04-24 04:29+0000\n"
11"PO-Revision-Date: 2015-04-24 04:29+0000\n"
12"Last-Translator: Gursharnjit_Singh <ubuntuser13@gmail.com>\n"
12"Last-Translator: Gursharnjit_Singh <ubuntuser13@gmail.com>\n"
13"Language-Team: Punjabi <pa@li.org>\n"
13"Language-Team: Punjabi <pa@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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: 2016-05-19 05:50+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -258,7 +258,7 @@ msgstr "ਘਰ"
258msgid "Also installed"
258msgid "Also installed"
259msgstr "ਨਾਲ ਇੰਸਟਾਲ ਹੋਇਆ"
259msgstr "ਨਾਲ ਇੰਸਟਾਲ ਹੋਇਆ"
260
260
261−#: qml/DisabledScreenNotice.qml:104
261+#: qml/DisabledScreenNotice.qml:109
262msgid ""
262msgid ""
263"Your device is now connected to an external display. Use this screen as a "
263"Your device is now connected to an external display. Use this screen as a "
264"touch pad to interact with the pointer."
264"touch pad to interact with the pointer."
po/pl.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2016-05-05 13:36+0000\n"
11"PO-Revision-Date: 2016-05-05 13:36+0000\n"
12"Last-Translator: dawidd6 <dawidd0811@gmail.com>\n"
12"Last-Translator: dawidd6 <dawidd0811@gmail.com>\n"
13"Language-Team: Polish <pl@li.org>\n"
13"Language-Team: Polish <pl@li.org>\n"
@@ -16,8 +16,8 @@ msgstr ""
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
17"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
18"|| n%100>=20) ? 1 : 2;\n"
18"|| n%100>=20) ? 1 : 2;\n"
19−"X-Launchpad-Export-Date: 2016-05-19 05:50+0000\n"
19+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
20−"X-Generator: Launchpad (build 18025)\n"
20+"X-Generator: Launchpad (build 18053)\n"
21
21
22#: plugins/IntegratedLightDM/Greeter.cpp:112
22#: plugins/IntegratedLightDM/Greeter.cpp:112
23msgid "Password: "
23msgid "Password: "
@@ -259,7 +259,7 @@ msgstr "Pulpit"
259msgid "Also installed"
259msgid "Also installed"
260msgstr "Również zainstalowane"
260msgstr "Również zainstalowane"
261
261
262−#: qml/DisabledScreenNotice.qml:104
262+#: qml/DisabledScreenNotice.qml:109
263msgid ""
263msgid ""
264"Your device is now connected to an external display. Use this screen as a "
264"Your device is now connected to an external display. Use this screen as a "
265"touch pad to interact with the pointer."
265"touch pad to interact with the pointer."
po/pt.po+7−7
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2016-02-18 01:11+0000\n"
11"PO-Revision-Date: 2016-02-18 01:11+0000\n"
12"Last-Translator: Ivo Xavier <ivoxavier.8@gmail.com>\n"
12"Last-Translator: Ivo Xavier <ivoxavier.8@gmail.com>\n"
13"Language-Team: Portuguese <pt@li.org>\n"
13"Language-Team: Portuguese <pt@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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: 2016-05-19 05:50+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -263,7 +263,7 @@ msgstr "Página inicial"
263msgid "Also installed"
263msgid "Also installed"
264msgstr "Também instalado"
264msgstr "Também instalado"
265
265
266−#: qml/DisabledScreenNotice.qml:104
266+#: qml/DisabledScreenNotice.qml:109
267msgid ""
267msgid ""
268"Your device is now connected to an external display. Use this screen as a "
268"Your device is now connected to an external display. Use this screen as a "
269"touch pad to interact with the pointer."
269"touch pad to interact with the pointer."
@@ -300,8 +300,8 @@ msgid ""
300"If passphrase is entered incorrectly, your phone will conduct a factory "
300"If passphrase is entered incorrectly, your phone will conduct a factory "
301"reset and all personal data will be deleted."
301"reset and all personal data will be deleted."
302msgstr ""
302msgstr ""
303−"Se a palavra-passe for introduzida incorretamente, o seu telemóvel apagará "
303+"Se a palavra-passe for introduzida incorretamente, a sua informação pessoal "
304−"toda a sua informação pessoal."
304+"será eliminada."
305
305
306#: qml/Greeter/NarrowView.qml:59
306#: qml/Greeter/NarrowView.qml:59
307msgid ""
307msgid ""
@@ -309,7 +309,7 @@ msgid ""
309"and all personal data will be deleted."
309"and all personal data will be deleted."
310msgstr ""
310msgstr ""
311"Se o código for introduzido incorretamente, todos os dados pessoais serão "
311"Se o código for introduzido incorretamente, todos os dados pessoais serão "
312−"apagados."
312+"eliminados"
313
313
314#: qml/Greeter/NarrowView.qml:116
314#: qml/Greeter/NarrowView.qml:116
315#, qt-format
315#, qt-format
po/pt_BR.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2015-08-05 04:40+0000\n"
11"PO-Revision-Date: 2015-08-05 04:40+0000\n"
12"Last-Translator: Julio Alexander Sieg <julio.sieg@gmail.com>\n"
12"Last-Translator: Julio Alexander Sieg <julio.sieg@gmail.com>\n"
13"Language-Team: Brazilian Portuguese <pt_BR@li.org>\n"
13"Language-Team: Brazilian Portuguese <pt_BR@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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: 2016-05-19 05:50+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -260,7 +260,7 @@ msgstr "Início"
260msgid "Also installed"
260msgid "Also installed"
261msgstr "Instalado também"
261msgstr "Instalado também"
262
262
263−#: qml/DisabledScreenNotice.qml:104
263+#: qml/DisabledScreenNotice.qml:109
264msgid ""
264msgid ""
265"Your device is now connected to an external display. Use this screen as a "
265"Your device is now connected to an external display. Use this screen as a "
266"touch pad to interact with the pointer."
266"touch pad to interact with the pointer."
po/ro.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2015-07-06 17:47+0000\n"
11"PO-Revision-Date: 2015-07-06 17:47+0000\n"
12"Last-Translator: Meriuță Cornel <meriutacornel@neacornel.eu>\n"
12"Last-Translator: Meriuță Cornel <meriutacornel@neacornel.eu>\n"
13"Language-Team: Romanian <ro@li.org>\n"
13"Language-Team: Romanian <ro@li.org>\n"
@@ -16,8 +16,8 @@ msgstr ""
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=3; plural=(n == 1 ? 0: (((n % 100 > 19) || ((n % 100 "
17"Plural-Forms: nplurals=3; plural=(n == 1 ? 0: (((n % 100 > 19) || ((n % 100 "
18"== 0) && (n != 0))) ? 2: 1));\n"
18"== 0) && (n != 0))) ? 2: 1));\n"
19−"X-Launchpad-Export-Date: 2016-05-19 05:50+0000\n"
19+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
20−"X-Generator: Launchpad (build 18025)\n"
20+"X-Generator: Launchpad (build 18053)\n"
21
21
22#: plugins/IntegratedLightDM/Greeter.cpp:112
22#: plugins/IntegratedLightDM/Greeter.cpp:112
23msgid "Password: "
23msgid "Password: "
@@ -263,7 +263,7 @@ msgstr "Acasă"
263msgid "Also installed"
263msgid "Also installed"
264msgstr "Alte programe instalate"
264msgstr "Alte programe instalate"
265
265
266−#: qml/DisabledScreenNotice.qml:104
266+#: qml/DisabledScreenNotice.qml:109
267msgid ""
267msgid ""
268"Your device is now connected to an external display. Use this screen as a "
268"Your device is now connected to an external display. Use this screen as a "
269"touch pad to interact with the pointer."
269"touch pad to interact with the pointer."
po/ru.po+30−26
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2015-07-06 05:33+0000\n"
11"PO-Revision-Date: 2015-07-06 05:33+0000\n"
12"Last-Translator: ☠Jay ZDLin☠ <Unknown>\n"
12"Last-Translator: ☠Jay ZDLin☠ <Unknown>\n"
13"Language-Team: Russian <ru@li.org>\n"
13"Language-Team: Russian <ru@li.org>\n"
@@ -16,8 +16,8 @@ msgstr ""
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
17"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
18"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
18"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
19−"X-Launchpad-Export-Date: 2016-05-19 05:50+0000\n"
19+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
20−"X-Generator: Launchpad (build 18025)\n"
20+"X-Generator: Launchpad (build 18053)\n"
21
21
22#: plugins/IntegratedLightDM/Greeter.cpp:112
22#: plugins/IntegratedLightDM/Greeter.cpp:112
23msgid "Password: "
23msgid "Password: "
@@ -186,7 +186,7 @@ msgstr "Добавить в избранное"
186
186
187#: qml/Dash/FiltersPopover.qml:60
187#: qml/Dash/FiltersPopover.qml:60
188msgid "Refine your results"
188msgid "Refine your results"
189−msgstr ""
189+msgstr "Уточнить результаты"
190
190
191#: qml/Dash/FiltersPopover.qml:69
191#: qml/Dash/FiltersPopover.qml:69
192msgid "Reset"
192msgid "Reset"
@@ -262,7 +262,7 @@ msgstr "Домой"
262msgid "Also installed"
262msgid "Also installed"
263msgstr "Также установлено"
263msgstr "Также установлено"
264
264
265−#: qml/DisabledScreenNotice.qml:104
265+#: qml/DisabledScreenNotice.qml:109
266msgid ""
266msgid ""
267"Your device is now connected to an external display. Use this screen as a "
267"Your device is now connected to an external display. Use this screen as a "
268"touch pad to interact with the pointer."
268"touch pad to interact with the pointer."
@@ -507,11 +507,11 @@ msgstr "Подключено"
507
507
508#: qml/Wizard/Pages/30-wifi.qml:163
508#: qml/Wizard/Pages/30-wifi.qml:163
509msgid "Available Wi-Fi networks"
509msgid "Available Wi-Fi networks"
510−msgstr ""
510+msgstr "Доступные Wi-Fi сети"
511
511
512#: qml/Wizard/Pages/30-wifi.qml:164
512#: qml/Wizard/Pages/30-wifi.qml:164
513msgid "No available Wi-Fi networks"
513msgid "No available Wi-Fi networks"
514−msgstr ""
514+msgstr "Нет доступных Wi-Fi сетей"
515
515
516#: qml/Wizard/Pages/30-wifi.qml:206 qml/Wizard/Pages/60-account.qml:65
516#: qml/Wizard/Pages/30-wifi.qml:206 qml/Wizard/Pages/60-account.qml:65
517#: qml/Wizard/Pages/sim.qml:101
517#: qml/Wizard/Pages/sim.qml:101
@@ -520,13 +520,15 @@ msgstr "Пропустить"
520
520
521#: qml/Wizard/Pages/40-location.qml:27
521#: qml/Wizard/Pages/40-location.qml:27
522msgid "Location Services"
522msgid "Location Services"
523−msgstr ""
523+msgstr "Службы геолокации"
524
524
525#: qml/Wizard/Pages/40-location.qml:83
525#: qml/Wizard/Pages/40-location.qml:83
526msgid ""
526msgid ""
527"Use GPS, Wi-Fi hotspots and mobile network anonymously to detect location "
527"Use GPS, Wi-Fi hotspots and mobile network anonymously to detect location "
528"(recommended)"
528"(recommended)"
529msgstr ""
529msgstr ""
530+"Использовать анонимно GPS, точки доступа Wi-Fi и мобильную сеть для "
531+"определения местоположения (рекомендуется)"
530
532
531#: qml/Wizard/Pages/40-location.qml:105
533#: qml/Wizard/Pages/40-location.qml:105
532#, qt-format
534#, qt-format
@@ -536,7 +538,7 @@ msgstr ""
536#: qml/Wizard/Pages/40-location.qml:106
538#: qml/Wizard/Pages/40-location.qml:106
537msgctxt "part of: Nokia HERE terms and conditions"
539msgctxt "part of: Nokia HERE terms and conditions"
538msgid "terms and conditions"
540msgid "terms and conditions"
539−msgstr ""
541+msgstr "условия и соглашения"
540
542
541#: qml/Wizard/Pages/40-location.qml:160
543#: qml/Wizard/Pages/40-location.qml:160
542msgid "GPS only"
544msgid "GPS only"
@@ -564,11 +566,11 @@ msgstr ""
564
566
565#: qml/Wizard/Pages/60-account.qml:48
567#: qml/Wizard/Pages/60-account.qml:48
566msgid "Preferred Name"
568msgid "Preferred Name"
567−msgstr ""
569+msgstr "Предпочитаемое имя"
568
570
569#: qml/Wizard/Pages/70-passwd-type.qml:39
571#: qml/Wizard/Pages/70-passwd-type.qml:39
570msgid "Lock Screen"
572msgid "Lock Screen"
571−msgstr ""
573+msgstr "Заблокировать экран"
572
574
573#: qml/Wizard/Pages/70-passwd-type.qml:101
575#: qml/Wizard/Pages/70-passwd-type.qml:101
574msgctxt "Label: Type of security method"
576msgctxt "Label: Type of security method"
@@ -578,16 +580,16 @@ msgstr "Создать новый пароль"
578#: qml/Wizard/Pages/70-passwd-type.qml:103
580#: qml/Wizard/Pages/70-passwd-type.qml:103
579msgctxt "Label: Type of security method"
581msgctxt "Label: Type of security method"
580msgid "Create passcode (numbers only)"
582msgid "Create passcode (numbers only)"
581−msgstr ""
583+msgstr "Создать парольный код (только цифры)"
582
584
583#: qml/Wizard/Pages/70-passwd-type.qml:105
585#: qml/Wizard/Pages/70-passwd-type.qml:105
584msgctxt "Label: Type of security method"
586msgctxt "Label: Type of security method"
585msgid "No lock code"
587msgid "No lock code"
586−msgstr ""
588+msgstr "Без кода разблокировки"
587
589
588#: qml/Wizard/Pages/75-report-check.qml:26 qml/Wizard/Pages/here-terms.qml:108
590#: qml/Wizard/Pages/75-report-check.qml:26 qml/Wizard/Pages/here-terms.qml:108
589msgid "Privacy Policy"
591msgid "Privacy Policy"
590−msgstr ""
592+msgstr "Политика конфиденциальности"
591
593
592#: qml/Wizard/Pages/75-report-check.qml:26
594#: qml/Wizard/Pages/75-report-check.qml:26
593msgid "Help Us Improve"
595msgid "Help Us Improve"
@@ -599,7 +601,7 @@ msgstr ""
599
601
600#: qml/Wizard/Pages/75-report-check.qml:60
602#: qml/Wizard/Pages/75-report-check.qml:60
601msgid "Privacy policy"
603msgid "Privacy policy"
602−msgstr ""
604+msgstr "Политика конфиденциальности"
603
605
604#: qml/Wizard/Pages/80-finished.qml:89
606#: qml/Wizard/Pages/80-finished.qml:89
605msgid "Welcome to Ubuntu"
607msgid "Welcome to Ubuntu"
@@ -607,11 +609,11 @@ msgstr "Добро пожаловать в Ubuntu"
607
609
608#: qml/Wizard/Pages/80-finished.qml:104
610#: qml/Wizard/Pages/80-finished.qml:104
609msgid "You are ready to use your device now"
611msgid "You are ready to use your device now"
610−msgstr ""
612+msgstr "Теперь устройство готово к использованию"
611
613
612#: qml/Wizard/Pages/80-finished.qml:124
614#: qml/Wizard/Pages/80-finished.qml:124
613msgid "Get Started"
615msgid "Get Started"
614−msgstr ""
616+msgstr "Приступая к работе"
615
617
616#: qml/Wizard/Pages/here-terms.qml:25
618#: qml/Wizard/Pages/here-terms.qml:25
617msgid "Terms & Conditions"
619msgid "Terms & Conditions"
@@ -619,7 +621,7 @@ msgstr "Условия использования"
619
621
620#: qml/Wizard/Pages/here-terms.qml:69
622#: qml/Wizard/Pages/here-terms.qml:69
621msgid "Your device uses positioning technologies provided by HERE."
623msgid "Your device uses positioning technologies provided by HERE."
622−msgstr ""
624+msgstr "Ваше устройство использует HERE для определения местоположения"
623
625
624#: qml/Wizard/Pages/here-terms.qml:81
626#: qml/Wizard/Pages/here-terms.qml:81
625msgid ""
627msgid ""
@@ -633,6 +635,8 @@ msgid ""
633"The information collected is used to analyze the service and to improve the "
635"The information collected is used to analyze the service and to improve the "
634"use of service, but not to identify you personally."
636"use of service, but not to identify you personally."
635msgstr ""
637msgstr ""
638+"Собираемая информация используется для анализа и улучшения сервиса, а не для "
639+"идентификации вашей личности."
636
640
637#: qml/Wizard/Pages/here-terms.qml:106
641#: qml/Wizard/Pages/here-terms.qml:106
638#, qt-format
642#, qt-format
@@ -659,11 +663,11 @@ msgstr "Введите заново."
659
663
660#: qml/Wizard/Pages/passcode-desktop.qml:30
664#: qml/Wizard/Pages/passcode-desktop.qml:30
661msgid "Lock Screen Passcode"
665msgid "Lock Screen Passcode"
662−msgstr ""
666+msgstr "Код блокировки экрана"
663
667
664#: qml/Wizard/Pages/passcode-desktop.qml:56
668#: qml/Wizard/Pages/passcode-desktop.qml:56
665msgid "Enter 4 numbers to setup your passcode"
669msgid "Enter 4 numbers to setup your passcode"
666−msgstr ""
670+msgstr "Введите код блокировки из 4 цифр"
667
671
668#: qml/Wizard/Pages/passcode-desktop.qml:65
672#: qml/Wizard/Pages/passcode-desktop.qml:65
669#: qml/Wizard/Pages/passcode-set.qml:54
673#: qml/Wizard/Pages/passcode-set.qml:54
@@ -672,15 +676,15 @@ msgstr ""
672
676
673#: qml/Wizard/Pages/passcode-desktop.qml:105
677#: qml/Wizard/Pages/passcode-desktop.qml:105
674msgid "Passcode too short"
678msgid "Passcode too short"
675−msgstr ""
679+msgstr "Код слишком короткий"
676
680
677#: qml/Wizard/Pages/passcode-desktop.qml:107
681#: qml/Wizard/Pages/passcode-desktop.qml:107
678msgid "Passcodes match"
682msgid "Passcodes match"
679−msgstr ""
683+msgstr "Коды совпадают"
680
684
681#: qml/Wizard/Pages/passcode-desktop.qml:109
685#: qml/Wizard/Pages/passcode-desktop.qml:109
682msgid "Passcodes do not match"
686msgid "Passcodes do not match"
683−msgstr ""
687+msgstr "Коды не совпадают"
684
688
685#: qml/Wizard/Pages/passcode-set.qml:62
689#: qml/Wizard/Pages/passcode-set.qml:62
686msgid "Passcode must be 4 characters long"
690msgid "Passcode must be 4 characters long"
@@ -688,7 +692,7 @@ msgstr "Код должен содержать 4 символа"
688
692
689#: qml/Wizard/Pages/password-set.qml:30
693#: qml/Wizard/Pages/password-set.qml:30
690msgid "Lock Screen Password"
694msgid "Lock Screen Password"
691−msgstr ""
695+msgstr "Пароль блокировки экрана"
692
696
693#: qml/Wizard/Pages/password-set.qml:61
697#: qml/Wizard/Pages/password-set.qml:61
694msgid "Enter at least 8 characters"
698msgid "Enter at least 8 characters"
@@ -737,11 +741,11 @@ msgstr "Пароли не совпадают"
737
741
738#: qml/Wizard/PasswordMeter.qml:93
742#: qml/Wizard/PasswordMeter.qml:93
739msgid "Strong password"
743msgid "Strong password"
740−msgstr ""
744+msgstr "Сильный пароль"
741
745
742#: qml/Wizard/PasswordMeter.qml:95
746#: qml/Wizard/PasswordMeter.qml:95
743msgid "Fair password"
747msgid "Fair password"
744−msgstr ""
748+msgstr "Неплохой пароль"
745
749
746#: qml/Wizard/PasswordMeter.qml:97
750#: qml/Wizard/PasswordMeter.qml:97
747msgid "Weak password"
751msgid "Weak password"
po/shn.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2015-11-10 12:09+0000\n"
11"PO-Revision-Date: 2015-11-10 12:09+0000\n"
12"Last-Translator: Rockworld <sumoisrock@gmail.com>\n"
12"Last-Translator: Rockworld <sumoisrock@gmail.com>\n"
13"Language-Team: Shan <shn@li.org>\n"
13"Language-Team: Shan <shn@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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) ? 0 : 1;\n"
17"Plural-Forms: nplurals=2; plural=(n == 1) ? 0 : 1;\n"
18−"X-Launchpad-Export-Date: 2016-05-19 05:50+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -256,7 +256,7 @@ msgstr ""
256msgid "Also installed"
256msgid "Also installed"
257msgstr ""
257msgstr ""
258
258
259−#: qml/DisabledScreenNotice.qml:104
259+#: qml/DisabledScreenNotice.qml:109
260msgid ""
260msgid ""
261"Your device is now connected to an external display. Use this screen as a "
261"Your device is now connected to an external display. Use this screen as a "
262"touch pad to interact with the pointer."
262"touch pad to interact with the pointer."
po/si.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2013-06-26 22:36+0000\n"
11"PO-Revision-Date: 2013-06-26 22:36+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Sinhalese <si@li.org>\n"
13"Language-Team: Sinhalese <si@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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: 2016-05-19 05:50+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -258,7 +258,7 @@ msgstr ""
258msgid "Also installed"
258msgid "Also installed"
259msgstr ""
259msgstr ""
260
260
261−#: qml/DisabledScreenNotice.qml:104
261+#: qml/DisabledScreenNotice.qml:109
262msgid ""
262msgid ""
263"Your device is now connected to an external display. Use this screen as a "
263"Your device is now connected to an external display. Use this screen as a "
264"touch pad to interact with the pointer."
264"touch pad to interact with the pointer."
po/sk.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2016-05-02 10:43+0000\n"
11"PO-Revision-Date: 2016-05-02 10:43+0000\n"
12"Last-Translator: P_E_T_O <Unknown>\n"
12"Last-Translator: P_E_T_O <Unknown>\n"
13"Language-Team: Slovak <sk@li.org>\n"
13"Language-Team: Slovak <sk@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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=3; plural=(n==1) ? 1 : (n>=2 && n<=4) ? 2 : 0;\n"
17"Plural-Forms: nplurals=3; plural=(n==1) ? 1 : (n>=2 && n<=4) ? 2 : 0;\n"
18−"X-Launchpad-Export-Date: 2016-05-19 05:50+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20"Language: sk\n"
20"Language: sk\n"
21
21
22#: plugins/IntegratedLightDM/Greeter.cpp:112
22#: plugins/IntegratedLightDM/Greeter.cpp:112
@@ -265,7 +265,7 @@ msgstr "Domov"
265msgid "Also installed"
265msgid "Also installed"
266msgstr "Tiež nainštalované"
266msgstr "Tiež nainštalované"
267
267
268−#: qml/DisabledScreenNotice.qml:104
268+#: qml/DisabledScreenNotice.qml:109
269msgid ""
269msgid ""
270"Your device is now connected to an external display. Use this screen as a "
270"Your device is now connected to an external display. Use this screen as a "
271"touch pad to interact with the pointer."
271"touch pad to interact with the pointer."
po/sl.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2016-01-31 18:34+0000\n"
11"PO-Revision-Date: 2016-01-31 18:34+0000\n"
12"Last-Translator: Bernard Banko <Unknown>\n"
12"Last-Translator: Bernard Banko <Unknown>\n"
13"Language-Team: Slovenian <sl@li.org>\n"
13"Language-Team: Slovenian <sl@li.org>\n"
@@ -16,8 +16,8 @@ msgstr ""
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=4; plural=(n%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || "
17"Plural-Forms: nplurals=4; plural=(n%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || "
18"n%100==4 ? 3 : 0);\n"
18"n%100==4 ? 3 : 0);\n"
19−"X-Launchpad-Export-Date: 2016-05-19 05:50+0000\n"
19+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
20−"X-Generator: Launchpad (build 18025)\n"
20+"X-Generator: Launchpad (build 18053)\n"
21
21
22#: plugins/IntegratedLightDM/Greeter.cpp:112
22#: plugins/IntegratedLightDM/Greeter.cpp:112
23msgid "Password: "
23msgid "Password: "
@@ -263,7 +263,7 @@ msgstr "Domov"
263msgid "Also installed"
263msgid "Also installed"
264msgstr "Tudi nameščeno"
264msgstr "Tudi nameščeno"
265
265
266−#: qml/DisabledScreenNotice.qml:104
266+#: qml/DisabledScreenNotice.qml:109
267msgid ""
267msgid ""
268"Your device is now connected to an external display. Use this screen as a "
268"Your device is now connected to an external display. Use this screen as a "
269"touch pad to interact with the pointer."
269"touch pad to interact with the pointer."
po/sq.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2016-04-21 06:03+0000\n"
11"PO-Revision-Date: 2016-04-21 06:03+0000\n"
12"Last-Translator: Indrit Bashkimi <indrit.bashkimi@gmail.com>\n"
12"Last-Translator: Indrit Bashkimi <indrit.bashkimi@gmail.com>\n"
13"Language-Team: sq\n"
13"Language-Team: sq\n"
@@ -15,8 +15,8 @@ msgstr ""
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: 2016-05-19 05:49+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:08+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20"Language: sq\n"
20"Language: sq\n"
21
21
22#: plugins/IntegratedLightDM/Greeter.cpp:112
22#: plugins/IntegratedLightDM/Greeter.cpp:112
@@ -257,7 +257,7 @@ msgstr "Shtëpia"
257msgid "Also installed"
257msgid "Also installed"
258msgstr ""
258msgstr ""
259
259
260−#: qml/DisabledScreenNotice.qml:104
260+#: qml/DisabledScreenNotice.qml:109
261msgid ""
261msgid ""
262"Your device is now connected to an external display. Use this screen as a "
262"Your device is now connected to an external display. Use this screen as a "
263"touch pad to interact with the pointer."
263"touch pad to interact with the pointer."
po/sr.po+4−4
@@ -8,7 +8,7 @@ msgid ""
8msgstr ""
8msgstr ""
9"Project-Id-Version: unity\n"
9"Project-Id-Version: unity\n"
10"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
11−"POT-Creation-Date: 2016-05-18 11:19+0000\n"
11+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
12"PO-Revision-Date: 2016-05-04 19:50+0000\n"
12"PO-Revision-Date: 2016-05-04 19:50+0000\n"
13"Last-Translator: Bojan Bogdanović <Unknown>\n"
13"Last-Translator: Bojan Bogdanović <Unknown>\n"
14"Language-Team: српски <xfce4@xfce4.org>\n"
14"Language-Team: српски <xfce4@xfce4.org>\n"
@@ -17,8 +17,8 @@ msgstr ""
17"Content-Transfer-Encoding: 8bit\n"
17"Content-Transfer-Encoding: 8bit\n"
18"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
18"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
19"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
19"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
20−"X-Launchpad-Export-Date: 2016-05-19 05:50+0000\n"
20+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
21−"X-Generator: Launchpad (build 18025)\n"
21+"X-Generator: Launchpad (build 18053)\n"
22"Language: sr\n"
22"Language: sr\n"
23
23
24#: plugins/IntegratedLightDM/Greeter.cpp:112
24#: plugins/IntegratedLightDM/Greeter.cpp:112
@@ -262,7 +262,7 @@ msgstr "Почетна"
262msgid "Also installed"
262msgid "Also installed"
263msgstr "Такође инсталиран"
263msgstr "Такође инсталиран"
264
264
265−#: qml/DisabledScreenNotice.qml:104
265+#: qml/DisabledScreenNotice.qml:109
266msgid ""
266msgid ""
267"Your device is now connected to an external display. Use this screen as a "
267"Your device is now connected to an external display. Use this screen as a "
268"touch pad to interact with the pointer."
268"touch pad to interact with the pointer."
po/sv.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2016-03-25 05:01+0000\n"
11"PO-Revision-Date: 2016-03-25 05:01+0000\n"
12"Last-Translator: Josef Andersson <Unknown>\n"
12"Last-Translator: Josef Andersson <Unknown>\n"
13"Language-Team: Swedish\n"
13"Language-Team: Swedish\n"
@@ -15,8 +15,8 @@ msgstr ""
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: 2016-05-19 05:50+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20"Language: sv\n"
20"Language: sv\n"
21
21
22#: plugins/IntegratedLightDM/Greeter.cpp:112
22#: plugins/IntegratedLightDM/Greeter.cpp:112
@@ -260,7 +260,7 @@ msgstr "Hem"
260msgid "Also installed"
260msgid "Also installed"
261msgstr "Även installerat"
261msgstr "Även installerat"
262
262
263−#: qml/DisabledScreenNotice.qml:104
263+#: qml/DisabledScreenNotice.qml:109
264msgid ""
264msgid ""
265"Your device is now connected to an external display. Use this screen as a "
265"Your device is now connected to an external display. Use this screen as a "
266"touch pad to interact with the pointer."
266"touch pad to interact with the pointer."
po/sw.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2015-07-17 20:02+0000\n"
11"PO-Revision-Date: 2015-07-17 20:02+0000\n"
12"Last-Translator: Valentine <mwangi_valentino@yahoo.com>\n"
12"Last-Translator: Valentine <mwangi_valentino@yahoo.com>\n"
13"Language-Team: Swahili <sw@li.org>\n"
13"Language-Team: Swahili <sw@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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: 2016-05-19 05:50+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -258,7 +258,7 @@ msgstr "Nyumbani"
258msgid "Also installed"
258msgid "Also installed"
259msgstr ""
259msgstr ""
260
260
261−#: qml/DisabledScreenNotice.qml:104
261+#: qml/DisabledScreenNotice.qml:109
262msgid ""
262msgid ""
263"Your device is now connected to an external display. Use this screen as a "
263"Your device is now connected to an external display. Use this screen as a "
264"touch pad to interact with the pointer."
264"touch pad to interact with the pointer."
po/ta.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2013-10-24 11:36+0000\n"
11"PO-Revision-Date: 2013-10-24 11:36+0000\n"
12"Last-Translator: Arun Kumar - அருண் குமார் <thangam.arunx@gmail.com>\n"
12"Last-Translator: Arun Kumar - அருண் குமார் <thangam.arunx@gmail.com>\n"
13"Language-Team: Ubuntu Tamil Team/Free Tamil Computing/Thamizha\n"
13"Language-Team: Ubuntu Tamil Team/Free Tamil Computing/Thamizha\n"
@@ -15,8 +15,8 @@ msgstr ""
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: 2016-05-19 05:50+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20"Language: ta\n"
20"Language: ta\n"
21
21
22#: plugins/IntegratedLightDM/Greeter.cpp:112
22#: plugins/IntegratedLightDM/Greeter.cpp:112
@@ -257,7 +257,7 @@ msgstr ""
257msgid "Also installed"
257msgid "Also installed"
258msgstr ""
258msgstr ""
259
259
260−#: qml/DisabledScreenNotice.qml:104
260+#: qml/DisabledScreenNotice.qml:109
261msgid ""
261msgid ""
262"Your device is now connected to an external display. Use this screen as a "
262"Your device is now connected to an external display. Use this screen as a "
263"touch pad to interact with the pointer."
263"touch pad to interact with the pointer."
po/te.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2014-07-19 10:04+0000\n"
11"PO-Revision-Date: 2014-07-19 10:04+0000\n"
12"Last-Translator: Praveen Illa <mail2ipn@gmail.com>\n"
12"Last-Translator: Praveen Illa <mail2ipn@gmail.com>\n"
13"Language-Team: Telugu <te@li.org>\n"
13"Language-Team: Telugu <te@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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: 2016-05-19 05:50+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -256,7 +256,7 @@ msgstr ""
256msgid "Also installed"
256msgid "Also installed"
257msgstr ""
257msgstr ""
258
258
259−#: qml/DisabledScreenNotice.qml:104
259+#: qml/DisabledScreenNotice.qml:109
260msgid ""
260msgid ""
261"Your device is now connected to an external display. Use this screen as a "
261"Your device is now connected to an external display. Use this screen as a "
262"touch pad to interact with the pointer."
262"touch pad to interact with the pointer."
po/th.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2014-10-02 04:55+0000\n"
11"PO-Revision-Date: 2014-10-02 04:55+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Thai <th@li.org>\n"
13"Language-Team: Thai <th@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2016-05-19 05:50+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -256,7 +256,7 @@ msgstr ""
256msgid "Also installed"
256msgid "Also installed"
257msgstr ""
257msgstr ""
258
258
259−#: qml/DisabledScreenNotice.qml:104
259+#: qml/DisabledScreenNotice.qml:109
260msgid ""
260msgid ""
261"Your device is now connected to an external display. Use this screen as a "
261"Your device is now connected to an external display. Use this screen as a "
262"touch pad to interact with the pointer."
262"touch pad to interact with the pointer."
po/tr.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2015-03-22 15:56+0000\n"
11"PO-Revision-Date: 2015-03-22 15:56+0000\n"
12"Last-Translator: Arda Ünlü <aarda.uunlu@gmail.com>\n"
12"Last-Translator: Arda Ünlü <aarda.uunlu@gmail.com>\n"
13"Language-Team: Turkish <tr@li.org>\n"
13"Language-Team: Turkish <tr@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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: 2016-05-19 05:50+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -256,7 +256,7 @@ msgstr "Ev"
256msgid "Also installed"
256msgid "Also installed"
257msgstr "Ayrıca kurulan"
257msgstr "Ayrıca kurulan"
258
258
259−#: qml/DisabledScreenNotice.qml:104
259+#: qml/DisabledScreenNotice.qml:109
260msgid ""
260msgid ""
261"Your device is now connected to an external display. Use this screen as a "
261"Your device is now connected to an external display. Use this screen as a "
262"touch pad to interact with the pointer."
262"touch pad to interact with the pointer."
po/ug.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2015-12-01 07:37+0000\n"
11"PO-Revision-Date: 2015-12-01 07:37+0000\n"
12"Last-Translator: Eltikin <eltikinuyghur@hotmail.com>\n"
12"Last-Translator: Eltikin <eltikinuyghur@hotmail.com>\n"
13"Language-Team: Uyghur Computer Science Association <UKIJ@yahoogroups.com>\n"
13"Language-Team: Uyghur Computer Science Association <UKIJ@yahoogroups.com>\n"
@@ -15,8 +15,8 @@ msgstr ""
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=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2016-05-19 05:50+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -257,7 +257,7 @@ msgstr "ماكان"
257msgid "Also installed"
257msgid "Also installed"
258msgstr "قايتىدىن ئورنات"
258msgstr "قايتىدىن ئورنات"
259
259
260−#: qml/DisabledScreenNotice.qml:104
260+#: qml/DisabledScreenNotice.qml:109
261msgid ""
261msgid ""
262"Your device is now connected to an external display. Use this screen as a "
262"Your device is now connected to an external display. Use this screen as a "
263"touch pad to interact with the pointer."
263"touch pad to interact with the pointer."
po/uk.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2016-04-01 17:32+0000\n"
11"PO-Revision-Date: 2016-04-01 17:32+0000\n"
12"Last-Translator: Yuri Chornoivan <yurchor@gmail.com>\n"
12"Last-Translator: Yuri Chornoivan <yurchor@gmail.com>\n"
13"Language-Team: Ukrainian <uk@li.org>\n"
13"Language-Team: Ukrainian <uk@li.org>\n"
@@ -16,8 +16,8 @@ msgstr ""
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
17"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
18"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
18"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
19−"X-Launchpad-Export-Date: 2016-05-19 05:50+0000\n"
19+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
20−"X-Generator: Launchpad (build 18025)\n"
20+"X-Generator: Launchpad (build 18053)\n"
21
21
22#: plugins/IntegratedLightDM/Greeter.cpp:112
22#: plugins/IntegratedLightDM/Greeter.cpp:112
23msgid "Password: "
23msgid "Password: "
@@ -266,7 +266,7 @@ msgstr "Домівка"
266msgid "Also installed"
266msgid "Also installed"
267msgstr "Також встановлено"
267msgstr "Також встановлено"
268
268
269−#: qml/DisabledScreenNotice.qml:104
269+#: qml/DisabledScreenNotice.qml:109
270msgid ""
270msgid ""
271"Your device is now connected to an external display. Use this screen as a "
271"Your device is now connected to an external display. Use this screen as a "
272"touch pad to interact with the pointer."
272"touch pad to interact with the pointer."
po/unity8.pot+23−23
@@ -8,7 +8,7 @@ msgid ""
8msgstr ""
8msgstr ""
9"Project-Id-Version: unity8\n"
9"Project-Id-Version: unity8\n"
10"Report-Msgid-Bugs-To: \n"
10"Report-Msgid-Bugs-To: \n"
11−"POT-Creation-Date: 2016-05-18 11:19+0000\n"
11+"POT-Creation-Date: 2016-05-27 13:54+0000\n"
12"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
12"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14"Language-Team: LANGUAGE <LL@li.org>\n"
14"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -74,7 +74,7 @@ msgid "Log Out"
74msgstr ""
74msgstr ""
75
75
76#: qml/Components/Dialogs.qml:161 qml/Components/Dialogs.qml:217
76#: qml/Components/Dialogs.qml:161 qml/Components/Dialogs.qml:217
77−#: qml/Dash/DashPageHeader.qml:298 qml/Wizard/Pages/passcode-confirm.qml:32
77+#: qml/Dash/DashPageHeader.qml:295 qml/Wizard/Pages/passcode-confirm.qml:32
78#: qml/Wizard/Pages/passcode-set.qml:32
78#: qml/Wizard/Pages/passcode-set.qml:32
79msgid "Cancel"
79msgid "Cancel"
80msgstr ""
80msgstr ""
@@ -155,26 +155,26 @@ msgstr ""
155msgid "Close all"
155msgid "Close all"
156msgstr ""
156msgstr ""
157
157
158−#: qml/Dash/DashPageHeader.qml:337
158+#: qml/Dash/DashPageHeader.qml:333
159msgctxt "Button: Open the Ubuntu Store"
159msgctxt "Button: Open the Ubuntu Store"
160msgid "Store"
160msgid "Store"
161msgstr ""
161msgstr ""
162
162
163−#: qml/Dash/DashPageHeader.qml:344
163+#: qml/Dash/DashPageHeader.qml:340
164msgctxt "Button: Start a search in the current dash scope"
164msgctxt "Button: Start a search in the current dash scope"
165msgid "Search"
165msgid "Search"
166msgstr ""
166msgstr ""
167
167
168−#: qml/Dash/DashPageHeader.qml:354
168+#: qml/Dash/DashPageHeader.qml:350
169msgctxt "Button: Show the current dash scope settings"
169msgctxt "Button: Show the current dash scope settings"
170msgid "Settings"
170msgid "Settings"
171msgstr ""
171msgstr ""
172
172
173−#: qml/Dash/DashPageHeader.qml:361
173+#: qml/Dash/DashPageHeader.qml:357
174msgid "Remove from Favorites"
174msgid "Remove from Favorites"
175msgstr ""
175msgstr ""
176
176
177−#: qml/Dash/DashPageHeader.qml:361
177+#: qml/Dash/DashPageHeader.qml:357
178msgid "Add to Favorites"
178msgid "Add to Favorites"
179msgstr ""
179msgstr ""
180
180
@@ -186,7 +186,7 @@ msgstr ""
186msgid "Reset"
186msgid "Reset"
187msgstr ""
187msgstr ""
188
188
189−#: qml/Dash/GenericScopeView.qml:579 qml/Dash/GenericScopeView.qml:764
189+#: qml/Dash/GenericScopeView.qml:579 qml/Dash/GenericScopeView.qml:774
190msgid "Show less"
190msgid "Show less"
191msgstr ""
191msgstr ""
192
192
@@ -199,11 +199,11 @@ msgctxt "Label: Hint for dash search line edit"
199msgid "Search"
199msgid "Search"
200msgstr ""
200msgstr ""
201
201
202−#: qml/Dash/PageHeaderExtraPanel.qml:55
202+#: qml/Dash/PageHeaderExtraPanel.qml:56
203msgid "Recent Searches"
203msgid "Recent Searches"
204msgstr ""
204msgstr ""
205
205
206−#: qml/Dash/PageHeaderExtraPanel.qml:66
206+#: qml/Dash/PageHeaderExtraPanel.qml:67
207msgid "Clear All"
207msgid "Clear All"
208msgstr ""
208msgstr ""
209
209
@@ -216,15 +216,15 @@ msgid "Less..."
216msgstr ""
216msgstr ""
217
217
218#: qml/Dash/Previews/PreviewCommentInput.qml:68
218#: qml/Dash/Previews/PreviewCommentInput.qml:68
219−#: qml/Dash/Previews/PreviewRatingInput.qml:174
219+#: qml/Dash/Previews/PreviewRatingInput.qml:175
220msgid "Send"
220msgid "Send"
221msgstr ""
221msgstr ""
222
222
223−#: qml/Dash/Previews/PreviewRatingInput.qml:84
223+#: qml/Dash/Previews/PreviewRatingInput.qml:82
224msgid "Rate this"
224msgid "Rate this"
225msgstr ""
225msgstr ""
226
226
227−#: qml/Dash/Previews/PreviewRatingInput.qml:129
227+#: qml/Dash/Previews/PreviewRatingInput.qml:157
228msgid "Add a review"
228msgid "Add a review"
229msgstr ""
229msgstr ""
230
230
@@ -244,19 +244,19 @@ msgstr ""
244msgid "Enable location data"
244msgid "Enable location data"
245msgstr ""
245msgstr ""
246
246
247−#: qml/Dash/ScopesList.qml:67
247+#: qml/Dash/ScopesList.qml:55
248msgid "Manage"
248msgid "Manage"
249msgstr ""
249msgstr ""
250
250
251−#: qml/Dash/ScopesList.qml:113
251+#: qml/Dash/ScopesList.qml:101
252msgid "Home"
252msgid "Home"
253msgstr ""
253msgstr ""
254
254
255−#: qml/Dash/ScopesList.qml:114
255+#: qml/Dash/ScopesList.qml:102
256msgid "Also installed"
256msgid "Also installed"
257msgstr ""
257msgstr ""
258
258
259−#: qml/DisabledScreenNotice.qml:104
259+#: qml/DisabledScreenNotice.qml:109
260msgid ""
260msgid ""
261"Your device is now connected to an external display. Use this screen as a "
261"Your device is now connected to an external display. Use this screen as a "
262"touch pad to interact with the pointer."
262"touch pad to interact with the pointer."
@@ -400,18 +400,18 @@ msgstr ""
400msgid "Failed, tap to retry"
400msgid "Failed, tap to retry"
401msgstr ""
401msgstr ""
402
402
403−#: qml/Panel/Indicators/MessageMenuItemFactory.qml:155
403+#: qml/Panel/Indicators/MessageMenuItemFactory.qml:151
404−#: qml/Panel/Indicators/MessageMenuItemFactory.qml:214
404+#: qml/Panel/Indicators/MessageMenuItemFactory.qml:210
405msgctxt "Button: Send a reply message"
405msgctxt "Button: Send a reply message"
406msgid "Send"
406msgid "Send"
407msgstr ""
407msgstr ""
408
408
409−#: qml/Panel/Indicators/MessageMenuItemFactory.qml:156
409+#: qml/Panel/Indicators/MessageMenuItemFactory.qml:152
410msgctxt "Label: Hint in message indicator line edit"
410msgctxt "Label: Hint in message indicator line edit"
411msgid "Reply"
411msgid "Reply"
412msgstr ""
412msgstr ""
413
413
414−#: qml/Panel/Indicators/MessageMenuItemFactory.qml:213
414+#: qml/Panel/Indicators/MessageMenuItemFactory.qml:209
415msgctxt "Button: Call back on phone"
415msgctxt "Button: Call back on phone"
416msgid "Call back"
416msgid "Call back"
417msgstr ""
417msgstr ""
@@ -474,7 +474,7 @@ msgid "Language"
474msgstr ""
474msgstr ""
475
475
476#: qml/Wizard/Pages/10-welcome.qml:156 qml/Wizard/Pages/30-wifi.qml:206
476#: qml/Wizard/Pages/10-welcome.qml:156 qml/Wizard/Pages/30-wifi.qml:206
477−#: qml/Wizard/Pages/40-location.qml:271 qml/Wizard/Pages/50-timezone.qml:267
477+#: qml/Wizard/Pages/40-location.qml:271 qml/Wizard/Pages/50-timezone.qml:270
478#: qml/Wizard/Pages/60-account.qml:65 qml/Wizard/Pages/70-passwd-type.qml:144
478#: qml/Wizard/Pages/60-account.qml:65 qml/Wizard/Pages/70-passwd-type.qml:144
479#: qml/Wizard/Pages/75-report-check.qml:84
479#: qml/Wizard/Pages/75-report-check.qml:84
480#: qml/Wizard/Pages/passcode-desktop.qml:124
480#: qml/Wizard/Pages/passcode-desktop.qml:124
@@ -539,7 +539,7 @@ msgstr ""
539msgid "Time Zone"
539msgid "Time Zone"
540msgstr ""
540msgstr ""
541
541
542−#: qml/Wizard/Pages/50-timezone.qml:178
542+#: qml/Wizard/Pages/50-timezone.qml:181
543msgid "Enter your city"
543msgid "Enter your city"
544msgstr ""
544msgstr ""
545
545
po/ur.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2015-05-05 03:12+0000\n"
11"PO-Revision-Date: 2015-05-05 03:12+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Urdu <ur@li.org>\n"
13"Language-Team: Urdu <ur@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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: 2016-05-19 05:50+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -256,7 +256,7 @@ msgstr ""
256msgid "Also installed"
256msgid "Also installed"
257msgstr ""
257msgstr ""
258
258
259−#: qml/DisabledScreenNotice.qml:104
259+#: qml/DisabledScreenNotice.qml:109
260msgid ""
260msgid ""
261"Your device is now connected to an external display. Use this screen as a "
261"Your device is now connected to an external display. Use this screen as a "
262"touch pad to interact with the pointer."
262"touch pad to interact with the pointer."
po/uz.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2015-07-04 16:03+0000\n"
11"PO-Revision-Date: 2015-07-04 16:03+0000\n"
12"Last-Translator: Learner <muzaffar.habibullayev@yandex.ru>\n"
12"Last-Translator: Learner <muzaffar.habibullayev@yandex.ru>\n"
13"Language-Team: Uzbek <uz@li.org>\n"
13"Language-Team: Uzbek <uz@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2016-05-19 05:50+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -256,7 +256,7 @@ msgstr ""
256msgid "Also installed"
256msgid "Also installed"
257msgstr ""
257msgstr ""
258
258
259−#: qml/DisabledScreenNotice.qml:104
259+#: qml/DisabledScreenNotice.qml:109
260msgid ""
260msgid ""
261"Your device is now connected to an external display. Use this screen as a "
261"Your device is now connected to an external display. Use this screen as a "
262"touch pad to interact with the pointer."
262"touch pad to interact with the pointer."
po/vi.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2014-01-15 01:19+0000\n"
11"PO-Revision-Date: 2014-01-15 01:19+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Vietnamese <vi@li.org>\n"
13"Language-Team: Vietnamese <vi@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2016-05-19 05:50+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -256,7 +256,7 @@ msgstr ""
256msgid "Also installed"
256msgid "Also installed"
257msgstr ""
257msgstr ""
258
258
259−#: qml/DisabledScreenNotice.qml:104
259+#: qml/DisabledScreenNotice.qml:109
260msgid ""
260msgid ""
261"Your device is now connected to an external display. Use this screen as a "
261"Your device is now connected to an external display. Use this screen as a "
262"touch pad to interact with the pointer."
262"touch pad to interact with the pointer."
po/wo.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2015-10-29 11:16+0000\n"
11"PO-Revision-Date: 2015-10-29 11:16+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Wolof <wo@li.org>\n"
13"Language-Team: Wolof <wo@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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: 2016-05-19 05:50+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -256,7 +256,7 @@ msgstr "Njëlbeen"
256msgid "Also installed"
256msgid "Also installed"
257msgstr "Yiñ samp tamit"
257msgstr "Yiñ samp tamit"
258
258
259−#: qml/DisabledScreenNotice.qml:104
259+#: qml/DisabledScreenNotice.qml:109
260msgid ""
260msgid ""
261"Your device is now connected to an external display. Use this screen as a "
261"Your device is now connected to an external display. Use this screen as a "
262"touch pad to interact with the pointer."
262"touch pad to interact with the pointer."
po/xh.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2013-09-28 13:20+0000\n"
11"PO-Revision-Date: 2013-09-28 13:20+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Xhosa <xh@li.org>\n"
13"Language-Team: Xhosa <xh@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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: 2016-05-19 05:50+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -256,7 +256,7 @@ msgstr ""
256msgid "Also installed"
256msgid "Also installed"
257msgstr ""
257msgstr ""
258
258
259−#: qml/DisabledScreenNotice.qml:104
259+#: qml/DisabledScreenNotice.qml:109
260msgid ""
260msgid ""
261"Your device is now connected to an external display. Use this screen as a "
261"Your device is now connected to an external display. Use this screen as a "
262"touch pad to interact with the pointer."
262"touch pad to interact with the pointer."
po/zh_CN.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2016-04-13 06:27+0000\n"
11"PO-Revision-Date: 2016-04-13 06:27+0000\n"
12"Last-Translator: YunQiang Su <wzssyqa@gmail.com>\n"
12"Last-Translator: YunQiang Su <wzssyqa@gmail.com>\n"
13"Language-Team: Chinese (Simplified) <zh_CN@li.org>\n"
13"Language-Team: Chinese (Simplified) <zh_CN@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2016-05-19 05:50+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -257,7 +257,7 @@ msgstr "首页"
257msgid "Also installed"
257msgid "Also installed"
258msgstr "已安装"
258msgstr "已安装"
259
259
260−#: qml/DisabledScreenNotice.qml:104
260+#: qml/DisabledScreenNotice.qml:109
261msgid ""
261msgid ""
262"Your device is now connected to an external display. Use this screen as a "
262"Your device is now connected to an external display. Use this screen as a "
263"touch pad to interact with the pointer."
263"touch pad to interact with the pointer."
po/zh_HK.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2014-08-10 11:45+0000\n"
11"PO-Revision-Date: 2014-08-10 11:45+0000\n"
12"Last-Translator: Daniel Cheung <daniel.2345@hotmail.com>\n"
12"Last-Translator: Daniel Cheung <daniel.2345@hotmail.com>\n"
13"Language-Team: Chinese (Hong Kong) <zh_HK@li.org>\n"
13"Language-Team: Chinese (Hong Kong) <zh_HK@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2016-05-19 05:50+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20
20
21#: plugins/IntegratedLightDM/Greeter.cpp:112
21#: plugins/IntegratedLightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
@@ -256,7 +256,7 @@ msgstr ""
256msgid "Also installed"
256msgid "Also installed"
257msgstr ""
257msgstr ""
258
258
259−#: qml/DisabledScreenNotice.qml:104
259+#: qml/DisabledScreenNotice.qml:109
260msgid ""
260msgid ""
261"Your device is now connected to an external display. Use this screen as a "
261"Your device is now connected to an external display. Use this screen as a "
262"touch pad to interact with the pointer."
262"touch pad to interact with the pointer."
po/zh_TW.po+4−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
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: 2016-05-18 11:19+0000\n"
10+"POT-Creation-Date: 2016-05-20 08:44+0000\n"
11"PO-Revision-Date: 2016-02-24 04:40+0000\n"
11"PO-Revision-Date: 2016-02-24 04:40+0000\n"
12"Last-Translator: Po-Hsu Lin <po-hsu.lin@canonical.com>\n"
12"Last-Translator: Po-Hsu Lin <po-hsu.lin@canonical.com>\n"
13"Language-Team: Chinese (Traditional) <zh_TW@li.org>\n"
13"Language-Team: Chinese (Traditional) <zh_TW@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
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=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2016-05-19 05:50+0000\n"
18+"X-Launchpad-Export-Date: 2016-05-25 06:09+0000\n"
19−"X-Generator: Launchpad (build 18025)\n"
19+"X-Generator: Launchpad (build 18053)\n"
20"Language: zh_TW\n"
20"Language: zh_TW\n"
21
21
22#: plugins/IntegratedLightDM/Greeter.cpp:112
22#: plugins/IntegratedLightDM/Greeter.cpp:112
@@ -256,7 +256,7 @@ msgstr "家屋"
256msgid "Also installed"
256msgid "Also installed"
257msgstr "也有安裝"
257msgstr "也有安裝"
258
258
259−#: qml/DisabledScreenNotice.qml:104
259+#: qml/DisabledScreenNotice.qml:109
260msgid ""
260msgid ""
261"Your device is now connected to an external display. Use this screen as a "
261"Your device is now connected to an external display. Use this screen as a "
262"touch pad to interact with the pointer."
262"touch pad to interact with the pointer."
qml/Components/Dialogs.qml+2−2
@@ -185,7 +185,7 @@ Item {
185 unitySessionService.reboot();
185 unitySessionService.reboot();
186 rebootDialog.hide();
186 rebootDialog.hide();
187 }
187 }
188− color: UbuntuColors.red
188+ color: theme.palette.normal.negative
189 }
189 }
190 }
190 }
191 }
191 }
@@ -203,7 +203,7 @@ Item {
203 powerDialog.hide();
203 powerDialog.hide();
204 root.powerOffClicked();
204 root.powerOffClicked();
205 }
205 }
206− color: UbuntuColors.red
206+ color: theme.palette.normal.negative
207 }
207 }
208 Button {
208 Button {
209 text: i18n.ctr("Button: Restart the system", "Restart")
209 text: i18n.ctr("Button: Restart the system", "Restart")
qml/Components/DragHandle.qml+43−25
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2013 Canonical, Ltd.
2+ * Copyright (C) 2013,2016 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
@@ -38,12 +38,12 @@ import Ubuntu.Gestures 0.1
38 anchors.bottom: parent.bottom
38 anchors.bottom: parent.bottom
39 width: units.gu(2)
39 width: units.gu(2)
40
40
41− direction: DirectionalDragArea::Leftwards
41+ direction: SwipeArea::Leftwards
42 }
42 }
43 }
43 }
44
44
45 */
45 */
46−DirectionalDragArea {
46+SwipeArea {
47 id: dragArea
47 id: dragArea
48
48
49 property bool stretch: false
49 property bool stretch: false
@@ -70,15 +70,16 @@ DirectionalDragArea {
70 property: "targetValue"
70 property: "targetValue"
71 duration: 150
71 duration: 150
72 velocity: -1
72 velocity: -1
73+
73− to: Direction.isPositive(direction) ? d.startValue + hintDisplacement
74+ to: d.incrementTargetProp ? d.startValue + hintDisplacement
74− : d.startValue - hintDisplacement
75+ : d.startValue - hintDisplacement
75 property real targetValue
76 property real targetValue
76 onTargetValueChanged: {
77 onTargetValueChanged: {
77 if (!running) {
78 if (!running) {
78 return;
79 return;
79 }
80 }
80
81
81− if (Direction.isPositive(direction)) {
82+ if (d.incrementTargetProp) {
82 if (parent[d.targetProp] < targetValue) {
83 if (parent[d.targetProp] < targetValue) {
83 parent[d.targetProp] = targetValue;
84 parent[d.targetProp] = targetValue;
84 }
85 }
@@ -93,19 +94,24 @@ DirectionalDragArea {
93 // Private stuff
94 // Private stuff
94 QtObject {
95 QtObject {
95 id: d
96 id: d
97+
98+ // Whether movement along the designated direction will increment the value of the target property
99+ readonly property bool incrementTargetProp: (Direction.isPositive(direction) && !dragArea.stretch)
100+ || (dragArea.stretch && !d.dragParent.shown)
101+
96 property real startValue
102 property real startValue
97 property real minValue: {
103 property real minValue: {
98 if (direction == Direction.Horizontal) {
104 if (direction == Direction.Horizontal) {
99 return startValue - maxTotalDragDistance;
105 return startValue - maxTotalDragDistance;
100− } else if (Direction.isPositive(direction)) {
106+ } else if (incrementTargetProp) {
101 return startValue;
107 return startValue;
102 } else {
108 } else {
103 return startValue - maxTotalDragDistance;
109 return startValue - maxTotalDragDistance;
104 }
110 }
105 }
111 }
106
112
107− property real maxValue: Direction.isPositive(direction) ? startValue + maxTotalDragDistance
113+ property real maxValue: incrementTargetProp ? startValue + maxTotalDragDistance
108− : startValue
114+ : startValue;
109
115
110 property var dragParent: dragArea.parent
116 property var dragParent: dragArea.parent
111
117
@@ -118,26 +124,26 @@ DirectionalDragArea {
118 }
124 }
119 }
125 }
120
126
121− function limitMovement(inputStep) {
127+ function limitMovement(distance) {
122− var targetValue = MathUtils.clamp(dragParent[targetProp] + inputStep, minValue, maxValue);
128+ var targetValue = MathUtils.clamp(d.startValue + distance, minValue, maxValue);
123− var step = targetValue - dragParent[targetProp];
129+ var diff = targetValue - d.startValue;
124
130
125 if (hintDisplacement == 0) {
131 if (hintDisplacement == 0) {
126− return step;
132+ return diff;
127 }
133 }
128
134
129 // we should not go behind hintingAnimation's current value
135 // we should not go behind hintingAnimation's current value
130− if (Direction.isPositive(direction)) {
136+ if (d.incrementTargetProp) {
131− if (dragParent[targetProp] + step < hintingAnimation.targetValue) {
137+ if (d.startValue + diff < hintingAnimation.targetValue) {
132− step = hintingAnimation.targetValue - dragParent[targetProp];
138+ diff = hintingAnimation.targetValue - d.startValue;
133 }
139 }
134 } else {
140 } else {
135− if (dragParent[targetProp] + step > hintingAnimation.targetValue) {
141+ if (d.startValue + diff > hintingAnimation.targetValue) {
136− step = hintingAnimation.targetValue - dragParent[targetProp];
142+ diff = hintingAnimation.targetValue - d.startValue;
137 }
143 }
138 }
144 }
139
145
140− return step;
146+ return diff;
141 }
147 }
142
148
143 function onFinishedRecognizedGesture() {
149 function onFinishedRecognizedGesture() {
@@ -171,19 +177,31 @@ DirectionalDragArea {
171 objectName: "edgeDragEvaluator"
177 objectName: "edgeDragEvaluator"
172 id: dragEvaluator
178 id: dragEvaluator
173 // Effectively convert distance into the drag position projected onto the gesture direction axis
179 // Effectively convert distance into the drag position projected onto the gesture direction axis
174− trackedPosition: Direction.isPositive(dragArea.direction) ? sceneDistance : -sceneDistance
180+ trackedPosition: Direction.isPositive(dragArea.direction) ? distance : -distance
175 maxDragDistance: maxTotalDragDistance
181 maxDragDistance: maxTotalDragDistance
176 direction: dragArea.direction
182 direction: dragArea.direction
177 }
183 }
178
184
179 onDistanceChanged: {
185 onDistanceChanged: {
180 if (dragging) {
186 if (dragging) {
181− // don't go the whole distance in order to smooth out the movement
187+ if (!Direction.isPositive(direction))
188+ distance = -distance;
189+
190+ if (dragArea.stretch &&
191+ ((!Direction.isPositive(direction) && !d.dragParent.shown)
192+ ||
193+ (Direction.isPositive(direction) && d.dragParent.shown))
194+ )
195+ {
196+ // This happens when you have a stretching showable being shown from the right or
197+ // top edge (and consequently being hidden when dragged towards the right/top edge)
198+ // In those situations, dimension expansion/retraction happens in the opposite
199+ // sign of the axis direction
182− var step = distance * 0.3;
200+ distance = -distance;
183−
201+ }
184− step = d.limitMovement(step);
185
202
203+ var toAdd = d.limitMovement(distance);
186− parent[d.targetProp] += step;
204+ parent[d.targetProp] = d.startValue + toAdd;
187 }
205 }
188 }
206 }
189
207
qml/Components/FloatingFlickable.qmlnew file+59
@@ -0,0 +1,59 @@
1+/*
2+ * Copyright (C) 2015-2016 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.4
18+import Ubuntu.Components 1.3
19+import Ubuntu.Gestures 0.1
20+
21+/*
22+ A Flickable that can be put in front of the item to be flicked and
23+ still have the item-to-be-flicked receive input events that are not flicks.
24+
25+ Ie, it's a Flickable that, input-wise, is transparent to non-flick gestures.
26+
27+ With a regular Flickable you would have to make the item-to-be-flicked a child
28+ of Flicakble to achieve the same result. FloatingFlickable has no such requirement
29+ or limitation.
30+ */
31+Item {
32+ property alias contentWidth: flickable.contentWidth
33+ property alias contentHeight: flickable.contentHeight
34+ property alias contentX: flickable.contentX
35+ property alias contentY: flickable.contentY
36+ property alias direction: swipeArea.direction
37+
38+ MouseEventGenerator {
39+ id: mouseEventGenerator
40+ targetItem: flickable
41+ }
42+
43+ Flickable {
44+ id: flickable
45+ enabled: false
46+ anchors.fill: parent
47+ flickableDirection: Direction.isHorizontal(swipeArea.direction) ? Flickable.HorizontalFlick : Flickable.VerticalFlick
48+ }
49+
50+ SwipeArea {
51+ id: swipeArea
52+ anchors.fill: parent
53+ direction: Direction.Horizontal
54+
55+ onTouchPositionChanged: mouseEventGenerator.move(touchPosition);
56+ onDraggingChanged: dragging ? mouseEventGenerator.press(touchPosition)
57+ : mouseEventGenerator.release(touchPosition)
58+ }
59+}
qml/Components/Header.qmldeleted−28
@@ -1,28 +0,0 @@
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 Ubuntu.Components 1.3
18−import Ubuntu.Components.Themes.Ambiance 1.3
19−
20−PageHeadStyle {
21− // FIXME: Don't use this but PageHeader from Ubuntu.Components 1.3.
22− id: root
23−
24− property var styledItem: root
25− property string title
26− property var config: PageHeadConfiguration {}
27− property var contents: null
28−}
qml/Components/InputMethod.qml+2−2
@@ -30,8 +30,8 @@ Item {
30
30
31 consumesInput: true
31 consumesInput: true
32
32
33− surfaceWidth: width
33+ surfaceWidth: root.enabled ? width : -1
34− surfaceHeight: height
34+ surfaceHeight: root.enabled ? height : -1
35 surface: SurfaceManager.inputMethodSurface
35 surface: SurfaceManager.inputMethodSurface
36
36
37 onLiveChanged: {
37 onLiveChanged: {
qml/Components/ModeSwitchWarningDialog.qml+1−1
@@ -86,7 +86,7 @@ ShellDialog {
86 Button {
86 Button {
87 objectName: "forceCloseButton"
87 objectName: "forceCloseButton"
88 text: i18n.tr("Close all")
88 text: i18n.tr("Close all")
89− color: UbuntuColors.red
89+ color: theme.palette.normal.negative
90 onClicked: {
90 onClicked: {
91 root.forceClose();
91 root.forceClose();
92 }
92 }
qml/Components/PanelState/PanelState.qml+3−3
@@ -26,8 +26,8 @@ QtObject {
26 property bool dropShadow: false
26 property bool dropShadow: false
27 property int panelHeight: 0
27 property int panelHeight: 0
28
28
29− signal close()
29+ signal closeClicked()
30− signal minimize()
30+ signal minimizeClicked()
31− signal maximize()
31+ signal restoreClicked()
32 signal focusMaximizedApp()
32 signal focusMaximizedApp()
33}
33}
qml/Components/Rating.qml+1
@@ -21,6 +21,7 @@ import Ubuntu.Components 1.3
21
21
22StyledItem {
22StyledItem {
23 id: root
23 id: root
24+ implicitHeight: units.gu(2)
24
25
25 //! True if it accepts user input.
26 //! True if it accepts user input.
26 property bool interactive: true
27 property bool interactive: true
qml/Components/RatingStyle.qml+3
@@ -36,6 +36,9 @@ Row {
36 property url urlIconHalf: styledItem.urlIconHalf || "graphics/icon_star_half.png"
36 property url urlIconHalf: styledItem.urlIconHalf || "graphics/icon_star_half.png"
37
37
38 Image {
38 Image {
39+ height: parent.height
40+ fillMode: Image.PreserveAspectFit
41+ sourceSize.height: height
39 opacity: styledItem.value < 0 ? 0.4 : 1 // Let's make the stars look inactive for a not-set value
42 opacity: styledItem.value < 0 ? 0.4 : 1 // Let's make the stars look inactive for a not-set value
40 source: {
43 source: {
41 if (index === repeater.indexHalfValue) return repeater.urlIconHalf;
44 if (index === repeater.indexHalfValue) return repeater.urlIconHalf;
qml/Components/WindowControlButtons.qml+18−7
@@ -25,9 +25,11 @@ Row {
25 property bool active: false
25 property bool active: false
26 property bool closeButtonShown: true
26 property bool closeButtonShown: true
27
27
28− signal close()
28+ signal closeClicked()
29− signal minimize()
29+ signal minimizeClicked()
30− signal maximize()
30+ signal maximizeClicked()
31+ signal maximizeVerticallyClicked()
32+ signal maximizeHorizontallyClicked()
31
33
32 MouseArea {
34 MouseArea {
33 id: closeWindowButton
35 id: closeWindowButton
@@ -35,7 +37,7 @@ Row {
35 hoverEnabled: true
37 hoverEnabled: true
36 height: parent.height
38 height: parent.height
37 width: height
39 width: height
38− onClicked: root.close()
40+ onClicked: root.closeClicked()
39 visible: root.closeButtonShown
41 visible: root.closeButtonShown
40
42
41 Rectangle {
43 Rectangle {
@@ -43,7 +45,7 @@ Row {
43 width: units.gu(2)
45 width: units.gu(2)
44 height: units.gu(2)
46 height: units.gu(2)
45 radius: height / 2
47 radius: height / 2
46− color: UbuntuColors.red
48+ color: theme.palette.normal.negative
47 visible: parent.containsMouse
49 visible: parent.containsMouse
48 }
50 }
49 Icon {
51 Icon {
@@ -62,7 +64,7 @@ Row {
62 hoverEnabled: true
64 hoverEnabled: true
63 height: parent.height
65 height: parent.height
64 width: height
66 width: height
65− onClicked: root.minimize()
67+ onClicked: root.minimizeClicked()
66
68
67 Rectangle {
69 Rectangle {
68 anchors.centerIn: parent
70 anchors.centerIn: parent
@@ -88,7 +90,16 @@ Row {
88 hoverEnabled: true
90 hoverEnabled: true
89 height: parent.height
91 height: parent.height
90 width: height
92 width: height
93+ acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
91− onClicked: root.maximize()
94+ onClicked: {
95+ if (mouse.button == Qt.LeftButton) {
96+ root.maximizeClicked();
97+ } else if (mouse.button == Qt.RightButton) {
98+ root.maximizeHorizontallyClicked();
99+ } else if (mouse.button == Qt.MiddleButton) {
100+ root.maximizeVerticallyClicked();
101+ }
102+ }
92
103
93 Rectangle {
104 Rectangle {
94 anchors.centerIn: parent
105 anchors.centerIn: parent
qml/Dash/CardCarousel.qml−1
@@ -66,7 +66,6 @@ DashRenderer {
66 item.cardData = Qt.binding(function() { return model; });
66 item.cardData = Qt.binding(function() { return model; });
67 item.fontScale = Qt.binding(function() { return carousel.fontScale; });
67 item.fontScale = Qt.binding(function() { return carousel.fontScale; });
68 item.showHeader = Qt.binding(function() { return loader.explicitlyScaled; });
68 item.showHeader = Qt.binding(function() { return loader.explicitlyScaled; });
69− item.artShapeStyle = "shadow";
70 item.scopeStyle = cardCarousel.scopeStyle;
69 item.scopeStyle = cardCarousel.scopeStyle;
71 }
70 }
72 }
71 }
qml/Dash/CardGrid.qml−2
@@ -25,7 +25,6 @@ DashRenderer {
25 if (!cardTool || !cardTool.template || typeof cardTool.template["collapsed-rows"] != "number") return 2;
25 if (!cardTool || !cardTool.template || typeof cardTool.template["collapsed-rows"] != "number") return 2;
26 return cardTool.template["collapsed-rows"];
26 return cardTool.template["collapsed-rows"];
27 }
27 }
28− property string artShapeStyle: "inset";
29 property string backgroundShapeStyle: "inset";
28 property string backgroundShapeStyle: "inset";
30 property alias minimumHorizontalSpacing: grid.minimumHorizontalSpacing
29 property alias minimumHorizontalSpacing: grid.minimumHorizontalSpacing
31
30
@@ -71,7 +70,6 @@ DashRenderer {
71 item.fixedArtShapeSize = Qt.binding(function() { return cardTool.artShapeSize; });
70 item.fixedArtShapeSize = Qt.binding(function() { return cardTool.artShapeSize; });
72 item.cardData = Qt.binding(function() { return model; });
71 item.cardData = Qt.binding(function() { return model; });
73 item.scopeStyle = root.scopeStyle;
72 item.scopeStyle = root.scopeStyle;
74− item.artShapeStyle = root.artShapeStyle;
75 item.backgroundShapeStyle = root.backgroundShapeStyle;
73 item.backgroundShapeStyle = root.backgroundShapeStyle;
76 }
74 }
77 Connections {
75 Connections {
qml/Dash/CardTool.qml+6−2
@@ -66,7 +66,11 @@ Item {
66 return layout;
66 return layout;
67 }
67 }
68
68
69+
70+ // Not readonly because gets overwritten from GenericScopeView in some cases
71+ property string artShapeStyle: categoryLayout === "carousel" ? "shadow" : "inset"
72+
69− property var cardComponent: CardCreatorCache.getCardComponent(cardTool.template, cardTool.components, false);
73+ property var cardComponent: CardCreatorCache.getCardComponent(cardTool.template, cardTool.components, false, artShapeStyle);
70
74
71 // FIXME: Saviq
75 // FIXME: Saviq
72 // Only way for the card below to actually be laid out completely.
76 // Only way for the card below to actually be laid out completely.
@@ -208,7 +212,7 @@ Item {
208 "attributes": attributesModel.model,
212 "attributes": attributesModel.model,
209 "socialActions": socialActionsModel.model
213 "socialActions": socialActionsModel.model
210 }
214 }
211− sourceComponent: CardCreatorCache.getCardComponent(cardTool.template, cardTool.components, true);
215+ sourceComponent: CardCreatorCache.getCardComponent(cardTool.template, cardTool.components, true, artShapeStyle);
212 onLoaded: {
216 onLoaded: {
213 item.objectName = "cardToolCard";
217 item.objectName = "cardToolCard";
214 item.width = Qt.binding(function() { return cardTool.cardWidth !== -1 ? cardTool.cardWidth : item.implicitWidth; });
218 item.width = Qt.binding(function() { return cardTool.cardWidth !== -1 ? cardTool.cardWidth : item.implicitWidth; });
qml/Dash/Dash.qml+3−3
@@ -349,7 +349,7 @@ Showable {
349 }
349 }
350 }
350 }
351
351
352− DirectionalDragArea {
352+ SwipeArea {
353 id: overviewDragHandle
353 id: overviewDragHandle
354 objectName: "overviewDragHandle"
354 objectName: "overviewDragHandle"
355 z: 1
355 z: 1
@@ -364,10 +364,10 @@ Showable {
364 anchors { left: parent.left; right: parent.right; bottom: parent.bottom }
364 anchors { left: parent.left; right: parent.right; bottom: parent.bottom }
365 height: units.gu(2)
365 height: units.gu(2)
366
366
367− onSceneDistanceChanged: {
367+ onDistanceChanged: {
368 if (dragging) {
368 if (dragging) {
369 bottomEdgeController.enableAnimation = false;
369 bottomEdgeController.enableAnimation = false;
370− bottomEdgeController.progress = Math.max(0, Math.min(1, sceneDistance / fullMovement));
370+ bottomEdgeController.progress = Math.max(0, Math.min(1, distance / fullMovement));
371 }
371 }
372 }
372 }
373
373
qml/Dash/DashApplication.qml−3
@@ -22,9 +22,6 @@ MainView {
22 implicitWidth: units.gu(40)
22 implicitWidth: units.gu(40)
23 implicitHeight: units.gu(68)
23 implicitHeight: units.gu(68)
24
24
25− // Workaround bug #1475643
26− headerColor: Qt.rgba(0, 0, 0, 0)
27−
28 Dash {
25 Dash {
29 anchors.fill: parent
26 anchors.fill: parent
30 }
27 }
qml/Dash/DashCategoryBase.qml+3−11
@@ -24,17 +24,9 @@ Item {
24 /* Relevant really only for ListViewWithPageHeader case: specify how many pixels we can overlap with the section header */
24 /* Relevant really only for ListViewWithPageHeader case: specify how many pixels we can overlap with the section header */
25 readonly property int allowedOverlap: units.dp(1)
25 readonly property int allowedOverlap: units.dp(1)
26
26
27− property real __heightToClip: {
27+ property real heightToClip: 0
28− // Check this is in position where clipping is needed
29− if (typeof ListViewWithPageHeader !== 'undefined') {
30− if (typeof heightToClip !== 'undefined') {
31− if (heightToClip >= allowedOverlap) {
28+ readonly property real __heightToClip: heightToClip >= allowedOverlap ? heightToClip - allowedOverlap : 0
32− return heightToClip - allowedOverlap;
29+
33− }
34− }
35− }
36− return 0;
37− }
38
30
39 /*!
31 /*!
40 \internal
32 \internal
qml/Dash/DashPageHeader.qml+31−36
@@ -16,7 +16,7 @@
16
16
17import QtQuick 2.4
17import QtQuick 2.4
18import Ubuntu.Components 1.3
18import Ubuntu.Components 1.3
19−import Ubuntu.Components.Themes.Ambiance 1.3
19+import Ubuntu.Components.Popups 1.3
20import Ubuntu.Components.ListItems 1.3
20import Ubuntu.Components.ListItems 1.3
21import "../Components"
21import "../Components"
22
22
@@ -78,13 +78,13 @@ Item {
78 }
78 }
79 }
79 }
80
80
81− function closePopup(keepFocus) {
81+ function closePopup(keepFocus, keepSearch) {
82 if (extraPanel.visible) {
82 if (extraPanel.visible) {
83 extraPanel.visible = false;
83 extraPanel.visible = false;
84 } else if (!keepFocus) {
84 } else if (!keepFocus) {
85− unfocus();
85+ unfocus(keepSearch);
86 }
86 }
87− if (!searchTextField.text && !root.navigationTag && searchHistory.count == 0) {
87+ if (!keepSearch && !searchTextField.text && !root.navigationTag && searchHistory.count == 0) {
88 headerContainer.showSearch = false;
88 headerContainer.showSearch = false;
89 }
89 }
90 }
90 }
@@ -97,9 +97,9 @@ Item {
97 closePopup(keepFocus);
97 closePopup(keepFocus);
98 }
98 }
99
99
100− function unfocus() {
100+ function unfocus(keepSearch) {
101 searchTextField.focus = false;
101 searchTextField.focus = false;
102− if (!searchTextField.text && !root.navigationTag) {
102+ if (!keepSearch && !searchTextField.text && !root.navigationTag) {
103 headerContainer.showSearch = false;
103 headerContainer.showSearch = false;
104 }
104 }
105 }
105 }
@@ -142,7 +142,7 @@ Item {
142 objectName: "headerContainer"
142 objectName: "headerContainer"
143 clip: contentY < height
143 clip: contentY < height
144 anchors { left: parent.left; top: parent.top; right: parent.right }
144 anchors { left: parent.left; top: parent.top; right: parent.right }
145− height: header.contentHeight
145+ height: header.__styleInstance.contentHeight
146 contentHeight: headersColumn.height
146 contentHeight: headersColumn.height
147 interactive: false
147 interactive: false
148 contentY: showSearch ? 0 : height
148 contentY: showSearch ? 0 : height
@@ -173,22 +173,18 @@ Item {
173 id: headersColumn
173 id: headersColumn
174 anchors { left: parent.left; right: parent.right }
174 anchors { left: parent.left; right: parent.right }
175
175
176− PageHeadStyle {
176+ PageHeader {
177− // FIXME: Replace PageHeadStyle from the Ambiance theme by the new PageHeader from Ubuntu.Components 1.3.
178 id: searchHeader
177 id: searchHeader
179 anchors { left: parent.left; right: parent.right }
178 anchors { left: parent.left; right: parent.right }
180 opacity: headerContainer.clip || headerContainer.showSearch ? 1 : 0 // setting visible false cause column to relayout
179 opacity: headerContainer.clip || headerContainer.showSearch ? 1 : 0 // setting visible false cause column to relayout
181− __separator_visible: false
180+
182− // Required to keep PageHeadStyle noise down as it expects the Page's properties around.
181+ StyleHints {
183− property var styledItem: searchHeader
184− property color dividerColor: "transparent" // Doesn't matter as we don't have PageHeadSections
185− property color panelColor: background.topColor
186− panelForegroundColor: config.foregroundColor
187− backgroundColor: "transparent"
188− config: PageHeadConfiguration {
189 foregroundColor: root.scopeStyle ? root.scopeStyle.headerForeground : theme.palette.normal.baseText
182 foregroundColor: root.scopeStyle ? root.scopeStyle.headerForeground : theme.palette.normal.baseText
183+ backgroundColor: "transparent"
184+ dividerColor: "transparent"
190 }
185 }
186+
191− property var contents: Item {
187+ contents: Item {
192 anchors.fill: parent
188 anchors.fill: parent
193
189
194 TextField {
190 TextField {
@@ -273,7 +269,7 @@ Item {
273 anchors.fill: parent
269 anchors.fill: parent
274 anchors.margins: units.gu(2)
270 anchors.margins: units.gu(2)
275 name: "filters"
271 name: "filters"
276− color: root.activeFiltersCount > 0 ? UbuntuColors.orange : header.config.foregroundColor
272+ color: root.activeFiltersCount > 0 ? theme.palette.normal.positive : header.__styleInstance.foregroundColor
277 }
273 }
278
274
279 onClicked: {
275 onClicked: {
@@ -283,6 +279,7 @@ Item {
283
279
284 AbstractButton {
280 AbstractButton {
285 id: cancelButton
281 id: cancelButton
282+ objectName: "cancelButton"
286 width: cancelLabel.width + cancelLabel.anchors.rightMargin + cancelLabel.anchors.leftMargin
283 width: cancelLabel.width + cancelLabel.anchors.rightMargin + cancelLabel.anchors.leftMargin
287 anchors {
284 anchors {
288 top: parent.top
285 top: parent.top
@@ -296,7 +293,7 @@ Item {
296 Label {
293 Label {
297 id: cancelLabel
294 id: cancelLabel
298 text: i18n.tr("Cancel")
295 text: i18n.tr("Cancel")
299− color: header.panelForegroundColor
296+ color: header.__styleInstance.foregroundColor
300 verticalAlignment: Text.AlignVCenter
297 verticalAlignment: Text.AlignVCenter
301 anchors {
298 anchors {
302 verticalCenter: parent.verticalCenter
299 verticalCenter: parent.verticalCenter
@@ -309,28 +306,27 @@ Item {
309 }
306 }
310 }
307 }
311
308
312− PageHeadStyle {
309+ PageHeader {
313− // FIXME: Replace PageHeadStyle from the Ambiance theme by the new PageHeader from Ubuntu.Components 1.3.
314 id: header
310 id: header
315 objectName: "innerPageHeader"
311 objectName: "innerPageHeader"
316 anchors { left: parent.left; right: parent.right }
312 anchors { left: parent.left; right: parent.right }
317 height: headerContainer.height
313 height: headerContainer.height
318 opacity: headerContainer.clip || !headerContainer.showSearch ? 1 : 0 // setting visible false cause column to relayout
314 opacity: headerContainer.clip || !headerContainer.showSearch ? 1 : 0 // setting visible false cause column to relayout
319− __separator_visible: false
315+ title: root.title
320− property var styledItem: header
316+
321− property color dividerColor: "transparent" // Doesn't matter as we don't have PageHeadSections
317+ StyleHints {
322− property color panelColor: background.topColor
323− panelForegroundColor: config.foregroundColor
324− backgroundColor: "transparent"
325− config: PageHeadConfiguration {
326− title: root.title
327 foregroundColor: root.scopeStyle ? root.scopeStyle.headerForeground : theme.palette.normal.baseText
318 foregroundColor: root.scopeStyle ? root.scopeStyle.headerForeground : theme.palette.normal.baseText
328− backAction: Action {
319+ backgroundColor: "transparent"
320+ dividerColor: "transparent"
321+ }
322+
323+ leadingActionBar.actions: Action {
329− iconName: backIsClose ? "close" : "back"
324+ iconName: backIsClose ? "close" : "back"
330− visible: root.showBackButton
325+ visible: root.showBackButton
331− onTriggered: root.backClicked()
326+ onTriggered: root.backClicked()
332− }
327+ }
333
328
329+ trailingActionBar {
334 actions: [
330 actions: [
335 Action {
331 Action {
336 objectName: "store"
332 objectName: "store"
@@ -366,7 +362,6 @@ Item {
366 ]
362 ]
367 }
363 }
368
364
369− property var contents: null
370 Component.onCompleted: root.refreshLogo()
365 Component.onCompleted: root.refreshLogo()
371
366
372 Component {
367 Component {
qml/Dash/Filters/FilterOptionSelector.qml+4
@@ -25,6 +25,8 @@ FilterWidget {
25
25
26 implicitHeight: expandingItem.height
26 implicitHeight: expandingItem.height
27
27
28+ signal filterSelected()
29+
28 ListItems.Expandable {
30 ListItems.Expandable {
29 id: expandingItem
31 id: expandingItem
30 objectName: "expandingItem"
32 objectName: "expandingItem"
@@ -67,6 +69,7 @@ FilterWidget {
67 width: parent.width
69 width: parent.width
68 Repeater {
70 Repeater {
69 model: widgetData.options
71 model: widgetData.options
72+ objectName: "optionsRepeater"
70
73
71 ListItems.Standard {
74 ListItems.Standard {
72 text: label
75 text: label
@@ -83,6 +86,7 @@ FilterWidget {
83
86
84 onClicked: {
87 onClicked: {
85 widgetData.options.setChecked(index, !checked);
88 widgetData.options.setChecked(index, !checked);
89+ root.filterSelected()
86 }
90 }
87 }
91 }
88 }
92 }
qml/Dash/Filters/FilterWidgetFactory.qml+8
@@ -31,6 +31,9 @@ Item {
31 //! Widget data, forwarded to the widget as is.
31 //! Widget data, forwarded to the widget as is.
32 property var widgetData: null
32 property var widgetData: null
33
33
34+ // Emitted iff filter type is FilterOptionSelector
35+ signal singleSelectionFilterSelected()
36+
34 implicitHeight: title.height + title.anchors.topMargin + loader.height
37 implicitHeight: title.height + title.anchors.topMargin + loader.height
35
38
36 Label {
39 Label {
@@ -77,5 +80,10 @@ Item {
77 item.widgetId = Qt.binding(function() { return root.widgetId } )
80 item.widgetId = Qt.binding(function() { return root.widgetId } )
78 item.widgetData = Qt.binding(function() { return root.widgetData } )
81 item.widgetData = Qt.binding(function() { return root.widgetData } )
79 }
82 }
83+
84+ Connections {
85+ target: widgetType == Filters.OptionSelectorFilter ? loader.item : null
86+ onFilterSelected: root.singleSelectionFilterSelected()
87+ }
80 }
88 }
81}
89}
qml/Dash/GenericScopeView.qml+14−4
@@ -345,10 +345,10 @@ FocusScope {
345 if (scope && scope.id === "clickscope") {
345 if (scope && scope.id === "clickscope") {
346 if (categoryId === "predefined" || categoryId === "local") {
346 if (categoryId === "predefined" || categoryId === "local") {
347 cardTool.artShapeSize = Qt.binding(function() { return Qt.size(units.gu(8), units.gu(7.5)) });
347 cardTool.artShapeSize = Qt.binding(function() { return Qt.size(units.gu(8), units.gu(7.5)) });
348− item.artShapeStyle = "icon";
348+ cardTool.artShapeStyle = "icon";
349 } else {
349 } else {
350 // Should be ubuntu store icon
350 // Should be ubuntu store icon
351− item.artShapeStyle = "flat";
351+ cardTool.artShapeStyle = "flat";
352 item.backgroundShapeStyle = "shadow";
352 item.backgroundShapeStyle = "shadow";
353 }
353 }
354 }
354 }
@@ -616,10 +616,10 @@ FocusScope {
616 sectionProperty: "name"
616 sectionProperty: "name"
617 sectionDelegate: ListItems.Header {
617 sectionDelegate: ListItems.Header {
618 objectName: "dashSectionHeader" + (delegate ? delegate.category : "")
618 objectName: "dashSectionHeader" + (delegate ? delegate.category : "")
619+ property int delegateIndex: -1
619 readonly property var delegate: categoryView.item(delegateIndex)
620 readonly property var delegate: categoryView.item(delegateIndex)
620 width: categoryView.width
621 width: categoryView.width
621− height: section != "" ? units.gu(5) : 0
622+ height: text != "" ? units.gu(5) : 0
622− text: section
623 color: scopeStyle ? scopeStyle.foreground : theme.palette.normal.baseText
623 color: scopeStyle ? scopeStyle.foreground : theme.palette.normal.baseText
624 iconName: delegate && delegate.headerLink ? "go-next" : ""
624 iconName: delegate && delegate.headerLink ? "go-next" : ""
625 onClicked: {
625 onClicked: {
@@ -662,6 +662,10 @@ FocusScope {
662 onShowFiltersPopup: { // item
662 onShowFiltersPopup: { // item
663 extraPanel.visible = false;
663 extraPanel.visible = false;
664 scopeView.filtersPopover = PopupUtils.open(Qt.resolvedUrl("FiltersPopover.qml"), item, { "contentWidth": scopeView.width - units.gu(2) } );
664 scopeView.filtersPopover = PopupUtils.open(Qt.resolvedUrl("FiltersPopover.qml"), item, { "contentWidth": scopeView.width - units.gu(2) } );
665+ scopeView.filtersPopover.Component.onDestruction.connect(function () {
666+ categoryView.pageHeader.closePopup(false, true);
667+ categoryView.pageHeader.unfocus(true); // remove the focus from the search field
668+ })
665 }
669 }
666 }
670 }
667
671
@@ -683,12 +687,18 @@ FocusScope {
683 onHistoryItemClicked: {
687 onHistoryItemClicked: {
684 SearchHistoryModel.addQuery(text);
688 SearchHistoryModel.addQuery(text);
685 categoryView.pageHeader.searchQuery = text;
689 categoryView.pageHeader.searchQuery = text;
690+ categoryView.pageHeader.unfocus();
686 }
691 }
687
692
688 onDashNavigationLeafClicked: {
693 onDashNavigationLeafClicked: {
689 categoryView.pageHeader.closePopup();
694 categoryView.pageHeader.closePopup();
690 categoryView.pageHeader.unfocus();
695 categoryView.pageHeader.unfocus();
691 }
696 }
697+
698+ onExtraPanelOptionSelected: {
699+ categoryView.pageHeader.closePopup();
700+ categoryView.pageHeader.unfocus();
701+ }
692 }
702 }
693 }
703 }
694
704
qml/Dash/PageHeaderExtraPanel.qml+34−10
@@ -24,7 +24,7 @@ Item {
24
24
25 readonly property real searchesHeight: recentSearchesRepeater.count > 0 ? searchColumn.height + recentSearchesLabels.height + recentSearchesLabels.anchors.topMargin : 0
25 readonly property real searchesHeight: recentSearchesRepeater.count > 0 ? searchColumn.height + recentSearchesLabels.height + recentSearchesLabels.anchors.topMargin : 0
26
26
27− implicitHeight: searchesHeight + dashNavigation.implicitHeight + dashNavigation.anchors.topMargin + primaryFilter.height + primaryFilter.anchors.topMargin
27+ implicitHeight: searchesHeight + dashNavigation.implicitHeight + dashNavigation.anchors.topMargin + primaryFilterContainer.height + primaryFilterContainer.anchors.topMargin
28
28
29 // Set by parent
29 // Set by parent
30 property ListModel searchHistory
30 property ListModel searchHistory
@@ -36,6 +36,7 @@ Item {
36
36
37 signal historyItemClicked(string text)
37 signal historyItemClicked(string text)
38 signal dashNavigationLeafClicked()
38 signal dashNavigationLeafClicked()
39+ signal extraPanelOptionSelected()
39
40
40 function resetNavigation() {
41 function resetNavigation() {
41 dashNavigation.resetNavigation();
42 dashNavigation.resetNavigation();
@@ -124,7 +125,7 @@ Item {
124 color: "#888888"
125 color: "#888888"
125 }
126 }
126
127
127− divider.visible: index != repeater.count - 1 || (scope && scope.hasNavigation) || primaryFilter.active
128+ divider.visible: index != recentSearchesRepeater.count - 1 || (scope && scope.hasNavigation) || primaryFilter.active
128
129
129 onClicked: root.historyItemClicked(query)
130 onClicked: root.historyItemClicked(query)
130 }
131 }
@@ -145,22 +146,45 @@ Item {
145 onLeafClicked: root.dashNavigationLeafClicked();
146 onLeafClicked: root.dashNavigationLeafClicked();
146 }
147 }
147
148
148− Filters.FilterWidgetFactory {
149+ Flickable {
150+ id: primaryFilterContainer
151+ objectName: "primaryFilterContainer"
152+
153+ height: {
149− id: primaryFilter
154+ if (!primaryFilter.active) {
150− active: scope && !scope.hasNavigation
155+ return 0;
156+ } else if (contentHeight > dashNavigation.availableHeight) {
157+ return dashNavigation.availableHeight;
158+ } else {
159+ return contentHeight;
160+ }
161+ }
151
162
152− property var filter: active ? scope.primaryNavigationFilter : null
163+ clip: true
164+ contentHeight: primaryFilter.implicitHeight
153
165
154 anchors {
166 anchors {
155 top: recentSearchesRepeater.count > 0 ? searchColumn.bottom : parent.top
167 top: recentSearchesRepeater.count > 0 ? searchColumn.bottom : parent.top
156− topMargin: active && recentSearchesRepeater.count > 0 ? units.gu(2) : 0
168+ topMargin: primaryFilter.active && recentSearchesRepeater.count > 0 ? units.gu(2) : 0
157 left: parent.left
169 left: parent.left
158 right: parent.right
170 right: parent.right
159 }
171 }
160
172
173+ Filters.FilterWidgetFactory {
174+ id: primaryFilter
175+ objectName: "primaryFilter"
176+
177+ active: scope && !scope.hasNavigation
178+
179+ anchors.fill: parent
180+ property var filter: active ? scope.primaryNavigationFilter : null
181+
161− widgetId: filter ? filter.filterId : ""
182+ widgetId: filter ? filter.filterId : ""
162− widgetType: filter ? filter.filterType : -1
183+ widgetType: filter ? filter.filterType : -1
163− widgetData: filter
184+ widgetData: filter
185+
186+ onSingleSelectionFilterSelected: extraPanelOptionSelected()
187+ }
164 }
188 }
165
189
166 // This is outside the item
190 // This is outside the item
qml/Dash/Previews/PreviewActions.qml+1−1
@@ -66,7 +66,7 @@ PreviewWidget {
66 visible: root.actions && root.actions.length > 0
66 visible: root.actions && root.actions.length > 0
67 onTriggeredAction: root.triggered(root.widgetId, actionData.id, actionData)
67 onTriggeredAction: root.triggered(root.widgetId, actionData.id, actionData)
68 width: (root.width - units.gu(1)) / 2
68 width: (root.width - units.gu(1)) / 2
69− color: root.scopeStyle ? root.scopeStyle.previewButtonColor : UbuntuColors.orange
69+ color: root.scopeStyle ? root.scopeStyle.previewButtonColor : theme.palette.normal.positive
70 }
70 }
71 }
71 }
72}
72}
qml/Dash/Previews/PreviewPayments.qml+1−1
@@ -35,7 +35,7 @@ PreviewWidget {
35 id: paymentButton
35 id: paymentButton
36 objectName: "paymentButton"
36 objectName: "paymentButton"
37
37
38− color: UbuntuColors.orange
38+ color: theme.palette.normal.positive
39 text: paymentClient.formattedPrice
39 text: paymentClient.formattedPrice
40 onClicked: {
40 onClicked: {
41 paymentClient.start();
41 paymentClient.start();
qml/Dash/Previews/PreviewRatingInput.qml+41−42
@@ -40,14 +40,16 @@ PreviewWidget {
40 switch(widgetData["visible"]) {
40 switch(widgetData["visible"]) {
41 default:
41 default:
42 case "both":
42 case "both":
43− return ratingLabelAndWidgetContainer.implicitHeight + reviewContainer.implicitHeight;
43+ return ratingLabelAndWidgetContainer.implicitHeight + (reviewContainer.visible ? reviewContainer.implicitHeight : 0);
44 case "rating":
44 case "rating":
45 return ratingLabelAndWidgetContainer.implicitHeight;
45 return ratingLabelAndWidgetContainer.implicitHeight;
46 case "review":
46 case "review":
47 return reviewContainer.implicitHeight;
47 return reviewContainer.implicitHeight;
48− }
48+ }
49 }
49 }
50
50
51+ clip: reviewContainer.visible
52+
51 property alias ratingValue: rating.value
53 property alias ratingValue: rating.value
52 property alias reviewText: reviewTextArea.text
54 property alias reviewText: reviewTextArea.text
53
55
@@ -64,21 +66,17 @@ PreviewWidget {
64 triggered(root.widgetId, "rated", data);
66 triggered(root.widgetId, "rated", data);
65 }
67 }
66
68
67− Item {
69+ Column {
68 id: ratingLabelAndWidgetContainer
70 id: ratingLabelAndWidgetContainer
69− anchors {
70− left: parent.left
71− right: parent.right
71+ anchors { left: parent.left; right: parent.right; }
72− }
72+ spacing: units.gu(0.5)
73− implicitHeight: rating.height
74 visible: widgetData["visible"] !== "review"
73 visible: widgetData["visible"] !== "review"
75
74
76 Label {
75 Label {
76+ id: ratingLabel
77 objectName: "ratingLabel"
77 objectName: "ratingLabel"
78− anchors {
78+ anchors { left: parent.left; right: parent.right; }
79− verticalCenter: parent.verticalCenter
79+ fontSize: "large"
80− left: parent.left
81− }
82 color: root.scopeStyle ? root.scopeStyle.foreground : theme.palette.normal.baseText
80 color: root.scopeStyle ? root.scopeStyle.foreground : theme.palette.normal.baseText
83 opacity: .8
81 opacity: .8
84 text: widgetData["rating-label"] || i18n.tr("Rate this")
82 text: widgetData["rating-label"] || i18n.tr("Rate this")
@@ -87,23 +85,22 @@ PreviewWidget {
87 Rating {
85 Rating {
88 id: rating
86 id: rating
89 objectName: "rating"
87 objectName: "rating"
90− anchors {
88+ anchors.left: parent.left
91− verticalCenter: parent.verticalCenter
92− right: parent.right
93− }
94 size: 5
89 size: 5
90+ height: units.gu(4)
95 onValueChanged: {
91 onValueChanged: {
96 if (widgetData["visible"] === "rating") root.submit();
92 if (widgetData["visible"] === "rating") root.submit();
97 }
93 }
98
94
99− property var urlIconEmpty: widgetData["rating-icon-empty"]
95+ property var urlIconEmpty: widgetData["rating-icon-empty"] || "image://theme/non-starred"
100− property var urlIconFull: widgetData["rating-icon-full"]
96+ property var urlIconFull: widgetData["rating-icon-full"] || "image://theme/starred"
101 }
97 }
102 }
98 }
103
99
104 Item {
100 Item {
105 id: reviewContainer
101 id: reviewContainer
102+ objectName: "reviewContainer"
106− implicitHeight: reviewLabel.implicitHeight + reviewSubmitContainer.implicitHeight + anchors.topMargin
103+ implicitHeight: visible ? reviewSubmitContainer.implicitHeight + anchors.topMargin : 0
107
104
108 readonly property real innerMargin: units.gu(1)
105 readonly property real innerMargin: units.gu(1)
109
106
@@ -112,32 +109,31 @@ PreviewWidget {
112 right: parent.right
109 right: parent.right
113 top: ratingLabelAndWidgetContainer.visible ? ratingLabelAndWidgetContainer.bottom : parent.top
110 top: ratingLabelAndWidgetContainer.visible ? ratingLabelAndWidgetContainer.bottom : parent.top
114 bottom: parent.bottom
111 bottom: parent.bottom
115− topMargin: ratingLabelAndWidgetContainer.visible ? reviewContainer.innerMargin : 0
112+ topMargin: ratingLabelAndWidgetContainer.visible ? innerMargin : 0
113+ }
114+ visible: {
115+ switch(widgetData["visible"]) {
116+ default:
117+ case "both":
118+ return widgetData["required"] === "review" || rating.value > 0;
119+ case "rating":
120+ return false;
121+ case "review":
122+ return true;
123+ }
116 }
124 }
117− visible: widgetData["visible"] !== "rating"
118
125
119− Label {
126+ Behavior on implicitHeight {
120− objectName: "reviewLabel"
127+ UbuntuNumberAnimation {
121− id: reviewLabel
128+ duration: UbuntuAnimation.FastDuration
122− anchors {
129+ easing.type: Easing.OutCubic
123− top: parent.top
124− left: parent.left
125− right: parent.right
126 }
130 }
127− color: root.scopeStyle ? root.scopeStyle.foreground : theme.palette.normal.baseText
128− opacity: .8
129− text: widgetData["review-label"] || i18n.tr("Add a review")
130 }
131 }
131
132
132 Item {
133 Item {
133 id: reviewSubmitContainer
134 id: reviewSubmitContainer
135+ objectName: "reviewSubmitContainer"
134− anchors {
136+ anchors.fill: parent
135− top: reviewLabel.bottom
136− left: parent.left
137− right: parent.right
138− bottom: parent.bottom
139− topMargin: reviewContainer.innerMargin
140− }
141 implicitHeight: reviewTextArea.implicitHeight + anchors.topMargin
137 implicitHeight: reviewTextArea.implicitHeight + anchors.topMargin
142
138
143 TextArea {
139 TextArea {
@@ -148,12 +144,17 @@ PreviewWidget {
148 if(inputMethodVisible && activeFocus)
144 if(inputMethodVisible && activeFocus)
149 root.makeSureVisible(reviewTextArea);
145 root.makeSureVisible(reviewTextArea);
150 }
146 }
147+ onVisibleChanged: {
148+ if (visible && widgetData["visible"] !== "review")
149+ focus = true;
150+ }
151 anchors {
151 anchors {
152 top: parent.top
152 top: parent.top
153 left: parent.left
153 left: parent.left
154 right: submitButton.left
154 right: submitButton.left
155 rightMargin: reviewContainer.innerMargin
155 rightMargin: reviewContainer.innerMargin
156 }
156 }
157+ placeholderText: widgetData["review-label"] || i18n.tr("Add a review")
157 }
158 }
158
159
159 Button {
160 Button {
@@ -170,11 +171,9 @@ PreviewWidget {
170 top: parent.top
171 top: parent.top
171 right: parent.right
172 right: parent.right
172 }
173 }
173− color: readyToSubmit ? theme.palette.selected.base : theme.palette.normal.base
174+ enabled: readyToSubmit
174 text: widgetData["submit-label"] || i18n.tr("Send")
175 text: widgetData["submit-label"] || i18n.tr("Send")
175− onClicked: {
176+ onClicked: root.submit()
176− if (readyToSubmit) root.submit()
177− }
178 }
177 }
179 }
178 }
180 }
179 }
qml/Dash/ScopesList.qml+1−13
@@ -49,18 +49,6 @@ Item {
49 anchors.fill: parent
49 anchors.fill: parent
50 }
50 }
51
51
52− Binding {
53− target: root.scope
54− property: "searchQuery"
55− value: header.searchQuery
56− }
57−
58− Binding {
59− target: header
60− property: "searchQuery"
61− value: root.scope ? root.scope.searchQuery : ""
62− }
63−
64 DashPageHeader {
52 DashPageHeader {
65 id: header
53 id: header
66 objectName: "pageHeader"
54 objectName: "pageHeader"
@@ -70,7 +58,7 @@ Item {
70 showBackButton: true
58 showBackButton: true
71 backIsClose: root.state == "edit"
59 backIsClose: root.state == "edit"
72 storeEntryEnabled: root.state == "browse"
60 storeEntryEnabled: root.state == "browse"
73− searchEntryEnabled: false // Disable search for now
61+ searchEntryEnabled: false
74 scopeStyle: root.scopeStyle
62 scopeStyle: root.scopeStyle
75 onBackClicked: {
63 onBackClicked: {
76 if (backIsClose) {
64 if (backIsClose) {
qml/DisabledScreenNotice.qml+7
@@ -18,6 +18,7 @@ import QtQuick 2.4
18import QtQuick.Layouts 1.1
18import QtQuick.Layouts 1.1
19import Ubuntu.Components 1.3
19import Ubuntu.Components 1.3
20import Unity.Session 0.1
20import Unity.Session 0.1
21+import Unity.Screens 0.1
21import QtQuick.Window 2.2
22import QtQuick.Window 2.2
22import "Components"
23import "Components"
23
24
@@ -35,6 +36,10 @@ Item {
35 name: applicationArguments.deviceName
36 name: applicationArguments.deviceName
36 }
37 }
37
38
39+ Screens {
40+ id: screens
41+ }
42+
38 Item {
43 Item {
39 id: contentContainer
44 id: contentContainer
40 objectName: "contentContainer"
45 objectName: "contentContainer"
@@ -119,6 +124,8 @@ Item {
119
124
120 InputMethod {
125 InputMethod {
121 id: inputMethod
126 id: inputMethod
127+ // Don't resize when there is only one screen to avoid resize clashing with the InputMethod in the Shell.
128+ enabled: screens.count > 1
122 objectName: "inputMethod"
129 objectName: "inputMethod"
123 anchors.fill: parent
130 anchors.fill: parent
124 }
131 }
qml/Launcher/Launcher.qml+16−24
@@ -31,14 +31,14 @@ FocusScope {
31 property int panelWidth: units.gu(10)
31 property int panelWidth: units.gu(10)
32 property int dragAreaWidth: units.gu(1)
32 property int dragAreaWidth: units.gu(1)
33 property int minimizeDistance: units.gu(26)
33 property int minimizeDistance: units.gu(26)
34− property real progress: dragArea.dragging && dragArea.touchX > panelWidth ?
34+ property real progress: dragArea.dragging && dragArea.touchPosition.x > panelWidth ?
35− (width * (dragArea.touchX-panelWidth) / (width - panelWidth)) : 0
35+ (width * (dragArea.touchPosition.x-panelWidth) / (width - panelWidth)) : 0
36
36
37 property bool superPressed: false
37 property bool superPressed: false
38 property bool superTabPressed: false
38 property bool superTabPressed: false
39
39
40 readonly property bool dragging: dragArea.dragging
40 readonly property bool dragging: dragArea.dragging
41− readonly property real dragDistance: dragArea.dragging ? dragArea.touchX : 0
41+ readonly property real dragDistance: dragArea.dragging ? dragArea.touchPosition.x : 0
42 readonly property real visibleWidth: panel.width + panel.x
42 readonly property real visibleWidth: panel.width + panel.x
43
43
44 readonly property bool shown: panel.x > -panel.width
44 readonly property bool shown: panel.x > -panel.width
@@ -273,6 +273,18 @@ FocusScope {
273 }
273 }
274 }
274 }
275
275
276+ InverseMouseArea {
277+ id: closeMouseArea
278+ anchors.fill: panel
279+ enabled: root.state == "visible" && (!root.lockedVisible || panel.highlightIndex >= -1)
280+ visible: enabled
281+ onPressed: {
282+ mouse.accepted = false;
283+ panel.highlightIndex = -2;
284+ root.hide();
285+ }
286+ }
287+
276 MouseArea {
288 MouseArea {
277 id: launcherDragArea
289 id: launcherDragArea
278 enabled: root.available && (root.state == "visible" || root.state == "visibleTemporary") && !root.lockedVisible
290 enabled: root.available && (root.state == "visible" || root.state == "visibleTemporary") && !root.lockedVisible
@@ -293,26 +305,6 @@ FocusScope {
293 }
305 }
294 }
306 }
295
307
296− InverseMouseArea {
297− id: closeMouseArea
298− anchors.fill: panel
299− enabled: root.state == "visible" && (!root.lockedVisible || panel.highlightIndex >= -1)
300− visible: enabled
301− onPressed: {
302− panel.highlightIndex = -2
303− root.hide();
304− }
305− }
306−
307− Rectangle {
308− id: backgroundShade
309− anchors.fill: parent
310− color: "black"
311− opacity: root.state == "visible" && !root.lockedVisible ? 0.6 : 0
312−
313− Behavior on opacity { NumberAnimation { duration: UbuntuAnimation.BriskDuration } }
314− }
315−
316 EdgeBarrier {
308 EdgeBarrier {
317 id: edgeBarrier
309 id: edgeBarrier
318 edge: Qt.LeftEdge
310 edge: Qt.LeftEdge
@@ -400,7 +392,7 @@ FocusScope {
400 }
392 }
401 }
393 }
402
394
403− DirectionalDragArea {
395+ SwipeArea {
404 id: dragArea
396 id: dragArea
405 objectName: "launcherDragArea"
397 objectName: "launcherDragArea"
406
398
qml/Launcher/LauncherDelegate.qml+2−2
@@ -164,7 +164,7 @@ Item {
164 }
164 }
165 width: Math.min(root.itemWidth, Math.max(units.gu(2), countLabel.implicitWidth + units.gu(1)))
165 width: Math.min(root.itemWidth, Math.max(units.gu(2), countLabel.implicitWidth + units.gu(1)))
166 height: units.gu(2)
166 height: units.gu(2)
167− backgroundColor: UbuntuColors.green
167+ backgroundColor: theme.palette.normal.positive
168 visible: root.countVisible
168 visible: root.countVisible
169 aspect: UbuntuShape.Flat
169 aspect: UbuntuShape.Flat
170
170
@@ -207,7 +207,7 @@ Item {
207 top: parent.top
207 top: parent.top
208 bottom: parent.bottom
208 bottom: parent.bottom
209 }
209 }
210− backgroundColor: UbuntuColors.blue
210+ backgroundColor: theme.palette.normal.activity
211 borderSource: "none"
211 borderSource: "none"
212 width: progressOverlay.width
212 width: progressOverlay.width
213 }
213 }
qml/Notifications/Notification.qml+20−5
@@ -55,11 +55,13 @@ StyledItem {
55 name: "Ubuntu.Components.Themes.Ambiance"
55 name: "Ubuntu.Components.Themes.Ambiance"
56 }
56 }
57
57
58+ signal dismissed()
59+
58 readonly property bool expanded: {
60 readonly property bool expanded: {
59 var result = false;
61 var result = false;
60
62
61 if (type === Notification.SnapDecision) {
63 if (type === Notification.SnapDecision) {
62− if (ListView.view.currentIndex === index) {
64+ if (ListView.view.currentIndex === index || fullscreen) {
63 result = true;
65 result = true;
64 } else {
66 } else {
65 if (ListView.view.count > 2) {
67 if (ListView.view.count > 2) {
@@ -99,10 +101,15 @@ StyledItem {
99 }
101 }
100
102
101 function closeNotification() {
103 function closeNotification() {
102− if (notification.actions.count > 1) { // perform the "reject" action
104+ if (index === ListView.view.currentIndex) { // reset to get the 1st snap decision expanded
103− notification.notification.invokeAction(notification.actions.data(1, ActionModel.RoleActionId));
105+ ListView.view.currentIndex = -1;
104 }
106 }
107+
108+ // perform the "reject" action
109+ notification.notification.invokeAction(notification.actions.data(1, ActionModel.RoleActionId));
110+
105 notification.notification.close();
111 notification.notification.close();
112+ notification.dismissed()
106 }
113 }
107
114
108 Behavior on x {
115 Behavior on x {
@@ -115,6 +122,12 @@ StyledItem {
115 }
122 }
116 }
123 }
117
124
125+ onFullscreenChanged: {
126+ if (fullscreen) {
127+ notification.notification.urgency = Notification.Critical;
128+ }
129+ }
130+
118 Behavior on height {
131 Behavior on height {
119 UbuntuNumberAnimation {
132 UbuntuNumberAnimation {
120 duration: UbuntuAnimation.SnapDuration
133 duration: UbuntuAnimation.SnapDuration
@@ -188,6 +201,7 @@ StyledItem {
188 onNameOwnerChanged: {
201 onNameOwnerChanged: {
189 if (lastNameOwner !== "" && nameOwner === "" && notification.notification !== undefined) {
202 if (lastNameOwner !== "" && nameOwner === "" && notification.notification !== undefined) {
190 notification.notification.close()
203 notification.notification.close()
204+ notification.dismissed()
191 }
205 }
192 lastNameOwner = nameOwner
206 lastNameOwner = nameOwner
193 }
207 }
@@ -199,7 +213,7 @@ StyledItem {
199 anchors.fill: parent
213 anchors.fill: parent
200 objectName: "interactiveArea"
214 objectName: "interactiveArea"
201
215
202− drag.target: notification
216+ drag.target: !fullscreen ? notification : undefined
203 drag.axis: Drag.XAxis
217 drag.axis: Drag.XAxis
204 drag.minimumX: -notification.width
218 drag.minimumX: -notification.width
205 drag.maximumX: notification.width
219 drag.maximumX: notification.width
@@ -382,7 +396,7 @@ StyledItem {
382 objectName: "dialogListView"
396 objectName: "dialogListView"
383 spacing: notification.margins
397 spacing: notification.margins
384
398
385− visible: count > 0
399+ visible: count > 0 && (notification.expanded || notification.fullscreen)
386
400
387 anchors {
401 anchors {
388 left: parent.left
402 left: parent.left
@@ -413,6 +427,7 @@ StyledItem {
413 }
427 }
414 onAccepted: {
428 onAccepted: {
415 notification.notification.invokeAction(actionRepeater.itemAt(0).actionId)
429 notification.notification.invokeAction(actionRepeater.itemAt(0).actionId)
430+ notification.dismissed()
416 }
431 }
417 }
432 }
418 }
433 }
qml/Notifications/NotificationMenuItemFactory.qml+4
@@ -146,19 +146,23 @@ Loader {
146 errorText: errorAction.valid ? errorAction.state : ""
146 errorText: errorAction.valid ? errorAction.state : ""
147 retryText: notification.body
147 retryText: notification.body
148 background: menuFactory.background
148 background: menuFactory.background
149+ darkenBackground: 0.4
149
150
150 onEntered: {
151 onEntered: {
151 menuModel.changeState(menuIndex, passphrase);
152 menuModel.changeState(menuIndex, passphrase);
152 clear(false);
153 clear(false);
154+ notification.dismissed()
153 }
155 }
154
156
155 onCancel: {
157 onCancel: {
156 menuModel.activate(menuIndex, false);
158 menuModel.activate(menuIndex, false);
159+ notification.dismissed()
157 }
160 }
158
161
159 onEmergencyCall: {
162 onEmergencyCall: {
160 shell.startLockedApp("dialer-app");
163 shell.startLockedApp("dialer-app");
161 menuModel.activate(menuIndex, false);
164 menuModel.activate(menuIndex, false);
165+ notification.dismissed()
162 }
166 }
163
167
164 property var extendedData: menuData && menuData.ext || undefined
168 property var extendedData: menuData && menuData.ext || undefined
qml/Notifications/Notifications.qml+18−9
@@ -41,18 +41,25 @@ ListView {
41 filterRegExp: RegExp(UnityNotifications.Notification.SnapDecision)
41 filterRegExp: RegExp(UnityNotifications.Notification.SnapDecision)
42 }
42 }
43
43
44− property bool topmostIsFullscreen: false
44+ readonly property bool topmostIsFullscreen: fullscreenIndex != -1
45 spacing: topmostIsFullscreen ? 0 : units.gu(1)
45 spacing: topmostIsFullscreen ? 0 : units.gu(1)
46
46
47 currentIndex: count > 1 ? 1 : -1
47 currentIndex: count > 1 ? 1 : -1
48
48
49+ property int fullscreenIndex: -1
50+ onFullscreenIndexChanged: {
51+ if (fullscreenIndex != -1) {
52+ positionViewAtIndex(fullscreenIndex, ListView.Beginning);
53+ }
54+ }
55+
49 delegate: Notification {
56 delegate: Notification {
50 objectName: "notification" + index
57 objectName: "notification" + index
51 width: parent.width
58 width: parent.width
52 type: model.type
59 type: model.type
53 hints: model.hints
60 hints: model.hints
54 iconSource: model.icon
61 iconSource: model.icon
55− secondaryIconSource: model.secondaryIcon
62+ secondaryIconSource: model.secondaryIcon ? model.secondaryIcon : ""
56 summary: model.summary
63 summary: model.summary
57 body: model.body
64 body: model.body
58 value: model.value ? model.value : -1
65 value: model.value ? model.value : -1
@@ -69,16 +76,18 @@ ListView {
69 // FIXME: disabled all transitions because of LP: #1354406 workaround
76 // FIXME: disabled all transitions because of LP: #1354406 workaround
70 //layer.enabled: add.running || remove.running || populate.running
77 //layer.enabled: add.running || remove.running || populate.running
71
78
72− Component.onCompleted: {
79+ onFullscreenChanged: updateListTopMostIsFullscreen();
73− if (index == 1) {
80+
74− notificationList.topmostIsFullscreen = fullscreen
81+ function updateListTopMostIsFullscreen() {
82+ if (fullscreen) {
83+ fullscreenIndex = index;
75 }
84 }
76 }
85 }
77
86
78− onFullscreenChanged: {
87+ onDismissed: {
79− // index 1 because 0 is the PlaceHolder...
88+ if (fullscreenIndex == index) {
80− if (index == 1) {
89+ fullscreenIndex = -1;
81− notificationList.topmostIsFullscreen = fullscreen
90+ notificationList.positionViewAtBeginning();
82 }
91 }
83 }
92 }
84 }
93 }
qml/Panel/Indicators/MenuItemFactory.qml+2−2
@@ -377,11 +377,11 @@ Item {
377 property int menuIndex: -1
377 property int menuIndex: -1
378 property var extendedData: menuData && menuData.ext || undefined
378 property var extendedData: menuData && menuData.ext || undefined
379
379
380− property date serverTime: new Date(getExtendedProperty(extendedData, "xCanonicalTime", 0) * 1000)
380+ readonly property date serverTime: new Date(getExtendedProperty(extendedData, "xCanonicalTime", 0) * 1000)
381 LiveTimer {
381 LiveTimer {
382 frequency: LiveTimer.Relative
382 frequency: LiveTimer.Relative
383 relativeTime: alarmItem.serverTime
383 relativeTime: alarmItem.serverTime
384− onTrigger: alarmItem.serverTime = new Date(getExtendedProperty(extendedData, "xCanonicalTime", 0) * 1000)
384+ onTrigger: alarmItem.time = i18n.relativeDateTime(alarmItem.serverTime)
385 }
385 }
386
386
387 text: menuData && menuData.label || ""
387 text: menuData && menuData.label || ""
qml/Panel/Indicators/MessageMenuItemFactory.qml+1−5
@@ -123,11 +123,7 @@ Loader {
123 menuModel.activate(menuIndex, false);
123 menuModel.activate(menuIndex, false);
124 }
124 }
125 onTriggered: {
125 onTriggered: {
126− if (selected) {
126+ menuModel.activate(menuIndex, true);
127− menuDeselected();
128− } else {
129− menuSelected();
130− }
131 }
127 }
132 }
128 }
133 }
129 }
qml/Panel/IndicatorsMenu.qml+17−13
@@ -39,7 +39,7 @@ Showable {
39 property bool showOnClick: true
39 property bool showOnClick: true
40 property color panelColor: theme.palette.normal.background
40 property color panelColor: theme.palette.normal.background
41
41
42− signal showTapped(point position)
42+ signal showTapped()
43
43
44 // TODO: Perhaps we need a animation standard for showing/hiding? Each showable seems to
44 // TODO: Perhaps we need a animation standard for showing/hiding? Each showable seems to
45 // use its own values. Need to ask design about this.
45 // use its own values. Need to ask design about this.
@@ -204,7 +204,7 @@ Showable {
204 } else {
204 } else {
205 var touchReleaseTime = new Date().getTime();
205 var touchReleaseTime = new Date().getTime();
206 if (touchReleaseTime - touchPressTime <= 300) {
206 if (touchReleaseTime - touchPressTime <= 300) {
207− root.showTapped(Qt.point(touchSceneX, touchSceneY));
207+ root.showTapped();
208 }
208 }
209 }
209 }
210 }
210 }
@@ -233,10 +233,10 @@ Showable {
233 stretch: true
233 stretch: true
234 maxTotalDragDistance: openedHeight - expandedPanelHeight - handle.height
234 maxTotalDragDistance: openedHeight - expandedPanelHeight - handle.height
235
235
236− onTouchSceneXChanged: {
236+ onTouchPositionChanged: {
237 if (root.state === "locked") {
237 if (root.state === "locked") {
238− d.xDisplacementSinceLock += (touchSceneX - d.lastHideTouchSceneX)
238+ d.xDisplacementSinceLock += (touchPosition.x - d.lastHideTouchX)
239− d.lastHideTouchSceneX = touchSceneX;
239+ d.lastHideTouchX = touchPosition.x;
240 }
240 }
241 }
241 }
242 }
242 }
@@ -244,7 +244,11 @@ Showable {
244 PanelVelocityCalculator {
244 PanelVelocityCalculator {
245 id: yVelocityCalculator
245 id: yVelocityCalculator
246 velocityThreshold: d.hasCommitted ? 0.1 : 0.3
246 velocityThreshold: d.hasCommitted ? 0.1 : 0.3
247− trackedValue: d.activeDragHandle ? d.activeDragHandle.touchSceneY : 0
247+ trackedValue: d.activeDragHandle ?
248+ (Direction.isPositive(d.activeDragHandle.direction) ?
249+ d.activeDragHandle.distance :
250+ -d.activeDragHandle.distance)
251+ : 0
248
252
249 onVelocityAboveThresholdChanged: d.updateState()
253 onVelocityAboveThresholdChanged: d.updateState()
250 }
254 }
@@ -271,13 +275,13 @@ Showable {
271 id: d
275 id: d
272 property var activeDragHandle: showDragHandle.dragging ? showDragHandle : hideDragHandle.dragging ? hideDragHandle : null
276 property var activeDragHandle: showDragHandle.dragging ? showDragHandle : hideDragHandle.dragging ? hideDragHandle : null
273 property bool hasCommitted: false
277 property bool hasCommitted: false
274− property real lastHideTouchSceneX: 0
278+ property real lastHideTouchX: 0
275 property real xDisplacementSinceLock: 0
279 property real xDisplacementSinceLock: 0
276 onXDisplacementSinceLockChanged: d.updateState()
280 onXDisplacementSinceLockChanged: d.updateState()
277
281
278 property real rowMappedLateralPosition: {
282 property real rowMappedLateralPosition: {
279 if (!d.activeDragHandle) return -1;
283 if (!d.activeDragHandle) return -1;
280− return d.activeDragHandle.mapToItem(bar, d.activeDragHandle.touchX, 0).x;
284+ return d.activeDragHandle.mapToItem(bar, d.activeDragHandle.touchPosition.x, 0).x;
281 }
285 }
282
286
283 function updateState() {
287 function updateState() {
@@ -305,7 +309,7 @@ Showable {
305 script: {
309 script: {
306 yVelocityCalculator.reset();
310 yVelocityCalculator.reset();
307 // initial item selection
311 // initial item selection
308− if (!d.hasCommitted) bar.selectItemAt(d.activeDragHandle ? d.activeDragHandle.touchX : -1);
312+ if (!d.hasCommitted) bar.selectItemAt(d.activeDragHandle ? d.activeDragHandle.touchPosition.x : -1);
309 d.hasCommitted = false;
313 d.hasCommitted = false;
310 }
314 }
311 }
315 }
@@ -323,7 +327,7 @@ Showable {
323 target: leftScroller
327 target: leftScroller
324 lateralPosition: {
328 lateralPosition: {
325 if (!d.activeDragHandle) return -1;
329 if (!d.activeDragHandle) return -1;
326− var mapped = d.activeDragHandle.mapToItem(leftScroller, d.activeDragHandle.touchX, 0);
330+ var mapped = d.activeDragHandle.mapToItem(leftScroller, d.activeDragHandle.touchPosition.x, 0);
327 return mapped.x;
331 return mapped.x;
328 }
332 }
329 }
333 }
@@ -332,7 +336,7 @@ Showable {
332 target: rightScroller
336 target: rightScroller
333 lateralPosition: {
337 lateralPosition: {
334 if (!d.activeDragHandle) return -1;
338 if (!d.activeDragHandle) return -1;
335− var mapped = d.activeDragHandle.mapToItem(rightScroller, d.activeDragHandle.touchX, 0);
339+ var mapped = d.activeDragHandle.mapToItem(rightScroller, d.activeDragHandle.touchPosition.x, 0);
336 return mapped.x;
340 return mapped.x;
337 }
341 }
338 }
342 }
@@ -342,7 +346,7 @@ Showable {
342 StateChangeScript {
346 StateChangeScript {
343 script: {
347 script: {
344 d.xDisplacementSinceLock = 0;
348 d.xDisplacementSinceLock = 0;
345− d.lastHideTouchSceneX = hideDragHandle.touchSceneX;
349+ d.lastHideTouchX = hideDragHandle.touchPosition.x;
346 }
350 }
347 }
351 }
348 PropertyChanges { target: bar; expanded: true }
352 PropertyChanges { target: bar; expanded: true }
@@ -354,7 +358,7 @@ Showable {
354 PropertyChanges {
358 PropertyChanges {
355 target: d;
359 target: d;
356 hasCommitted: true
360 hasCommitted: true
357− lastHideTouchSceneX: 0
361+ lastHideTouchX: 0
358 xDisplacementSinceLock: 0
362 xDisplacementSinceLock: 0
359 restoreEntryValues: false
363 restoreEntryValues: false
360 }
364 }
qml/Panel/Panel.qml+21−20
@@ -30,22 +30,13 @@ Item {
30 property real indicatorAreaShowProgress: 1.0
30 property real indicatorAreaShowProgress: 1.0
31 property bool locked: false
31 property bool locked: false
32
32
33− Rectangle {
33+ MouseArea {
34− id: darkenedArea
35− property real darkenedOpacity: 0.6
36− anchors {
37− fill: parent
34+ anchors.fill: parent
38− topMargin: panelHeight
35+ anchors.topMargin: panelHeight
39− }
40− color: "black"
41− opacity: indicators.unitProgress * darkenedOpacity
42 visible: !indicators.fullyClosed
36 visible: !indicators.fullyClosed
43−
37+ enabled: visible
44− MouseArea {
45− anchors.fill: parent
46− onClicked: if (indicators.fullyOpened) indicators.hide();
38+ onClicked: if (indicators.fullyOpened) indicators.hide();
47− hoverEnabled: true // should also eat hover events, otherwise they will pass through
39+ hoverEnabled: true // should also eat hover events, otherwise they will pass through
48− }
49 }
40 }
50
41
51 Binding {
42 Binding {
@@ -89,7 +80,7 @@ Item {
89
80
90 Rectangle {
81 Rectangle {
91 id: indicatorAreaBackground
82 id: indicatorAreaBackground
92− color: callHint.visible ? UbuntuColors.green : theme.palette.normal.background
83+ color: callHint.visible ? theme.palette.normal.positive : theme.palette.normal.background
93 anchors {
84 anchors {
94 top: parent.top
85 top: parent.top
95 left: parent.left
86 left: parent.left
@@ -101,6 +92,7 @@ Item {
101 }
92 }
102
93
103 MouseArea {
94 MouseArea {
95+ objectName: "windowControlArea"
104 anchors {
96 anchors {
105 top: parent.top
97 top: parent.top
106 left: parent.left
98 left: parent.left
@@ -109,7 +101,16 @@ Item {
109 height: indicators.minimizedPanelHeight
101 height: indicators.minimizedPanelHeight
110 hoverEnabled: true
102 hoverEnabled: true
111 onClicked: callHint.visible ? callHint.showLiveCall() : PanelState.focusMaximizedApp()
103 onClicked: callHint.visible ? callHint.showLiveCall() : PanelState.focusMaximizedApp()
112− onDoubleClicked: PanelState.maximize()
104+ onDoubleClicked: PanelState.restoreClicked()
105+
106+ property bool mouseWasPressed: false
107+ onPressed: mouseWasPressed = containsPress
108+ onMouseYChanged: {
109+ if (mouseWasPressed && mouseY > panelHeight) {
110+ PanelState.restoreClicked(); // restore the window when "dragging" the panel down
111+ mouseWasPressed = false;
112+ }
113+ }
113
114
114 // WindowControlButtons inside the mouse area, otherwise QML doesn't grok nested hover events :/
115 // WindowControlButtons inside the mouse area, otherwise QML doesn't grok nested hover events :/
115 // cf. https://bugreports.qt.io/browse/QTBUG-32909
116 // cf. https://bugreports.qt.io/browse/QTBUG-32909
@@ -126,10 +127,10 @@ Item {
126 height: indicators.minimizedPanelHeight - anchors.topMargin - anchors.bottomMargin
127 height: indicators.minimizedPanelHeight - anchors.topMargin - anchors.bottomMargin
127 visible: PanelState.buttonsVisible && parent.containsMouse && !root.locked && !callHint.visible
128 visible: PanelState.buttonsVisible && parent.containsMouse && !root.locked && !callHint.visible
128 active: PanelState.buttonsVisible
129 active: PanelState.buttonsVisible
130+ onCloseClicked: PanelState.closeClicked()
131+ onMinimizeClicked: PanelState.minimizeClicked()
132+ onMaximizeClicked: PanelState.restoreClicked()
129 closeButtonShown: PanelState.closeButtonShown
133 closeButtonShown: PanelState.closeButtonShown
130− onClose: PanelState.close()
131− onMinimize: PanelState.minimize()
132− onMaximize: PanelState.maximize()
133 }
134 }
134 }
135 }
135
136
qml/Shell.qml+4−3
@@ -41,13 +41,15 @@ import Unity.Notifications 1.0 as NotificationBackend
41import Unity.Session 0.1
41import Unity.Session 0.1
42import Unity.DashCommunicator 0.1
42import Unity.DashCommunicator 0.1
43import Unity.Indicators 0.1 as Indicators
43import Unity.Indicators 0.1 as Indicators
44−import Cursor 1.0
44+import Cursor 1.1
45import WindowManager 0.1
45import WindowManager 0.1
46
46
47
47
48−Item {
48+StyledItem {
49 id: shell
49 id: shell
50
50
51+ theme.name: "Ubuntu.Components.Themes.SuruDark"
52+
51 // to be set from outside
53 // to be set from outside
52 property int orientationAngle: 0
54 property int orientationAngle: 0
53 property int orientation
55 property int orientation
@@ -171,7 +173,6 @@ Item {
171 }
173 }
172
174
173 Component.onCompleted: {
175 Component.onCompleted: {
174− theme.name = "Ubuntu.Components.Themes.SuruDark"
175 finishStartUpTimer.start();
176 finishStartUpTimer.start();
176 }
177 }
177
178
qml/Stages/DecoratedWindow.qml+11−7
@@ -46,9 +46,11 @@ FocusScope {
46 property alias widthIncrement: applicationWindow.widthIncrement
46 property alias widthIncrement: applicationWindow.widthIncrement
47 property alias heightIncrement: applicationWindow.heightIncrement
47 property alias heightIncrement: applicationWindow.heightIncrement
48
48
49− signal close()
49+ signal closeClicked()
50− signal maximize()
50+ signal maximizeClicked()
51− signal minimize()
51+ signal maximizeHorizontallyClicked()
52+ signal maximizeVerticallyClicked()
53+ signal minimizeClicked()
52 signal decorationPressed()
54 signal decorationPressed()
53
55
54 Rectangle {
56 Rectangle {
@@ -62,7 +64,7 @@ FocusScope {
62 Rectangle {
64 Rectangle {
63 anchors { left: selectionHighlight.left; right: selectionHighlight.right; bottom: selectionHighlight.bottom; }
65 anchors { left: selectionHighlight.left; right: selectionHighlight.right; bottom: selectionHighlight.bottom; }
64 height: units.dp(2)
66 height: units.dp(2)
65− color: UbuntuColors.orange
67+ color: theme.palette.normal.focus
66 visible: highlightShown
68 visible: highlightShown
67 }
69 }
68
70
@@ -86,9 +88,11 @@ FocusScope {
86 title: applicationWindow.title
88 title: applicationWindow.title
87 visible: root.decorationShown
89 visible: root.decorationShown
88
90
89− onClose: root.close();
91+ onCloseClicked: root.closeClicked();
92+ onMaximizeClicked: { root.decorationPressed(); root.maximizeClicked(); }
93+ onMaximizeHorizontallyClicked: { root.decorationPressed(); root.maximizeHorizontallyClicked(); }
90− onMaximize: { root.decorationPressed(); root.maximize(); }
94+ onMaximizeVerticallyClicked: { root.decorationPressed(); root.maximizeVerticallyClicked(); }
91− onMinimize: root.minimize();
95+ onMinimizeClicked: root.minimizeClicked();
92 onPressed: root.decorationPressed();
96 onPressed: root.decorationPressed();
93 }
97 }
94
98
qml/Stages/DesktopSpread.qml+1−1
@@ -494,7 +494,7 @@ FocusScope {
494 // Rectangle {
494 // Rectangle {
495 // anchors { left: parent.left; right: parent.right; bottom: parent.bottom }
495 // anchors { left: parent.left; right: parent.right; bottom: parent.bottom }
496 // height: units.dp(2)
496 // height: units.dp(2)
497− // color: UbuntuColors.orange
497+ // color: theme.palette.normal.focus
498 // visible: index == 0 // TODO: should be active workspace index
498 // visible: index == 0 // TODO: should be active workspace index
499 // }
499 // }
500 }
500 }
qml/Stages/DesktopSpreadDelegate.qml+1−1
@@ -83,7 +83,7 @@ Item {
83 Rectangle {
83 Rectangle {
84 anchors { left: selectionHighlight.left; right: selectionHighlight.right; bottom: selectionHighlight.bottom; }
84 anchors { left: selectionHighlight.left; right: selectionHighlight.right; bottom: selectionHighlight.bottom; }
85 height: units.dp(2)
85 height: units.dp(2)
86− color: UbuntuColors.orange
86+ color: theme.palette.normal.focus
87 visible: root.highlightShown
87 visible: root.highlightShown
88 antialiasing: true
88 antialiasing: true
89 }
89 }
qml/Stages/DesktopStage.qml+55−43
@@ -90,7 +90,8 @@ AbstractStage {
90 GlobalShortcut {
90 GlobalShortcut {
91 id: minimizeRestoreShortcut
91 id: minimizeRestoreShortcut
92 shortcut: Qt.MetaModifier|Qt.ControlModifier|Qt.Key_Down
92 shortcut: Qt.MetaModifier|Qt.ControlModifier|Qt.Key_Down
93− onTriggered: priv.focusedAppDelegate.maximized || priv.focusedAppDelegate.maximizedLeft || priv.focusedAppDelegate.maximizedRight
93+ onTriggered: priv.focusedAppDelegate.maximized || priv.focusedAppDelegate.maximizedLeft || priv.focusedAppDelegate.maximizedRight ||
94+ priv.focusedAppDelegate.maximizedHorizontally || priv.focusedAppDelegate.maximizedVertically
94 ? priv.focusedAppDelegate.restoreFromMaximized() : priv.focusedAppDelegate.minimize()
95 ? priv.focusedAppDelegate.restoreFromMaximized() : priv.focusedAppDelegate.minimize()
95 active: priv.focusedAppDelegate !== null
96 active: priv.focusedAppDelegate !== null
96 }
97 }
@@ -159,9 +160,9 @@ AbstractStage {
159
160
160 Connections {
161 Connections {
161 target: PanelState
162 target: PanelState
162− onClose: { if (priv.focusedAppDelegate) { priv.focusedAppDelegate.close(); } }
163+ onCloseClicked: { if (priv.focusedAppDelegate) { priv.focusedAppDelegate.close(); } }
163− onMinimize: { if (priv.focusedAppDelegate) { priv.focusedAppDelegate.minimize(); } }
164+ onMinimizeClicked: { if (priv.focusedAppDelegate) { priv.focusedAppDelegate.minimize(); } }
164− onMaximize: { if (priv.focusedAppDelegate) { priv.focusedAppDelegate.restoreFromMaximized(); } }
165+ onRestoreClicked: { if (priv.focusedAppDelegate) { priv.focusedAppDelegate.restoreFromMaximized(); } }
165 onFocusMaximizedApp: {
166 onFocusMaximizedApp: {
166 if (priv.foregroundMaximizedAppDelegate) {
167 if (priv.foregroundMaximizedAppDelegate) {
167 priv.foregroundMaximizedAppDelegate.focus = true;
168 priv.foregroundMaximizedAppDelegate.focus = true;
@@ -276,19 +277,16 @@ AbstractStage {
276 property alias widthIncrement: decoratedWindow.widthIncrement
277 property alias widthIncrement: decoratedWindow.widthIncrement
277 property alias heightIncrement: decoratedWindow.heightIncrement
278 property alias heightIncrement: decoratedWindow.heightIncrement
278
279
279− QtObject {
280− id: appDelegatePrivate
281− property bool maximized: false
280+ readonly property bool maximized: windowState & WindowStateStorage.WindowStateMaximized
282− property bool maximizedLeft: false
281+ readonly property bool maximizedLeft: windowState & WindowStateStorage.WindowStateMaximizedLeft
283− property bool maximizedRight: false
282+ readonly property bool maximizedRight: windowState & WindowStateStorage.WindowStateMaximizedRight
284− property bool minimized: false
283+ readonly property bool maximizedHorizontally: windowState & WindowStateStorage.WindowStateMaximizedHorizontally
285− }
284+ readonly property bool maximizedVertically: windowState & WindowStateStorage.WindowStateMaximizedVertically
286− readonly property alias maximized: appDelegatePrivate.maximized
285+ readonly property bool minimized: windowState & WindowStateStorage.WindowStateMinimized
287− readonly property alias maximizedLeft: appDelegatePrivate.maximizedLeft
288− readonly property alias maximizedRight: appDelegatePrivate.maximizedRight
289− readonly property alias minimized: appDelegatePrivate.minimized
290 readonly property alias fullscreen: decoratedWindow.fullscreen
286 readonly property alias fullscreen: decoratedWindow.fullscreen
291
287
288+ property int windowState: WindowStateStorage.WindowStateNormal
289+
292 readonly property var application: model.application
290 readonly property var application: model.application
293 property bool animationsEnabled: true
291 property bool animationsEnabled: true
294 property alias title: decoratedWindow.title
292 property alias title: decoratedWindow.title
@@ -386,43 +384,45 @@ AbstractStage {
386
384
387 function maximize(animated) {
385 function maximize(animated) {
388 animationsEnabled = (animated === undefined) || animated;
386 animationsEnabled = (animated === undefined) || animated;
389− appDelegatePrivate.minimized = false;
387+ windowState = WindowStateStorage.WindowStateMaximized;
390− appDelegatePrivate.maximized = true;
388+ }
391− appDelegatePrivate.maximizedLeft = false;
389+ function maximizeLeft(animated) {
392− appDelegatePrivate.maximizedRight = false;
390+ animationsEnabled = (animated === undefined) || animated;
391+ windowState = WindowStateStorage.WindowStateMaximizedLeft;
392+ }
393+ function maximizeRight(animated) {
394+ animationsEnabled = (animated === undefined) || animated;
395+ windowState = WindowStateStorage.WindowStateMaximizedRight;
393 }
396 }
394− function maximizeLeft() {
397+ function maximizeHorizontally(animated) {
395− appDelegatePrivate.minimized = false;
398+ animationsEnabled = (animated === undefined) || animated;
396− appDelegatePrivate.maximized = false;
399+ windowState = WindowStateStorage.WindowStateMaximizedHorizontally;
397− appDelegatePrivate.maximizedLeft = true;
398− appDelegatePrivate.maximizedRight = false;
399 }
400 }
400− function maximizeRight() {
401+ function maximizeVertically(animated) {
401− appDelegatePrivate.minimized = false;
402+ animationsEnabled = (animated === undefined) || animated;
402− appDelegatePrivate.maximized = false;
403+ windowState = WindowStateStorage.WindowStateMaximizedVertically;
403− appDelegatePrivate.maximizedLeft = false;
404− appDelegatePrivate.maximizedRight = true;
405 }
404 }
406 function minimize(animated) {
405 function minimize(animated) {
407 animationsEnabled = (animated === undefined) || animated;
406 animationsEnabled = (animated === undefined) || animated;
408− appDelegatePrivate.minimized = true;
407+ windowState |= WindowStateStorage.WindowStateMinimized; // add the minimized bit
409 }
408 }
410 function restoreFromMaximized(animated) {
409 function restoreFromMaximized(animated) {
411 animationsEnabled = (animated === undefined) || animated;
410 animationsEnabled = (animated === undefined) || animated;
412− appDelegatePrivate.minimized = false;
411+ windowState = WindowStateStorage.WindowStateNormal;
413− appDelegatePrivate.maximized = false;
414− appDelegatePrivate.maximizedLeft = false;
415− appDelegatePrivate.maximizedRight = false;
416 }
412 }
417 function restore(animated) {
413 function restore(animated) {
418 animationsEnabled = (animated === undefined) || animated;
414 animationsEnabled = (animated === undefined) || animated;
419− appDelegatePrivate.minimized = false;
415+ windowState &= ~WindowStateStorage.WindowStateMinimized; // clear the minimized bit
420 if (maximized)
416 if (maximized)
421 maximize();
417 maximize();
422 else if (maximizedLeft)
418 else if (maximizedLeft)
423 maximizeLeft();
419 maximizeLeft();
424 else if (maximizedRight)
420 else if (maximizedRight)
425 maximizeRight();
421 maximizeRight();
422+ else if (maximizedHorizontally)
423+ maximizeHorizontally();
424+ else if (maximizedVertically)
425+ maximizeVertically();
426
426
427 focus = true;
427 focus = true;
428 }
428 }
@@ -453,8 +453,7 @@ AbstractStage {
453 },
453 },
454 State {
454 State {
455 name: "normal";
455 name: "normal";
456− when: !appDelegate.maximized && !appDelegate.minimized
456+ when: appDelegate.windowState == WindowStateStorage.WindowStateNormal
457− && !appDelegate.maximizedLeft && !appDelegate.maximizedRight
458 PropertyChanges {
457 PropertyChanges {
459 target: appDelegate;
458 target: appDelegate;
460 visuallyMinimized: false;
459 visuallyMinimized: false;
@@ -502,13 +501,23 @@ AbstractStage {
502 requestedHeight: appContainer.height - PanelState.panelHeight
501 requestedHeight: appContainer.height - PanelState.panelHeight
503 }
502 }
504 },
503 },
504+ State {
505+ name: "maximizedHorizontally"; when: appDelegate.maximizedHorizontally && !appDelegate.minimized
506+ PropertyChanges { target: appDelegate; x: root.leftMargin }
507+ PropertyChanges { target: decoratedWindow; requestedWidth: appContainer.width - root.leftMargin }
508+ },
509+ State {
510+ name: "maximizedVertically"; when: appDelegate.maximizedVertically && !appDelegate.minimized
511+ PropertyChanges { target: appDelegate; y: PanelState.panelHeight }
512+ PropertyChanges { target: decoratedWindow; requestedHeight: appContainer.height - PanelState.panelHeight }
513+ },
505 State {
514 State {
506 name: "minimized"; when: appDelegate.minimized
515 name: "minimized"; when: appDelegate.minimized
507 PropertyChanges {
516 PropertyChanges {
508 target: appDelegate;
517 target: appDelegate;
509 x: -appDelegate.width / 2;
518 x: -appDelegate.width / 2;
510 scale: units.gu(5) / appDelegate.width;
519 scale: units.gu(5) / appDelegate.width;
511− opacity: 0
520+ opacity: 0;
512 visuallyMinimized: true;
521 visuallyMinimized: true;
513 visuallyMaximized: false
522 visuallyMaximized: false
514 }
523 }
@@ -611,10 +620,13 @@ AbstractStage {
611 requestedWidth: appDelegate.requestedWidth
620 requestedWidth: appDelegate.requestedWidth
612 requestedHeight: appDelegate.requestedHeight
621 requestedHeight: appDelegate.requestedHeight
613
622
614− onClose: { appDelegate.close(); }
623+ onCloseClicked: { appDelegate.close(); }
615− onMaximize: appDelegate.maximized || appDelegate.maximizedLeft || appDelegate.maximizedRight
624+ onMaximizeClicked: appDelegate.maximized || appDelegate.maximizedLeft || appDelegate.maximizedRight
625+ || appDelegate.maximizedHorizontally || appDelegate.maximizedVertically
616− ? appDelegate.restoreFromMaximized() : appDelegate.maximize()
626+ ? appDelegate.restoreFromMaximized() : appDelegate.maximize()
627+ onMaximizeHorizontallyClicked: appDelegate.maximizedHorizontally ? appDelegate.restoreFromMaximized() : appDelegate.maximizeHorizontally()
628+ onMaximizeVerticallyClicked: appDelegate.maximizedVertically ? appDelegate.restoreFromMaximized() : appDelegate.maximizeVertically()
617− onMinimize: appDelegate.minimize()
629+ onMinimizeClicked: appDelegate.minimize()
618 onDecorationPressed: { appDelegate.focus = true; }
630 onDecorationPressed: { appDelegate.focus = true; }
619 }
631 }
620
632
@@ -650,7 +662,7 @@ AbstractStage {
650 }
662 }
651 }
663 }
652
664
653− DirectionalDragArea {
665+ SwipeArea {
654 direction: Direction.Leftwards
666 direction: Direction.Leftwards
655 anchors { top: parent.top; right: parent.right; bottom: parent.bottom }
667 anchors { top: parent.top; right: parent.right; bottom: parent.bottom }
656 width: units.gu(1)
668 width: units.gu(1)
qml/Stages/PhoneStage.qml+4−4
@@ -713,7 +713,7 @@ AbstractStage {
713 enabled: spreadDragArea.dragging
713 enabled: spreadDragArea.dragging
714 }
714 }
715
715
716− DirectionalDragArea {
716+ SwipeArea {
717 id: spreadDragArea
717 id: spreadDragArea
718 objectName: "spreadDragArea"
718 objectName: "spreadDragArea"
719 direction: Direction.Leftwards
719 direction: Direction.Leftwards
@@ -724,10 +724,10 @@ AbstractStage {
724
724
725 property var gesturePoints: new Array()
725 property var gesturePoints: new Array()
726
726
727− onTouchXChanged: {
727+ onTouchPositionChanged: {
728 if (dragging) {
728 if (dragging) {
729 // Gesture recognized. Let's move the spreadView with the finger
729 // Gesture recognized. Let's move the spreadView with the finger
730− var dragX = Math.min(touchX + width, width); // Prevent dragging rightwards
730+ var dragX = Math.min(touchPosition.x + width, width); // Prevent dragging rightwards
731 dragX = -dragX + spreadDragArea.width - spreadView.shift;
731 dragX = -dragX + spreadDragArea.width - spreadView.shift;
732 // Don't allow dragging further than the animation crossing with phase2's animation
732 // Don't allow dragging further than the animation crossing with phase2's animation
733 var maxMovement = spreadView.width * spreadView.positionMarker4 - spreadView.shift;
733 var maxMovement = spreadView.width * spreadView.positionMarker4 - spreadView.shift;
@@ -739,7 +739,7 @@ AbstractStage {
739 spreadView.contentX = -spreadView.shift;
739 spreadView.contentX = -spreadView.shift;
740 }
740 }
741
741
742− gesturePoints.push(touchX);
742+ gesturePoints.push(touchPosition.x);
743 }
743 }
744
744
745 onDraggingChanged: {
745 onDraggingChanged: {
qml/Stages/SideStage.qml+1−2
@@ -98,8 +98,7 @@ Showable {
98 id: hideSideStageDragArea
98 id: hideSideStageDragArea
99 objectName: "hideSideStageDragArea"
99 objectName: "hideSideStageDragArea"
100
100
101− direction: Direction.Leftwards
101+ direction: Direction.Rightwards
102− rotation: 180
103 enabled: root.shown
102 enabled: root.shown
104 anchors.right: root.left
103 anchors.right: root.left
105 width: sideStageDragHandle.width
104 width: sideStageDragHandle.width
qml/Stages/Splash.qml+6−17
@@ -29,7 +29,7 @@ Item {
29 property color footerColor: d.undefinedColor
29 property color footerColor: d.undefinedColor
30 property alias imageSource: overlaidImage.source
30 property alias imageSource: overlaidImage.source
31 property url icon
31 property url icon
32− property alias title: headerConfig.title
32+ property alias title: header.title
33 property alias showHeader: header.visible
33 property alias showHeader: header.visible
34
34
35 Ambiance.Palette {
35 Ambiance.Palette {
@@ -75,25 +75,14 @@ Item {
75 style: Component { MainViewStyle {theme: styledItem.fakeTheme} }
75 style: Component { MainViewStyle {theme: styledItem.fakeTheme} }
76 }
76 }
77
77
78− Ambiance.PageHeadStyle {
78+ PageHeader {
79− // FIXME: Replace PageHeadStyle by PageHeader from Ubuntu.Components 1.3.
80 id: header
79 id: header
81− anchors {
82− left: parent.left;
83− right: parent.right
80+ anchors { left: parent.left; right: parent.right }
84− }
81+ StyleHints {
85− property var styledItem: header
86− // FIXME Keep in sync with SDK's MainView.qml values of these two colors
87− property color dividerColor: Qt.darker(styledItem.backgroundColor, 1.1)
88− property color panelColor: Qt.lighter(styledItem.backgroundColor, 1.1)
89− panelForegroundColor: config.foregroundColor
90− backgroundColor: "transparent"
91− config: PageHeadConfiguration {
92− id: headerConfig
93 foregroundColor: styledItem.fakeTheme.palette.normal.backgroundText
82 foregroundColor: styledItem.fakeTheme.palette.normal.backgroundText
83+ backgroundColor: "transparent"
84+ dividerColor: styledItem.fakeTheme.palette.normal.base
94 }
85 }
95−
96− property var contents: null
97 }
86 }
98
87
99 Image {
88 Image {
qml/Stages/SpreadDelegate.qml+1−1
@@ -286,7 +286,7 @@ FocusScope {
286 Rectangle {
286 Rectangle {
287 anchors { left: selectionHighlight.left; right: selectionHighlight.right; bottom: selectionHighlight.bottom; }
287 anchors { left: selectionHighlight.left; right: selectionHighlight.right; bottom: selectionHighlight.bottom; }
288 height: units.dp(2)
288 height: units.dp(2)
289− color: UbuntuColors.orange
289+ color: theme.palette.normal.focus
290 visible: root.highlightShown
290 visible: root.highlightShown
291 antialiasing: true
291 antialiasing: true
292 }
292 }
qml/Stages/SurfaceContainer.qml+3
@@ -34,6 +34,9 @@ FocusScope {
34 property int surfaceOrientationAngle: 0
34 property int surfaceOrientationAngle: 0
35 property bool resizeSurface: true
35 property bool resizeSurface: true
36 property bool isPromptSurface: false
36 property bool isPromptSurface: false
37+ // FIME - dont export, use interactive property. Need to fix qtmir to handle consumesInputChanged
38+ // to update surface activeFocus. See mock MirSurfaceItem.
39+ property alias consumesInput: surfaceItem.consumesInput
37
40
38 onSurfaceChanged: {
41 onSurfaceChanged: {
39 // Not a binding because animations might remove the surface from the surfaceItem
42 // Not a binding because animations might remove the surface from the surfaceItem
qml/Stages/TabletStage.qml+8−7
@@ -752,7 +752,7 @@ AbstractStage {
752
752
753 readonly property bool wantsMainStage: stage == ApplicationInfoInterface.MainStage
753 readonly property bool wantsMainStage: stage == ApplicationInfoInterface.MainStage
754
754
755− readonly property bool isDash: model.application.appId == "unity8-dash"
755+ readonly property bool isDash: application.appId == "unity8-dash"
756
756
757 onFocusChanged: {
757 onFocusChanged: {
758 if (focus && !spreadRepeater.startingUp) {
758 if (focus && !spreadRepeater.startingUp) {
@@ -768,7 +768,7 @@ AbstractStage {
768 onFocusRequested: spreadTile.focus = true;
768 onFocusRequested: spreadTile.focus = true;
769 }
769 }
770 Connections {
770 Connections {
771− target: model.application
771+ target: spreadTile.application
772 onFocusRequested: {
772 onFocusRequested: {
773 if (!model.surface) {
773 if (!model.surface) {
774 // when an app has no surfaces, we assume there's only one entry representing it:
774 // when an app has no surfaces, we assume there's only one entry representing it:
@@ -844,7 +844,7 @@ AbstractStage {
844 _constructing = false;
844 _constructing = false;
845 }
845 }
846 Component.onDestruction: {
846 Component.onDestruction: {
847− WindowStateStorage.saveStage(model.application.appId, stage);
847+ WindowStateStorage.saveStage(application.appId, stage);
848 }
848 }
849
849
850 function refreshStage() {
850 function refreshStage() {
@@ -1073,6 +1073,7 @@ AbstractStage {
1073
1073
1074 surface: spreadDelegate ? spreadDelegate.surface : null
1074 surface: spreadDelegate ? spreadDelegate.surface : null
1075
1075
1076+ consumesInput: false
1076 interactive: false
1077 interactive: false
1077 resizeSurface: false
1078 resizeSurface: false
1078 focus: false
1079 focus: false
@@ -1105,7 +1106,7 @@ AbstractStage {
1105 enabled: spreadDragArea.dragging
1106 enabled: spreadDragArea.dragging
1106 }
1107 }
1107
1108
1108− DirectionalDragArea {
1109+ SwipeArea {
1109 id: spreadDragArea
1110 id: spreadDragArea
1110 objectName: "spreadDragArea"
1111 objectName: "spreadDragArea"
1111 x: parent.width - root.dragAreaWidth
1112 x: parent.width - root.dragAreaWidth
@@ -1116,18 +1117,18 @@ AbstractStage {
1116
1117
1117 property var gesturePoints: new Array()
1118 property var gesturePoints: new Array()
1118
1119
1119− onTouchXChanged: {
1120+ onTouchPositionChanged: {
1120 if (!dragging) {
1121 if (!dragging) {
1121 spreadView.phase = 0;
1122 spreadView.phase = 0;
1122 spreadView.contentX = -spreadView.shift;
1123 spreadView.contentX = -spreadView.shift;
1123 }
1124 }
1124
1125
1125 if (dragging) {
1126 if (dragging) {
1126− var dragX = -touchX + spreadDragArea.width - spreadView.shift;
1127+ var dragX = -touchPosition.x + spreadDragArea.width - spreadView.shift;
1127 var maxDrag = spreadView.width * spreadView.positionMarker4 - spreadView.shift;
1128 var maxDrag = spreadView.width * spreadView.positionMarker4 - spreadView.shift;
1128 spreadView.contentX = Math.min(dragX, maxDrag);
1129 spreadView.contentX = Math.min(dragX, maxDrag);
1129 }
1130 }
1130− gesturePoints.push(touchX);
1131+ gesturePoints.push(touchPosition.x);
1131 }
1132 }
1132
1133
1133 onDraggingChanged: {
1134 onDraggingChanged: {
qml/Stages/WindowDecoration.qml+12−8
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2014-2015 Canonical, Ltd.
2+ * Copyright (C) 2014-2016 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
@@ -29,11 +29,13 @@ MouseArea {
29 property bool active: false
29 property bool active: false
30 hoverEnabled: true
30 hoverEnabled: true
31
31
32− signal close()
32+ signal closeClicked()
33− signal minimize()
33+ signal minimizeClicked()
34− signal maximize()
34+ signal maximizeClicked()
35+ signal maximizeHorizontallyClicked()
36+ signal maximizeVerticallyClicked()
35
37
36− onDoubleClicked: root.maximize()
38+ onDoubleClicked: root.maximizeClicked()
37
39
38 QtObject {
40 QtObject {
39 id: priv
41 id: priv
@@ -84,10 +86,12 @@ MouseArea {
84 id: buttons
86 id: buttons
85 height: parent.height
87 height: parent.height
86 active: root.active
88 active: root.active
89+ onCloseClicked: root.closeClicked();
90+ onMinimizeClicked: root.minimizeClicked();
91+ onMaximizeClicked: root.maximizeClicked();
92+ onMaximizeHorizontallyClicked: root.maximizeHorizontallyClicked();
93+ onMaximizeVerticallyClicked: root.maximizeVerticallyClicked();
87 closeButtonShown: root.target.application.appId !== "unity8-dash"
94 closeButtonShown: root.target.application.appId !== "unity8-dash"
88− onClose: root.close();
89− onMinimize: root.minimize();
90− onMaximize: root.maximize();
91 }
95 }
92
96
93 Label {
97 Label {
qml/Stages/WindowResizeArea.qml+25−5
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2014-2015 Canonical, Ltd.
2+ * Copyright (C) 2014-2016 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
@@ -81,15 +81,35 @@ MouseArea {
81 target.y = Qt.binding(function() { return Math.max(Math.min(windowGeometry.y, root.screenHeight - target.requestedHeight), PanelState.panelHeight); });
81 target.y = Qt.binding(function() { return Math.max(Math.min(windowGeometry.y, root.screenHeight - target.requestedHeight), PanelState.panelHeight); });
82
82
83 var windowState = windowStateStorage.getState(root.windowId, WindowStateStorage.WindowStateNormal)
83 var windowState = windowStateStorage.getState(root.windowId, WindowStateStorage.WindowStateNormal)
84− if (windowState === WindowStateStorage.WindowStateMaximized) {
84+ switch (windowState) {
85+ case WindowStateStorage.WindowStateNormal:
86+ break;
87+ case WindowStateStorage.WindowStateMaximized:
85− target.maximize(false)
88+ target.maximize(false);
89+ break;
90+ case WindowStateStorage.WindowStateMaximizedLeft:
91+ target.maximizeLeft(false);
92+ break;
93+ case WindowStateStorage.WindowStateMaximizedRight:
94+ target.maximizeRight(false);
95+ break;
96+ case WindowStateStorage.WindowStateMaximizedHorizontally:
97+ target.maximizeHorizontally(false);
98+ break;
99+ case WindowStateStorage.WindowStateMaximizedVertically:
100+ target.maximizeVertically(false);
101+ break;
102+ default:
103+ console.warn("Unsupported window state");
104+ break;
86 }
105 }
106+
87 priv.updateNormalGeometry();
107 priv.updateNormalGeometry();
88 }
108 }
89
109
90 function saveWindowState() {
110 function saveWindowState() {
91− windowStateStorage.saveState(root.windowId, target.state == "maximized" ? WindowStateStorage.WindowStateMaximized : WindowStateStorage.WindowStateNormal)
111+ windowStateStorage.saveState(root.windowId, target.windowState & ~WindowStateStorage.WindowStateMinimized); // clear the minimized bit when saving
92− windowStateStorage.saveGeometry(root.windowId, Qt.rect(priv.normalX, priv.normalY, priv.normalWidth, priv.normalHeight))
112+ windowStateStorage.saveGeometry(root.windowId, Qt.rect(priv.normalX, priv.normalY, priv.normalWidth, priv.normalHeight));
93 }
113 }
94
114
95 QtObject {
115 QtObject {
qml/Tutorial/TutorialBottom.qml+3−3
@@ -51,7 +51,7 @@ TutorialPage {
51 readonly property real dragAreaHeight: units.gu(3) // based on PageWithBottomEdge.qml
51 readonly property real dragAreaHeight: units.gu(3) // based on PageWithBottomEdge.qml
52 readonly property real targetDistance: height * 0.2 + dragAreaHeight // based on PageWithBottomEdge.qml
52 readonly property real targetDistance: height * 0.2 + dragAreaHeight // based on PageWithBottomEdge.qml
53
53
54− opacityOverride: dragArea.dragging ? 1 - (-dragArea.distance / targetDistance) : 1
54+ opacityOverride: dragArea.dragging ? 1 - (dragArea.distance / targetDistance) : 1
55
55
56 mouseArea {
56 mouseArea {
57 anchors.bottomMargin: root.dragAreaHeight
57 anchors.bottomMargin: root.dragAreaHeight
@@ -95,9 +95,9 @@ TutorialPage {
95
95
96 // Watches drag events but does not intercept them, so that the app beneath
96 // Watches drag events but does not intercept them, so that the app beneath
97 // will still drag the bottom edge up.
97 // will still drag the bottom edge up.
98− DirectionalDragArea {
98+ SwipeArea {
99 id: dragArea
99 id: dragArea
100− monitorOnly: true
100+ grabGesture: false
101 direction: Direction.Upwards
101 direction: Direction.Upwards
102 anchors.left: parent.left
102 anchors.left: parent.left
103 anchors.right: parent.right
103 anchors.right: parent.right
qml/Wizard/Pages/50-timezone.qml+5−2
@@ -18,7 +18,7 @@ import QtQuick 2.4
18import QtQuick.Layouts 1.1
18import QtQuick.Layouts 1.1
19import Ubuntu.Components 1.3
19import Ubuntu.Components 1.3
20import Wizard 0.1
20import Wizard 0.1
21−import Ubuntu.SystemSettings.TimeDate 1.0
21+import Ubuntu.SystemSettings.TimeDate 1.1
22import Utils 0.1 as Utils
22import Utils 0.1 as Utils
23import ".." as LocalComponents
23import ".." as LocalComponents
24
24
@@ -30,6 +30,7 @@ LocalComponents.Page {
30 forwardButtonSourceComponent: forwardButton
30 forwardButtonSourceComponent: forwardButton
31
31
32 property string selectedTimeZone: ""
32 property string selectedTimeZone: ""
33+ property string selectedTimeZoneName: ""
33 readonly property bool showingMap: wideMode && width >= units.gu(110)
34 readonly property bool showingMap: wideMode && width >= units.gu(110)
34
35
35 // for testing
36 // for testing
@@ -67,6 +68,7 @@ LocalComponents.Page {
67
68
68 function resetViews() {
69 function resetViews() {
69 selectedTimeZone = ""
70 selectedTimeZone = ""
71+ selectedTimeZoneName = ""
70 tzList.currentIndex = -1
72 tzList.currentIndex = -1
71 highlightImage.source = ""
73 highlightImage.source = ""
72 pinImage.x = 0;
74 pinImage.x = 0;
@@ -144,6 +146,7 @@ LocalComponents.Page {
144 highlightTimezone(offset);
146 highlightTimezone(offset);
145 ListView.view.currentIndex = index;
147 ListView.view.currentIndex = index;
146 selectedTimeZone = timeZone;
148 selectedTimeZone = timeZone;
149+ selectedTimeZoneName = city;
147 //print("Clicked at city with coords:", longitude, latitude);
150 //print("Clicked at city with coords:", longitude, latitude);
148 //print("Clicked on TZ:", timeZone);
151 //print("Clicked on TZ:", timeZone);
149 //print("Highlight at (x,y):", longitudeToX(longitude, map.width), latitudeToY(latitude, map.height));
152 //print("Highlight at (x,y):", longitudeToX(longitude, map.width), latitudeToY(latitude, map.height));
@@ -267,7 +270,7 @@ LocalComponents.Page {
267 text: i18n.tr("Next")
270 text: i18n.tr("Next")
268 enabled: selectedTimeZone != ""
271 enabled: selectedTimeZone != ""
269 onClicked: {
272 onClicked: {
270− timeDatePanel.timeZone = selectedTimeZone;
273+ timeDatePanel.setTimeZone(selectedTimeZone, selectedTimeZoneName);
271 pageStack.next();
274 pageStack.next();
272 }
275 }
273 }
276 }
src/CMakeLists.txt+1−4
@@ -2,7 +2,6 @@ pkg_check_modules(CONNECTIVITY REQUIRED connectivity-qt1)
2
2
3include_directories(
3include_directories(
4 ${Qt5Gui_PRIVATE_INCLUDE_DIRS}
4 ${Qt5Gui_PRIVATE_INCLUDE_DIRS}
5− ${CMAKE_SOURCE_DIR}/libs/UbuntuGestures
6 ${CONNECTIVITY_INCLUDE_DIRS}
5 ${CONNECTIVITY_INCLUDE_DIRS}
7)
6)
8
7
@@ -24,6 +23,7 @@ set(SOURCE_FILES
24 ShellApplication.cpp
23 ShellApplication.cpp
25 ShellView.cpp
24 ShellView.cpp
26 UnityCommandLineParser.cpp
25 UnityCommandLineParser.cpp
26+ UnixSignalHandler.cpp
27 ${QML_FILES} # This is to make qml and image files appear in the IDE's project tree
27 ${QML_FILES} # This is to make qml and image files appear in the IDE's project tree
28)
28)
29
29
@@ -44,9 +44,6 @@ if (ENABLE_TOUCH_EMULATION)
44 target_link_libraries(${SHELL_APP} ${MOUSETOUCHADAPTOR_LIBS_LDFLAGS})
44 target_link_libraries(${SHELL_APP} ${MOUSETOUCHADAPTOR_LIBS_LDFLAGS})
45endif()
45endif()
46
46
47−# For it to find libUbuntuGestures.so
48−set_target_properties(${SHELL_APP} PROPERTIES INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${SHELL_PRIVATE_LIBDIR}")
49−
50# install binaries
47# install binaries
51install(TARGETS ${SHELL_APP}
48install(TARGETS ${SHELL_APP}
52 RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
49 RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
src/Dash/CMakeLists.txt+1
@@ -1,6 +1,7 @@
1set(DASH_SRCS
1set(DASH_SRCS
2 main.cpp
2 main.cpp
3 ../CachingNetworkManagerFactory.cpp
3 ../CachingNetworkManagerFactory.cpp
4+ ../UnixSignalHandler.cpp
4)
5)
5
6
6if (ENABLE_TOUCH_EMULATION)
7if (ENABLE_TOUCH_EMULATION)
src/Dash/main.cpp+6
@@ -32,6 +32,7 @@
32 #include "../MouseTouchAdaptor.h"
32 #include "../MouseTouchAdaptor.h"
33#endif
33#endif
34#include "../CachingNetworkManagerFactory.h"
34#include "../CachingNetworkManagerFactory.h"
35+#include "../UnixSignalHandler.h"
35
36
36int main(int argc, const char *argv[])
37int main(int argc, const char *argv[])
37{
38{
@@ -116,6 +117,11 @@ int main(int argc, const char *argv[])
116 view->setSource(source);
117 view->setSource(source);
117 view->show();
118 view->show();
118
119
120+ UnixSignalHandler signalHandler([]{
121+ QGuiApplication::exit(0);
122+ });
123+ signalHandler.setupUnixSignalHandlers();
124+
119 int result = application->exec();
125 int result = application->exec();
120
126
121 delete view;
127 delete view;
tools/unix-signal-handler.cpp → src/UnixSignalHandler.cpprenamed+1−1
@@ -16,7 +16,7 @@
16 * Author: Marcus Tomlinson <marcus.tomlinson@canonical.com>
16 * Author: Marcus Tomlinson <marcus.tomlinson@canonical.com>
17 */
17 */
18
18
19−#include "unix-signal-handler.h"
19+#include "UnixSignalHandler.h"
20
20
21#include <QDebug>
21#include <QDebug>
22
22
tools/unix-signal-handler.h → src/UnixSignalHandler.hrenamed

The content is the same.

src/main.cpp+6
@@ -17,6 +17,7 @@
17// local
17// local
18#include "ShellApplication.h"
18#include "ShellApplication.h"
19#include "qmldebuggerutils.h"
19#include "qmldebuggerutils.h"
20+#include "UnixSignalHandler.h"
20
21
21int main(int argc, const char *argv[])
22int main(int argc, const char *argv[])
22{
23{
@@ -32,6 +33,11 @@ int main(int argc, const char *argv[])
32
33
33 ShellApplication *application = new ShellApplication(argc, (char**)argv, isMirServer);
34 ShellApplication *application = new ShellApplication(argc, (char**)argv, isMirServer);
34
35
36+ UnixSignalHandler signalHandler([]{
37+ QGuiApplication::exit(0);
38+ });
39+ signalHandler.setupUnixSignalHandlers();
40+
35 int result = application->exec();
41 int result = application->exec();
36
42
37 application->destroyResources();
43 application->destroyResources();
tests/CMakeLists.txt−1
@@ -135,7 +135,6 @@ install(DIRECTORY data graphics
135
135
136
136
137# Actual test definitions
137# Actual test definitions
138−add_subdirectory(libs)
139add_subdirectory(plugins)
138add_subdirectory(plugins)
140add_subdirectory(qmltests)
139add_subdirectory(qmltests)
141add_subdirectory(whitespace)
140add_subdirectory(whitespace)
tests/autopilot/unity8/dash.py+2−3
@@ -175,9 +175,8 @@ class Dash(ubuntuuitoolkit.UbuntuUIToolkitCustomProxyObjectBase):
175 return page_header.select_single(objectName='searchTextField')
175 return page_header.select_single(objectName='searchTextField')
176
176
177 def _get_current_page_header(self):
177 def _get_current_page_header(self):
178− dashContentList = self.select_single(objectName="dashContentList")
178+ all_scopes = self.dash_content_list.select_many("GenericScopeView")
179− all_headers = dashContentList.select_many("QQuickLoader")
179+ for i in all_scopes:
180− for i in all_headers:
181 if i.isCurrent:
180 if i.isCurrent:
182 return i.select_single(objectName="scopePageHeader")
181 return i.select_single(objectName="scopePageHeader")
183 return None
182 return None
tests/libs/CMakeLists.txtdeleted−1
@@ -1 +0,0 @@
1−add_subdirectory(UbuntuGestures)
tests/libs/UbuntuGestures/CMakeLists.txtdeleted−20
@@ -1,20 +0,0 @@
1−include_directories(
2− ${CMAKE_SOURCE_DIR}/libs/UbuntuGestures
3− ${CMAKE_CURRENT_BINARY_DIR}
4− )
5−
6−macro(add_gesture_test CLASSNAME)
7− add_executable(${CLASSNAME}TestExec tst_${CLASSNAME}.cpp)
8− qt5_use_modules(${CLASSNAME}TestExec Test Core Gui Quick)
9− target_link_libraries(${CLASSNAME}TestExec UbuntuGestures)
10− install(TARGETS ${CLASSNAME}TestExec
11− DESTINATION "${SHELL_PRIVATE_LIBDIR}/tests/libs/UbuntuGestures"
12− )
13− set_target_properties(${CLASSNAME}TestExec PROPERTIES
14− INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${SHELL_PRIVATE_LIBDIR}"
15− )
16−
17− add_unity8_unittest(${CLASSNAME} ${CLASSNAME}TestExec)
18−endmacro(add_gesture_test)
19−
20−add_gesture_test(TouchRegistry)
tests/libs/UbuntuGestures/tst_TouchRegistry.cppdeleted−974
@@ -1,974 +0,0 @@
1−/*
2− * Copyright (C) 2014-2015 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#include <QtTest>
18−#include <QSet>
19−#include <QTouchEvent>
20−
21−#include <Timer.h>
22−#include <TouchOwnershipEvent.h>
23−#include <TouchRegistry.h>
24−#include <UnownedTouchEvent.h>
25−
26−using namespace UbuntuGestures;
27−
28−class TouchMemento {
29−public:
30− TouchMemento(const QTouchEvent *touchEvent);
31− Qt::TouchPointStates touchPointStates;
32− QList<QTouchEvent::TouchPoint> touchPoints;
33−
34− bool containsTouchWithId(int touchId) const;
35−};
36−
37−class DummyCandidate : public QQuickItem
38−{
39− Q_OBJECT
40−public:
41− bool event(QEvent *e) override;
42− QSet<int> ownedTouches;
43− QSet<int> lostTouches;
44− QList<TouchMemento> unownedTouchEvents;
45−
46−Q_SIGNALS:
47− void gainedOwnership();
48− void lostOwnership();
49−};
50−
51−class tst_TouchRegistry : public QObject
52−{
53− Q_OBJECT
54−public:
55− tst_TouchRegistry() : QObject(0) { }
56−private Q_SLOTS:
57− void initTestCase() {} // will be called before the first test function is executed
58− void cleanupTestCase() {} // will be called after the last test function was executed.
59−
60− void init(); // called right before each and every test function is executed
61− void cleanup(); // called right after each and every test function is executed
62−
63− void requestWithNoCandidates();
64− void lateCandidateRequestGetsNothing();
65− void lateCandidateGestOwnershipOnceEarlyCandidateQuits();
66− void dispatchesTouchEventsToCandidates();
67− void dispatchesTouchEventsToWatchers();
68− void keepDispatchingToWatchersAfterLastCandidateGivesUp();
69− void candidatesAndWatchers_1();
70− void candidatesAndWatchers_2();
71− void rejectingTouchfterItsEnd();
72− void removeOldUndecidedCandidates();
73− void interimOwnerWontGetUnownedTouchEvents();
74− void candidateVanishes();
75− void candicateOwnershipReentrace();
76−
77−private:
78− TouchRegistry *touchRegistry;
79−};
80−
81−void tst_TouchRegistry::init()
82−{
83− touchRegistry = TouchRegistry::instance();
84−}
85−
86−void tst_TouchRegistry::cleanup()
87−{
88− delete touchRegistry;
89−}
90−
91−void tst_TouchRegistry::requestWithNoCandidates()
92−{
93− DummyCandidate candidate;
94−
95− {
96− QList<QTouchEvent::TouchPoint> touchPoints;
97− touchPoints.append(QTouchEvent::TouchPoint(0));
98− touchPoints[0].setState(Qt::TouchPointPressed);
99− QTouchEvent touchEvent(QEvent::TouchBegin,
100− 0 /* device */,
101− Qt::NoModifier,
102− Qt::TouchPointPressed,
103− touchPoints);
104− touchRegistry->update(&touchEvent);
105− }
106−
107− touchRegistry->requestTouchOwnership(0, &candidate);
108−
109− QVERIFY(candidate.ownedTouches.contains(0));
110−}
111−
112−void tst_TouchRegistry::lateCandidateRequestGetsNothing()
113−{
114− DummyCandidate earlyCandidate;
115− earlyCandidate.setObjectName("early");
116− DummyCandidate lateCandidate;
117− lateCandidate.setObjectName("late");
118−
119− {
120− QList<QTouchEvent::TouchPoint> touchPoints;
121− touchPoints.append(QTouchEvent::TouchPoint(0));
122− touchPoints[0].setState(Qt::TouchPointPressed);
123− QTouchEvent touchEvent(QEvent::TouchBegin,
124− 0 /* device */,
125− Qt::NoModifier,
126− Qt::TouchPointPressed,
127− touchPoints);
128− touchRegistry->update(&touchEvent);
129− }
130−
131− touchRegistry->addCandidateOwnerForTouch(0, &earlyCandidate);
132− touchRegistry->addCandidateOwnerForTouch(0, &lateCandidate);
133−
134− QVERIFY(earlyCandidate.ownedTouches.isEmpty());
135− QVERIFY(lateCandidate.ownedTouches.isEmpty());
136−
137− touchRegistry->requestTouchOwnership(0, &lateCandidate);
138−
139− QVERIFY(earlyCandidate.ownedTouches.isEmpty());
140− QVERIFY(lateCandidate.ownedTouches.isEmpty());
141−
142− touchRegistry->requestTouchOwnership(0, &earlyCandidate);
143−
144− QVERIFY(earlyCandidate.ownedTouches.contains(0));
145− QVERIFY(lateCandidate.ownedTouches.isEmpty());
146−}
147−
148−void tst_TouchRegistry::lateCandidateGestOwnershipOnceEarlyCandidateQuits()
149−{
150− DummyCandidate earlyCandidate;
151− DummyCandidate lateCandidate;
152−
153− {
154− QList<QTouchEvent::TouchPoint> touchPoints;
155− touchPoints.append(QTouchEvent::TouchPoint(0));
156− touchPoints[0].setState(Qt::TouchPointPressed);
157− QTouchEvent touchEvent(QEvent::TouchBegin,
158− 0 /* device */,
159− Qt::NoModifier,
160− Qt::TouchPointPressed,
161− touchPoints);
162− touchRegistry->update(&touchEvent);
163− }
164−
165− touchRegistry->addCandidateOwnerForTouch(0, &earlyCandidate);
166− touchRegistry->addCandidateOwnerForTouch(0, &lateCandidate);
167−
168− QVERIFY(earlyCandidate.ownedTouches.isEmpty());
169− QVERIFY(lateCandidate.ownedTouches.isEmpty());
170−
171− touchRegistry->requestTouchOwnership(0, &lateCandidate);
172−
173− QVERIFY(earlyCandidate.ownedTouches.isEmpty());
174− QVERIFY(lateCandidate.ownedTouches.isEmpty());
175−
176− touchRegistry->removeCandidateOwnerForTouch(0, &earlyCandidate);
177−
178− QVERIFY(earlyCandidate.ownedTouches.isEmpty());
179− QVERIFY(lateCandidate.ownedTouches.contains(0));
180−}
181−
182−void tst_TouchRegistry::dispatchesTouchEventsToCandidates()
183−{
184− QQuickItem rootItem;
185−
186− DummyCandidate candidate0;
187− candidate0.setObjectName("0");
188− candidate0.setParentItem(&rootItem);
189− candidate0.setX(1);
190− candidate0.setY(2);
191−
192− DummyCandidate candidate1;
193− candidate1.setObjectName("1");
194− candidate0.setParentItem(&rootItem);
195− candidate1.setX(3);
196− candidate1.setY(4);
197−
198− {
199− QList<QTouchEvent::TouchPoint> touchPoints;
200− touchPoints.append(QTouchEvent::TouchPoint(0));
201− touchPoints[0].setState(Qt::TouchPointPressed);
202− touchPoints[0].setRect(QRect(10, 10, 0, 0));
203− QTouchEvent touchEvent(QEvent::TouchBegin,
204− 0 /* device */,
205− Qt::NoModifier,
206− Qt::TouchPointPressed,
207− touchPoints);
208− touchRegistry->update(&touchEvent);
209− }
210−
211− touchRegistry->addCandidateOwnerForTouch(0, &candidate0);
212−
213− {
214− QList<QTouchEvent::TouchPoint> touchPoints;
215− touchPoints.append(QTouchEvent::TouchPoint(0));
216− touchPoints[0].setState(Qt::TouchPointMoved);
217− touchPoints[0].setRect(QRect(11, 11, 0, 0));
218− touchPoints.append(QTouchEvent::TouchPoint(1));
219− touchPoints[1].setState(Qt::TouchPointPressed);
220− touchPoints[1].setRect(QRect(20, 20, 0, 0));
221− QTouchEvent touchEvent(QEvent::TouchUpdate,
222− 0 /* device */,
223− Qt::NoModifier,
224− Qt::TouchPointPressed | Qt::TouchPointMoved,
225− touchPoints);
226− touchRegistry->update(&touchEvent);
227− }
228−
229− // candidate0 should have received an update on the touch he's interested on.
230− QCOMPARE(candidate0.unownedTouchEvents.count(), 1);
231− // make sure only touch 0 is there (i.e. no mention of touch 1)
232− QCOMPARE(candidate0.unownedTouchEvents[0].touchPoints.count(), 1);
233− QCOMPARE(candidate0.unownedTouchEvents[0].touchPoints[0].id(), 0);
234− // Check that the points local coordinates have been mapped to candidate0's coordinate system.
235− QCOMPARE(candidate0.unownedTouchEvents[0].touchPoints[0].rect().x(), 11 - candidate0.x());
236− QCOMPARE(candidate0.unownedTouchEvents[0].touchPoints[0].rect().y(), 11 - candidate0.y());
237−
238− touchRegistry->addCandidateOwnerForTouch(1, &candidate1);
239−
240− {
241− QList<QTouchEvent::TouchPoint> touchPoints;
242− touchPoints.append(QTouchEvent::TouchPoint(0));
243− touchPoints[0].setState(Qt::TouchPointMoved);
244− touchPoints[0].setRect(QRect(12, 12, 0, 0));
245− touchPoints.append(QTouchEvent::TouchPoint(1));
246− touchPoints[1].setState(Qt::TouchPointMoved);
247− touchPoints[1].setRect(QRect(21, 21, 0, 0));
248− QTouchEvent touchEvent(QEvent::TouchUpdate,
249− 0 /* device */,
250− Qt::NoModifier,
251− Qt::TouchPointPressed | Qt::TouchPointMoved,
252− touchPoints);
253− touchRegistry->update(&touchEvent);
254− }
255−
256− // candidate0 gets updates only for touch 0 and
257− // candidate1 gets updates only for touch 1
258−
259− QCOMPARE(candidate0.unownedTouchEvents.count(), 2);
260− QCOMPARE(candidate0.unownedTouchEvents[1].touchPoints.count(), 1);
261− QCOMPARE(candidate0.unownedTouchEvents[1].touchPoints[0].id(), 0);
262−
263− QCOMPARE(candidate1.unownedTouchEvents.count(), 1);
264− QCOMPARE(candidate1.unownedTouchEvents[0].touchPoints.count(), 1);
265− QCOMPARE(candidate1.unownedTouchEvents[0].touchPoints[0].id(), 1);
266−}
267−
268−void tst_TouchRegistry::dispatchesTouchEventsToWatchers()
269−{
270− QQuickItem rootItem;
271−
272− DummyCandidate watcher;
273− watcher.setObjectName("watcher");
274− watcher.setParentItem(&rootItem);
275− watcher.setX(1);
276− watcher.setY(2);
277−
278− {
279− QList<QTouchEvent::TouchPoint> touchPoints;
280− touchPoints.append(QTouchEvent::TouchPoint(0));
281− touchPoints[0].setState(Qt::TouchPointPressed);
282− touchPoints[0].setRect(QRect(10, 10, 0, 0));
283− QTouchEvent touchEvent(QEvent::TouchBegin,
284− 0 /* device */,
285− Qt::NoModifier,
286− Qt::TouchPointPressed,
287− touchPoints);
288− touchRegistry->update(&touchEvent);
289− }
290−
291− touchRegistry->addTouchWatcher(0, &watcher);
292−
293− {
294− QList<QTouchEvent::TouchPoint> touchPoints;
295− touchPoints.append(QTouchEvent::TouchPoint(0));
296− touchPoints[0].setState(Qt::TouchPointMoved);
297− touchPoints[0].setRect(QRect(11, 11, 0, 0));
298− touchPoints.append(QTouchEvent::TouchPoint(1));
299− touchPoints[1].setState(Qt::TouchPointPressed);
300− touchPoints[1].setRect(QRect(20, 20, 0, 0));
301− QTouchEvent touchEvent(QEvent::TouchUpdate,
302− 0 /* device */,
303− Qt::NoModifier,
304− Qt::TouchPointPressed | Qt::TouchPointMoved,
305− touchPoints);
306− touchRegistry->update(&touchEvent);
307− }
308−
309− // watcher should have received an update on the touch he's interested on.
310− QCOMPARE(watcher.unownedTouchEvents.count(), 1);
311− // make sure only touch 0 is there (i.e. no mention of touch 1)
312− QCOMPARE(watcher.unownedTouchEvents[0].touchPoints.count(), 1);
313− QCOMPARE(watcher.unownedTouchEvents[0].touchPoints[0].id(), 0);
314− // Check that the points local coordinates have been mapped to watcher's coordinate system.
315− QCOMPARE(watcher.unownedTouchEvents[0].touchPoints[0].rect().x(), 11 - watcher.x());
316− QCOMPARE(watcher.unownedTouchEvents[0].touchPoints[0].rect().y(), 11 - watcher.y());
317−
318− {
319− QList<QTouchEvent::TouchPoint> touchPoints;
320− touchPoints.append(QTouchEvent::TouchPoint(0));
321− touchPoints[0].setState(Qt::TouchPointMoved);
322− touchPoints[0].setRect(QRect(12, 12, 0, 0));
323− touchPoints.append(QTouchEvent::TouchPoint(1));
324− touchPoints[1].setState(Qt::TouchPointMoved);
325− touchPoints[1].setRect(QRect(21, 21, 0, 0));
326− QTouchEvent touchEvent(QEvent::TouchUpdate,
327− 0 /* device */,
328− Qt::NoModifier,
329− Qt::TouchPointPressed | Qt::TouchPointMoved,
330− touchPoints);
331− touchRegistry->update(&touchEvent);
332− }
333−
334− // watcher gets updates only for touch 0
335−
336− QCOMPARE(watcher.unownedTouchEvents.count(), 2);
337− QCOMPARE(watcher.unownedTouchEvents[1].touchPoints.count(), 1);
338− QCOMPARE(watcher.unownedTouchEvents[1].touchPoints[0].id(), 0);
339−}
340−
341−void tst_TouchRegistry::keepDispatchingToWatchersAfterLastCandidateGivesUp()
342−{
343− DummyCandidate item;
344−
345− {
346− QList<QTouchEvent::TouchPoint> touchPoints;
347− touchPoints.append(QTouchEvent::TouchPoint(0));
348− touchPoints[0].setState(Qt::TouchPointPressed);
349− QTouchEvent touchEvent(QEvent::TouchBegin,
350− 0 /* device */,
351− Qt::NoModifier,
352− Qt::TouchPointPressed,
353− touchPoints);
354− touchRegistry->update(&touchEvent);
355− }
356−
357− touchRegistry->addCandidateOwnerForTouch(0, &item);
358−
359− {
360− QList<QTouchEvent::TouchPoint> touchPoints;
361− touchPoints.append(QTouchEvent::TouchPoint(0));
362− touchPoints[0].setState(Qt::TouchPointMoved);
363− touchPoints.append(QTouchEvent::TouchPoint(1));
364− touchPoints[1].setState(Qt::TouchPointPressed);
365− QTouchEvent touchEvent(QEvent::TouchUpdate,
366− 0 /* device */,
367− Qt::NoModifier,
368− Qt::TouchPointPressed | Qt::TouchPointMoved,
369− touchPoints);
370− touchRegistry->update(&touchEvent);
371− }
372−
373− QCOMPARE(item.unownedTouchEvents.count(), 1);
374− QCOMPARE(item.unownedTouchEvents[0].touchPoints.count(), 1);
375− QCOMPARE(item.unownedTouchEvents[0].touchPoints[0].id(), 0);
376− item.unownedTouchEvents.clear();
377−
378− touchRegistry->addTouchWatcher(1, &item);
379−
380− {
381− QList<QTouchEvent::TouchPoint> touchPoints;
382− touchPoints.append(QTouchEvent::TouchPoint(0));
383− touchPoints[0].setState(Qt::TouchPointMoved);
384− touchPoints.append(QTouchEvent::TouchPoint(1));
385− touchPoints[1].setState(Qt::TouchPointMoved);
386− QTouchEvent touchEvent(QEvent::TouchUpdate,
387− 0 /* device */,
388− Qt::NoModifier,
389− Qt::TouchPointMoved,
390− touchPoints);
391− touchRegistry->update(&touchEvent);
392− }
393−
394− QCOMPARE(item.unownedTouchEvents.count(), 1);
395− QCOMPARE(item.unownedTouchEvents[0].touchPoints.count(), 2);
396− QVERIFY(item.unownedTouchEvents[0].containsTouchWithId(0));
397− QVERIFY(item.unownedTouchEvents[0].containsTouchWithId(1));
398− item.unownedTouchEvents.clear();
399−
400− {
401− QList<QTouchEvent::TouchPoint> touchPoints;
402− touchPoints.append(QTouchEvent::TouchPoint(0));
403− touchPoints[0].setState(Qt::TouchPointReleased);
404− touchPoints.append(QTouchEvent::TouchPoint(1));
405− touchPoints[1].setState(Qt::TouchPointMoved);
406− QTouchEvent touchEvent(QEvent::TouchUpdate,
407− 0 /* device */,
408− Qt::NoModifier,
409− Qt::TouchPointReleased | Qt::TouchPointMoved,
410− touchPoints);
411− touchRegistry->update(&touchEvent);
412− }
413−
414− QCOMPARE(item.unownedTouchEvents.count(), 1);
415− QCOMPARE(item.unownedTouchEvents[0].touchPoints.count(), 2);
416− QVERIFY(item.unownedTouchEvents[0].containsTouchWithId(0));
417− QVERIFY(item.unownedTouchEvents[0].containsTouchWithId(1));
418− item.unownedTouchEvents.clear();
419−
420− touchRegistry->removeCandidateOwnerForTouch(0, &item);
421−
422− {
423− QList<QTouchEvent::TouchPoint> touchPoints;
424− touchPoints.append(QTouchEvent::TouchPoint(1));
425− touchPoints[0].setState(Qt::TouchPointReleased);
426− QTouchEvent touchEvent(QEvent::TouchEnd,
427− 0 /* device */,
428− Qt::NoModifier,
429− Qt::TouchPointReleased,
430− touchPoints);
431− touchRegistry->update(&touchEvent);
432− }
433−
434− QCOMPARE(item.unownedTouchEvents.count(), 1);
435− QCOMPARE(item.unownedTouchEvents[0].touchPoints.count(), 1);
436− QVERIFY(item.unownedTouchEvents[0].containsTouchWithId(1));
437− item.unownedTouchEvents.clear();
438−
439− QVERIFY(touchRegistry->m_touchInfoPool.isEmpty());
440−}
441−
442−/*
443− Regression test that reproduces a problematic scenario that came up during manual testing.
444− It reproduces the interaction between TouchRegistry and a DirectionalDragArea
445− */
446−void tst_TouchRegistry::candidatesAndWatchers_1()
447−{
448− DummyCandidate item;
449−
450− {
451− QList<QTouchEvent::TouchPoint> touchPoints;
452− touchPoints.append(QTouchEvent::TouchPoint(0));
453− touchPoints[0].setState(Qt::TouchPointPressed);
454− QTouchEvent touchEvent(QEvent::TouchBegin,
455− 0 /* device */,
456− Qt::NoModifier,
457− Qt::TouchPointPressed,
458− touchPoints);
459− touchRegistry->update(&touchEvent);
460− }
461−
462− touchRegistry->addCandidateOwnerForTouch(0, &item);
463−
464− {
465− QList<QTouchEvent::TouchPoint> touchPoints;
466− touchPoints.append(QTouchEvent::TouchPoint(0));
467− touchPoints[0].setState(Qt::TouchPointMoved);
468− touchPoints.append(QTouchEvent::TouchPoint(1));
469− touchPoints[1].setState(Qt::TouchPointPressed);
470− QTouchEvent touchEvent(QEvent::TouchUpdate,
471− 0 /* device */,
472− Qt::NoModifier,
473− Qt::TouchPointPressed | Qt::TouchPointMoved,
474− touchPoints);
475− touchRegistry->update(&touchEvent);
476− }
477−
478− touchRegistry->addTouchWatcher(1, &item);
479−
480− touchRegistry->removeCandidateOwnerForTouch(0, &item);
481−
482− touchRegistry->addTouchWatcher(0, &item);
483−
484− {
485− QList<QTouchEvent::TouchPoint> touchPoints;
486− touchPoints.append(QTouchEvent::TouchPoint(0));
487− touchPoints[0].setState(Qt::TouchPointReleased);
488− touchPoints.append(QTouchEvent::TouchPoint(1));
489− touchPoints[1].setState(Qt::TouchPointMoved);
490− QTouchEvent touchEvent(QEvent::TouchUpdate,
491− 0 /* device */,
492− Qt::NoModifier,
493− Qt::TouchPointReleased | Qt::TouchPointMoved,
494− touchPoints);
495− touchRegistry->update(&touchEvent);
496− }
497−
498− {
499− QList<QTouchEvent::TouchPoint> touchPoints;
500− touchPoints.append(QTouchEvent::TouchPoint(1));
501− touchPoints[0].setState(Qt::TouchPointReleased);
502− QTouchEvent touchEvent(QEvent::TouchEnd,
503− 0 /* device */,
504− Qt::NoModifier,
505− Qt::TouchPointReleased,
506− touchPoints);
507− touchRegistry->update(&touchEvent);
508− }
509−
510− QVERIFY(touchRegistry->m_touchInfoPool.isEmpty());
511−
512− item.unownedTouchEvents.clear();
513−
514− {
515− QList<QTouchEvent::TouchPoint> touchPoints;
516− touchPoints.append(QTouchEvent::TouchPoint(0));
517− touchPoints[0].setState(Qt::TouchPointPressed);
518− QTouchEvent touchEvent(QEvent::TouchBegin,
519− 0 /* device */,
520− Qt::NoModifier,
521− Qt::TouchPointPressed,
522− touchPoints);
523− touchRegistry->update(&touchEvent);
524− }
525−
526− // Haven't made any subscription for that new touch 0.
527− QCOMPARE(item.unownedTouchEvents.count(), 0);
528−}
529−
530−/*
531− Regression test that reproduces a problematic scenario that came up during manual testing.
532− It reproduces the interaction between TouchRegistry, DirectionalDragArea and a TouchGate.
533− */
534−void tst_TouchRegistry::candidatesAndWatchers_2()
535−{
536− DummyCandidate directionalDragArea;
537− directionalDragArea.setObjectName("DirectionalDragArea");
538−
539− DummyCandidate touchGate;
540− touchGate.setObjectName("TouchGate");
541−
542− // [DDA] 1298 TouchBegin (id:0, state:pressed, scenePos:(147,1023))
543− {
544− QList<QTouchEvent::TouchPoint> touchPoints;
545− touchPoints.append(QTouchEvent::TouchPoint(0));
546− touchPoints[0].setState(Qt::TouchPointPressed);
547− QTouchEvent touchEvent(QEvent::TouchBegin,
548− 0 /* device */,
549− Qt::NoModifier,
550− Qt::TouchPointPressed,
551− touchPoints);
552− touchRegistry->update(&touchEvent);
553− }
554−
555− // [TouchRegistry] addCandidateOwnerForTouch id 0 candidate DirectionalDragArea
556− touchRegistry->addCandidateOwnerForTouch(0, &directionalDragArea);
557−
558− // [TouchRegistry] requestTouchOwnership id 0 candidate TouchGate
559− touchRegistry->requestTouchOwnership(0, &touchGate);
560−
561− //[TouchRegistry] got TouchUpdate (id:0, state:moved, scenePos:(147,1023)) (id:1, state:pressed, scenePos:(327,792))
562− {
563− QList<QTouchEvent::TouchPoint> touchPoints;
564− touchPoints.append(QTouchEvent::TouchPoint(0));
565− touchPoints[0].setState(Qt::TouchPointMoved);
566− touchPoints.append(QTouchEvent::TouchPoint(1));
567− touchPoints[1].setState(Qt::TouchPointPressed);
568− QTouchEvent touchEvent(QEvent::TouchUpdate,
569− 0 /* device */,
570− Qt::NoModifier,
571− Qt::TouchPointPressed | Qt::TouchPointMoved,
572− touchPoints);
573− touchRegistry->update(&touchEvent);
574− }
575−
576− // [TouchRegistry] addTouchWatcher id 1 watcher DirectionalDragArea
577− touchRegistry->addTouchWatcher(1, &directionalDragArea);
578−
579− // [TouchRegistry] removeCandidateOwnerForTouch id 0 candidate DirectionalDragArea
580− touchRegistry->removeCandidateOwnerForTouch(0, &directionalDragArea);
581−
582− //[TouchRegistry] sending TouchWonershipEvent(id = 0 gained) to candidate TouchGate
583− QCOMPARE(touchGate.ownedTouches.count(), 1);
584− QVERIFY(touchGate.ownedTouches.contains(0));
585−
586− // [TouchRegistry] addTouchWatcher id 0 watcher DirectionalDragArea
587− touchRegistry->addTouchWatcher(0, &directionalDragArea);
588−
589− // [TouchRegistry] requestTouchOwnership id 1 candidate TouchGate
590− touchRegistry->requestTouchOwnership(1, &touchGate);
591−
592− //[TouchRegistry] sending TouchWonershipEvent(id = 1 gained) to candidate TouchGate
593− QCOMPARE(touchGate.ownedTouches.count(), 2);
594− QVERIFY(touchGate.ownedTouches.contains(1));
595−
596− directionalDragArea.unownedTouchEvents.clear();
597− touchGate.unownedTouchEvents.clear();
598−
599− //[TouchRegistry] got TouchUpdate (id:0, state:moved, scenePos:(148,1025)) (id:1, state:moved, scenePos:(329,795))
600− {
601− QList<QTouchEvent::TouchPoint> touchPoints;
602− touchPoints.append(QTouchEvent::TouchPoint(0));
603− touchPoints[0].setState(Qt::TouchPointMoved);
604− touchPoints.append(QTouchEvent::TouchPoint(1));
605− touchPoints[1].setState(Qt::TouchPointMoved);
606− QTouchEvent touchEvent(QEvent::TouchUpdate,
607− 0 /* device */,
608− Qt::NoModifier,
609− Qt::TouchPointMoved,
610− touchPoints);
611− touchRegistry->update(&touchEvent);
612− }
613−
614− //vvvvv DDA Watchers are being ignored from now on vvvvvvv
615−
616− QCOMPARE(directionalDragArea.unownedTouchEvents.count(), 1);
617− QCOMPARE(directionalDragArea.unownedTouchEvents.first().touchPoints.count(), 2);
618− QVERIFY(directionalDragArea.unownedTouchEvents.first().containsTouchWithId(0));
619− QVERIFY(directionalDragArea.unownedTouchEvents.first().containsTouchWithId(1));
620−
621− QVERIFY(touchGate.unownedTouchEvents.isEmpty());
622−
623− directionalDragArea.unownedTouchEvents.clear();
624−
625− //[TouchRegistry] got TouchUpdate (id:0, state:moved, scenePos:(151,1029)) (id:1, state:released, scenePos:(329,795))
626− {
627− QList<QTouchEvent::TouchPoint> touchPoints;
628− touchPoints.append(QTouchEvent::TouchPoint(0));
629− touchPoints[0].setState(Qt::TouchPointMoved);
630− touchPoints.append(QTouchEvent::TouchPoint(1));
631− touchPoints[1].setState(Qt::TouchPointReleased);
632− QTouchEvent touchEvent(QEvent::TouchUpdate,
633− 0 /* device */,
634− Qt::NoModifier,
635− Qt::TouchPointMoved | Qt::TouchPointReleased,
636− touchPoints);
637− touchRegistry->update(&touchEvent);
638− }
639−
640− QCOMPARE(directionalDragArea.unownedTouchEvents.count(), 1);
641− QCOMPARE(directionalDragArea.unownedTouchEvents.first().touchPoints.count(), 2);
642− QVERIFY(directionalDragArea.unownedTouchEvents.first().containsTouchWithId(0));
643− QVERIFY(directionalDragArea.unownedTouchEvents.first().containsTouchWithId(1));
644−
645− QVERIFY(touchGate.unownedTouchEvents.isEmpty());
646−
647− directionalDragArea.unownedTouchEvents.clear();
648−
649− //[TouchRegistry] got TouchEnd (id:0, state:released, scenePos:(157,1034))
650− {
651− QList<QTouchEvent::TouchPoint> touchPoints;
652− touchPoints.append(QTouchEvent::TouchPoint(0));
653− touchPoints[0].setState(Qt::TouchPointReleased);
654− QTouchEvent touchEvent(QEvent::TouchEnd,
655− 0 /* device */,
656− Qt::NoModifier,
657− Qt::TouchPointReleased,
658− touchPoints);
659− touchRegistry->update(&touchEvent);
660− }
661−
662− QCOMPARE(directionalDragArea.unownedTouchEvents.count(), 1);
663− QCOMPARE(directionalDragArea.unownedTouchEvents.first().touchPoints.count(), 1);
664− QVERIFY(directionalDragArea.unownedTouchEvents.first().containsTouchWithId(0));
665−
666− QVERIFY(touchGate.unownedTouchEvents.isEmpty());
667−}
668−
669−void tst_TouchRegistry::rejectingTouchfterItsEnd()
670−{
671− DummyCandidate earlyCandidate;
672− DummyCandidate lateCandidate;
673−
674− {
675− QList<QTouchEvent::TouchPoint> touchPoints;
676− touchPoints.append(QTouchEvent::TouchPoint(0));
677− touchPoints[0].setState(Qt::TouchPointPressed);
678− QTouchEvent touchEvent(QEvent::TouchBegin,
679− 0 /* device */,
680− Qt::NoModifier,
681− Qt::TouchPointPressed,
682− touchPoints);
683− touchRegistry->update(&touchEvent);
684− }
685−
686− touchRegistry->addCandidateOwnerForTouch(0, &earlyCandidate);
687− touchRegistry->addCandidateOwnerForTouch(0, &lateCandidate);
688−
689− QVERIFY(earlyCandidate.ownedTouches.isEmpty());
690− QVERIFY(lateCandidate.ownedTouches.isEmpty());
691−
692− touchRegistry->requestTouchOwnership(0, &lateCandidate);
693−
694− QVERIFY(earlyCandidate.ownedTouches.isEmpty());
695− QVERIFY(lateCandidate.ownedTouches.isEmpty());
696−
697− {
698− QList<QTouchEvent::TouchPoint> touchPoints;
699− touchPoints.append(QTouchEvent::TouchPoint(0));
700− touchPoints[0].setState(Qt::TouchPointReleased);
701− QTouchEvent touchEvent(QEvent::TouchEnd,
702− 0 /* device */,
703− Qt::NoModifier,
704− Qt::TouchPointPressed,
705− touchPoints);
706− touchRegistry->update(&touchEvent);
707− }
708−
709− QVERIFY(earlyCandidate.ownedTouches.isEmpty());
710− QVERIFY(lateCandidate.ownedTouches.isEmpty());
711−
712− touchRegistry->removeCandidateOwnerForTouch(0, &earlyCandidate);
713−
714− QCOMPARE(lateCandidate.ownedTouches.count(), 1);
715− QVERIFY(lateCandidate.ownedTouches.contains(0));
716−
717− // Check that there's no trace left of touch 0 as we no longer need to keep tabs on it.
718− QVERIFY(!touchRegistry->findTouchInfo(0));
719−}
720−
721−void tst_TouchRegistry::removeOldUndecidedCandidates()
722−{
723− FakeTimerFactory *fakeTimerFactory = new FakeTimerFactory;
724− touchRegistry->setTimerFactory(fakeTimerFactory);
725−
726− DummyCandidate undecidedCandidate;
727− undecidedCandidate.setObjectName("undecided");
728−
729− DummyCandidate candidateThatWantsTouch;
730− candidateThatWantsTouch.setObjectName("wantsTouch");
731−
732− {
733− QList<QTouchEvent::TouchPoint> touchPoints;
734− touchPoints.append(QTouchEvent::TouchPoint(0));
735− touchPoints[0].setState(Qt::TouchPointPressed);
736− QTouchEvent touchEvent(QEvent::TouchBegin,
737− 0 /* device */,
738− Qt::NoModifier,
739− Qt::TouchPointPressed,
740− touchPoints);
741− touchRegistry->update(&touchEvent);
742− }
743−
744− touchRegistry->addCandidateOwnerForTouch(0, &undecidedCandidate);
745−
746− touchRegistry->requestTouchOwnership(0, &candidateThatWantsTouch);
747−
748− QVERIFY(undecidedCandidate.ownedTouches.isEmpty());
749− QVERIFY(undecidedCandidate.lostTouches.isEmpty());
750− QVERIFY(candidateThatWantsTouch.ownedTouches.isEmpty());
751− QVERIFY(candidateThatWantsTouch.lostTouches.isEmpty());
752−
753− // Simulate that enough time has passed to cause the CandidateInactivityTimer to timeout,
754− // making TouchRegistry consider that undecidedCantidate defaulted.
755− fakeTimerFactory->updateTime(10000);
756−
757− QVERIFY(undecidedCandidate.ownedTouches.isEmpty());
758− QVERIFY(undecidedCandidate.lostTouches.contains(0));
759− QVERIFY(candidateThatWantsTouch.ownedTouches.contains(0));
760− QVERIFY(candidateThatWantsTouch.lostTouches.isEmpty());
761−}
762−
763−/*
764− An item that calls requestTouchOwnership() without first having called addCandidateOwnerForTouch()
765− is assumed to be the interim owner of the touch point, thus there's no point in sending
766− UnownedTouchEvents to him as he already gets proper QTouchEvents from QQuickWindow because
767− he didn't ignore the first QTouchEvent with that touch point.
768− */
769−void tst_TouchRegistry::interimOwnerWontGetUnownedTouchEvents()
770−{
771− FakeTimerFactory *fakeTimerFactory = new FakeTimerFactory;
772− touchRegistry->setTimerFactory(fakeTimerFactory);
773−
774− DummyCandidate undecidedCandidate;
775− undecidedCandidate.setObjectName("undecided");
776−
777− DummyCandidate interimOwner;
778− interimOwner.setObjectName("interimOwner");
779−
780− {
781− QList<QTouchEvent::TouchPoint> touchPoints;
782− touchPoints.append(QTouchEvent::TouchPoint(0));
783− touchPoints[0].setState(Qt::TouchPointPressed);
784− QTouchEvent touchEvent(QEvent::TouchBegin,
785− 0 /* device */,
786− Qt::NoModifier,
787− Qt::TouchPointPressed,
788− touchPoints);
789− touchRegistry->update(&touchEvent);
790− }
791−
792− touchRegistry->addCandidateOwnerForTouch(0, &undecidedCandidate);
793− touchRegistry->requestTouchOwnership(0, &interimOwner);
794−
795− {
796− QList<QTouchEvent::TouchPoint> touchPoints;
797− touchPoints.append(QTouchEvent::TouchPoint(0));
798− touchPoints[0].setState(Qt::TouchPointMoved);
799− QTouchEvent touchEvent(QEvent::TouchUpdate,
800− 0 /* device */,
801− Qt::NoModifier,
802− Qt::TouchPointMoved,
803− touchPoints);
804− touchRegistry->update(&touchEvent);
805− }
806−
807− QCOMPARE(undecidedCandidate.unownedTouchEvents.count(), 1);
808− QCOMPARE(interimOwner.unownedTouchEvents.count(), 0);
809−
810− {
811− QList<QTouchEvent::TouchPoint> touchPoints;
812− touchPoints.append(QTouchEvent::TouchPoint(0));
813− touchPoints[0].setState(Qt::TouchPointMoved);
814− QTouchEvent touchEvent(QEvent::TouchUpdate,
815− 0 /* device */,
816− Qt::NoModifier,
817− Qt::TouchPointMoved,
818− touchPoints);
819− touchRegistry->update(&touchEvent);
820− }
821−
822− QCOMPARE(undecidedCandidate.unownedTouchEvents.count(), 2);
823− QCOMPARE(interimOwner.unownedTouchEvents.count(), 0);
824−}
825−
826−/*
827− Regression test for https://bugs.launchpad.net/ubuntu/+source/unity8/+bug/1473492
828−
829− Bug caused by candidates getting deleted before ownership resolution
830− */
831−void tst_TouchRegistry::candidateVanishes()
832−{
833− DummyCandidate mainCandidate;
834− DummyCandidate *missingCandidate = new DummyCandidate;
835−
836− {
837− QList<QTouchEvent::TouchPoint> touchPoints;
838− touchPoints.append(QTouchEvent::TouchPoint(0));
839− touchPoints[0].setState(Qt::TouchPointPressed);
840− QTouchEvent touchEvent(QEvent::TouchBegin,
841− 0 /* device */,
842− Qt::NoModifier,
843− Qt::TouchPointPressed,
844− touchPoints);
845− touchRegistry->update(&touchEvent);
846− }
847−
848− touchRegistry->addCandidateOwnerForTouch(0, &mainCandidate);
849− touchRegistry->addCandidateOwnerForTouch(0, missingCandidate);
850−
851− {
852− QList<QTouchEvent::TouchPoint> touchPoints;
853− touchPoints.append(QTouchEvent::TouchPoint(0));
854− touchPoints[0].setState(Qt::TouchPointMoved);
855− QTouchEvent touchEvent(QEvent::TouchUpdate,
856− 0 /* device */,
857− Qt::NoModifier,
858− Qt::TouchPointMoved,
859− touchPoints);
860− touchRegistry->update(&touchEvent);
861− }
862−
863− // This candidate suddenly disappears without having removed its candidacy.
864− delete missingCandidate;
865− missingCandidate = nullptr;
866−
867− touchRegistry->requestTouchOwnership(0, &mainCandidate);
868−
869− QVERIFY(mainCandidate.ownedTouches.contains(0));
870−}
871−
872−/*
873− Regression test for canidate reentrance
874−
875− Bug caused by candidates getting removed during ownership resolution
876− */
877−void tst_TouchRegistry::candicateOwnershipReentrace()
878−{
879− DummyCandidate mainCandidate;
880− DummyCandidate candicate2;
881− DummyCandidate candicate3;
882−
883− {
884− QList<QTouchEvent::TouchPoint> touchPoints;
885− touchPoints.append(QTouchEvent::TouchPoint(0));
886− touchPoints[0].setState(Qt::TouchPointPressed);
887− QTouchEvent touchEvent(QEvent::TouchBegin,
888− 0 /* device */,
889− Qt::NoModifier,
890− Qt::TouchPointPressed,
891− touchPoints);
892− touchRegistry->update(&touchEvent);
893− }
894−
895− // Re-entrance!
896− connect(&candicate2, &DummyCandidate::lostOwnership, this, [&]() {
897− touchRegistry->removeCandidateOwnerForTouch(0, &candicate2);
898− });
899−
900− touchRegistry->addCandidateOwnerForTouch(0, &mainCandidate);
901− touchRegistry->addCandidateOwnerForTouch(0, &candicate2);
902− touchRegistry->addCandidateOwnerForTouch(0, &candicate3);
903−
904− {
905− QList<QTouchEvent::TouchPoint> touchPoints;
906− touchPoints.append(QTouchEvent::TouchPoint(0));
907− touchPoints[0].setState(Qt::TouchPointMoved);
908− QTouchEvent touchEvent(QEvent::TouchUpdate,
909− 0 /* device */,
910− Qt::NoModifier,
911− Qt::TouchPointMoved,
912− touchPoints);
913− touchRegistry->update(&touchEvent);
914− }
915−
916− touchRegistry->requestTouchOwnership(0, &mainCandidate);
917−
918− QCOMPARE(mainCandidate.ownedTouches.count(), 1);
919− QCOMPARE(candicate2.lostTouches.count(), 1);
920− QCOMPARE(candicate3.lostTouches.count(), 1);
921−}
922−
923−
924−////////////// TouchMemento //////////
925−
926−TouchMemento::TouchMemento(const QTouchEvent *touchEvent)
927− : touchPointStates(touchEvent->touchPointStates()), touchPoints(touchEvent->touchPoints())
928−{
929−}
930−
931−bool TouchMemento::containsTouchWithId(int touchId) const
932−{
933− for (int i = 0; i < touchPoints.count(); ++i) {
934− if (touchPoints.at(i).id() == touchId) {
935− return true;
936− }
937− }
938− return false;
939−}
940−
941−////////////// DummyCandidate //////////
942−
943−bool DummyCandidate::event(QEvent *e)
944−{
945− if (e->type() == TouchOwnershipEvent::touchOwnershipEventType()) {
946− TouchOwnershipEvent *touchOwnershipEvent = static_cast<TouchOwnershipEvent *>(e);
947−
948− // NB: Cannot use QVERIFY here because the macro doesn't return a boolean and is
949− // meant for use only directly in the body of a test function
950− if (ownedTouches.contains(touchOwnershipEvent->touchId()))
951− qFatal("Sent ownership event for a touch that is already owned.");
952− if (lostTouches.contains(touchOwnershipEvent->touchId()))
953− qFatal("Sent ownership event for a touch that has already been lost.");
954−
955− if (touchOwnershipEvent->gained()) {
956− ownedTouches.insert(touchOwnershipEvent->touchId());
957− Q_EMIT gainedOwnership();
958− } else {
959− lostTouches.insert(touchOwnershipEvent->touchId());
960− Q_EMIT lostOwnership();
961− }
962− return true;
963− } else if (e->type() == UnownedTouchEvent::unownedTouchEventType()) {
964− UnownedTouchEvent *unownedTouchEvent = static_cast<UnownedTouchEvent *>(e);
965− unownedTouchEvents.append(TouchMemento(unownedTouchEvent->touchEvent()));
966− return true;
967− } else {
968− return QObject::event(e);
969− }
970−}
971−
972−QTEST_GUILESS_MAIN(tst_TouchRegistry)
973−
974−#include "tst_TouchRegistry.moc"
tests/mocks/Cursor/qmldir+1−1
@@ -1,2 +1,2 @@
1module Cursor
1module Cursor
2−Cursor 1.0 Cursor.qml
2+Cursor 1.1 Cursor.qml
tests/mocks/GSettings.1.0/fake_gsettings.cpp+1
@@ -22,6 +22,7 @@ GSettingsControllerQml* GSettingsControllerQml::s_controllerInstance = 0;
22
22
23GSettingsControllerQml::GSettingsControllerQml()
23GSettingsControllerQml::GSettingsControllerQml()
24 : m_disableHeight(false)
24 : m_disableHeight(false)
25+ , m_lockedOutTime(0)
25 , m_usageMode("Staged")
26 , m_usageMode("Staged")
26 , m_autohideLauncher(false)
27 , m_autohideLauncher(false)
27 , m_launcherWidth(8)
28 , m_launcherWidth(8)
tests/mocks/GSettings.1.0/fake_gsettings.h+2−2
@@ -61,8 +61,8 @@ class GSettingsQml: public QObject, public QQmlParserStatus
61public:
61public:
62 GSettingsQml(QObject *parent = nullptr);
62 GSettingsQml(QObject *parent = nullptr);
63
63
64− void classBegin();
64+ void classBegin() override;
65− void componentComplete();
65+ void componentComplete() override;
66
66
67 GSettingsSchemaQml * schema() const;
67 GSettingsSchemaQml * schema() const;
68 QVariant disableHeight() const;
68 QVariant disableHeight() const;
tests/mocks/IntegratedLightDM/liblightdm/GreeterPrivate.h−1
@@ -41,7 +41,6 @@ public:
41 void handleRespond(const QString &response);
41 void handleRespond(const QString &response);
42
42
43protected:
43protected:
44− GreeterImpl *m_impl; // if the backend needs more private data
45 Greeter * const q_ptr;
44 Greeter * const q_ptr;
46
45
47private:
46private:
tests/mocks/QtMultimedia/audio.cpp+3−3
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2013, 2015 Canonical, Ltd.
2+ * Copyright (C) 2013-2016 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
@@ -21,7 +21,7 @@
21Audio::Audio(QObject* parent):
21Audio::Audio(QObject* parent):
22 QObject(parent),
22 QObject(parent),
23 m_playbackState(StoppedState),
23 m_playbackState(StoppedState),
24− m_playlist(0)
24+ m_playlist(nullptr)
25{
25{
26 qsrand(time(nullptr));
26 qsrand(time(nullptr));
27 m_timer.setInterval(1000);
27 m_timer.setInterval(1000);
@@ -109,7 +109,7 @@ void Audio::timerEvent()
109
109
110Audio::AudioRole Audio::audioRole() const
110Audio::AudioRole Audio::audioRole() const
111{
111{
112− return Audio::multimedia;
112+ return Audio::MusicRole;
113}
113}
114
114
115void Audio::setAudioRole(Audio::AudioRole audioRole)
115void Audio::setAudioRole(Audio::AudioRole audioRole)
tests/mocks/QtMultimedia/audio.h+12−6
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2012, 2013, 2015 Canonical, Ltd.
2+ * Copyright (C) 2012-2016 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
@@ -44,13 +44,19 @@ public:
44 };
44 };
45
45
46 enum AudioRole {
46 enum AudioRole {
47− alarm,
47+ UnknownRole,
48− alert,
48+ MusicRole,
49− multimedia,
49+ VideoRole,
50− phone
50+ VoiceCommunicationRole,
51+ AlarmRole,
52+ NotificationRole,
53+ RingtoneRole,
54+ AccessibilityRole,
55+ SonificationRole,
56+ GameRole
51 };
57 };
52
58
53− explicit Audio(QObject *parent = 0);
59+ explicit Audio(QObject *parent = nullptr);
54
60
55 QUrl source() const;
61 QUrl source() const;
56 void setSource(const QUrl &source);
62 void setSource(const QUrl &source);
tests/mocks/Ubuntu/Payments/MockPayments.cpp+1
@@ -21,6 +21,7 @@
21
21
22MockPayments::MockPayments(QObject *parent)
22MockPayments::MockPayments(QObject *parent)
23 : QObject(parent)
23 : QObject(parent)
24+ , m_price(0)
24{
25{
25}
26}
26
27
tests/mocks/Ubuntu/SystemSettings/TimeDate/CMakeLists.txt+1−1
@@ -1 +1 @@
1−add_unity8_mock(Ubuntu.SystemSettings.TimeDate 1.0 Ubuntu/SystemSettings/TimeDate)
1+add_unity8_mock(Ubuntu.SystemSettings.TimeDate 1.1 Ubuntu/SystemSettings/TimeDate)
tests/mocks/Ubuntu/SystemSettings/TimeDate/MockTimeDate.qml+15−3
@@ -18,8 +18,20 @@ import QtQuick 2.4
18
18
19Item {
19Item {
20 id: root
20 id: root
21− property string timeZone: "Europe/Prague"
21+ readonly property alias timeZone: d.timeZone
22− onTimeZoneChanged: root.timeZoneChangedCalled(root.timeZone);
22+ readonly property alias timeZoneName: d.timeZoneName
23
23
24− signal timeZoneChangedCalled(string tz);
24+ signal timeZoneChangedCalled(string tz, string name) // only in mock
25+
26+ function setTimeZone(tz, name) {
27+ d.timeZone = tz;
28+ d.timeZoneName = name;
29+ timeZoneChangedCalled(tz, name);
30+ }
31+
32+ QtObject {
33+ id: d
34+ property string timeZone: "Europe/Prague"
35+ property string timeZoneName: "Prague"
36+ }
25}
37}
tests/mocks/Ubuntu/SystemSettings/TimeDate/qmldir+1−1
@@ -1,2 +1,2 @@
1module Ubuntu.SystemSettings.TimeDate
1module Ubuntu.SystemSettings.TimeDate
2−UbuntuTimeDatePanel 1.0 MockTimeDate.qml
2+UbuntuTimeDatePanel 1.1 MockTimeDate.qml
tests/mocks/Unity/Application/ApplicationInfo.h+1−1
@@ -67,7 +67,7 @@ public:
67
67
68 QUrl icon() const override { return m_icon; }
68 QUrl icon() const override { return m_icon; }
69
69
70− Q_INVOKABLE void setStage(Stage value); // invokable only for mock
70+ Q_INVOKABLE void setStage(Stage value) override; // invokable only for mock
71 Stage stage() const override { return m_stage; }
71 Stage stage() const override { return m_stage; }
72
72
73 Q_INVOKABLE void setState(State value);
73 Q_INVOKABLE void setState(State value);
tests/mocks/Unity/Application/MirSurface.h+2−2
@@ -96,8 +96,8 @@ public:
96 int widthIncrement() const override { return m_widthIncrement; }
96 int widthIncrement() const override { return m_widthIncrement; }
97 int heightIncrement() const override { return m_heightIncrement; }
97 int heightIncrement() const override { return m_heightIncrement; }
98
98
99− virtual void setKeymap(const QString &);
99+ void setKeymap(const QString &) override;
100− virtual QString keymap() const;
100+ QString keymap() const override;
101
101
102 Mir::ShellChrome shellChrome() const override;
102 Mir::ShellChrome shellChrome() const override;
103
103
tests/mocks/Unity/Application/MirSurfaceItem.cpp+17−7
@@ -40,6 +40,7 @@ using namespace unity::shell::application;
40MirSurfaceItem::MirSurfaceItem(QQuickItem *parent)
40MirSurfaceItem::MirSurfaceItem(QQuickItem *parent)
41 : MirSurfaceItemInterface(parent)
41 : MirSurfaceItemInterface(parent)
42 , m_qmlSurface(nullptr)
42 , m_qmlSurface(nullptr)
43+ , m_qmlContentComponent(nullptr)
43 , m_qmlItem(nullptr)
44 , m_qmlItem(nullptr)
44 , m_consumesInput(false)
45 , m_consumesInput(false)
45 , m_surfaceWidth(0)
46 , m_surfaceWidth(0)
@@ -56,7 +57,11 @@ MirSurfaceItem::MirSurfaceItem(QQuickItem *parent)
56 Qt::ExtraButton9 | Qt::ExtraButton10 | Qt::ExtraButton11 |
57 Qt::ExtraButton9 | Qt::ExtraButton10 | Qt::ExtraButton11 |
57 Qt::ExtraButton12 | Qt::ExtraButton13);
58 Qt::ExtraButton12 | Qt::ExtraButton13);
58
59
60+ connect(this, &QQuickItem::activeFocusChanged, this, &MirSurfaceItem::updateMirSurfaceActiveFocus);
59 connect(this, &QQuickItem::visibleChanged, this, &MirSurfaceItem::updateMirSurfaceVisibility);
61 connect(this, &QQuickItem::visibleChanged, this, &MirSurfaceItem::updateMirSurfaceVisibility);
62+ connect(this, &MirSurfaceItem::consumesInputChanged, this, [this]() {
63+ updateMirSurfaceActiveFocus(hasActiveFocus());
64+ });
60}
65}
61
66
62MirSurfaceItem::~MirSurfaceItem()
67MirSurfaceItem::~MirSurfaceItem()
@@ -234,6 +239,10 @@ void MirSurfaceItem::setSurface(MirSurfaceInterface* surface)
234 delete m_qmlContentComponent;
239 delete m_qmlContentComponent;
235 m_qmlContentComponent = nullptr;
240 m_qmlContentComponent = nullptr;
236
241
242+ if (hasActiveFocus() && m_consumesInput && m_qmlSurface->live()) {
243+ m_qmlSurface->setActiveFocus(false);
244+ }
245+
237 disconnect(m_qmlSurface, nullptr, this, nullptr);
246 disconnect(m_qmlSurface, nullptr, this, nullptr);
238 m_qmlSurface->unregisterView((qintptr)this);
247 m_qmlSurface->unregisterView((qintptr)this);
239 }
248 }
@@ -243,8 +252,6 @@ void MirSurfaceItem::setSurface(MirSurfaceInterface* surface)
243 if (m_qmlSurface) {
252 if (m_qmlSurface) {
244 m_qmlSurface->registerView((qintptr)this);
253 m_qmlSurface->registerView((qintptr)this);
245
254
246− m_qmlSurface->setActiveFocus(hasActiveFocus());
247−
248 updateSurfaceSize();
255 updateSurfaceSize();
249 updateMirSurfaceVisibility();
256 updateMirSurfaceVisibility();
250
257
@@ -277,17 +284,20 @@ void MirSurfaceItem::setSurface(MirSurfaceInterface* surface)
277 default:
284 default:
278 qFatal("MirSurfaceItem: Unhandled component status");
285 qFatal("MirSurfaceItem: Unhandled component status");
279 }
286 }
287+
288+ if (m_consumesInput) {
289+ m_qmlSurface->setActiveFocus(hasActiveFocus());
290+ }
280 }
291 }
281
292
282 Q_EMIT surfaceChanged(m_qmlSurface);
293 Q_EMIT surfaceChanged(m_qmlSurface);
283}
294}
284
295
285−void MirSurfaceItem::itemChange(ItemChange change, const ItemChangeData & value)
296+
297+void MirSurfaceItem::updateMirSurfaceActiveFocus(bool focused)
286{
298{
287− if (change == QQuickItem::ItemActiveFocusHasChanged) {
299+ if (m_qmlSurface && m_consumesInput && m_qmlSurface->live()) {
288− if (m_qmlSurface) {
289− m_qmlSurface->setActiveFocus(value.boolValue);
300+ m_qmlSurface->setActiveFocus(focused);
290− }
291 }
301 }
292}
302}
293
303
tests/mocks/Unity/Application/MirSurfaceItem.h+1−1
@@ -98,12 +98,12 @@ protected:
98 void mousePressEvent(QMouseEvent * event) override;
98 void mousePressEvent(QMouseEvent * event) override;
99 void mouseMoveEvent(QMouseEvent * event) override;
99 void mouseMoveEvent(QMouseEvent * event) override;
100 void mouseReleaseEvent(QMouseEvent * event) override;
100 void mouseReleaseEvent(QMouseEvent * event) override;
101− void itemChange(ItemChange change, const ItemChangeData & value) override;
102
101
103private Q_SLOTS:
102private Q_SLOTS:
104 void onComponentStatusChanged(QQmlComponent::Status status);
103 void onComponentStatusChanged(QQmlComponent::Status status);
105 void updateScreenshot(QUrl screenshot);
104 void updateScreenshot(QUrl screenshot);
106 void updateMirSurfaceVisibility();
105 void updateMirSurfaceVisibility();
106+ void updateMirSurfaceActiveFocus(bool focused);
107
107
108private:
108private:
109 void createQmlContentItem();
109 void createQmlContentItem();
tests/mocks/Unity/InputInfo/plugin.h+1−1
@@ -24,7 +24,7 @@ class InputInfoPlugin : public QQmlExtensionPlugin
24 Q_OBJECT
24 Q_OBJECT
25 Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
25 Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
26public:
26public:
27− void registerTypes(const char *uri);
27+ void registerTypes(const char *uri) override;
28};
28};
29
29
30#endif // INPUTINFO_PLUGIN_H
30#endif // INPUTINFO_PLUGIN_H
tests/mocks/Unity/Screens/plugin.h+1−1
@@ -21,5 +21,5 @@ class UnityScreensPlugin : public QQmlExtensionPlugin {
21 Q_OBJECT
21 Q_OBJECT
22 Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0")
22 Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0")
23public:
23public:
24− virtual void registerTypes(const char* uri);
24+ void registerTypes(const char* uri) override;
25};
25};
tests/mocks/Unity/fake_scope.cpp+6−3
@@ -32,7 +32,7 @@ Scope::Scope(Scopes* parent) : Scope("MockScope5", "Mock Scope", false, parent)
32{
32{
33}
33}
34
34
35−Scope::Scope(QString const& id, QString const& name, bool favorite, Scopes* parent, int categories, bool returnNullPreview)
35+Scope::Scope(QString const& id, QString const& name, bool favorite, Scopes* parent, int categories, bool returnNullPreview, const QStringList primaryNavigationFilterOptionLabels)
36 : unity::shell::scopes::ScopeInterface(parent)
36 : unity::shell::scopes::ScopeInterface(parent)
37 , m_id(id)
37 , m_id(id)
38 , m_name(name)
38 , m_name(name)
@@ -49,10 +49,11 @@ Scope::Scope(QString const& id, QString const& name, bool favorite, Scopes* pare
49 , m_filters(new Filters(this))
49 , m_filters(new Filters(this))
50 , m_returnNullPreview(returnNullPreview)
50 , m_returnNullPreview(returnNullPreview)
51{
51{
52+ m_primaryNavigationFilter = new FakeOptionSelectorFilter("OSF3", "PFTag", "Which food you like More", false, primaryNavigationFilterOptionLabels, this);
52 m_filters->addFakeFilters();
53 m_filters->addFakeFilters();
53−
54− m_primaryNavigationFilter = new FakeOptionSelectorFilter("OSF3", "PFTag", "Which food you like More", false, QStringList() << "meat" << "vegetables", this);
55 connect(m_filters, &Filters::activeFiltersCountChanged, this, &Scope::activeFiltersCountChanged);
54 connect(m_filters, &Filters::activeFiltersCountChanged, this, &Scope::activeFiltersCountChanged);
55+ connect(m_primaryNavigationFilter, &FakeOptionSelectorFilter::isActiveChanged,
56+ this, &unity::shell::scopes::ScopeInterface::primaryNavigationTagChanged);
56}
57}
57
58
58QString Scope::id() const
59QString Scope::id() const
@@ -326,6 +327,8 @@ unity::shell::scopes::FiltersInterface* Scope::filters() const
326
327
327QString Scope::primaryNavigationTag() const
328QString Scope::primaryNavigationTag() const
328{
329{
330+ if (m_hasPrimaryFilter && m_primaryNavigationFilter->isActive())
331+ return m_primaryNavigationFilter->filterTag();
329 if (m_currentNavigationId == "root")
332 if (m_currentNavigationId == "root")
330 return QString();
333 return QString();
331 else
334 else
tests/mocks/Unity/fake_scope.h+1−1
@@ -34,7 +34,7 @@ class Scope : public unity::shell::scopes::ScopeInterface
34
34
35public:
35public:
36 Scope(Scopes* parent = 0);
36 Scope(Scopes* parent = 0);
37− Scope(QString const& id, QString const& name, bool favorite, Scopes* parent = 0, int categories = 20, bool returnNullPreview = false);
37+ Scope(QString const& id, QString const& name, bool favorite, Scopes* parent = 0, int categories = 20, bool returnNullPreview = false, const QStringList primaryNavigationFilterOptionLabels = QStringList() << "meat" << "vegetables");
38
38
39 /* getters */
39 /* getters */
40 QString id() const override;
40 QString id() const override;
tests/mocks/Unity/fake_scopes.cpp+11
@@ -60,6 +60,17 @@ void Scopes::updateScopes()
60 addScope(new Scope("MockScope7", "MS7", false, this));
60 addScope(new Scope("MockScope7", "MS7", false, this));
61 addScope(new Scope("MockScope8", "MS8", false, this));
61 addScope(new Scope("MockScope8", "MS8", false, this));
62 addScope(new Scope("MockScope9", "MS9", false, this));
62 addScope(new Scope("MockScope9", "MS9", false, this));
63+
64+ Scope *longNavigationScope = new Scope(
65+ "LongPrimaryNavigation", "LongPrimaryNavigation", true, this, 1, false,
66+ QStringList() << "Meat" << "Vegetables" << "BBQ" << "Burritos"
67+ << "Pasta" << "Pancakes" << "Seafood" << "Soup" << "Bugs"
68+ << "Pudding" << "Chocolate" << "Gluten-Free" << "Hamburgers"
69+ << "Pho" << "Panang Curry" << "Lumpia" << "Sushi");
70+
71+ longNavigationScope->setHasNavigation(false);
72+ addScope(longNavigationScope);
73+
63 addScope(new Scope("NullPreviewScope", "NPS", false, this, 1, true));
74 addScope(new Scope("NullPreviewScope", "NPS", false, this, 1, true));
64 m_scopesOverview = new ScopesOverview(this);
75 m_scopesOverview = new ScopesOverview(this);
65
76
tests/mocks/Utils/plugin.h+1−1
@@ -26,7 +26,7 @@ class FakeUtilsPlugin : public QQmlExtensionPlugin
26 Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
26 Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
27
27
28public:
28public:
29− void registerTypes(const char *uri);
29+ void registerTypes(const char *uri) override;
30};
30};
31
31
32#endif
32#endif
tests/mocks/Utils/windowstatestorage.cpp+1
@@ -50,6 +50,7 @@ QRect WindowStateStorage::getGeometry(const QString &windowId, const QRect &defa
50void WindowStateStorage::saveStage(const QString &appId, int stage)
50void WindowStateStorage::saveStage(const QString &appId, int stage)
51{
51{
52 m_stage[appId] = stage;
52 m_stage[appId] = stage;
53+ Q_EMIT stageSaved(appId, stage);
53}
54}
54
55
55int WindowStateStorage::getStage(const QString &appId) const
56int WindowStateStorage::getStage(const QString &appId) const
tests/mocks/Utils/windowstatestorage.h+17−3
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright 2015 Canonical Ltd.
2+ * Copyright 2015-2016 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 Lesser General Public License as published by
5 * it under the terms of the GNU Lesser General Public License as published by
@@ -25,9 +25,20 @@ class WindowStateStorage: public QObject
25 Q_ENUMS(WindowState)
25 Q_ENUMS(WindowState)
26public:
26public:
27 enum WindowState {
27 enum WindowState {
28− WindowStateNormal,
28+ WindowStateNormal = 1 << 0,
29− WindowStateMaximized
29+ WindowStateMaximized = 1 << 1,
30+ WindowStateMinimized = 1 << 2,
31+ WindowStateFullscreen = 1 << 3,
32+ WindowStateMaximizedLeft = 1 << 4,
33+ WindowStateMaximizedRight = 1 << 5,
34+ WindowStateMaximizedHorizontally = 1 << 6,
35+ WindowStateMaximizedVertically = 1 << 7
30 };
36 };
37+ Q_DECLARE_FLAGS(WindowStates, WindowState)
38+#if (QT_VERSION >= QT_VERSION_CHECK(5, 5, 0))
39+ Q_FLAG(WindowStates)
40+#endif
41+
31 WindowStateStorage(QObject *parent = 0);
42 WindowStateStorage(QObject *parent = 0);
32
43
33 Q_INVOKABLE void saveState(const QString &windowId, WindowState state);
44 Q_INVOKABLE void saveState(const QString &windowId, WindowState state);
@@ -45,6 +56,9 @@ public:
45Q_SIGNALS:
56Q_SIGNALS:
46 void geometryChanged(const QVariantMap& geometry);
57 void geometryChanged(const QVariantMap& geometry);
47
58
59+ // For testing.
60+ void stageSaved(const QString& appId, int stage);
61+
48private:
62private:
49 void setGeometry(const QVariantMap& geometry);
63 void setGeometry(const QVariantMap& geometry);
50 QVariantMap geometry() const;
64 QVariantMap geometry() const;
tests/mocks/libusermetrics/UserMetrics.cpp+1−1
@@ -220,7 +220,7 @@ int UserMetricsData::length() const
220}
220}
221
221
222UserMetricsPrivate::UserMetricsPrivate(UserMetrics *parent) :
222UserMetricsPrivate::UserMetricsPrivate(UserMetrics *parent) :
223− q_ptr(parent), m_firstColor(this), m_secondColor(this)
223+ q_ptr(parent), m_firstColor(this), m_secondColor(this), m_currentDay(0)
224{
224{
225 m_fakeData.insert("", UserMetricsDataPtr(new UserMetricsData(this)));
225 m_fakeData.insert("", UserMetricsDataPtr(new UserMetricsData(this)));
226}
226}
tests/plugins/CMakeLists.txt+2−1
@@ -1,8 +1,9 @@
1add_subdirectory(AccountsService)
1add_subdirectory(AccountsService)
2+add_subdirectory(Cursor)
3+add_subdirectory(Dash)
2add_subdirectory(GlobalShortcut)
4add_subdirectory(GlobalShortcut)
3add_subdirectory(Greeter)
5add_subdirectory(Greeter)
4add_subdirectory(IntegratedLightDM)
6add_subdirectory(IntegratedLightDM)
5−add_subdirectory(Dash)
6add_subdirectory(Ubuntu)
7add_subdirectory(Ubuntu)
7add_subdirectory(Unity)
8add_subdirectory(Unity)
8add_subdirectory(Utils)
9add_subdirectory(Utils)
tests/plugins/Cursor/CMakeLists.txtnew file+8
@@ -0,0 +1,8 @@
1+include(QmlTest)
2+
3+set(UNITY_IMPORT_PATHS
4+ ${CMAKE_BINARY_DIR}/tests/utils/modules
5+ ${UNITY_PLUGINPATH}
6+)
7+
8+add_manual_qml_test(. Cursor IMPORT_PATHS ${UNITY_IMPORT_PATHS})
tests/plugins/Cursor/TextEntry.qmlnew file+34
@@ -0,0 +1,34 @@
1+/*
2+ * Copyright (C) 2016 Canonical, Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it under
5+ * the terms of the GNU Lesser General Public License version 3, as published by
6+ * the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful, but WITHOUT
9+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11+ * Lesser General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.4
18+
19+Column {
20+ property alias name: entryText.text
21+ property alias value: textInput.text
22+ Text { id: entryText }
23+ Rectangle {
24+ color: "white"
25+ width: parent.width - 20
26+ height: 40
27+ TextInput {
28+ id: textInput
29+ anchors.fill: parent
30+ verticalAlignment: TextInput.AlignVCenter
31+ selectByMouse: true
32+ }
33+ }
34+}
tests/plugins/Cursor/tst_Cursor.qmlnew file+144
@@ -0,0 +1,144 @@
1+/*
2+ * Copyright (C) 2016 Canonical, Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it under
5+ * the terms of the GNU Lesser General Public License version 3, as published by
6+ * the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful, but WITHOUT
9+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11+ * Lesser General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+
18+import QtQuick 2.4
19+import Cursor 1.1
20+
21+Rectangle {
22+ id: root
23+ color: "blue"
24+ width: 400
25+ height: 600
26+
27+ property string themeName: "default"
28+ property string cursorName: "left_ptr"
29+
30+ CursorImageInfo {
31+ id: imageInfo
32+ themeName: root.themeName
33+ cursorName: root.cursorName
34+ }
35+
36+ Item {
37+ id: cursor
38+ x: (200 - animatedSprite.width) / 2
39+ y: (root.height - animatedSprite.height) / 2
40+
41+ AnimatedSprite {
42+ id: animatedSprite
43+
44+ x: -imageInfo.hotspot.x
45+ y: -imageInfo.hotspot.y
46+ source: "image://cursor/" + root.themeName + "/" + root.cursorName
47+
48+ interpolate: false
49+
50+ width: imageInfo.frameWidth
51+ height: imageInfo.frameHeight
52+
53+ frameCount: imageInfo.frameCount
54+ frameDuration: imageInfo.frameDuration
55+ frameWidth: imageInfo.frameWidth
56+ frameHeight: imageInfo.frameHeight
57+ }
58+ }
59+
60+ Rectangle {
61+ id: hotspotCrossH
62+ color: "red"
63+ width: 200
64+ height: 1
65+ anchors.top: cursor.top
66+ opacity: 0.6
67+ }
68+ Rectangle {
69+ id: hotspotCrossV
70+ color: "red"
71+ width: 1
72+ anchors.left: cursor.left
73+ anchors.top: parent.top
74+ anchors.bottom: parent.bottom
75+ opacity: 0.6
76+ }
77+ MouseArea {
78+ anchors.top: parent.top
79+ anchors.bottom: parent.bottom
80+ anchors.left: parent.left
81+ anchors.right: controls.left
82+ onClicked: {
83+ if (hotspotCrossH.visible) {
84+ hotspotCrossH.visible = false;
85+ hotspotCrossV.visible = false;
86+ } else {
87+ hotspotCrossH.visible = true;
88+ hotspotCrossV.visible = true;
89+ }
90+ }
91+ }
92+
93+ Rectangle {
94+ id: controls
95+ color: "lightgrey"
96+ anchors.right: parent.right
97+ anchors.top: parent.top
98+ anchors.bottom: parent.bottom
99+ width: root.width - 200
100+
101+ Column {
102+ anchors.fill: parent
103+ anchors.margins: 10
104+
105+ TextEntry { id: themeNameEntry; name: "themeName"; value: "default" }
106+
107+ Item {width: 10; height: 20}
108+
109+ TextEntry { id: cursorNameEntry; name: "cursorName"; value: "left_ptr" }
110+
111+ Item {width: 10; height: 40}
112+
113+ Rectangle {
114+ color: applyMouseArea.pressed ? "green" : "lightslategray"
115+ width: parent.width - 20
116+ height: 40
117+ Text { anchors.centerIn: parent; text: "Apply" }
118+ MouseArea {
119+ id: applyMouseArea
120+ anchors.fill: parent
121+ onClicked: {
122+ root.themeName = themeNameEntry.value;
123+ root.cursorName = cursorNameEntry.value;
124+ }
125+ }
126+ }
127+
128+ Item {width: 10; height: 10}
129+ Rectangle {
130+ color: "black"
131+ height: 2
132+ anchors.left: parent.left
133+ anchors.right: parent.right
134+ }
135+ Item {width: 10; height: 10}
136+
137+ Text { text: "frameWidth: " + imageInfo.frameWidth }
138+ Text { text: "frameHeight: " + imageInfo.frameHeight }
139+ Text { text: "frameCount: " + imageInfo.frameCount }
140+ Text { text: "frameDuration: " + imageInfo.frameDuration }
141+ Text { text: "currentFrame: " + animatedSprite.currentFrame }
142+ }
143+ }
144+}
tests/plugins/Dash/cardcreator/1.res+8−26
@@ -1,7 +1,6 @@
1AbstractButton {
1AbstractButton {
2 id: root;
2 id: root;
3 property var cardData;
3 property var cardData;
4− property string artShapeStyle: "inset";
5 property string backgroundShapeStyle: "inset";
4 property string backgroundShapeStyle: "inset";
6 property real fontScale: 1.0;
5 property real fontScale: 1.0;
7 property var scopeStyle: null;
6 property var scopeStyle: null;
@@ -22,6 +21,7 @@ Item {
22 id: artShapeLoader;
21 id: artShapeLoader;
23 objectName: "artShapeLoader";
22 objectName: "artShapeLoader";
24 readonly property string cardArt: cardData && cardData["art"] || "";
23 readonly property string cardArt: cardData && cardData["art"] || "";
24+ onCardArtChanged: { if (item) { item.image.source = cardArt; } }
25 active: cardArt != "";
25 active: cardArt != "";
26 asynchronous: true;
26 asynchronous: true;
27 visible: status == Loader.Ready;
27 visible: status == Loader.Ready;
@@ -30,30 +30,12 @@ Item {
30 objectName: "artShape";
30 objectName: "artShape";
31 visible: image.status == Image.Ready;
31 visible: image.status == Image.Ready;
32 readonly property alias image: artImage;
32 readonly property alias image: artImage;
33− Loader {
33+ UbuntuShape {
34 anchors.fill: parent;
34 anchors.fill: parent;
35− visible: true;
36− sourceComponent: root.artShapeStyle === "icon" ? artShapeIconComponent : artShapeShapeComponent;
37− Component {
38− id: artShapeShapeComponent;
39− UbuntuShape {
40− source: artImage;
35+ source: artImage;
41− sourceFillMode: UbuntuShape.PreserveAspectCrop;
36+ sourceFillMode: UbuntuShape.PreserveAspectCrop;
42− radius: "medium";
37+ radius: "medium";
43− aspect: {
44− switch (root.artShapeStyle) {
45− case "inset": return UbuntuShape.Inset;
38+ aspect: UbuntuShape.Inset;
46− case "shadow": return UbuntuShape.DropShadow;
47− default:
48− case "flat": return UbuntuShape.Flat;
49− }
50− }
51− }
52− }
53− Component {
54− id: artShapeIconComponent;
55− ProportionalShape { source: artImage; aspect: UbuntuShape.DropShadow; }
56− }
57 }
39 }
58 readonly property real fixedArtShapeSizeAspect: (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) ? root.fixedArtShapeSize.width / root.fixedArtShapeSize.height : -1;
40 readonly property real fixedArtShapeSizeAspect: (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) ? root.fixedArtShapeSize.width / root.fixedArtShapeSize.height : -1;
59 readonly property real aspect: fixedArtShapeSizeAspect > 0 ? fixedArtShapeSizeAspect : 1.6;
41 readonly property real aspect: fixedArtShapeSizeAspect > 0 ? fixedArtShapeSizeAspect : 1.6;
@@ -73,7 +55,7 @@ Item {
73 objectName: "artImage";
55 objectName: "artImage";
74 source: artShapeLoader.cardArt;
56 source: artShapeLoader.cardArt;
75 asynchronous: true;
57 asynchronous: true;
76− visible: !true;
58+ visible: false;
77 width: root.width;
59 width: root.width;
78 height: width / artShape.aspect;
60 height: width / artShape.aspect;
79 }
61 }
@@ -105,7 +87,7 @@ UbuntuShape {
105 id: touchdown;
87 id: touchdown;
106 objectName: "touchdown";
88 objectName: "touchdown";
107 anchors { fill: artShapeHolder }
89 anchors { fill: artShapeHolder }
108− visible: root.artShapeStyle != "shadow" && root.artShapeStyle != "icon" && root.pressed;
90+ visible: root.pressed;
109 radius: "medium";
91 radius: "medium";
110 borderSource: "radius_pressed.sci"
92 borderSource: "radius_pressed.sci"
111}
93}
tests/plugins/Dash/cardcreator/1.res.cardcreator+8−26
@@ -1,7 +1,6 @@
1AbstractButton {
1AbstractButton {
2 id: root;
2 id: root;
3 property var cardData;
3 property var cardData;
4− property string artShapeStyle: "inset";
5 property string backgroundShapeStyle: "inset";
4 property string backgroundShapeStyle: "inset";
6 property real fontScale: 1.0;
5 property real fontScale: 1.0;
7 property var scopeStyle: null;
6 property var scopeStyle: null;
@@ -21,6 +20,7 @@ Item {
21 id: artShapeLoader;
20 id: artShapeLoader;
22 objectName: "artShapeLoader";
21 objectName: "artShapeLoader";
23 readonly property string cardArt: cardData && cardData["art"] || "";
22 readonly property string cardArt: cardData && cardData["art"] || "";
23+ onCardArtChanged: { if (item) { item.image.source = cardArt; } }
24 active: cardArt != "";
24 active: cardArt != "";
25 asynchronous: false;
25 asynchronous: false;
26 visible: status == Loader.Ready;
26 visible: status == Loader.Ready;
@@ -29,30 +29,12 @@ Item {
29 objectName: "artShape";
29 objectName: "artShape";
30 visible: image.status == Image.Ready;
30 visible: image.status == Image.Ready;
31 readonly property alias image: artImage;
31 readonly property alias image: artImage;
32− Loader {
32+ UbuntuShape {
33 anchors.fill: parent;
33 anchors.fill: parent;
34− visible: true;
35− sourceComponent: root.artShapeStyle === "icon" ? artShapeIconComponent : artShapeShapeComponent;
36− Component {
37− id: artShapeShapeComponent;
38− UbuntuShape {
39− source: artImage;
34+ source: artImage;
40− sourceFillMode: UbuntuShape.PreserveAspectCrop;
35+ sourceFillMode: UbuntuShape.PreserveAspectCrop;
41− radius: "medium";
36+ radius: "medium";
42− aspect: {
43− switch (root.artShapeStyle) {
44− case "inset": return UbuntuShape.Inset;
37+ aspect: UbuntuShape.Inset;
45− case "shadow": return UbuntuShape.DropShadow;
46− default:
47− case "flat": return UbuntuShape.Flat;
48− }
49− }
50− }
51− }
52− Component {
53− id: artShapeIconComponent;
54− ProportionalShape { source: artImage; aspect: UbuntuShape.DropShadow; }
55− }
56 }
38 }
57 readonly property real fixedArtShapeSizeAspect: (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) ? root.fixedArtShapeSize.width / root.fixedArtShapeSize.height : -1;
39 readonly property real fixedArtShapeSizeAspect: (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) ? root.fixedArtShapeSize.width / root.fixedArtShapeSize.height : -1;
58 readonly property real aspect: fixedArtShapeSizeAspect > 0 ? fixedArtShapeSizeAspect : 1.6;
40 readonly property real aspect: fixedArtShapeSizeAspect > 0 ? fixedArtShapeSizeAspect : 1.6;
@@ -72,7 +54,7 @@ Item {
72 objectName: "artImage";
54 objectName: "artImage";
73 source: artShapeLoader.cardArt;
55 source: artShapeLoader.cardArt;
74 asynchronous: false;
56 asynchronous: false;
75− visible: !true;
57+ visible: false;
76 width: root.width;
58 width: root.width;
77 height: width / artShape.aspect;
59 height: width / artShape.aspect;
78 }
60 }
@@ -104,7 +86,7 @@ UbuntuShape {
104 id: touchdown;
86 id: touchdown;
105 objectName: "touchdown";
87 objectName: "touchdown";
106 anchors { fill: artShapeHolder }
88 anchors { fill: artShapeHolder }
107− visible: root.artShapeStyle != "shadow" && root.artShapeStyle != "icon" && root.pressed;
89+ visible: root.pressed;
108 radius: "medium";
90 radius: "medium";
109 borderSource: "radius_pressed.sci"
91 borderSource: "radius_pressed.sci"
110}
92}
tests/plugins/Dash/cardcreator/1.tst+1
@@ -1,3 +1,4 @@
1template: {"card-layout":"vertical","card-size":"small","category-layout":"grid","collapsed-rows":2}
1template: {"card-layout":"vertical","card-size":"small","category-layout":"grid","collapsed-rows":2}
2components: {"art":{"aspect-ratio":1.6,"field":"art"},"title":{"field":"title"},"attributes":{}}
2components: {"art":{"aspect-ratio":1.6,"field":"art"},"title":{"field":"title"},"attributes":{}}
3+artShapeStyle: inset
3result: 1.res
4result: 1.res
tests/plugins/Dash/cardcreator/10.res−9
@@ -1,7 +1,6 @@
1AbstractButton {
1AbstractButton {
2 id: root;
2 id: root;
3 property var cardData;
3 property var cardData;
4− property string artShapeStyle: "inset";
5 property string backgroundShapeStyle: "inset";
4 property string backgroundShapeStyle: "inset";
6 property real fontScale: 1.0;
5 property real fontScale: 1.0;
7 property var scopeStyle: null;
6 property var scopeStyle: null;
@@ -127,13 +126,5 @@ top: titleLabel.bottom;
127
126
128 ]
127 ]
129 }
128 }
130−UbuntuShape {
131− id: touchdown;
132− objectName: "touchdown";
133− anchors { fill: backgroundLoader }
134− visible: root.artShapeStyle != "shadow" && root.artShapeStyle != "icon" && root.pressed;
135− radius: "medium";
136− borderSource: "radius_pressed.sci"
137− }
138implicitHeight: row.y + row.height + units.gu(1);
129implicitHeight: row.y + row.height + units.gu(1);
139}
130}
tests/plugins/Dash/cardcreator/10.res.cardcreator−9
@@ -1,7 +1,6 @@
1AbstractButton {
1AbstractButton {
2 id: root;
2 id: root;
3 property var cardData;
3 property var cardData;
4− property string artShapeStyle: "inset";
5 property string backgroundShapeStyle: "inset";
4 property string backgroundShapeStyle: "inset";
6 property real fontScale: 1.0;
5 property real fontScale: 1.0;
7 property var scopeStyle: null;
6 property var scopeStyle: null;
@@ -125,13 +124,5 @@ top: titleLabel.bottom;
125
124
126 ]
125 ]
127 }
126 }
128−UbuntuShape {
129− id: touchdown;
130− objectName: "touchdown";
131− anchors { fill: backgroundLoader }
132− visible: root.artShapeStyle != "shadow" && root.artShapeStyle != "icon" && root.pressed;
133− radius: "medium";
134− borderSource: "radius_pressed.sci"
135− }
136implicitHeight: row.y + row.height + units.gu(1);
127implicitHeight: row.y + row.height + units.gu(1);
137}
128}
tests/plugins/Dash/cardcreator/10.tst+1
@@ -1,3 +1,4 @@
1template: {"card-background":{"elements":["#E9E9E9"],"type":"color"},"card-layout":"vertical","card-size":"medium","category-layout":"grid","collapsed-rows":2, "card-background": { "type": "color", "elements": [ "\\", ": 3; } Item { } function moo () { \"" ] } }
1template: {"card-background":{"elements":["#E9E9E9"],"type":"color"},"card-layout":"vertical","card-size":"medium","category-layout":"grid","collapsed-rows":2, "card-background": { "type": "color", "elements": [ "\\", ": 3; } Item { } function moo () { \"" ] } }
2components: {"art":{"aspect-ratio":1},"background":{"field":"background"},"mascot":{"field":"icon"},"subtitle":{"field":"author"},"title":{"field":"title"},"attributes":{}}
2components: {"art":{"aspect-ratio":1},"background":{"field":"background"},"mascot":{"field":"icon"},"subtitle":{"field":"author"},"title":{"field":"title"},"attributes":{}}
3+artShapeStyle: shadow
3result: 10.res
4result: 10.res
tests/plugins/Dash/cardcreator/11.res+11−29
@@ -1,7 +1,6 @@
1AbstractButton {
1AbstractButton {
2 id: root;
2 id: root;
3 property var cardData;
3 property var cardData;
4− property string artShapeStyle: "inset";
5 property string backgroundShapeStyle: "inset";
4 property string backgroundShapeStyle: "inset";
6 property real fontScale: 1.0;
5 property real fontScale: 1.0;
7 property var scopeStyle: null;
6 property var scopeStyle: null;
@@ -60,6 +59,7 @@ Item {
60 id: artShapeLoader;
59 id: artShapeLoader;
61 objectName: "artShapeLoader";
60 objectName: "artShapeLoader";
62 readonly property string cardArt: cardData && cardData["art"] || decodeURI("%5C");
61 readonly property string cardArt: cardData && cardData["art"] || decodeURI("%5C");
62+ onCardArtChanged: { if (item) { item.image.source = cardArt; } }
63 active: cardArt != "";
63 active: cardArt != "";
64 asynchronous: true;
64 asynchronous: true;
65 visible: status == Loader.Ready;
65 visible: status == Loader.Ready;
@@ -68,32 +68,14 @@ Item {
68 objectName: "artShape";
68 objectName: "artShape";
69 visible: image.status == Image.Ready;
69 visible: image.status == Image.Ready;
70 readonly property alias image: artImage;
70 readonly property alias image: artImage;
71− Loader {
71+ UbuntuShape {
72− anchors.fill: parent;
72+ anchors.fill: parent;
73− visible: true;
74− sourceComponent: root.artShapeStyle === "icon" ? artShapeIconComponent : artShapeShapeComponent;
75− Component {
76− id: artShapeShapeComponent;
77− UbuntuShape {
78− source: artImage;
73+ source: artImage;
79− sourceFillMode: UbuntuShape.PreserveAspectCrop;
74+ sourceFillMode: UbuntuShape.PreserveAspectCrop;
80− radius: "medium";
75+ radius: "medium";
81− aspect: {
82− switch (root.artShapeStyle) {
83− case "inset": return UbuntuShape.Inset;
84− case "shadow": return UbuntuShape.DropShadow;
85− default:
86− case "flat": return UbuntuShape.Flat;
76+ aspect: UbuntuShape.Flat;
87− }
88− }
89− }
90− }
91− Component {
92− id: artShapeIconComponent;
93− ProportionalShape { source: artImage; aspect: UbuntuShape.DropShadow; }
94− }
95− }
77+ }
96− readonly property real fixedArtShapeSizeAspect: (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) ? root.fixedArtShapeSize.width / root.fixedArtShapeSize.height : -1;
78+ readonly property real fixedArtShapeSizeAspect: (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) ? root.fixedArtShapeSize.width / root.fixedArtShapeSize.height : -1;
97 readonly property real aspect: fixedArtShapeSizeAspect > 0 ? fixedArtShapeSizeAspect : 1;
79 readonly property real aspect: fixedArtShapeSizeAspect > 0 ? fixedArtShapeSizeAspect : 1;
98 Component.onCompleted: { updateWidthHeightBindings(); }
80 Component.onCompleted: { updateWidthHeightBindings(); }
99 Connections { target: root; onFixedArtShapeSizeChanged: updateWidthHeightBindings(); }
81 Connections { target: root; onFixedArtShapeSizeChanged: updateWidthHeightBindings(); }
@@ -111,7 +93,7 @@ Item {
111 objectName: "artImage";
93 objectName: "artImage";
112 source: artShapeLoader.cardArt;
94 source: artShapeLoader.cardArt;
113 asynchronous: true;
95 asynchronous: true;
114− visible: !true;
96+ visible: false;
115 width: root.width;
97 width: root.width;
116 height: width / artShape.aspect;
98 height: width / artShape.aspect;
117 onStatusChanged: if (status === Image.Error) source = decodeURI("%5C");
99 onStatusChanged: if (status === Image.Error) source = decodeURI("%5C");
@@ -199,7 +181,7 @@ UbuntuShape {
199 id: touchdown;
181 id: touchdown;
200 objectName: "touchdown";
182 objectName: "touchdown";
201 anchors { fill: backgroundLoader }
183 anchors { fill: backgroundLoader }
202− visible: root.artShapeStyle != "shadow" && root.artShapeStyle != "icon" && root.pressed;
184+ visible: root.pressed;
203 radius: "medium";
185 radius: "medium";
204 borderSource: "radius_pressed.sci"
186 borderSource: "radius_pressed.sci"
205 }
187 }
tests/plugins/Dash/cardcreator/11.res.cardcreator+10−28
@@ -1,7 +1,6 @@
1AbstractButton {
1AbstractButton {
2 id: root;
2 id: root;
3 property var cardData;
3 property var cardData;
4− property string artShapeStyle: "inset";
5 property string backgroundShapeStyle: "inset";
4 property string backgroundShapeStyle: "inset";
6 property real fontScale: 1.0;
5 property real fontScale: 1.0;
7 property var scopeStyle: null;
6 property var scopeStyle: null;
@@ -59,6 +58,7 @@ Item {
59 id: artShapeLoader;
58 id: artShapeLoader;
60 objectName: "artShapeLoader";
59 objectName: "artShapeLoader";
61 readonly property string cardArt: cardData && cardData["art"] || "";
60 readonly property string cardArt: cardData && cardData["art"] || "";
61+ onCardArtChanged: { if (item) { item.image.source = cardArt; } }
62 active: cardArt != "";
62 active: cardArt != "";
63 asynchronous: false;
63 asynchronous: false;
64 visible: status == Loader.Ready;
64 visible: status == Loader.Ready;
@@ -67,31 +67,13 @@ Item {
67 objectName: "artShape";
67 objectName: "artShape";
68 visible: image.status == Image.Ready;
68 visible: image.status == Image.Ready;
69 readonly property alias image: artImage;
69 readonly property alias image: artImage;
70− Loader {
70+ UbuntuShape {
71− anchors.fill: parent;
71+ anchors.fill: parent;
72− visible: true;
73− sourceComponent: root.artShapeStyle === "icon" ? artShapeIconComponent : artShapeShapeComponent;
74− Component {
75− id: artShapeShapeComponent;
76− UbuntuShape {
77− source: artImage;
72+ source: artImage;
78− sourceFillMode: UbuntuShape.PreserveAspectCrop;
73+ sourceFillMode: UbuntuShape.PreserveAspectCrop;
79− radius: "medium";
74+ radius: "medium";
80− aspect: {
81− switch (root.artShapeStyle) {
82− case "inset": return UbuntuShape.Inset;
83− case "shadow": return UbuntuShape.DropShadow;
84− default:
85− case "flat": return UbuntuShape.Flat;
75+ aspect: UbuntuShape.Flat;
86− }
87− }
88− }
89− }
90− Component {
91− id: artShapeIconComponent;
92− ProportionalShape { source: artImage; aspect: UbuntuShape.DropShadow; }
93− }
94− }
76+ }
95 readonly property real fixedArtShapeSizeAspect: (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) ? root.fixedArtShapeSize.width / root.fixedArtShapeSize.height : -1;
77 readonly property real fixedArtShapeSizeAspect: (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) ? root.fixedArtShapeSize.width / root.fixedArtShapeSize.height : -1;
96 readonly property real aspect: fixedArtShapeSizeAspect > 0 ? fixedArtShapeSizeAspect : 1;
78 readonly property real aspect: fixedArtShapeSizeAspect > 0 ? fixedArtShapeSizeAspect : 1;
97 Component.onCompleted: { updateWidthHeightBindings(); }
79 Component.onCompleted: { updateWidthHeightBindings(); }
@@ -110,7 +92,7 @@ Item {
110 objectName: "artImage";
92 objectName: "artImage";
111 source: artShapeLoader.cardArt;
93 source: artShapeLoader.cardArt;
112 asynchronous: false;
94 asynchronous: false;
113− visible: !true;
95+ visible: false;
114 width: root.width;
96 width: root.width;
115 height: width / artShape.aspect;
97 height: width / artShape.aspect;
116 }
98 }
@@ -195,7 +177,7 @@ UbuntuShape {
195 id: touchdown;
177 id: touchdown;
196 objectName: "touchdown";
178 objectName: "touchdown";
197 anchors { fill: backgroundLoader }
179 anchors { fill: backgroundLoader }
198− visible: root.artShapeStyle != "shadow" && root.artShapeStyle != "icon" && root.pressed;
180+ visible: root.pressed;
199 radius: "medium";
181 radius: "medium";
200 borderSource: "radius_pressed.sci"
182 borderSource: "radius_pressed.sci"
201 }
183 }
tests/plugins/Dash/cardcreator/11.tst+1
@@ -1,3 +1,4 @@
1template: {"card-background":{"elements":["#E9E9E9"],"type":"color"},"card-layout":"vertical","card-size":"medium","category-layout":"grid","collapsed-rows":2 }
1template: {"card-background":{"elements":["#E9E9E9"],"type":"color"},"card-layout":"vertical","card-size":"medium","category-layout":"grid","collapsed-rows":2 }
2components: {"art":{"aspect-ratio":1,"field":"art","fallback":"\\"},"background":{"field":"background"},"mascot":{"field":"icon","fallback":"\""},"subtitle":{"field":"author"},"title":{"field":"title"},"attributes":{}}
2components: {"art":{"aspect-ratio":1,"field":"art","fallback":"\\"},"background":{"field":"background"},"mascot":{"field":"icon","fallback":"\""},"subtitle":{"field":"author"},"title":{"field":"title"},"attributes":{}}
3+artShapeStyle: flat
3result: 11.res
4result: 11.res
tests/plugins/Dash/cardcreator/12.res+8−26
@@ -1,7 +1,6 @@
1AbstractButton {
1AbstractButton {
2 id: root;
2 id: root;
3 property var cardData;
3 property var cardData;
4− property string artShapeStyle: "inset";
5 property string backgroundShapeStyle: "inset";
4 property string backgroundShapeStyle: "inset";
6 property real fontScale: 1.0;
5 property real fontScale: 1.0;
7 property var scopeStyle: null;
6 property var scopeStyle: null;
@@ -22,6 +21,7 @@ Item {
22 id: artShapeLoader;
21 id: artShapeLoader;
23 objectName: "artShapeLoader";
22 objectName: "artShapeLoader";
24 readonly property string cardArt: cardData && cardData["art"] || "";
23 readonly property string cardArt: cardData && cardData["art"] || "";
24+ onCardArtChanged: { if (item) { item.image.source = cardArt; } }
25 active: cardArt != "";
25 active: cardArt != "";
26 asynchronous: true;
26 asynchronous: true;
27 visible: status == Loader.Ready;
27 visible: status == Loader.Ready;
@@ -30,30 +30,12 @@ Item {
30 objectName: "artShape";
30 objectName: "artShape";
31 visible: image.status == Image.Ready;
31 visible: image.status == Image.Ready;
32 readonly property alias image: artImage;
32 readonly property alias image: artImage;
33− Loader {
33+ UbuntuShape {
34 anchors.fill: parent;
34 anchors.fill: parent;
35− visible: true;
36− sourceComponent: root.artShapeStyle === "icon" ? artShapeIconComponent : artShapeShapeComponent;
37− Component {
38− id: artShapeShapeComponent;
39− UbuntuShape {
40− source: artImage;
35+ source: artImage;
41− sourceFillMode: UbuntuShape.PreserveAspectCrop;
36+ sourceFillMode: UbuntuShape.PreserveAspectCrop;
42− radius: "medium";
37+ radius: "medium";
43− aspect: {
44− switch (root.artShapeStyle) {
45− case "inset": return UbuntuShape.Inset;
46− case "shadow": return UbuntuShape.DropShadow;
47− default:
48− case "flat": return UbuntuShape.Flat;
38+ aspect: UbuntuShape.Flat;
49− }
50− }
51− }
52− }
53− Component {
54− id: artShapeIconComponent;
55− ProportionalShape { source: artImage; aspect: UbuntuShape.DropShadow; }
56− }
57 }
39 }
58 readonly property real fixedArtShapeSizeAspect: (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) ? root.fixedArtShapeSize.width / root.fixedArtShapeSize.height : -1;
40 readonly property real fixedArtShapeSizeAspect: (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) ? root.fixedArtShapeSize.width / root.fixedArtShapeSize.height : -1;
59 readonly property real aspect: fixedArtShapeSizeAspect > 0 ? fixedArtShapeSizeAspect : 0.75;
41 readonly property real aspect: fixedArtShapeSizeAspect > 0 ? fixedArtShapeSizeAspect : 0.75;
@@ -73,7 +55,7 @@ Item {
73 objectName: "artImage";
55 objectName: "artImage";
74 source: artShapeLoader.cardArt;
56 source: artShapeLoader.cardArt;
75 asynchronous: true;
57 asynchronous: true;
76− visible: !true;
58+ visible: false;
77 width: root.width;
59 width: root.width;
78 height: width / artShape.aspect;
60 height: width / artShape.aspect;
79 }
61 }
@@ -131,7 +113,7 @@ UbuntuShape {
131 id: touchdown;
113 id: touchdown;
132 objectName: "touchdown";
114 objectName: "touchdown";
133 anchors { fill: artShapeHolder }
115 anchors { fill: artShapeHolder }
134− visible: root.artShapeStyle != "shadow" && root.artShapeStyle != "icon" && root.pressed;
116+ visible: root.pressed;
135 radius: "medium";
117 radius: "medium";
136 borderSource: "radius_pressed.sci"
118 borderSource: "radius_pressed.sci"
137}
119}
tests/plugins/Dash/cardcreator/12.res.cardcreator+10−28
@@ -1,7 +1,6 @@
1−AbstractButton {
1+AbstractButton {
2 id: root;
2 id: root;
3 property var cardData;
3 property var cardData;
4− property string artShapeStyle: "inset";
5 property string backgroundShapeStyle: "inset";
4 property string backgroundShapeStyle: "inset";
6 property real fontScale: 1.0;
5 property real fontScale: 1.0;
7 property var scopeStyle: null;
6 property var scopeStyle: null;
@@ -17,10 +16,11 @@ Item {
17 height: root.fixedArtShapeSize.height > 0 ? root.fixedArtShapeSize.height : artShapeLoader.height;
16 height: root.fixedArtShapeSize.height > 0 ? root.fixedArtShapeSize.height : artShapeLoader.height;
18 width: root.fixedArtShapeSize.width > 0 ? root.fixedArtShapeSize.width : artShapeLoader.width;
17 width: root.fixedArtShapeSize.width > 0 ? root.fixedArtShapeSize.width : artShapeLoader.width;
19 anchors { horizontalCenter: parent.horizontalCenter; }
18 anchors { horizontalCenter: parent.horizontalCenter; }
20− Loader {
19+ Loader {
21 id: artShapeLoader;
20 id: artShapeLoader;
22 objectName: "artShapeLoader";
21 objectName: "artShapeLoader";
23 readonly property string cardArt: cardData && cardData["art"] || "";
22 readonly property string cardArt: cardData && cardData["art"] || "";
23+ onCardArtChanged: { if (item) { item.image.source = cardArt; } }
24 active: cardArt != "";
24 active: cardArt != "";
25 asynchronous: false;
25 asynchronous: false;
26 visible: status == Loader.Ready;
26 visible: status == Loader.Ready;
@@ -29,30 +29,12 @@ Item {
29 objectName: "artShape";
29 objectName: "artShape";
30 visible: image.status == Image.Ready;
30 visible: image.status == Image.Ready;
31 readonly property alias image: artImage;
31 readonly property alias image: artImage;
32− Loader {
32+ UbuntuShape {
33 anchors.fill: parent;
33 anchors.fill: parent;
34− visible: true;
35− sourceComponent: root.artShapeStyle === "icon" ? artShapeIconComponent : artShapeShapeComponent;
36− Component {
37− id: artShapeShapeComponent;
38− UbuntuShape {
39− source: artImage;
34+ source: artImage;
40− sourceFillMode: UbuntuShape.PreserveAspectCrop;
35+ sourceFillMode: UbuntuShape.PreserveAspectCrop;
41− radius: "medium";
36+ radius: "medium";
42− aspect: {
43− switch (root.artShapeStyle) {
44− case "inset": return UbuntuShape.Inset;
45− case "shadow": return UbuntuShape.DropShadow;
46− default:
47− case "flat": return UbuntuShape.Flat;
37+ aspect: UbuntuShape.Flat;
48− }
49− }
50− }
51− }
52− Component {
53− id: artShapeIconComponent;
54− ProportionalShape { source: artImage; aspect: UbuntuShape.DropShadow; }
55− }
56 }
38 }
57 readonly property real fixedArtShapeSizeAspect: (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) ? root.fixedArtShapeSize.width / root.fixedArtShapeSize.height : -1;
39 readonly property real fixedArtShapeSizeAspect: (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) ? root.fixedArtShapeSize.width / root.fixedArtShapeSize.height : -1;
58 readonly property real aspect: fixedArtShapeSizeAspect > 0 ? fixedArtShapeSizeAspect : 0.75;
40 readonly property real aspect: fixedArtShapeSizeAspect > 0 ? fixedArtShapeSizeAspect : 0.75;
@@ -72,7 +54,7 @@ Item {
72 objectName: "artImage";
54 objectName: "artImage";
73 source: artShapeLoader.cardArt;
55 source: artShapeLoader.cardArt;
74 asynchronous: false;
56 asynchronous: false;
75− visible: !true;
57+ visible: false;
76 width: root.width;
58 width: root.width;
77 height: width / artShape.aspect;
59 height: width / artShape.aspect;
78 }
60 }
@@ -130,7 +112,7 @@ UbuntuShape {
130 id: touchdown;
112 id: touchdown;
131 objectName: "touchdown";
113 objectName: "touchdown";
132 anchors { fill: artShapeHolder }
114 anchors { fill: artShapeHolder }
133− visible: root.artShapeStyle != "shadow" && root.artShapeStyle != "icon" && root.pressed;
115+ visible: root.pressed;
134 radius: "medium";
116 radius: "medium";
135 borderSource: "radius_pressed.sci"
117 borderSource: "radius_pressed.sci"
136}
118}
tests/plugins/Dash/cardcreator/12.tst+1
@@ -1,3 +1,4 @@
1template: {"card-layout":"vertical","card-size":"small","category-layout":"grid","collapsed-rows":2}
1template: {"card-layout":"vertical","card-size":"small","category-layout":"grid","collapsed-rows":2}
2components: {"art":{"aspect-ratio":0.75,"field":"art"},"subtitle":{"field":"price"},"title":{"field":"title"},"attributes":{},"social-actions":{}}
2components: {"art":{"aspect-ratio":0.75,"field":"art"},"subtitle":{"field":"price"},"title":{"field":"title"},"attributes":{},"social-actions":{}}
3+artShapeStyle: flat
3result: 12.res
4result: 12.res
tests/plugins/Dash/cardcreator/2.res−9
@@ -1,7 +1,6 @@
1AbstractButton {
1AbstractButton {
2 id: root;
2 id: root;
3 property var cardData;
3 property var cardData;
4− property string artShapeStyle: "inset";
5 property string backgroundShapeStyle: "inset";
4 property string backgroundShapeStyle: "inset";
6 property real fontScale: 1.0;
5 property real fontScale: 1.0;
7 property var scopeStyle: null;
6 property var scopeStyle: null;
@@ -126,13 +125,5 @@ CroppedImageMinimumSourceSize {
126
125
127 ]
126 ]
128 }
127 }
129−UbuntuShape {
130− id: touchdown;
131− objectName: "touchdown";
132− anchors { fill: backgroundLoader }
133− visible: root.artShapeStyle != "shadow" && root.artShapeStyle != "icon" && root.pressed;
134− radius: "medium";
135− borderSource: "radius_pressed.sci"
136−}
137implicitHeight: row.y + row.height + units.gu(1);
128implicitHeight: row.y + row.height + units.gu(1);
138}
129}
tests/plugins/Dash/cardcreator/2.res.cardcreator−9
@@ -1,7 +1,6 @@
1AbstractButton {
1AbstractButton {
2 id: root;
2 id: root;
3 property var cardData;
3 property var cardData;
4− property string artShapeStyle: "inset";
5 property string backgroundShapeStyle: "inset";
4 property string backgroundShapeStyle: "inset";
6 property real fontScale: 1.0;
5 property real fontScale: 1.0;
7 property var scopeStyle: null;
6 property var scopeStyle: null;
@@ -124,13 +123,5 @@ CroppedImageMinimumSourceSize {
124
123
125 ]
124 ]
126 }
125 }
127−UbuntuShape {
128− id: touchdown;
129− objectName: "touchdown";
130− anchors { fill: backgroundLoader }
131− visible: root.artShapeStyle != "shadow" && root.artShapeStyle != "icon" && root.pressed;
132− radius: "medium";
133− borderSource: "radius_pressed.sci"
134−}
135implicitHeight: row.y + row.height + units.gu(1);
126implicitHeight: row.y + row.height + units.gu(1);
136}
127}
tests/plugins/Dash/cardcreator/2.tst+1
@@ -1,3 +1,4 @@
1template: {"card-background":{"elements":["#E9E9E9"],"type":"color"},"card-layout":"vertical","card-size":"medium","category-layout":"grid","collapsed-rows":2}
1template: {"card-background":{"elements":["#E9E9E9"],"type":"color"},"card-layout":"vertical","card-size":"medium","category-layout":"grid","collapsed-rows":2}
2components: {"art":{"aspect-ratio":1},"background":{"field":"background"},"mascot":{"field":"icon"},"subtitle":{"field":"author"},"title":{"field":"title"},"attributes":{}}
2components: {"art":{"aspect-ratio":1},"background":{"field":"background"},"mascot":{"field":"icon"},"subtitle":{"field":"author"},"title":{"field":"title"},"attributes":{}}
3+artShapeStyle: icon
3result: 2.res
4result: 2.res
tests/plugins/Dash/cardcreator/3.res+5−33
@@ -1,7 +1,6 @@
1AbstractButton {
1AbstractButton {
2 id: root;
2 id: root;
3 property var cardData;
3 property var cardData;
4− property string artShapeStyle: "inset";
5 property string backgroundShapeStyle: "inset";
4 property string backgroundShapeStyle: "inset";
6 property real fontScale: 1.0;
5 property real fontScale: 1.0;
7 property var scopeStyle: null;
6 property var scopeStyle: null;
@@ -22,6 +21,7 @@ Item {
22 id: artShapeLoader;
21 id: artShapeLoader;
23 objectName: "artShapeLoader";
22 objectName: "artShapeLoader";
24 readonly property string cardArt: cardData && cardData["art"] || decodeURI("IHAVE%5C%22ESCAPED%5C%22QUOTES%5C%22");
23 readonly property string cardArt: cardData && cardData["art"] || decodeURI("IHAVE%5C%22ESCAPED%5C%22QUOTES%5C%22");
24+ onCardArtChanged: { if (item) { item.image.source = cardArt; } }
25 active: cardArt != "";
25 active: cardArt != "";
26 asynchronous: true;
26 asynchronous: true;
27 visible: status == Loader.Ready;
27 visible: status == Loader.Ready;
@@ -30,30 +30,10 @@ Item {
30 objectName: "artShape";
30 objectName: "artShape";
31 visible: image.status == Image.Ready;
31 visible: image.status == Image.Ready;
32 readonly property alias image: artImage;
32 readonly property alias image: artImage;
33− Loader {
33+ ProportionalShape {
34 anchors.fill: parent;
34 anchors.fill: parent;
35− visible: true;
36− sourceComponent: root.artShapeStyle === "icon" ? artShapeIconComponent : artShapeShapeComponent;
37− Component {
38− id: artShapeShapeComponent;
39− UbuntuShape {
40− source: artImage;
35+ source: artImage;
41− sourceFillMode: UbuntuShape.PreserveAspectCrop;
42− radius: "medium";
43− aspect: {
44− switch (root.artShapeStyle) {
45− case "inset": return UbuntuShape.Inset;
46− case "shadow": return UbuntuShape.DropShadow;
47− default:
48− case "flat": return UbuntuShape.Flat;
49− }
50− }
51− }
52− }
53− Component {
54− id: artShapeIconComponent;
55− ProportionalShape { source: artImage; aspect: UbuntuShape.DropShadow; }
36+ aspect: UbuntuShape.DropShadow;
56− }
57 }
37 }
58 readonly property real fixedArtShapeSizeAspect: (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) ? root.fixedArtShapeSize.width / root.fixedArtShapeSize.height : -1;
38 readonly property real fixedArtShapeSizeAspect: (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) ? root.fixedArtShapeSize.width / root.fixedArtShapeSize.height : -1;
59 readonly property real aspect: fixedArtShapeSizeAspect > 0 ? fixedArtShapeSizeAspect : 0.75;
39 readonly property real aspect: fixedArtShapeSizeAspect > 0 ? fixedArtShapeSizeAspect : 0.75;
@@ -73,7 +53,7 @@ Item {
73 objectName: "artImage";
53 objectName: "artImage";
74 source: artShapeLoader.cardArt;
54 source: artShapeLoader.cardArt;
75 asynchronous: true;
55 asynchronous: true;
76− visible: !true;
56+ visible: false;
77 width: root.width;
57 width: root.width;
78 height: width / artShape.aspect;
58 height: width / artShape.aspect;
79 onStatusChanged: if (status === Image.Error) source = decodeURI("IHAVE%5C%22ESCAPED%5C%22QUOTES%5C%22");
59 onStatusChanged: if (status === Image.Error) source = decodeURI("IHAVE%5C%22ESCAPED%5C%22QUOTES%5C%22");
@@ -120,13 +100,5 @@ Label {
120 text: cardData && cardData["subtitle"] || "";
100 text: cardData && cardData["subtitle"] || "";
121 font.weight: Font.Light;
101 font.weight: Font.Light;
122 }
102 }
123−UbuntuShape {
124− id: touchdown;
125− objectName: "touchdown";
126− anchors { fill: artShapeHolder }
127− visible: root.artShapeStyle != "shadow" && root.artShapeStyle != "icon" && root.pressed;
128− radius: "medium";
129− borderSource: "radius_pressed.sci"
130−}
131implicitHeight: subtitleLabel.y + subtitleLabel.height + units.gu(1);
103implicitHeight: subtitleLabel.y + subtitleLabel.height + units.gu(1);
132}
104}
tests/plugins/Dash/cardcreator/3.res.cardcreator+5−33
@@ -1,7 +1,6 @@
1AbstractButton {
1AbstractButton {
2 id: root;
2 id: root;
3 property var cardData;
3 property var cardData;
4− property string artShapeStyle: "inset";
5 property string backgroundShapeStyle: "inset";
4 property string backgroundShapeStyle: "inset";
6 property real fontScale: 1.0;
5 property real fontScale: 1.0;
7 property var scopeStyle: null;
6 property var scopeStyle: null;
@@ -21,6 +20,7 @@ Item {
21 id: artShapeLoader;
20 id: artShapeLoader;
22 objectName: "artShapeLoader";
21 objectName: "artShapeLoader";
23 readonly property string cardArt: cardData && cardData["art"] || "";
22 readonly property string cardArt: cardData && cardData["art"] || "";
23+ onCardArtChanged: { if (item) { item.image.source = cardArt; } }
24 active: cardArt != "";
24 active: cardArt != "";
25 asynchronous: false;
25 asynchronous: false;
26 visible: status == Loader.Ready;
26 visible: status == Loader.Ready;
@@ -29,30 +29,10 @@ Item {
29 objectName: "artShape";
29 objectName: "artShape";
30 visible: image.status == Image.Ready;
30 visible: image.status == Image.Ready;
31 readonly property alias image: artImage;
31 readonly property alias image: artImage;
32− Loader {
32+ ProportionalShape {
33 anchors.fill: parent;
33 anchors.fill: parent;
34− visible: true;
35− sourceComponent: root.artShapeStyle === "icon" ? artShapeIconComponent : artShapeShapeComponent;
36− Component {
37− id: artShapeShapeComponent;
38− UbuntuShape {
39− source: artImage;
34+ source: artImage;
40− sourceFillMode: UbuntuShape.PreserveAspectCrop;
41− radius: "medium";
42− aspect: {
43− switch (root.artShapeStyle) {
44− case "inset": return UbuntuShape.Inset;
45− case "shadow": return UbuntuShape.DropShadow;
46− default:
47− case "flat": return UbuntuShape.Flat;
48− }
49− }
50− }
51− }
52− Component {
53− id: artShapeIconComponent;
54− ProportionalShape { source: artImage; aspect: UbuntuShape.DropShadow; }
35+ aspect: UbuntuShape.DropShadow;
55− }
56 }
36 }
57 readonly property real fixedArtShapeSizeAspect: (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) ? root.fixedArtShapeSize.width / root.fixedArtShapeSize.height : -1;
37 readonly property real fixedArtShapeSizeAspect: (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) ? root.fixedArtShapeSize.width / root.fixedArtShapeSize.height : -1;
58 readonly property real aspect: fixedArtShapeSizeAspect > 0 ? fixedArtShapeSizeAspect : 0.75;
38 readonly property real aspect: fixedArtShapeSizeAspect > 0 ? fixedArtShapeSizeAspect : 0.75;
@@ -72,7 +52,7 @@ Item {
72 objectName: "artImage";
52 objectName: "artImage";
73 source: artShapeLoader.cardArt;
53 source: artShapeLoader.cardArt;
74 asynchronous: false;
54 asynchronous: false;
75− visible: !true;
55+ visible: false;
76 width: root.width;
56 width: root.width;
77 height: width / artShape.aspect;
57 height: width / artShape.aspect;
78 }
58 }
@@ -118,13 +98,5 @@ Label {
118 text: cardData && cardData["subtitle"] || "";
98 text: cardData && cardData["subtitle"] || "";
119 font.weight: Font.Light;
99 font.weight: Font.Light;
120 }
100 }
121−UbuntuShape {
122− id: touchdown;
123− objectName: "touchdown";
124− anchors { fill: artShapeHolder }
125− visible: root.artShapeStyle != "shadow" && root.artShapeStyle != "icon" && root.pressed;
126− radius: "medium";
127− borderSource: "radius_pressed.sci"
128−}
129implicitHeight: subtitleLabel.y + subtitleLabel.height + units.gu(1);
101implicitHeight: subtitleLabel.y + subtitleLabel.height + units.gu(1);
130}
102}
tests/plugins/Dash/cardcreator/3.tst+1
@@ -1,3 +1,4 @@
1template: {"card-layout":"vertical","card-size":"small","category-layout":"grid","collapsed-rows":2}
1template: {"card-layout":"vertical","card-size":"small","category-layout":"grid","collapsed-rows":2}
2components: {"art":{"aspect-ratio":0.75,"field":"art","fallback":"IHAVE\\\"ESCAPED\\\"QUOTES\\\""},"subtitle":{"field":"price"},"title":{"field":"title"},"attributes":{}}
2components: {"art":{"aspect-ratio":0.75,"field":"art","fallback":"IHAVE\\\"ESCAPED\\\"QUOTES\\\""},"subtitle":{"field":"price"},"title":{"field":"title"},"attributes":{}}
3+artShapeStyle: icon
3result: 3.res
4result: 3.res
tests/plugins/Dash/cardcreator/4.res+1−2
@@ -1,7 +1,6 @@
1AbstractButton {
1AbstractButton {
2 id: root;
2 id: root;
3 property var cardData;
3 property var cardData;
4− property string artShapeStyle: "inset";
5 property string backgroundShapeStyle: "inset";
4 property string backgroundShapeStyle: "inset";
6 property real fontScale: 1.0;
5 property real fontScale: 1.0;
7 property var scopeStyle: null;
6 property var scopeStyle: null;
@@ -103,7 +102,7 @@ UbuntuShape {
103 id: touchdown;
102 id: touchdown;
104 objectName: "touchdown";
103 objectName: "touchdown";
105 anchors { fill: root }
104 anchors { fill: root }
106− visible: root.artShapeStyle != "shadow" && root.artShapeStyle != "icon" && root.pressed;
105+ visible: root.pressed;
107 radius: "medium";
106 radius: "medium";
108 borderSource: "radius_pressed.sci"
107 borderSource: "radius_pressed.sci"
109}
108}
tests/plugins/Dash/cardcreator/4.res.cardcreator+1−2
@@ -1,7 +1,6 @@
1AbstractButton {
1AbstractButton {
2 id: root;
2 id: root;
3 property var cardData;
3 property var cardData;
4− property string artShapeStyle: "inset";
5 property string backgroundShapeStyle: "inset";
4 property string backgroundShapeStyle: "inset";
6 property real fontScale: 1.0;
5 property real fontScale: 1.0;
7 property var scopeStyle: null;
6 property var scopeStyle: null;
@@ -101,7 +100,7 @@ UbuntuShape {
101 id: touchdown;
100 id: touchdown;
102 objectName: "touchdown";
101 objectName: "touchdown";
103 anchors { fill: root }
102 anchors { fill: root }
104− visible: root.artShapeStyle != "shadow" && root.artShapeStyle != "icon" && root.pressed;
103+ visible: root.pressed;
105 radius: "medium";
104 radius: "medium";
106 borderSource: "radius_pressed.sci"
105 borderSource: "radius_pressed.sci"
107}
106}
tests/plugins/Dash/cardcreator/4.tst+1
@@ -1,3 +1,4 @@
1template: {"card-layout":"horizontal","card-size":"large","category-layout":"grid","collapsed-rows":2}
1template: {"card-layout":"horizontal","card-size":"large","category-layout":"grid","collapsed-rows":2}
2components: {"art":{"aspect-ratio":1},"mascot":{"field":"mascot"},"subtitle":{"field":"domain"},"title":{"field":"title"},"attributes":{}}
2components: {"art":{"aspect-ratio":1},"mascot":{"field":"mascot"},"subtitle":{"field":"domain"},"title":{"field":"title"},"attributes":{}}
3+artShapeStyle: flat
3result: 4.res
4result: 4.res
tests/plugins/Dash/cardcreator/5.res+2−35
@@ -1,7 +1,6 @@
1AbstractButton {
1AbstractButton {
2 id: root;
2 id: root;
3 property var cardData;
3 property var cardData;
4− property string artShapeStyle: "inset";
5 property string backgroundShapeStyle: "inset";
4 property string backgroundShapeStyle: "inset";
6 property real fontScale: 1.0;
5 property real fontScale: 1.0;
7 property var scopeStyle: null;
6 property var scopeStyle: null;
@@ -22,6 +21,7 @@ Item {
22 id: artShapeLoader;
21 id: artShapeLoader;
23 objectName: "artShapeLoader";
22 objectName: "artShapeLoader";
24 readonly property string cardArt: cardData && cardData["art"] || "";
23 readonly property string cardArt: cardData && cardData["art"] || "";
24+ onCardArtChanged: { if (item) { item.image.source = cardArt; } }
25 active: cardArt != "";
25 active: cardArt != "";
26 asynchronous: true;
26 asynchronous: true;
27 visible: status == Loader.Ready;
27 visible: status == Loader.Ready;
@@ -30,31 +30,6 @@ Item {
30 objectName: "artShape";
30 objectName: "artShape";
31 visible: image.status == Image.Ready;
31 visible: image.status == Image.Ready;
32 readonly property alias image: artImage;
32 readonly property alias image: artImage;
33− Loader {
34− anchors.fill: parent;
35− visible: false;
36− sourceComponent: root.artShapeStyle === "icon" ? artShapeIconComponent : artShapeShapeComponent;
37− Component {
38− id: artShapeShapeComponent;
39− UbuntuShape {
40− source: artImage;
41− sourceFillMode: UbuntuShape.PreserveAspectCrop;
42− radius: "medium";
43− aspect: {
44− switch (root.artShapeStyle) {
45− case "inset": return UbuntuShape.Inset;
46− case "shadow": return UbuntuShape.DropShadow;
47− default:
48− case "flat": return UbuntuShape.Flat;
49− }
50− }
51− }
52− }
53− Component {
54− id: artShapeIconComponent;
55− ProportionalShape { source: artImage; aspect: UbuntuShape.DropShadow; }
56− }
57− }
58 readonly property real fixedArtShapeSizeAspect: (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) ? root.fixedArtShapeSize.width / root.fixedArtShapeSize.height : -1;
33 readonly property real fixedArtShapeSizeAspect: (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) ? root.fixedArtShapeSize.width / root.fixedArtShapeSize.height : -1;
59 readonly property real aspect: fixedArtShapeSizeAspect > 0 ? fixedArtShapeSizeAspect : 1;
34 readonly property real aspect: fixedArtShapeSizeAspect > 0 ? fixedArtShapeSizeAspect : 1;
60 Component.onCompleted: { updateWidthHeightBindings(); }
35 Component.onCompleted: { updateWidthHeightBindings(); }
@@ -73,7 +48,7 @@ Item {
73 objectName: "artImage";
48 objectName: "artImage";
74 source: artShapeLoader.cardArt;
49 source: artShapeLoader.cardArt;
75 asynchronous: true;
50 asynchronous: true;
76− visible: !false;
51+ visible: true;
77 width: root.width;
52 width: root.width;
78 height: width / artShape.aspect;
53 height: width / artShape.aspect;
79 }
54 }
@@ -138,13 +113,5 @@ Label {
138 text: cardData && cardData["subtitle"] || "";
113 text: cardData && cardData["subtitle"] || "";
139 font.weight: Font.Light;
114 font.weight: Font.Light;
140 }
115 }
141−UbuntuShape {
142− id: touchdown;
143− objectName: "touchdown";
144− anchors { fill: artShapeHolder }
145− visible: root.artShapeStyle != "shadow" && root.artShapeStyle != "icon" && root.pressed;
146− radius: "medium";
147− borderSource: "radius_pressed.sci"
148−}
149implicitHeight: artShapeHolder.height;
116implicitHeight: artShapeHolder.height;
150}
117}
tests/plugins/Dash/cardcreator/5.res.cardcreator+2−35
@@ -1,7 +1,6 @@
1AbstractButton {
1AbstractButton {
2 id: root;
2 id: root;
3 property var cardData;
3 property var cardData;
4− property string artShapeStyle: "inset";
5 property string backgroundShapeStyle: "inset";
4 property string backgroundShapeStyle: "inset";
6 property real fontScale: 1.0;
5 property real fontScale: 1.0;
7 property var scopeStyle: null;
6 property var scopeStyle: null;
@@ -21,6 +20,7 @@ Item {
21 id: artShapeLoader;
20 id: artShapeLoader;
22 objectName: "artShapeLoader";
21 objectName: "artShapeLoader";
23 readonly property string cardArt: cardData && cardData["art"] || "";
22 readonly property string cardArt: cardData && cardData["art"] || "";
23+ onCardArtChanged: { if (item) { item.image.source = cardArt; } }
24 active: cardArt != "";
24 active: cardArt != "";
25 asynchronous: false;
25 asynchronous: false;
26 visible: status == Loader.Ready;
26 visible: status == Loader.Ready;
@@ -29,31 +29,6 @@ Item {
29 objectName: "artShape";
29 objectName: "artShape";
30 visible: image.status == Image.Ready;
30 visible: image.status == Image.Ready;
31 readonly property alias image: artImage;
31 readonly property alias image: artImage;
32− Loader {
33− anchors.fill: parent;
34− visible: false;
35− sourceComponent: root.artShapeStyle === "icon" ? artShapeIconComponent : artShapeShapeComponent;
36− Component {
37− id: artShapeShapeComponent;
38− UbuntuShape {
39− source: artImage;
40− sourceFillMode: UbuntuShape.PreserveAspectCrop;
41− radius: "medium";
42− aspect: {
43− switch (root.artShapeStyle) {
44− case "inset": return UbuntuShape.Inset;
45− case "shadow": return UbuntuShape.DropShadow;
46− default:
47− case "flat": return UbuntuShape.Flat;
48− }
49− }
50− }
51− }
52− Component {
53− id: artShapeIconComponent;
54− ProportionalShape { source: artImage; aspect: UbuntuShape.DropShadow; }
55− }
56− }
57 readonly property real fixedArtShapeSizeAspect: (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) ? root.fixedArtShapeSize.width / root.fixedArtShapeSize.height : -1;
32 readonly property real fixedArtShapeSizeAspect: (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) ? root.fixedArtShapeSize.width / root.fixedArtShapeSize.height : -1;
58 readonly property real aspect: fixedArtShapeSizeAspect > 0 ? fixedArtShapeSizeAspect : 1;
33 readonly property real aspect: fixedArtShapeSizeAspect > 0 ? fixedArtShapeSizeAspect : 1;
59 Component.onCompleted: { updateWidthHeightBindings(); }
34 Component.onCompleted: { updateWidthHeightBindings(); }
@@ -72,7 +47,7 @@ Item {
72 objectName: "artImage";
47 objectName: "artImage";
73 source: artShapeLoader.cardArt;
48 source: artShapeLoader.cardArt;
74 asynchronous: false;
49 asynchronous: false;
75− visible: !false;
50+ visible: true;
76 width: root.width;
51 width: root.width;
77 height: width / artShape.aspect;
52 height: width / artShape.aspect;
78 }
53 }
@@ -137,13 +112,5 @@ Label {
137 text: cardData && cardData["subtitle"] || "";
112 text: cardData && cardData["subtitle"] || "";
138 font.weight: Font.Light;
113 font.weight: Font.Light;
139 }
114 }
140−UbuntuShape {
141− id: touchdown;
142− objectName: "touchdown";
143− anchors { fill: artShapeHolder }
144− visible: root.artShapeStyle != "shadow" && root.artShapeStyle != "icon" && root.pressed;
145− radius: "medium";
146− borderSource: "radius_pressed.sci"
147−}
148implicitHeight: artShapeHolder.height;
115implicitHeight: artShapeHolder.height;
149}
116}
tests/plugins/Dash/cardcreator/5.tst+1
@@ -1,3 +1,4 @@
1template: {"non-interactive":true,"card-layout":"vertical","card-size":"medium","category-layout":"carousel","collapsed-rows":2,"overlay":true}
1template: {"non-interactive":true,"card-layout":"vertical","card-size":"medium","category-layout":"carousel","collapsed-rows":2,"overlay":true}
2components: {"art":{"aspect-ratio":1,"field":"art","conciergeMode":true},"subtitle":{"field":"artist"},"title":{"field":"title"},"attributes":{}}
2components: {"art":{"aspect-ratio":1,"field":"art","conciergeMode":true},"subtitle":{"field":"artist"},"title":{"field":"title"},"attributes":{}}
3+artShapeStyle: shadow
3result: 5.res
4result: 5.res
tests/plugins/Dash/cardcreator/6.res+1−2
@@ -1,7 +1,6 @@
1AbstractButton {
1AbstractButton {
2 id: root;
2 id: root;
3 property var cardData;
3 property var cardData;
4− property string artShapeStyle: "inset";
5 property string backgroundShapeStyle: "inset";
4 property string backgroundShapeStyle: "inset";
6 property real fontScale: 1.0;
5 property real fontScale: 1.0;
7 property var scopeStyle: null;
6 property var scopeStyle: null;
@@ -119,7 +118,7 @@ UbuntuShape {
119 id: touchdown;
118 id: touchdown;
120 objectName: "touchdown";
119 objectName: "touchdown";
121 anchors { fill: backgroundLoader }
120 anchors { fill: backgroundLoader }
122− visible: root.artShapeStyle != "shadow" && root.artShapeStyle != "icon" && root.pressed;
121+ visible: root.pressed;
123 radius: "medium";
122 radius: "medium";
124 borderSource: "radius_pressed.sci"
123 borderSource: "radius_pressed.sci"
125}
124}
tests/plugins/Dash/cardcreator/6.res.cardcreator+1−2
@@ -1,7 +1,6 @@
1AbstractButton {
1AbstractButton {
2 id: root;
2 id: root;
3 property var cardData;
3 property var cardData;
4− property string artShapeStyle: "inset";
5 property string backgroundShapeStyle: "inset";
4 property string backgroundShapeStyle: "inset";
6 property real fontScale: 1.0;
5 property real fontScale: 1.0;
7 property var scopeStyle: null;
6 property var scopeStyle: null;
@@ -118,7 +117,7 @@ UbuntuShape {
118 id: touchdown;
117 id: touchdown;
119 objectName: "touchdown";
118 objectName: "touchdown";
120 anchors { fill: backgroundLoader }
119 anchors { fill: backgroundLoader }
121− visible: root.artShapeStyle != "shadow" && root.artShapeStyle != "icon" && root.pressed;
120+ visible: root.pressed;
122 radius: "medium";
121 radius: "medium";
123 borderSource: "radius_pressed.sci"
122 borderSource: "radius_pressed.sci"
124}
123}
tests/plugins/Dash/cardcreator/6.tst+1
@@ -1,3 +1,4 @@
1template: {"card-background":"http://assets.ubuntu.com/sites/ubuntu/latest/u/img/logos/logo-ubuntu-grey.png","card-layout":"vertical","card-size":"medium","category-layout":"grid","collapsed-rows":2}
1template: {"card-background":"http://assets.ubuntu.com/sites/ubuntu/latest/u/img/logos/logo-ubuntu-grey.png","card-layout":"vertical","card-size":"medium","category-layout":"grid","collapsed-rows":2}
2components: {"art":{"aspect-ratio":1},"background":{"field":"background"},"subtitle":{"field":"author"},"title":{"field":"title"},"emblem":{"field":"source"},"attributes":{}}
2components: {"art":{"aspect-ratio":1},"background":{"field":"background"},"subtitle":{"field":"author"},"title":{"field":"title"},"emblem":{"field":"source"},"attributes":{}}
3+artShapeStyle: inset
3result: 6.res
4result: 6.res
tests/plugins/Dash/cardcreator/7.res−9
@@ -1,7 +1,6 @@
1AbstractButton {
1AbstractButton {
2 id: root;
2 id: root;
3 property var cardData;
3 property var cardData;
4− property string artShapeStyle: "inset";
5 property string backgroundShapeStyle: "inset";
4 property string backgroundShapeStyle: "inset";
6 property real fontScale: 1.0;
5 property real fontScale: 1.0;
7 property var scopeStyle: null;
6 property var scopeStyle: null;
@@ -139,13 +138,5 @@ CroppedImageMinimumSourceSize {
139
138
140 ]
139 ]
141 }
140 }
142−UbuntuShape {
143− id: touchdown;
144− objectName: "touchdown";
145− anchors { fill: backgroundLoader }
146− visible: root.artShapeStyle != "shadow" && root.artShapeStyle != "icon" && root.pressed;
147− radius: "medium";
148− borderSource: "radius_pressed.sci"
149−}
150implicitHeight: row.y + row.height + units.gu(1);
141implicitHeight: row.y + row.height + units.gu(1);
151}
142}
tests/plugins/Dash/cardcreator/7.res.cardcreator−9
@@ -1,7 +1,6 @@
1AbstractButton {
1AbstractButton {
2 id: root;
2 id: root;
3 property var cardData;
3 property var cardData;
4− property string artShapeStyle: "inset";
5 property string backgroundShapeStyle: "inset";
4 property string backgroundShapeStyle: "inset";
6 property real fontScale: 1.0;
5 property real fontScale: 1.0;
7 property var scopeStyle: null;
6 property var scopeStyle: null;
@@ -137,13 +136,5 @@ CroppedImageMinimumSourceSize {
137
136
138 ]
137 ]
139 }
138 }
140−UbuntuShape {
141− id: touchdown;
142− objectName: "touchdown";
143− anchors { fill: backgroundLoader }
144− visible: root.artShapeStyle != "shadow" && root.artShapeStyle != "icon" && root.pressed;
145− radius: "medium";
146− borderSource: "radius_pressed.sci"
147−}
148implicitHeight: row.y + row.height + units.gu(1);
139implicitHeight: row.y + row.height + units.gu(1);
149}
140}
tests/plugins/Dash/cardcreator/7.tst+1
@@ -1,3 +1,4 @@
1template: {"card-background":{"elements":["#E9E9E9","#E9AAE9"],"type":"color"},"card-layout":"vertical","card-size":"medium","category-layout":"grid","collapsed-rows":2}
1template: {"card-background":{"elements":["#E9E9E9","#E9AAE9"],"type":"color"},"card-layout":"vertical","card-size":"medium","category-layout":"grid","collapsed-rows":2}
2components: {"art":{"aspect-ratio":1},"background":{"field":"background"},"mascot":{"field":"icon"},"subtitle":{"field":"author"},"title":{"field":"title"},"attributes":{"field":"attributes","max-count":2}}
2components: {"art":{"aspect-ratio":1},"background":{"field":"background"},"mascot":{"field":"icon"},"subtitle":{"field":"author"},"title":{"field":"title"},"attributes":{"field":"attributes","max-count":2}}
3+artShapeStyle: icon
3result: 7.res
4result: 7.res
tests/plugins/Dash/cardcreator/8.res+1−2
@@ -1,7 +1,6 @@
1AbstractButton {
1AbstractButton {
2 id: root;
2 id: root;
3 property var cardData;
3 property var cardData;
4− property string artShapeStyle: "inset";
5 property string backgroundShapeStyle: "inset";
4 property string backgroundShapeStyle: "inset";
6 property real fontScale: 1.0;
5 property real fontScale: 1.0;
7 property var scopeStyle: null;
6 property var scopeStyle: null;
@@ -101,7 +100,7 @@ UbuntuShape {
101 id: touchdown;
100 id: touchdown;
102 objectName: "touchdown";
101 objectName: "touchdown";
103 anchors { fill: backgroundLoader }
102 anchors { fill: backgroundLoader }
104− visible: root.artShapeStyle != "shadow" && root.artShapeStyle != "icon" && root.pressed;
103+ visible: root.pressed;
105 radius: "medium";
104 radius: "medium";
106 borderSource: "radius_pressed.sci"
105 borderSource: "radius_pressed.sci"
107}
106}
tests/plugins/Dash/cardcreator/8.res.cardcreator+1−2
@@ -1,7 +1,6 @@
1AbstractButton {
1AbstractButton {
2 id: root;
2 id: root;
3 property var cardData;
3 property var cardData;
4− property string artShapeStyle: "inset";
5 property string backgroundShapeStyle: "inset";
4 property string backgroundShapeStyle: "inset";
6 property real fontScale: 1.0;
5 property real fontScale: 1.0;
7 property var scopeStyle: null;
6 property var scopeStyle: null;
@@ -99,7 +98,7 @@ UbuntuShape {
99 id: touchdown;
98 id: touchdown;
100 objectName: "touchdown";
99 objectName: "touchdown";
101 anchors { fill: backgroundLoader }
100 anchors { fill: backgroundLoader }
102− visible: root.artShapeStyle != "shadow" && root.artShapeStyle != "icon" && root.pressed;
101+ visible: root.pressed;
103 radius: "medium";
102 radius: "medium";
104 borderSource: "radius_pressed.sci"
103 borderSource: "radius_pressed.sci"
105}
104}
tests/plugins/Dash/cardcreator/8.tst+1
@@ -1,3 +1,4 @@
1template: {"card-background":{"elements":["#E9E9E9","#E9AAE9"],"type":"color"},"card-layout":"vertical","card-size":"medium","category-layout":"grid","collapsed-rows":2}
1template: {"card-background":{"elements":["#E9E9E9","#E9AAE9"],"type":"color"},"card-layout":"vertical","card-size":"medium","category-layout":"grid","collapsed-rows":2}
2components: {"background":{"field":"background"},"mascot":{"field":"icon"},"title":{"field":"title"},"attributes":{}}
2components: {"background":{"field":"background"},"mascot":{"field":"icon"},"title":{"field":"title"},"attributes":{}}
3+artShapeStyle: inset
3result: 8.res
4result: 8.res
tests/plugins/Dash/cardcreator/9.res+1−2
@@ -1,7 +1,6 @@
1AbstractButton {
1AbstractButton {
2 id: root;
2 id: root;
3 property var cardData;
3 property var cardData;
4− property string artShapeStyle: "inset";
5 property string backgroundShapeStyle: "inset";
4 property string backgroundShapeStyle: "inset";
6 property real fontScale: 1.0;
5 property real fontScale: 1.0;
7 property var scopeStyle: null;
6 property var scopeStyle: null;
@@ -112,7 +111,7 @@ CardAudioProgress {
112 id: touchdown;
111 id: touchdown;
113 objectName: "touchdown";
112 objectName: "touchdown";
114 anchors { fill: root }
113 anchors { fill: root }
115− visible: root.artShapeStyle != "shadow" && root.artShapeStyle != "icon" && root.pressed;
114+ visible: root.pressed;
116 radius: "medium";
115 radius: "medium";
117 borderSource: "radius_pressed.sci"
116 borderSource: "radius_pressed.sci"
118 }
117 }
tests/plugins/Dash/cardcreator/9.res.cardcreator+1−2
@@ -1,7 +1,6 @@
1AbstractButton {
1AbstractButton {
2 id: root;
2 id: root;
3 property var cardData;
3 property var cardData;
4− property string artShapeStyle: "inset";
5 property string backgroundShapeStyle: "inset";
4 property string backgroundShapeStyle: "inset";
6 property real fontScale: 1.0;
5 property real fontScale: 1.0;
7 property var scopeStyle: null;
6 property var scopeStyle: null;
@@ -111,7 +110,7 @@ CardAudioProgress {
111 id: touchdown;
110 id: touchdown;
112 objectName: "touchdown";
111 objectName: "touchdown";
113 anchors { fill: root }
112 anchors { fill: root }
114− visible: root.artShapeStyle != "shadow" && root.artShapeStyle != "icon" && root.pressed;
113+ visible: root.pressed;
115 radius: "medium";
114 radius: "medium";
116 borderSource: "radius_pressed.sci"
115 borderSource: "radius_pressed.sci"
117 }
116 }
tests/plugins/Dash/cardcreator/9.tst+1
@@ -1,3 +1,4 @@
1template: {"card-layout":"horizontal","card-size":"medium","category-layout":"grid","collapsed-rows":2,"quick-preview-type": "audio"}
1template: {"card-layout":"horizontal","card-size":"medium","category-layout":"grid","collapsed-rows":2,"quick-preview-type": "audio"}
2components: {"art":{"aspect-ratio":1},"subtitle":{"field":"author"},"title":{"field":"title"}, "quickPreviewData": "quickPreviewData"}
2components: {"art":{"aspect-ratio":1},"subtitle":{"field":"author"},"title":{"field":"title"}, "quickPreviewData": "quickPreviewData"}
3+artShapeStyle: inset
3result: 9.res
4result: 9.res
tests/plugins/Dash/cardcreatortest.cpp+9−6
@@ -78,6 +78,7 @@ private Q_SLOTS:
78 {
78 {
79 const QString templateString("template: ");
79 const QString templateString("template: ");
80 const QString componentsString("components: ");
80 const QString componentsString("components: ");
81+ const QString artShapeStyleString("artShapeStyle: ");
81 const QString resultString("result: ");
82 const QString resultString("result: ");
82
83
83 const QString testDirPath = testDataDir() + "/" TEST_DIR "/cardcreator/";
84 const QString testDirPath = testDataDir() + "/" TEST_DIR "/cardcreator/";
@@ -92,24 +93,26 @@ private Q_SLOTS:
92
93
93 QVERIFY(lines[0].startsWith(templateString));
94 QVERIFY(lines[0].startsWith(templateString));
94 QVERIFY(lines[1].startsWith(componentsString));
95 QVERIFY(lines[1].startsWith(componentsString));
95− QVERIFY(lines[2].startsWith(resultString));
96+ QVERIFY(lines[2].startsWith(artShapeStyleString));
97+ QVERIFY(lines[3].startsWith(resultString));
96
98
97 const QString templateJSON = lines[0].mid(templateString.length());
99 const QString templateJSON = lines[0].mid(templateString.length());
98 const QString componentsJSON = lines[1].mid(componentsString.length());
100 const QString componentsJSON = lines[1].mid(componentsString.length());
101+ const QString artShapeStyle = lines[2].mid(artShapeStyleString.length());
99− const QString resultFileName = lines[2].mid(resultString.length());
102+ const QString resultFileName = lines[3].mid(resultString.length());
100 QVariant cardStringResult;
103 QVariant cardStringResult;
101 QVariant createCardComponentResult;
104 QVariant createCardComponentResult;
102
105
103− QMetaObject::invokeMethod(view->rootObject(), "cardString", Q_RETURN_ARG(QVariant, cardStringResult), Q_ARG(QVariant, templateJSON), Q_ARG(QVariant, componentsJSON), Q_ARG(QVariant, false));
106+ QMetaObject::invokeMethod(view->rootObject(), "cardString", Q_RETURN_ARG(QVariant, cardStringResult), Q_ARG(QVariant, templateJSON), Q_ARG(QVariant, componentsJSON), Q_ARG(QVariant, false), Q_ARG(QVariant, artShapeStyle));
104 compareFileContents(testDirPath + resultFileName, cardStringResult.toString());
107 compareFileContents(testDirPath + resultFileName, cardStringResult.toString());
105
108
106− QMetaObject::invokeMethod(view->rootObject(), "cardString", Q_RETURN_ARG(QVariant, cardStringResult), Q_ARG(QVariant, templateJSON), Q_ARG(QVariant, componentsJSON), Q_ARG(QVariant, true));
109+ QMetaObject::invokeMethod(view->rootObject(), "cardString", Q_RETURN_ARG(QVariant, cardStringResult), Q_ARG(QVariant, templateJSON), Q_ARG(QVariant, componentsJSON), Q_ARG(QVariant, true), Q_ARG(QVariant, artShapeStyle));
107 compareFileContents(testDirPath + resultFileName + ".cardcreator", cardStringResult.toString());
110 compareFileContents(testDirPath + resultFileName + ".cardcreator", cardStringResult.toString());
108
111
109− QMetaObject::invokeMethod(view->rootObject(), "createCardComponent", Q_RETURN_ARG(QVariant, createCardComponentResult), Q_ARG(QVariant, templateJSON), Q_ARG(QVariant, componentsJSON), Q_ARG(QVariant, false));
112+ QMetaObject::invokeMethod(view->rootObject(), "createCardComponent", Q_RETURN_ARG(QVariant, createCardComponentResult), Q_ARG(QVariant, templateJSON), Q_ARG(QVariant, componentsJSON), Q_ARG(QVariant, false), Q_ARG(QVariant, artShapeStyle));
110 QVERIFY(createCardComponentResult.toBool());
113 QVERIFY(createCardComponentResult.toBool());
111
114
112− QMetaObject::invokeMethod(view->rootObject(), "createCardComponent", Q_RETURN_ARG(QVariant, createCardComponentResult), Q_ARG(QVariant, templateJSON), Q_ARG(QVariant, componentsJSON), Q_ARG(QVariant, true));
115+ QMetaObject::invokeMethod(view->rootObject(), "createCardComponent", Q_RETURN_ARG(QVariant, createCardComponentResult), Q_ARG(QVariant, templateJSON), Q_ARG(QVariant, componentsJSON), Q_ARG(QVariant, true), Q_ARG(QVariant, artShapeStyle));
113 QVERIFY(createCardComponentResult.toBool());
116 QVERIFY(createCardComponentResult.toBool());
114 }
117 }
115 }
118 }
tests/plugins/Dash/cardcreatortest.qml+4−4
@@ -19,11 +19,11 @@ import "../../../plugins/Dash/CardCreator.js" as CardCreator
19
19
20Item {
20Item {
21 id: root
21 id: root
22− function cardString(template, components, isCardCreator) {
22+ function cardString(template, components, isCardCreator, artShapeStyle) {
23− return CardCreator.cardString(JSON.parse(template), JSON.parse(components), isCardCreator);
23+ return CardCreator.cardString(JSON.parse(template), JSON.parse(components), isCardCreator, artShapeStyle);
24 }
24 }
25
25
26− function createCardComponent(template, components, isCardCreator) {
26+ function createCardComponent(template, components, isCardCreator, artShapeStyle) {
27− return CardCreator.createCardComponent(root, JSON.parse(template), JSON.parse(components), isCardCreator) !== null;
27+ return CardCreator.createCardComponent(root, JSON.parse(template), JSON.parse(components), isCardCreator, artShapeStyle) !== null;
28 }
28 }
29}
29}
tests/plugins/Dash/listviewwithpageheadersectionexternalmodeltest.cpp+2−2
@@ -153,12 +153,12 @@ private:
153
153
154 QString section(QQuickItem *item)
154 QString section(QQuickItem *item)
155 {
155 {
156− return item ? QQmlEngine::contextForObject(item)->parentContext()->contextProperty(QLatin1String("section")).toString() : QString();
156+ return item ? item->property("text").toString() : QString();
157 }
157 }
158
158
159 int sectionDelegateIndex(QQuickItem *item)
159 int sectionDelegateIndex(QQuickItem *item)
160 {
160 {
161− return item ? QQmlEngine::contextForObject(item)->parentContext()->contextProperty(QLatin1String("delegateIndex")).toInt() : -1;
161+ return item ? item->property("delegateIndex").toInt() : -1;
162 }
162 }
163
163
164private Q_SLOTS:
164private Q_SLOTS:
tests/plugins/Dash/listviewwithpageheadersectiontest.cpp+2−2
@@ -118,12 +118,12 @@ private:
118
118
119 QString section(QQuickItem *item) const
119 QString section(QQuickItem *item) const
120 {
120 {
121− return item ? QQmlEngine::contextForObject(item)->parentContext()->contextProperty(QLatin1String("section")).toString() : QString();
121+ return item ? item->property("text").toString() : QString();
122 }
122 }
123
123
124 int sectionDelegateIndex(QQuickItem *item) const
124 int sectionDelegateIndex(QQuickItem *item) const
125 {
125 {
126− return item ? QQmlEngine::contextForObject(item)->parentContext()->contextProperty(QLatin1String("delegateIndex")).toInt() : -1;
126+ return item ? item->property("delegateIndex").toInt() : -1;
127 }
127 }
128
128
129private Q_SLOTS:
129private Q_SLOTS:
tests/plugins/Dash/listviewwithpageheadertest.cpp+5
@@ -47,6 +47,11 @@ private:
47 QTRY_COMPARE(item->y(), pos);
47 QTRY_COMPARE(item->y(), pos);
48 QTRY_COMPARE(item->height(), height);
48 QTRY_COMPARE(item->height(), height);
49 QCOMPARE(QQuickItemPrivate::get(item->m_item)->culled, culled);
49 QCOMPARE(QQuickItemPrivate::get(item->m_item)->culled, culled);
50+ if (lvwph->delegate() == otherDelegate) {
51+ QCOMPARE(item->m_item->width(), lvwph->width());
52+ } else {
53+ QCOMPARE(item->m_item->width(), lvwph->width() - 20);
54+ }
50 }
55 }
51
56
52 void changeContentY(qreal change)
57 void changeContentY(qreal change)
tests/plugins/Dash/listviewwithpageheadertestsection.qml+3−2
@@ -97,9 +97,10 @@ Rectangle {
97 sectionProperty: "type"
97 sectionProperty: "type"
98 sectionDelegate: Component {
98 sectionDelegate: Component {
99 Rectangle {
99 Rectangle {
100+ property alias text: theText.text
100 color: "green"
101 color: "green"
101− height: section === "" ? 0 : section != "halfheight" ? 40 : 20;
102+ height: text === "" ? 0 : text != "halfheight" ? 40 : 20;
102− Text { text: section; font.pixelSize: 34 }
103+ Text { id: theText; font.pixelSize: 34 }
103 anchors { left: parent.left; right: parent.right }
104 anchors { left: parent.left; right: parent.right }
104 }
105 }
105 }
106 }
tests/plugins/Dash/listviewwithpageheadertestsectionexternalmodel.qml+2−1
@@ -65,9 +65,10 @@ Rectangle {
65 sectionProperty: "type"
65 sectionProperty: "type"
66 sectionDelegate: Component {
66 sectionDelegate: Component {
67 Rectangle {
67 Rectangle {
68+ property alias text: theText.text
68 color: "green"
69 color: "green"
69 height: 40
70 height: 40
70− Text { text: section; font.pixelSize: 34 }
71+ Text { id: theText; font.pixelSize: 34 }
71 anchors { left: parent.left; right: parent.right }
72 anchors { left: parent.left; right: parent.right }
72 }
73 }
73 }
74 }
tests/plugins/Dash/tst_ListViewWithPageHeaderQML.qml+4−2
@@ -81,9 +81,10 @@ Rectangle {
81 sectionDelegate: Component {
81 sectionDelegate: Component {
82 id: sectionHeaderComponent
82 id: sectionHeaderComponent
83 Rectangle {
83 Rectangle {
84+ property alias text: theText.text
84 color: "green"
85 color: "green"
85 height: listView.sectionHeaderHeight
86 height: listView.sectionHeaderHeight
86− Text { text: section; font.pixelSize: 34 }
87+ Text { id: theText; font.pixelSize: 34 }
87 anchors { left: parent.left; right: parent.right }
88 anchors { left: parent.left; right: parent.right }
88 }
89 }
89 }
90 }
@@ -92,9 +93,10 @@ Rectangle {
92 Component {
93 Component {
93 id: otherSectionHeaderComponent
94 id: otherSectionHeaderComponent
94 Rectangle {
95 Rectangle {
96+ property alias text: theText.text
95 color: "green"
97 color: "green"
96 height: 50
98 height: 50
97− Text { text: section; font.pixelSize: 34 }
99+ Text { id: theText; font.pixelSize: 34 }
98 anchors { left: parent.left; right: parent.right }
100 anchors { left: parent.left; right: parent.right }
99 }
101 }
100 }
102 }
tests/plugins/Dash/tst_ScopeStyle.qml+1−1
@@ -174,7 +174,7 @@ Rectangle {
174
174
175 function test_previewButtonColor_data() {
175 function test_previewButtonColor_data() {
176 return [
176 return [
177− { tag: "default", index: 0, previewButtonColor: UbuntuColors.orange },
177+ { tag: "default", index: 0, previewButtonColor: theme.palette.normal.positive },
178 { tag: "red", index: 1, previewButtonColor: "red" },
178 { tag: "red", index: 1, previewButtonColor: "red" },
179 ];
179 ];
180 }
180 }
tests/plugins/Ubuntu/Gestures/CMakeLists.txt+4−4
@@ -1,5 +1,7 @@
1include(QmlTest)
1include(QmlTest)
2
2
3+pkg_check_modules(UBUNTUGESTURES REQUIRED UbuntuGestures)
4+
3# DANGER! DANGER! Using Qt's private API!
5# DANGER! DANGER! Using Qt's private API!
4include_directories(
6include_directories(
5 ${Qt5Quick_PRIVATE_INCLUDE_DIRS}
7 ${Qt5Quick_PRIVATE_INCLUDE_DIRS}
@@ -7,7 +9,7 @@ include_directories(
7
9
8include_directories(
10include_directories(
9 ${CMAKE_SOURCE_DIR}/plugins/Ubuntu/Gestures
11 ${CMAKE_SOURCE_DIR}/plugins/Ubuntu/Gestures
10− ${CMAKE_SOURCE_DIR}/libs/UbuntuGestures
12+ ${UBUNTUGESTURES_INCLUDE_DIRS}
11 ${CMAKE_CURRENT_BINARY_DIR}
13 ${CMAKE_CURRENT_BINARY_DIR}
12 ${Qt5Gui_PRIVATE_INCLUDE_DIRS}
14 ${Qt5Gui_PRIVATE_INCLUDE_DIRS}
13 )
15 )
@@ -19,7 +21,7 @@ export_qmlfiles(UbuntuGesturesTest .
19macro(build_gesture_test CLASSNAME)
21macro(build_gesture_test CLASSNAME)
20 add_executable(${CLASSNAME}TestExec tst_${CLASSNAME}.cpp GestureTest.cpp TestItem.cpp)
22 add_executable(${CLASSNAME}TestExec tst_${CLASSNAME}.cpp GestureTest.cpp TestItem.cpp)
21 qt5_use_modules(${CLASSNAME}TestExec Test Core Qml Gui Quick)
23 qt5_use_modules(${CLASSNAME}TestExec Test Core Qml Gui Quick)
22− target_link_libraries(${CLASSNAME}TestExec UbuntuGesturesQml UbuntuGestures)
24+ target_link_libraries(${CLASSNAME}TestExec UbuntuGesturesQml ${UBUNTUGESTURES_LIBRARIES})
23 install(TARGETS ${CLASSNAME}TestExec
25 install(TARGETS ${CLASSNAME}TestExec
24 DESTINATION "${SHELL_PRIVATE_LIBDIR}/tests/plugins/Ubuntu/Gestures"
26 DESTINATION "${SHELL_PRIVATE_LIBDIR}/tests/plugins/Ubuntu/Gestures"
25 )
27 )
@@ -51,11 +53,9 @@ macro(add_gesture_ui_test CLASSNAME)
51 add_manual_qml_test(. ${CLASSNAME} IMPORT_PATHS ${UNITY_IMPORT_PATHS})
53 add_manual_qml_test(. ${CLASSNAME} IMPORT_PATHS ${UNITY_IMPORT_PATHS})
52endmacro()
54endmacro()
53
55
54−add_gesture_ui_test(DirectionalDragArea)
55add_gesture_ui_test(FloatingFlickable)
56add_gesture_ui_test(FloatingFlickable)
56add_gesture_ui_test(PressedOutsideNotifier)
57add_gesture_ui_test(PressedOutsideNotifier)
57add_gesture_ui_test(TouchDispatcher)
58add_gesture_ui_test(TouchDispatcher)
58add_gesture_ui_test(TouchGate)
59add_gesture_ui_test(TouchGate)
59−add_gesture_unit_test(Damper)
60add_gesture_unit_test(AxisVelocityCalculator)
60add_gesture_unit_test(AxisVelocityCalculator)
61add_gesture_ui_test(TouchGestureArea)
61add_gesture_ui_test(TouchGestureArea)
tests/plugins/Ubuntu/Gestures/DownwardsLauncher.qmldeleted−72
@@ -1,72 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.4
18−import Ubuntu.Gestures 0.1
19−import Ubuntu.Components 1.3
20−
21−Item {
22−
23− function reset() { launcher.y = -launcher.height }
24−
25− Rectangle {
26− id: launcher
27− color: "blue"
28− width: parent.width
29− height: units.gu(15)
30− x: 0
31− y: followDragArea()
32−
33− function followDragArea() {
34− return dragArea.distance < height ? -height + dragArea.distance : 0
35− }
36− }
37−
38− Rectangle {
39− id: dragAreaRect
40− opacity: dragArea.dragging ? 0.5 : 0.0
41− color: "green"
42− anchors.fill: dragArea
43− }
44−
45− DirectionalDragArea {
46− id: dragArea
47− objectName: "vpDragArea"
48−
49− height: units.gu(5)
50−
51− direction: Direction.Downwards
52−
53− onDraggingChanged: {
54− if (dragging) {
55− launcher.y = Qt.binding(launcher.followDragArea)
56− }
57− }
58−
59− anchors {
60− left: parent.left
61− right: parent.right
62− top: parent.top
63− }
64− }
65−
66− Label {
67− text: "Downwards"
68− anchors.top: parent.top
69− anchors.horizontalCenter: parent.horizontalCenter
70− anchors.topMargin: units.gu(1)
71− }
72−}
tests/plugins/Ubuntu/Gestures/GestureTest.cpp+2−2
@@ -22,8 +22,8 @@
22#include <QQuickView>
22#include <QQuickView>
23#include <QtTest>
23#include <QtTest>
24
24
25−#include <Timer.h>
25+#include <Timer>
26−#include <TouchRegistry.h>
26+#include <TouchRegistry>
27#include <paths.h>
27#include <paths.h>
28
28
29using namespace UbuntuGestures;
29using namespace UbuntuGestures;
tests/plugins/Ubuntu/Gestures/LeftwardsLauncher.qmldeleted−76
@@ -1,76 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.4
18−import Ubuntu.Gestures 0.1
19−import Ubuntu.Components 1.3
20−
21−Item {
22− id: root
23−
24− function reset() { launcher.x = Qt.binding(function(){return root.width;}); }
25−
26− Rectangle {
27− id: launcher
28− color: "blue"
29− width: units.gu(15)
30− height: parent.height
31− x: root.width
32− y: 0
33−
34− function followDragArea() {
35− return dragArea.distance > -width ?
36− root.width + dragArea.distance
37− :
38− root.width - width
39− }
40− }
41−
42− Rectangle {
43− id: dragAreaRect
44− opacity: dragArea.dragging ? 0.5 : 0.0
45− color: "green"
46− anchors.fill: dragArea
47− }
48−
49− DirectionalDragArea {
50− id: dragArea
51− objectName: "hnDragArea"
52−
53− width: units.gu(5)
54−
55− direction: Direction.Leftwards
56−
57− onDraggingChanged: {
58− if (dragging) {
59− launcher.x = Qt.binding(launcher.followDragArea)
60− }
61− }
62−
63− anchors {
64− right: parent.right
65− top: parent.top
66− bottom: parent.bottom
67− }
68− }
69−
70− Label {
71− text: "Leftwards"
72− anchors.right: parent.right
73− anchors.verticalCenter: parent.verticalCenter
74− anchors.rightMargin: units.gu(1)
75− }
76−}
tests/plugins/Ubuntu/Gestures/RightwardsLauncher.qmldeleted−76
@@ -1,76 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.4
18−import Ubuntu.Gestures 0.1
19−import Ubuntu.Components 1.3
20−
21−Item {
22− objectName: "rightwardsLauncher"
23−
24− function reset() { launcher.x = -launcher.width }
25−
26− Rectangle {
27− id: launcher
28− color: "blue"
29− width: units.gu(15)
30− height: parent.height
31− x: followDragArea()
32− y: 0
33−
34− function followDragArea() {
35− return dragArea.distance < width ? -width + dragArea.distance : 0
36− }
37− }
38−
39− Rectangle {
40− id: dragAreaRect
41− opacity: dragArea.dragging ? 0.5 : 0.0
42− color: "green"
43− anchors.fill: dragArea
44− }
45−
46− DirectionalDragArea {
47− id: dragArea
48− objectName: "hpDragArea"
49−
50− // give some room for items to be dynamically stacked right behind him
51− z: 10.0
52−
53− width: units.gu(5)
54−
55− direction: Direction.Rightwards
56−
57− onDraggingChanged: {
58− if (dragging) {
59− launcher.x = Qt.binding(launcher.followDragArea)
60− }
61− }
62−
63− anchors {
64− left: parent.left
65− top: parent.top
66− bottom: parent.bottom
67− }
68− }
69−
70− Label {
71− text: "Rightwards"
72− anchors.left: parent.left
73− anchors.verticalCenter: parent.verticalCenter
74− anchors.leftMargin: units.gu(1)
75− }
76−}
tests/plugins/Ubuntu/Gestures/UpwardsLauncher.qmldeleted−76
@@ -1,76 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.4
18−import Ubuntu.Gestures 0.1
19−import Ubuntu.Components 1.3
20−
21−Item {
22− id: root
23−
24− function reset() { launcher.y = Qt.binding(function(){return root.height;}); }
25−
26− Rectangle {
27− id: launcher
28− color: "blue"
29− width: parent.width
30− height: units.gu(15)
31− x: 0
32− y: root.height
33−
34− function followDragArea() {
35− return dragArea.distance > -height ?
36− root.height + dragArea.distance
37− :
38− root.height - height
39− }
40− }
41−
42− Rectangle {
43− id: dragAreaRect
44− opacity: dragArea.dragging ? 0.5 : 0.0
45− color: "green"
46− anchors.fill: dragArea
47− }
48−
49− DirectionalDragArea {
50− id: dragArea
51− objectName: "vnDragArea"
52−
53− height: units.gu(5)
54−
55− direction: Direction.Upwards
56−
57− onDraggingChanged: {
58− if (dragging) {
59− launcher.y = Qt.binding(launcher.followDragArea)
60− }
61− }
62−
63− anchors {
64− left: parent.left
65− right: parent.right
66− bottom: parent.bottom
67− }
68− }
69−
70− Label {
71− text: "Upwards"
72− anchors.bottom: parent.bottom
73− anchors.horizontalCenter: parent.horizontalCenter
74− anchors.bottomMargin: units.gu(1)
75− }
76−}
tests/plugins/Ubuntu/Gestures/tst_Damper.cppdeleted−40
@@ -1,40 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#include <QtTest/QtTest>
18−
19−#include <Damper.h>
20−
21−class tst_Damper : public QObject
22−{
23− Q_OBJECT
24−private Q_SLOTS:
25− void negativeMovement();
26−};
27−
28−void tst_Damper::negativeMovement()
29−{
30− Damper<qreal> damper;
31−
32− damper.setMaxDelta(3.0);
33− damper.reset(0.0);
34− damper.update(-5.0);
35− QCOMPARE(damper.value(), -2.0);
36−}
37−
38−QTEST_MAIN(tst_Damper)
39−
40−#include "tst_Damper.moc"
tests/plugins/Ubuntu/Gestures/tst_DirectionalDragArea.cppdeleted−1250
@@ -1,1250 +0,0 @@
1−/*
2− * Copyright (C) 2013-2015 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#include <QtTest/QtTest>
18−#include <QtCore/QObject>
19−#include <QtQuick/QQuickView>
20−#include <QtQml/QQmlEngine>
21−#include <QPointer>
22−#include <private/qquickmousearea_p.h>
23−
24−
25−#include <DirectionalDragArea.h>
26−#include <DirectionalDragArea_p.h>
27−#include <TouchRegistry.h>
28−
29−#include "GestureTest.h"
30−
31−using namespace UbuntuGestures;
32−
33−// Because QSignalSpy(directionalDragArea, SIGNAL(DirectionalDragArea::Status)) simply
34−// doesn't work
35−class StatusSpy : public QObject {
36− Q_OBJECT
37−public:
38− StatusSpy(DirectionalDragArea *edgeDragArea) {
39− m_recognized = false;
40− connect(edgeDragArea->d, &DirectionalDragAreaPrivate::statusChanged,
41− this, &StatusSpy::onStatusChanged);
42− }
43− bool recognized() {
44− return m_recognized;
45− }
46−
47−private Q_SLOTS:
48− void onStatusChanged(DirectionalDragAreaPrivate::Status status) {
49− m_recognized |= status == DirectionalDragAreaPrivate::Recognized;
50− }
51−
52−private:
53− bool m_recognized;
54−};
55−
56−/*
57− QQuickMouseArea::canceled() signal is not registered in the meta object system.
58− So using a QSignalSpy to track it won't work. Thus the only way to connect to it
59− is using its method address directly.
60− */
61−class MouseAreaSpy : public QObject
62−{
63− Q_OBJECT
64−public:
65− MouseAreaSpy(QQuickMouseArea *mouseArea)
66− : canceledCount(0)
67− {
68− connect(mouseArea, &QQuickMouseArea::canceled,
69− this, &MouseAreaSpy::onMouseAreaCanceled);
70− }
71−
72− int canceledCount;
73−
74−private Q_SLOTS:
75− void onMouseAreaCanceled() {
76− ++canceledCount;
77− }
78−};
79−
80−class tst_DirectionalDragArea: public GestureTest
81−{
82− Q_OBJECT
83−public:
84− tst_DirectionalDragArea();
85−private Q_SLOTS:
86− void init() override; // called right before each and every test function is executed
87−
88− void dragWithShortDirectionChange();
89− void recognitionTimerUsage();
90− void sceneXAndX();
91− void sceneYAndY();
92− void twoFingerTap();
93− void movingDDA();
94− void ignoreOldFinger();
95− void rotated();
96− void sceneDistance();
97− void sceneDistance_data();
98− void disabledWhileDragging();
99− void oneFingerDownFollowedByLateSecondFingerDown();
100− void givesUpWhenLosesTouch();
101− void threeFingerDrag();
102− void immediateRecognitionWhenConstraintsDisabled();
103− void withdrawTouchOwnershipCandidacyIfDisabledDuringRecognition();
104− void withdrawTouchOwnershipCandidacyIfDisabledDuringRecognition_data();
105− void gettingTouchOwnershipMakesMouseAreaBehindGetCanceled();
106− void interleavedTouches();
107− void makoRightEdgeDrag();
108− void makoRightEdgeDrag_verticalDownwards();
109− void makoLeftEdgeDrag_slowStart();
110− void makoLeftEdgeDrag_movesSlightlyBackwardsOnStart();
111−};
112−
113−tst_DirectionalDragArea::tst_DirectionalDragArea()
114− : GestureTest(QStringLiteral("tst_DirectionalDragArea.qml"))
115−{
116−}
117−
118−void tst_DirectionalDragArea::init()
119−{
120− GestureTest::init();
121−
122− // We shouldn't need the three lines below, but a compiz/unity7
123− // regression means we don't pass the test without them because
124− // the window doesn't have the proper size. Can be removed in the
125− // future if the regression is fixed and tests pass again
126− m_view->resize(m_view->rootObject()->width(), m_view->rootObject()->height());
127− QTRY_COMPARE(m_view->width(), (int)m_view->rootObject()->width());
128− QTRY_COMPARE(m_view->height(), (int)m_view->rootObject()->height());
129−}
130−
131−namespace {
132−QPointF calculateInitialTouchPos(DirectionalDragArea *edgeDragArea)
133−{
134− QPointF localCenter(edgeDragArea->width() / 2., edgeDragArea->height() / 2.);
135− return edgeDragArea->mapToScene(localCenter);
136−}
137−}
138−
139−/*
140− A directional drag should still be recognized if there is a momentaneous, small,
141− change in the direction of a drag. That should be accounted as input noise and
142− therefore ignored.
143− */
144−void tst_DirectionalDragArea::dragWithShortDirectionChange()
145−{
146− DirectionalDragArea *edgeDragArea =
147− m_view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
148− QVERIFY(edgeDragArea != 0);
149− edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
150− edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
151−
152− QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea);
153− QPointF touchPoint = initialTouchPos;
154−
155− qreal desiredDragDistance = edgeDragArea->d->distanceThreshold * 2.0;
156− QPointF dragDirectionVector(1.0, 0.0);
157− qreal touchStepDistance = edgeDragArea->d->distanceThreshold * 0.1f;
158− // make sure we are above maximum time
159− int touchStepTimeMs = edgeDragArea->d->maxTime / 20. ;
160− QPointF touchMovement = dragDirectionVector * touchStepDistance;
161−
162− QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
163−
164− // Move a bit in the proper direction
165− for (int i=0; i < 3; ++i) {
166− touchPoint += touchMovement;
167− passTime(touchStepTimeMs);
168− QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
169− }
170−
171− // Then a sudden and small movement to the opposite direction
172− touchPoint -= touchMovement*0.2;
173− passTime(touchStepTimeMs*0.2);
174− QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
175−
176− // And then resume movment in the correct direction until it crosses the distance and time
177− // thresholds.
178− do {
179− touchPoint += touchMovement;
180− passTime(touchStepTimeMs);
181− QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
182− } while ((touchPoint - initialTouchPos).manhattanLength() < desiredDragDistance
183− || m_fakeTimerFactory->timeSource()->msecsSinceReference() < (edgeDragArea->d->compositionTime * 1.5f));
184−
185− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::Recognized);
186−
187− QTest::touchEvent(m_view, m_device).release(0, touchPoint.toPoint());
188−}
189−
190−/*
191− Checks that the recognition timer is started and stopped appropriately.
192− I.e., check that it's running only while gesture recognition is taking place
193− (status == Undecided)
194− */
195−void tst_DirectionalDragArea::recognitionTimerUsage()
196−{
197− DirectionalDragArea *edgeDragArea =
198− m_view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
199− QVERIFY(edgeDragArea != 0);
200− AbstractTimer *fakeTimer = m_fakeTimerFactory->createTimer();
201− edgeDragArea->d->setRecognitionTimer(fakeTimer);
202− edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
203−
204− int timeStepMs = 5; // some arbitrary small value.
205−
206− QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea);
207− QPointF touchPoint = initialTouchPos;
208−
209− QPointF dragDirectionVector(1.0, 0.0);
210− QPointF touchMovement = dragDirectionVector * (edgeDragArea->d->distanceThreshold * 0.2f);
211−
212− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::WaitingForTouch);
213− QVERIFY(!fakeTimer->isRunning());
214−
215− QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
216−
217− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::Undecided);
218− QVERIFY(fakeTimer->isRunning());
219−
220− // Move beyond distance threshold and composition time to ensure recognition
221− while (m_fakeTimerFactory->timeSource()->msecsSinceReference() <= edgeDragArea->d->compositionTime ||
222− (touchPoint - initialTouchPos).manhattanLength() <= edgeDragArea->d->distanceThreshold) {
223−
224− QCOMPARE(edgeDragArea->d->status == DirectionalDragAreaPrivate::Undecided, fakeTimer->isRunning());
225−
226− touchPoint += touchMovement;
227− passTime(timeStepMs);
228− QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
229− }
230−
231− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::Recognized);
232− QVERIFY(!fakeTimer->isRunning());
233−}
234−
235−/*
236− Checks that it informs the X coordinate of the touch point in local and scene coordinates
237− correctly.
238− */
239−void tst_DirectionalDragArea::sceneXAndX()
240−{
241− DirectionalDragArea *edgeDragArea =
242− m_view->rootObject()->findChild<DirectionalDragArea*>("hnDragArea");
243− QVERIFY(edgeDragArea != 0);
244− edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
245− edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
246− edgeDragArea->setImmediateRecognition(true);
247−
248− QPointF touchScenePos(m_view->width() - (edgeDragArea->width()/2.0f), m_view->height()/2.0f);
249−
250− sendTouchPress(0 /* timestamp */, 0 /* id */, touchScenePos);
251−
252− QSignalSpy touchXSpy(edgeDragArea, &DirectionalDragArea::touchXChanged);
253− QSignalSpy touchSceneXSpy(edgeDragArea, &DirectionalDragArea::touchSceneXChanged);
254−
255− touchScenePos.rx() = m_view->width() / 2;
256− sendTouchUpdate(50 /* timestamp */, 0 /* id */, touchScenePos);
257−
258− QCOMPARE(touchXSpy.count(), 1);
259− QCOMPARE(touchSceneXSpy.count(), 1);
260− QCOMPARE(edgeDragArea->touchX(), touchScenePos.x() - edgeDragArea->x());
261− QCOMPARE(edgeDragArea->touchSceneX(), touchScenePos.x());
262−}
263−
264−/*
265− Checks that it informs the Y coordinate of the touch point in local and scene coordinates
266− correctly.
267− */
268−void tst_DirectionalDragArea::sceneYAndY()
269−{
270− DirectionalDragArea *edgeDragArea =
271− m_view->rootObject()->findChild<DirectionalDragArea*>("vnDragArea");
272− QVERIFY(edgeDragArea != 0);
273− edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
274− edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
275− edgeDragArea->setImmediateRecognition(true);
276−
277− QPointF touchScenePos(m_view->width()/2.0f, m_view->height() - (edgeDragArea->height()/2.0f));
278−
279− sendTouchPress(0 /* timestamp */, 0 /* id */, touchScenePos);
280−
281− QSignalSpy touchYSpy(edgeDragArea, &DirectionalDragArea::touchYChanged);
282− QSignalSpy touchSceneYSpy(edgeDragArea, &DirectionalDragArea::touchSceneYChanged);
283−
284− touchScenePos.ry() = m_view->height() / 2;
285− sendTouchUpdate(50 /* timestamp */, 0 /* id */, touchScenePos);
286−
287− QCOMPARE(touchYSpy.count(), 1);
288− QCOMPARE(touchSceneYSpy.count(), 1);
289− QCOMPARE(edgeDragArea->touchY(), touchScenePos.y() - edgeDragArea->y());
290− QCOMPARE(edgeDragArea->touchSceneY(), touchScenePos.y());
291−}
292−
293−/*
294− Regression test for https://bugs.launchpad.net/bugs/1228336
295−
296− Perform a quick two-finger double-tap and check that DirectionalDragArea properly
297− rejects those touch points. In the bug above it got confused and crashed.
298− */
299−void tst_DirectionalDragArea::twoFingerTap()
300−{
301− DirectionalDragArea *edgeDragArea =
302− m_view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
303− QVERIFY(edgeDragArea != 0);
304− edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
305− edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
306−
307− // Make touches evenly spaced along the edgeDragArea
308− QPoint touchAPos(edgeDragArea->width()/2.0f, m_view->height()*0.33f);
309− QPoint touchBPos(edgeDragArea->width()/2.0f, m_view->height()*0.66f);
310−
311− qint64 timeStepMsecs = 5; // some arbitrary, small value
312−
313− // Perform the first two-finger tap
314− // NB: using move() instead of stationary() becasue in the latter you cannot provide
315− // the touch position and therefore it's left with some garbage numbers.
316− QTest::touchEvent(m_view, m_device)
317− .press(0, touchAPos);
318−
319− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::Undecided);
320−
321− passTime(timeStepMsecs);
322− QTest::touchEvent(m_view, m_device)
323− .move(0, touchAPos)
324− .press(1, touchBPos);
325−
326− // A second touch point appeared during recognition, reject immediately as this
327− // can't be a single-touch gesture anymore.
328− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::WaitingForTouch);
329−
330− passTime(timeStepMsecs);
331− QTest::touchEvent(m_view, m_device)
332− .release(0, touchAPos)
333− .move(1, touchBPos);
334−
335− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::WaitingForTouch);
336−
337− passTime(timeStepMsecs);
338− QTest::touchEvent(m_view, m_device)
339− .release(1, touchBPos);
340−
341− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::WaitingForTouch);
342−
343− // Perform the second two-finger tap
344−
345− passTime(timeStepMsecs);
346− QTest::touchEvent(m_view, m_device)
347− .press(0, touchAPos);
348−
349− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::Undecided);
350−
351− passTime(timeStepMsecs);
352− QTest::touchEvent(m_view, m_device)
353− .move(0, touchAPos)
354− .press(1, touchBPos);
355−
356− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::WaitingForTouch);
357−
358− passTime(timeStepMsecs);
359− QTest::touchEvent(m_view, m_device)
360− .release(0, touchAPos)
361− .move(1, touchBPos);
362−
363− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::WaitingForTouch);
364−
365− passTime(timeStepMsecs);
366− QTest::touchEvent(m_view, m_device)
367− .release(1, touchBPos);
368−
369− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::WaitingForTouch);
370−}
371−
372−/*
373− Tests that gesture recognition works normally even if the DirectionalDragArea moves
374− during recognition.
375− This effectively means that we have to do gesture recognition with scene coordinates
376− instead of local item coordinates.
377− */
378−void tst_DirectionalDragArea::movingDDA()
379−{
380− QQuickItem *rightwardsLauncher = m_view->rootObject()->findChild<QQuickItem*>("rightwardsLauncher");
381− Q_ASSERT(rightwardsLauncher != 0);
382−
383− DirectionalDragArea *edgeDragArea =
384− rightwardsLauncher->findChild<DirectionalDragArea*>("hpDragArea");
385− Q_ASSERT(edgeDragArea != 0);
386− edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
387− edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
388−
389− QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea);
390− QPointF touchPoint = initialTouchPos;
391−
392− qreal desiredDragDistance = edgeDragArea->d->distanceThreshold * 2.0f;
393− QPointF dragDirectionVector(1.0f, 0.0f);
394−
395− qreal movementStepDistance = edgeDragArea->d->distanceThreshold * 0.1f;
396− QPointF touchMovement = dragDirectionVector * movementStepDistance;
397− int totalMovementSteps = qCeil(desiredDragDistance / movementStepDistance);
398− int movementTimeStepMs = (edgeDragArea->d->compositionTime * 1.5f) / totalMovementSteps;
399−
400− QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
401−
402− // Move it far ahead along the direction of the gesture
403− // rightwardsLauncher is a parent of our DirectionalDragArea. So moving it will move our DDA
404− rightwardsLauncher->setX(rightwardsLauncher->x() + edgeDragArea->d->distanceThreshold * 5.0f);
405−
406− for (int i = 0; i < totalMovementSteps; ++i) {
407− touchPoint += touchMovement;
408− passTime(movementTimeStepMs);
409− QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
410− }
411−
412− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::Recognized);
413−
414− QTest::touchEvent(m_view, m_device).release(0, touchPoint.toPoint());
415−}
416−
417−/*
418− The presence of and old, rejected, touch point lying on the DirectionalDragArea
419− shouldn't impede the recognition of a gesture from a new touch point.
420− */
421−void tst_DirectionalDragArea::ignoreOldFinger()
422−{
423− DirectionalDragArea *edgeDragArea =
424− m_view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
425− Q_ASSERT(edgeDragArea != 0);
426− edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
427− edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
428−
429− // Make touches evenly spaced along the edgeDragArea
430− QPoint touch0Pos(edgeDragArea->width()/2.0f, m_view->height()*0.33f);
431− QPoint touch1Pos(edgeDragArea->width()/2.0f, m_view->height()*0.66f);
432−
433− QTest::touchEvent(m_view, m_device).press(0, touch0Pos);
434−
435− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::Undecided);
436−
437− // leave it lying around for some time
438− passTime(edgeDragArea->d->maxTime * 10);
439−
440− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::WaitingForTouch);
441−
442− qreal desiredDragDistance = edgeDragArea->d->distanceThreshold * 2.0f;
443− QPointF dragDirectionVector(1.0f, 0.0f);
444−
445− qreal movementStepDistance = edgeDragArea->d->distanceThreshold * 0.1f;
446− QPointF touchMovement = dragDirectionVector * movementStepDistance;
447− int totalMovementSteps = qCeil(desiredDragDistance / movementStepDistance);
448− int movementTimeStepMs = (edgeDragArea->d->compositionTime * 1.5f) / totalMovementSteps;
449−
450− QTest::touchEvent(m_view, m_device)
451− .move(0, touch0Pos)
452− .press(1, touch1Pos);
453−
454− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::Undecided);
455−
456− for (int i = 0; i < totalMovementSteps; ++i) {
457− touch1Pos += touchMovement.toPoint();
458− passTime(movementTimeStepMs);
459− QTest::touchEvent(m_view, m_device)
460− .move(0, touch0Pos)
461− .move(1, touch1Pos);
462− }
463−
464− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::Recognized);
465−
466− QTest::touchEvent(m_view, m_device)
467− .move(0, touch0Pos)
468− .release(1, touch1Pos);
469−
470− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::WaitingForTouch);
471−}
472−
473−/*
474− A Rightwards DDA that is rotated 90 degrees clockwise should recognize gestures
475− that are done downwards in scene coordinates. I.e. the gesture recognition direction
476− should be in local coordinates, not scene coordinates.
477− */
478−void tst_DirectionalDragArea::rotated()
479−{
480− QQuickItem *baseItem = m_view->rootObject()->findChild<QQuickItem*>("baseItem");
481− baseItem->setRotation(90.);
482−
483− QQuickItem *rightwardsLauncher = m_view->rootObject()->findChild<QQuickItem*>("rightwardsLauncher");
484− Q_ASSERT(rightwardsLauncher != 0);
485−
486− DirectionalDragArea *edgeDragArea =
487− rightwardsLauncher->findChild<DirectionalDragArea*>("hpDragArea");
488− Q_ASSERT(edgeDragArea != 0);
489− edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
490− edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
491−
492− QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea);
493− QPointF touchPoint = initialTouchPos;
494−
495− qreal desiredDragDistance = edgeDragArea->d->distanceThreshold * 2.0f;
496− QPointF dragDirectionVector(0.0f, 1.0f);
497−
498− qreal movementStepDistance = edgeDragArea->d->distanceThreshold * 0.1f;
499− QPointF touchMovement = dragDirectionVector * movementStepDistance;
500− int totalMovementSteps = qCeil(desiredDragDistance / movementStepDistance);
501− int movementTimeStepMs = (edgeDragArea->d->compositionTime * 1.5f) / totalMovementSteps;
502−
503− QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
504−
505− for (int i = 0; i < totalMovementSteps; ++i) {
506− touchPoint += touchMovement;
507− passTime(movementTimeStepMs);
508− QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
509− }
510−
511− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::Recognized);
512−
513− QTest::touchEvent(m_view, m_device).release(0, touchPoint.toPoint());
514−}
515−
516−void tst_DirectionalDragArea::sceneDistance()
517−{
518− QQuickItem *baseItem = m_view->rootObject()->findChild<QQuickItem*>("baseItem");
519− QFETCH(qreal, rotation);
520− QFETCH(QPointF, dragDirectionVector);
521− baseItem->setRotation(rotation);
522−
523− QQuickItem *rightwardsLauncher = m_view->rootObject()->findChild<QQuickItem*>("rightwardsLauncher");
524− Q_ASSERT(rightwardsLauncher != 0);
525−
526− DirectionalDragArea *edgeDragArea =
527− rightwardsLauncher->findChild<DirectionalDragArea*>("hpDragArea");
528− Q_ASSERT(edgeDragArea != 0);
529− edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
530− edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
531−
532− // to disable the position smoothing so that we can more easily check sceneDistance values
533− edgeDragArea->setImmediateRecognition(true);
534−
535− QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea);
536− QPointF touchPoint = initialTouchPos;
537−
538− qreal desiredDragDistance = edgeDragArea->d->distanceThreshold * 2.0f;
539−
540− qreal movementStepDistance = edgeDragArea->d->distanceThreshold * 0.1f;
541− QPointF touchMovement = dragDirectionVector * movementStepDistance;
542− int totalMovementSteps = qCeil(desiredDragDistance / movementStepDistance);
543− int movementTimeStepMs = (edgeDragArea->d->compositionTime * 1.5f) / totalMovementSteps;
544−
545− qint64 timestamp = 0;
546−
547− sendTouchPress(timestamp, 0, touchPoint);
548−
549− for (int i = 0; i < totalMovementSteps; ++i) {
550− touchPoint += touchMovement;
551− timestamp += movementTimeStepMs;
552− sendTouchUpdate(timestamp, 0, touchPoint);
553− }
554−
555− qreal actualDragDistance = ((qreal)totalMovementSteps) * movementStepDistance;
556−
557− // DirectionalDragArea::sceneDistance() must match the actual drag distance as the
558− // drag was aligned with the gesture direction
559− // NB: qFuzzyCompare(), used internally by QCOMPARE(), is broken.
560− QVERIFY(qAbs(edgeDragArea->sceneDistance() - actualDragDistance) < 0.001);
561−
562− timestamp += movementTimeStepMs;
563− sendTouchRelease(timestamp, 0, touchPoint);
564−}
565−
566−void tst_DirectionalDragArea::sceneDistance_data()
567−{
568− QTest::addColumn<qreal>("rotation");
569− QTest::addColumn<QPointF>("dragDirectionVector");
570−
571− QTest::newRow("not rotated") << 0. << QPointF(1., 0.);
572− QTest::newRow("rotated by 90 degrees") << 90. << QPointF(0., 1.);
573−}
574−
575−/*
576− Regression test for https://bugs.launchpad.net/unity8/+bug/1276122
577−
578− The bug:
579− If setting "enabled: false" while the DirectionalDragArea's (DDA) dragging
580− property is true, the DDA stays in that state and doesn't recover any more.
581−*/
582−void tst_DirectionalDragArea::disabledWhileDragging()
583−{
584− DirectionalDragArea *edgeDragArea =
585− m_view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
586− Q_ASSERT(edgeDragArea != 0);
587− edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
588− edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
589−
590− QPointF touchPoint = calculateInitialTouchPos(edgeDragArea);
591−
592− qreal desiredDragDistance = edgeDragArea->d->distanceThreshold * 2.0f;
593− QPointF dragDirectionVector(1., 0.); // horizontal positive
594−
595− qreal movementStepDistance = edgeDragArea->d->distanceThreshold * 0.1f;
596− QPointF touchMovement = dragDirectionVector * movementStepDistance;
597− int totalMovementSteps = qCeil(desiredDragDistance / movementStepDistance);
598− int movementTimeStepMs = (edgeDragArea->d->compositionTime * 1.5f) / totalMovementSteps;
599−
600− QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
601−
602− for (int i = 0; i < totalMovementSteps; ++i) {
603− touchPoint += touchMovement;
604− passTime(movementTimeStepMs);
605− QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
606− }
607−
608− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::Recognized);
609− QCOMPARE(edgeDragArea->dragging(), true);
610−
611− // disable the dragArea while it's being dragged.
612− edgeDragArea->setEnabled(false);
613−
614− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::WaitingForTouch);
615− QCOMPARE(edgeDragArea->dragging(), false);
616−
617− QTest::touchEvent(m_view, m_device).release(0, touchPoint.toPoint());
618−}
619−
620−void tst_DirectionalDragArea::oneFingerDownFollowedByLateSecondFingerDown()
621−{
622− DirectionalDragArea *edgeDragArea =
623− m_view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
624− Q_ASSERT(edgeDragArea != 0);
625− edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
626− edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
627−
628− // Disable some constraints we're not interested in
629− edgeDragArea->d->setMaxTime(60 * 1000);
630−
631− // And ensure others have the values we want
632− edgeDragArea->d->compositionTime = 60;
633−
634− // Put an item right behind edgeDragArea to receive the touches ignored by it
635− DummyItem *dummyItem = new DummyItem;
636− dummyItem->setParentItem(edgeDragArea->parentItem());
637− dummyItem->setX(edgeDragArea->x());
638− dummyItem->setY(edgeDragArea->y());
639− dummyItem->setZ(edgeDragArea->z() - 1.0);
640− dummyItem->setWidth(edgeDragArea->width());
641− dummyItem->setHeight(edgeDragArea->height());
642−
643− // Make touches evenly spaced along the edgeDragArea
644− QPoint touch0Pos(edgeDragArea->width()/2.0f, m_view->height()*0.33f);
645− QPoint touch1Pos(edgeDragArea->width()/2.0f, m_view->height()*0.66f);
646−
647− QTest::touchEvent(m_view, m_device).press(0, touch0Pos);
648−
649− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::Undecided);
650−
651− // We are now going to be way beyond compositionTime
652− passTime(edgeDragArea->d->compositionTime*3);
653−
654− QTest::touchEvent(m_view, m_device)
655− .move(0, touch0Pos)
656− .press(1, touch1Pos);
657−
658− // A new touch has come, but as it can't be composed with touch 0, it should be
659− // ignored/rejected by the DirectionalDragArea
660− // Therefore the last event received by dummyItem must have both touch points (0 and 1)
661− {
662− TouchMemento &touchMemento = dummyItem->touchEvents.last();
663− QCOMPARE(touchMemento.touchPoints.count(), 2);
664− QVERIFY(touchMemento.containsTouchWithId(0));
665− QVERIFY(touchMemento.containsTouchWithId(1));
666− }
667−
668− passTime(30);
669−
670− QTest::touchEvent(m_view, m_device)
671− .move(0, touch0Pos)
672− .move(1, touch1Pos);
673−
674− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::Undecided);
675−
676− passTime(5);
677−
678− QTest::touchEvent(m_view, m_device)
679− .release(0, touch0Pos)
680− .move(1, touch1Pos);
681−
682− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::WaitingForTouch);
683−
684− passTime(5);
685−
686− QTest::touchEvent(m_view, m_device)
687− .release(1, touch1Pos);
688−
689− // Shouldn't be keepping info about touches that no longer exist or interest us
690− QVERIFY(edgeDragArea->d->activeTouches.isEmpty());
691−
692− delete dummyItem;
693−}
694−
695−void tst_DirectionalDragArea::givesUpWhenLosesTouch()
696−{
697− DirectionalDragArea *edgeDragArea =
698− m_view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
699− Q_ASSERT(edgeDragArea != 0);
700− edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
701− edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
702−
703− // Disable some constraints we're not interested in
704− edgeDragArea->d->setMaxTime(60 * 1000);
705−
706− // Put an item right in front of edgeDragArea
707− DummyItem *dummyItem = new DummyItem(edgeDragArea->parentItem());
708− dummyItem->setX(edgeDragArea->x());
709− dummyItem->setY(edgeDragArea->y());
710− dummyItem->setZ(edgeDragArea->z() + 1.0);
711− dummyItem->setWidth(edgeDragArea->width());
712− dummyItem->setHeight(edgeDragArea->height());
713−
714− QPoint touchPos(edgeDragArea->width()/2.0f, m_view->height()/2.0f);
715−
716− dummyItem->touchEventHandler = [&](QTouchEvent *event) {
717− m_touchRegistry->addCandidateOwnerForTouch(0, dummyItem);
718− event->ignore();
719− };
720−
721− QTest::touchEvent(m_view, m_device).press(0, touchPos);
722−
723− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::Undecided);
724−
725− m_touchRegistry->requestTouchOwnership(0, dummyItem);
726−
727− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::WaitingForTouch);
728−
729− dummyItem->grabTouchPoints({0});
730− dummyItem->touchEventHandler = [&](QTouchEvent *event) { event->accept(); };
731−
732− passTime(5);
733− QTest::touchEvent(m_view, m_device).release(0, touchPos);
734−
735− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::WaitingForTouch);
736−
737− QVERIFY(edgeDragArea->d->activeTouches.isEmpty());
738−}
739−
740−void tst_DirectionalDragArea::threeFingerDrag()
741−{
742− DirectionalDragArea *edgeDragArea =
743− m_view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
744− Q_ASSERT(edgeDragArea != 0);
745− edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
746− edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
747−
748− // Disable some constraints we're not interested in
749− edgeDragArea->d->setMaxTime(60 * 1000);
750−
751− // And ensure others have the values we want
752− edgeDragArea->d->compositionTime = 60;
753−
754− // Make touches evenly spaced along the edgeDragArea
755− QPoint touch0Pos(edgeDragArea->width()/2.0f, m_view->height()*0.25f);
756− QPoint touch1Pos(edgeDragArea->width()/2.0f, m_view->height()*0.50f);
757− QPoint touch2Pos(edgeDragArea->width()/2.0f, m_view->height()*0.75f);
758−
759− QTest::touchEvent(m_view, m_device)
760− .press(0, touch0Pos);
761−
762− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::Undecided);
763−
764− passTime(5);
765− QTest::touchEvent(m_view, m_device)
766− .move(0, touch0Pos)
767− .press(1, touch1Pos);
768−
769− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::WaitingForTouch);
770−
771− passTime(5);
772− QTest::touchEvent(m_view, m_device)
773− .move(0, touch0Pos)
774− .move(1, touch1Pos)
775− .press(2, touch2Pos);
776−
777− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::WaitingForTouch);
778−
779− passTime(10);
780− QTest::touchEvent(m_view, m_device)
781− .move(0, touch0Pos)
782− .move(1, touch1Pos)
783− .move(2, touch2Pos);
784−
785− passTime(200);
786− QTest::touchEvent(m_view, m_device)
787− .move(0, touch0Pos)
788− .release(1, touch1Pos)
789− .move(2, touch2Pos);
790−
791− passTime(10);
792− QTest::touchEvent(m_view, m_device)
793− .move(0, touch0Pos)
794− .release(2, touch2Pos);
795−
796− passTime(5);
797− QTest::touchEvent(m_view, m_device)
798− .release(0, touch0Pos);
799−
800− // Shouldn't be keepping info about touches that no longer exist or interest us
801− QVERIFY(edgeDragArea->d->activeTouches.isEmpty());
802−}
803−
804−/*
805− If all the relevant gesture recognition constraints/parameters have been disabled,
806− it means that the gesture recognition itself has been disabled and DirectionalDragArea
807− will therefore work like a simple touch area, merely reporting touch movement.
808− */
809−void tst_DirectionalDragArea::immediateRecognitionWhenConstraintsDisabled()
810−{
811− DirectionalDragArea *edgeDragArea =
812− m_view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
813− Q_ASSERT(edgeDragArea != 0);
814− edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
815− edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
816−
817− // Disable the minimum amount of constraints to ensure immediate recognition
818− edgeDragArea->d->setDistanceThreshold(0);
819− edgeDragArea->d->compositionTime = 0;
820−
821− // Put an item right behind edgeDragArea to receive the touches ignored by it
822− DummyItem *dummyItem = new DummyItem;
823− dummyItem->setParentItem(edgeDragArea->parentItem());
824− dummyItem->setX(edgeDragArea->x());
825− dummyItem->setY(edgeDragArea->y());
826− dummyItem->setZ(edgeDragArea->z() - 1.0);
827− dummyItem->setWidth(edgeDragArea->width());
828− dummyItem->setHeight(edgeDragArea->height());
829−
830− QPoint touch0Pos(edgeDragArea->width()/2.0f, m_view->height()/2.0f);
831−
832− QTest::touchEvent(m_view, m_device).press(0, touch0Pos);
833−
834− // check for immediate recognition
835− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::Recognized);
836−
837− // and therefore it should have immediately grabbed the touch point,
838− // not letting it leak to items behind him.
839− QCOMPARE(dummyItem->touchEvents.count(), 0);
840−}
841−
842−void tst_DirectionalDragArea::withdrawTouchOwnershipCandidacyIfDisabledDuringRecognition()
843−{
844− DirectionalDragArea *edgeDragArea =
845− m_view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
846− Q_ASSERT(edgeDragArea != 0);
847− edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
848− edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
849−
850− QPointF touchPoint = calculateInitialTouchPos(edgeDragArea);
851−
852− // Move less than the minimum needed for the drag gesture recognition
853− qreal desiredDragDistance = edgeDragArea->d->distanceThreshold * 0.5f;
854− QPointF dragDirectionVector(1., 0.); // horizontal positive
855−
856− qreal movementStepDistance = edgeDragArea->d->distanceThreshold * 0.1f;
857− QPointF touchMovement = dragDirectionVector * movementStepDistance;
858− int totalMovementSteps = qCeil(desiredDragDistance / movementStepDistance);
859− int movementTimeStepMs = (edgeDragArea->d->compositionTime * 0.8f) / totalMovementSteps;
860−
861− QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
862−
863− for (int i = 0; i < totalMovementSteps; ++i) {
864− touchPoint += touchMovement;
865− passTime(movementTimeStepMs);
866− QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
867− }
868−
869− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::Undecided);
870−
871− // edgeDragArea should be an undecided candidate
872− {
873− auto touchInfo = m_touchRegistry->findTouchInfo(0);
874− QCOMPARE(touchInfo->candidates.size(), 1);
875− QCOMPARE(touchInfo->candidates.at(0).item.data(), edgeDragArea);
876− QCOMPARE(touchInfo->candidates.at(0).state, TouchRegistry::CandidateInfo::Undecided);
877− }
878−
879− // disable the dragArea while it's still recognizing a possible drag gesture.
880− QFETCH(bool, disable);
881− if (disable) {
882− edgeDragArea->setEnabled(false);
883− } else {
884− edgeDragArea->setVisible(false);
885− }
886−
887− // edgeDragArea should no longer be a candidate
888− {
889− auto touchInfo = m_touchRegistry->findTouchInfo(0);
890− QCOMPARE(touchInfo->candidates.size(), 0);
891− }
892−
893− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::WaitingForTouch);
894−
895− QTest::touchEvent(m_view, m_device).release(0, touchPoint.toPoint());
896−}
897−
898−void tst_DirectionalDragArea::withdrawTouchOwnershipCandidacyIfDisabledDuringRecognition_data()
899−{
900− QTest::addColumn<bool>("disable");
901−
902− QTest::newRow("disabled") << true;
903− QTest::newRow("invisible") << false;
904−}
905−
906−void tst_DirectionalDragArea::gettingTouchOwnershipMakesMouseAreaBehindGetCanceled()
907−{
908− DirectionalDragArea *edgeDragArea =
909− m_view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
910− QVERIFY(edgeDragArea != nullptr);
911− edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
912− edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
913−
914− QQuickMouseArea *mouseArea =
915− m_view->rootObject()->findChild<QQuickMouseArea*>("mouseArea");
916− QVERIFY(mouseArea != nullptr);
917−
918− MouseAreaSpy mouseAreaSpy(mouseArea);
919−
920− QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea);
921− QPointF touchPoint = initialTouchPos;
922−
923− qreal desiredDragDistance = edgeDragArea->d->distanceThreshold * 2;
924− QPointF dragDirectionVector(1.0f, 0.0f); // rightwards
925− qreal movementStepDistance = edgeDragArea->d->distanceThreshold * 0.1f;
926− QPointF touchMovement = dragDirectionVector * movementStepDistance;
927− int totalMovementSteps = qCeil(desiredDragDistance / movementStepDistance);
928− int movementTimeStepMs = (edgeDragArea->d->compositionTime * 1.5f) / totalMovementSteps;
929−
930− QCOMPARE(mouseArea->pressed(), false);
931−
932− QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
933−
934− // The TouchBegin passes through the DirectionalDragArea and reaches the MouseArea behind it,
935− // where it's converted to a MouseEvent by QQuickWindow and sent to the MouseArea which then
936− // accepts it. Making it get pressed.
937− QCOMPARE(mouseArea->pressed(), true);
938− QCOMPARE(mouseAreaSpy.canceledCount, 0);
939−
940− for (int i = 0; i < totalMovementSteps; ++i) {
941− touchPoint += touchMovement;
942− passTime(movementTimeStepMs);
943− QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
944− }
945−
946− // As the DirectionalDragArea recognizes the gesture, it grabs the touch from the MouseArea,
947− // which should make the MouseArea get a cancelation event, which will then cause it to
948− // reset its state (going back to "unpressed"/"released").
949− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::Recognized);
950− QCOMPARE(mouseArea->pressed(), false);
951− QCOMPARE(mouseAreaSpy.canceledCount, 1);
952−
953− QTest::touchEvent(m_view, m_device).release(0, touchPoint.toPoint());
954−}
955−
956−void tst_DirectionalDragArea::interleavedTouches()
957−{
958− DirectionalDragArea *edgeDragArea =
959− m_view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
960− QVERIFY(edgeDragArea != 0);
961− edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
962− edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
963−
964− QPointF touch0 = edgeDragArea->mapToScene(
965− QPointF(edgeDragArea->width()*0.5, edgeDragArea->height()*0.3));
966−
967− qreal desiredDragDistance = edgeDragArea->d->distanceThreshold * 2;
968− QPointF dragDirectionVector(1.0f, 0.0f); // rightwards
969− qreal movementStepDistance = edgeDragArea->d->distanceThreshold * 0.1f;
970− QPointF touchMovement = dragDirectionVector * movementStepDistance;
971− int totalMovementSteps = qCeil(desiredDragDistance / movementStepDistance);
972− int movementTimeStepMs = (edgeDragArea->d->maxTime * 0.4f) / totalMovementSteps;
973−
974− QTest::touchEvent(m_view, m_device).press(0, touch0.toPoint());
975− for (int i = 0; i < totalMovementSteps; ++i) {
976− touch0 += touchMovement;
977− passTime(movementTimeStepMs);
978− QTest::touchEvent(m_view, m_device).move(0, touch0.toPoint());
979− }
980− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::Recognized);
981−
982− QPointF touch1 = edgeDragArea->mapToScene(
983− QPointF(edgeDragArea->width()*0.5, edgeDragArea->height()*0.6));
984−
985− QTest::touchEvent(m_view, m_device)
986− .move(0, touch0.toPoint())
987− .press(1, touch1.toPoint());
988−
989− touch1 += touchMovement;
990− passTime(movementTimeStepMs);
991− QTest::touchEvent(m_view, m_device)
992− .move(0, touch0.toPoint())
993− .move(1, touch1.toPoint());
994−
995− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::Recognized);
996−
997− QTest::touchEvent(m_view, m_device)
998− .release(0, touch0.toPoint())
999− .move(1, touch1.toPoint());
1000−
1001− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::WaitingForTouch);
1002−
1003− touch1 += touchMovement;
1004− passTime(movementTimeStepMs);
1005− QTest::touchEvent(m_view, m_device)
1006− .move(1, touch1.toPoint());
1007−
1008− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::WaitingForTouch);
1009−
1010− QPointF touch2 = edgeDragArea->mapToScene(
1011− QPointF(edgeDragArea->width()*0.5, edgeDragArea->height()*0.9));
1012−
1013− passTime(edgeDragArea->d->compositionTime + movementTimeStepMs);
1014− QTest::touchEvent(m_view, m_device)
1015− .move(1, touch1.toPoint())
1016− .press(2, touch2.toPoint());
1017−
1018− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::Undecided);
1019− QCOMPARE(edgeDragArea->d->touchId, 2);
1020−
1021− touch2 += touchMovement;
1022− passTime(movementTimeStepMs);
1023− QTest::touchEvent(m_view, m_device)
1024− .move(1, touch1.toPoint())
1025− .move(2, touch2.toPoint());
1026−
1027− touch1 += touchMovement;
1028− passTime(movementTimeStepMs);
1029− QTest::touchEvent(m_view, m_device)
1030− .move(1, touch1.toPoint())
1031− .move(2, touch2.toPoint());
1032−
1033− passTime(movementTimeStepMs);
1034− QTest::touchEvent(m_view, m_device)
1035− .release(1, touch1.toPoint())
1036− .move(2, touch2.toPoint());
1037−
1038− passTime(movementTimeStepMs);
1039− QTest::touchEvent(m_view, m_device)
1040− .release(2, touch2.toPoint());
1041−
1042− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::WaitingForTouch);
1043−}
1044−
1045−/*
1046− A valid right-edge drag performed on mako
1047− */
1048−void tst_DirectionalDragArea::makoRightEdgeDrag()
1049−{
1050− m_view->resize(768, 1280);
1051− QTest::qWait(300);
1052−
1053− DirectionalDragArea *edgeDragArea =
1054− m_view->rootObject()->findChild<DirectionalDragArea*>("hnDragArea");
1055− QVERIFY(edgeDragArea != nullptr);
1056− edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
1057− edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
1058−
1059− StatusSpy *statusSpy = new StatusSpy(edgeDragArea);
1060−
1061− edgeDragArea->d->setPixelsPerMm(320.0 /*mako ppi*/ * 0.03937 /* inches per mm*/);
1062−
1063− sendTouchPress(319744, 0, QPointF(767.001, 719.719));
1064− sendTouchUpdate(319765, 0, QPointF(765.744,729.973));
1065− sendTouchUpdate(319784, 0, QPointF(740.879,752.182));
1066− sendTouchUpdate(319803, 0, QPointF(689.698,795.795));
1067− sendTouchUpdate(319826, 0, QPointF(616.978,856.212));
1068− sendTouchUpdate(319845, 0, QPointF(558.769,906.157));
1069− sendTouchUpdate(319859, 0, QPointF(513.219,945.266));
1070− sendTouchUpdate(319878, 0, QPointF(481.31,975.496));
1071− sendTouchUpdate(319902, 0, QPointF(460.016,997.439));
1072− sendTouchUpdate(319920, 0, QPointF(449.761,1008.6));
1073− sendTouchUpdate(319929, 0, QPointF(445.891,1012.42));
1074− sendTouchUpdate(319947, 0, QPointF(444.884,1013.93));
1075− sendTouchUpdate(319965, 0, QPointF(444.461,1014.35));
1076− sendTouchUpdate(320057, 0, QPointF(444.71,1013.56));
1077− sendTouchUpdate(320138, 0, QPointF(445.434,1013.6));
1078− sendTouchUpdate(320154, 0, QPointF(446.338,1012.98));
1079− sendTouchUpdate(320171, 0, QPointF(447.232,1012.08));
1080− sendTouchRelease(320171, 0, QPointF(447.232,1012.08));
1081−
1082− QCOMPARE(statusSpy->recognized(), true);
1083−
1084− delete statusSpy;
1085−}
1086−
1087−/*
1088− A vertical, downwards swipe performed on mako near its right edge.
1089−
1090− The DirectionalDragArea on the right edge must not recognize this
1091− gesture.
1092− */
1093−void tst_DirectionalDragArea::makoRightEdgeDrag_verticalDownwards()
1094−{
1095− m_view->resize(768, 1280);
1096− QTest::qWait(300);
1097−
1098− DirectionalDragArea *edgeDragArea =
1099− m_view->rootObject()->findChild<DirectionalDragArea*>("hnDragArea");
1100− QVERIFY(edgeDragArea != nullptr);
1101− edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
1102− edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
1103−
1104− edgeDragArea->d->setPixelsPerMm(320.0 /*mako ppi*/ * 0.03937 /* inches per mm*/);
1105−
1106− StatusSpy *statusSpy = new StatusSpy(edgeDragArea);
1107−
1108− sendTouchPress(12012445, 26, QPointF(767.001,461.82));
1109− sendTouchUpdate(12012472, 26, QPointF(767.001,462.569));
1110− sendTouchUpdate(12012528, 26, QPointF(767.001,463.334));
1111− sendTouchUpdate(12012546, 26, QPointF(767.001,466.856));
1112− sendTouchUpdate(12012571, 26, QPointF(767.001,473.291));
1113− sendTouchUpdate(12012587, 26, QPointF(767.001,487.31));
1114− sendTouchUpdate(12012604, 26, QPointF(765.364,507.521));
1115− sendTouchUpdate(12012618, 26, QPointF(765.364,507.521));
1116− sendTouchUpdate(12012627, 26, QPointF(762.642,534.317));
1117− sendTouchUpdate(12012655, 26, QPointF(760.846,573.406));
1118− sendTouchUpdate(12012667, 26, QPointF(759.838,625.295));
1119− sendTouchUpdate(12012675, 26, QPointF(758.875,703.207));
1120− sendTouchUpdate(12012696, 26, QPointF(761.52,777.015));
1121− sendTouchUpdate(12012713, 26, QPointF(765.659,835.591));
1122− sendTouchUpdate(12012731, 26, QPointF(766.778,883.206));
1123− sendTouchUpdate(12012748, 26, QPointF(767.001,922.937));
1124− sendTouchUpdate(12012779, 26, QPointF(767.001,967.558));
1125− sendTouchUpdate(12012798, 26, QPointF(767.001,1006.12));
1126− sendTouchUpdate(12012809, 26, QPointF(767.001,1033.1));
1127− sendTouchRelease(12012810, 26, QPointF(767.001,1033.1));
1128−
1129− QCOMPARE(statusSpy->recognized(), false);
1130−
1131− delete statusSpy;
1132−}
1133−
1134−/*
1135− A valid left-edge drag performed on mako. This one starts a bit slow than speeds up
1136− */
1137−void tst_DirectionalDragArea::makoLeftEdgeDrag_slowStart()
1138−{
1139− m_view->resize(768, 1280);
1140− QTest::qWait(300);
1141−
1142− DirectionalDragArea *edgeDragArea =
1143− m_view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
1144− QVERIFY(edgeDragArea != nullptr);
1145− edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
1146− edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
1147−
1148− edgeDragArea->d->setPixelsPerMm(320.0 /*mako ppi*/ * 0.03937 /* inches per mm*/);
1149−
1150− StatusSpy *statusSpy = new StatusSpy(edgeDragArea);
1151−
1152− sendTouchPress(4002267, 77, QPointF(0,885.154));
1153− sendTouchUpdate(4002275, 77, QPointF(0,886.214));
1154− sendTouchUpdate(4002311, 77, QPointF(1.09568,887.75));
1155− sendTouchUpdate(4002329, 77, QPointF(3.53647,890.191));
1156− sendTouchUpdate(4002347, 77, QPointF(7.87434,892.879));
1157− sendTouchUpdate(4002366, 77, QPointF(12.3036,895.075));
1158− sendTouchUpdate(4002384, 77, QPointF(15.8885,896.849));
1159− sendTouchUpdate(4002406, 77, QPointF(18.4504,897.88));
1160− sendTouchUpdate(4002420, 77, QPointF(20.2429,898.149));
1161− sendTouchUpdate(4002439, 77, QPointF(20.9945,898.149));
1162− sendTouchUpdate(4002457, 77, QPointF(21.8819,898.149));
1163− sendTouchUpdate(4002480, 77, QPointF(22.7454,897.389));
1164− sendTouchUpdate(4002493, 77, QPointF(23.5456,896.589));
1165− sendTouchUpdate(4002511, 77, QPointF(24.5435,895.031));
1166− sendTouchUpdate(4002529, 77, QPointF(25.4271,892.32));
1167− sendTouchUpdate(4002548, 77, QPointF(26.3145,889.658));
1168− sendTouchUpdate(4002566, 77, QPointF(27.2004,886.999));
1169− sendTouchUpdate(4002584, 77, QPointF(28.035,885.048));
1170− sendTouchUpdate(4002603, 77, QPointF(29.9684,883.167));
1171− sendTouchUpdate(4002620, 77, QPointF(33.3591,881.403));
1172− sendTouchUpdate(4002639, 77, QPointF(44.1017,879.642));
1173− sendTouchUpdate(4002657, 77, QPointF(64.828,878.502));
1174− sendTouchUpdate(4002675, 77, QPointF(87.9486,878.157));
1175− sendTouchUpdate(4002693, 77, QPointF(112.96,877.742));
1176− sendTouchUpdate(4002711, 77, QPointF(138.903,877.157));
1177− sendTouchUpdate(4002729, 77, QPointF(163.204,877.157));
1178− sendTouchUpdate(4002747, 77, QPointF(182.127,877.157));
1179− sendTouchUpdate(4002765, 77, QPointF(194.478,877.657));
1180− sendTouchUpdate(4002785, 77, QPointF(201.474,878.508));
1181− sendTouchUpdate(4002803, 77, QPointF(204.855,879.401));
1182− sendTouchUpdate(4002822, 77, QPointF(206.616,880.281));
1183− sendTouchUpdate(4002839, 77, QPointF(207.115,880.906));
1184− sendTouchUpdate(4002894, 77, QPointF(206.865,881.184));
1185− sendTouchUpdate(4002912, 77, QPointF(206.865,882.143));
1186− sendTouchUpdate(4002930, 77, QPointF(206.865,883.106));
1187− sendTouchUpdate(4002949, 77, QPointF(206.526,883.994));
1188− sendTouchUpdate(4002967, 77, QPointF(205.866,884.88));
1189− sendTouchUpdate(4002985, 77, QPointF(205.866,885.766));
1190− sendTouchUpdate(4003005, 77, QPointF(205.866,886.654));
1191− sendTouchUpdate(4003021, 77, QPointF(205.366,887.537));
1192− sendTouchUpdate(4003039, 77, QPointF(204.592,888.428));
1193− sendTouchUpdate(4003050, 77, QPointF(204.367,888.653));
1194− sendTouchRelease(4003050, 77, QPointF(204.367,888.653));
1195−
1196− QCOMPARE(statusSpy->recognized(), true);
1197−
1198− delete statusSpy;
1199−}
1200−
1201−void tst_DirectionalDragArea::makoLeftEdgeDrag_movesSlightlyBackwardsOnStart()
1202−{
1203− m_view->resize(768, 1280);
1204− QTest::qWait(300);
1205−
1206− DirectionalDragArea *edgeDragArea =
1207− m_view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
1208− QVERIFY(edgeDragArea != nullptr);
1209− edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
1210− edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
1211−
1212− edgeDragArea->d->setPixelsPerMm(320.0 /*mako ppi*/ * 0.03937 /* inches per mm*/);
1213−
1214− StatusSpy *statusSpy = new StatusSpy(edgeDragArea);
1215−
1216− sendTouchPress(41097, 24, QPointF(13.9909,827.177));
1217− sendTouchUpdate(41120, 24, QPointF(19.2375,825.677));
1218− sendTouchUpdate(41138, 24, QPointF(18.4057,826.177));
1219− sendTouchUpdate(41161, 24, QPointF(20.1067,825.867));
1220− sendTouchUpdate(41177, 24, QPointF(21.8869,824.977));
1221− sendTouchUpdate(41193, 24, QPointF(24.7603,823.494));
1222− sendTouchUpdate(41211, 24, QPointF(28.3889,821.725));
1223− sendTouchUpdate(41229, 24, QPointF(32.2909,819.955));
1224− sendTouchUpdate(41247, 24, QPointF(38.2251,817.431));
1225− sendTouchUpdate(41266, 24, QPointF(52.4182,814.223));
1226− sendTouchUpdate(41284, 24, QPointF(85.8465,809.483));
1227− sendTouchUpdate(41302, 24, QPointF(126.091,802.741));
1228− sendTouchUpdate(41320, 24, QPointF(153.171,797.977));
1229− sendTouchUpdate(41338, 24, QPointF(170.565,795.077));
1230− sendTouchUpdate(41356, 24, QPointF(178.685,794.101));
1231− sendTouchUpdate(41375, 24, QPointF(183.706,793.225));
1232− sendTouchUpdate(41393, 24, QPointF(186.112,793.19));
1233− sendTouchUpdate(41411, 24, QPointF(187.634,793.19));
1234− sendTouchUpdate(41429, 24, QPointF(188.505,793.19));
1235− sendTouchUpdate(41532, 24, QPointF(187.816,793.19));
1236− sendTouchUpdate(41538, 24, QPointF(186.902,793.19));
1237− sendTouchUpdate(41557, 24, QPointF(186.01,793.19));
1238− sendTouchUpdate(41575, 24, QPointF(185.125,793.444));
1239− sendTouchUpdate(41593, 24, QPointF(184.229,793.69));
1240− sendTouchUpdate(41605, 24, QPointF(183.88,793.69));
1241− sendTouchRelease(41607, 24, QPointF(183.88,793.69));
1242−
1243− QCOMPARE(statusSpy->recognized(), true);
1244−
1245− delete statusSpy;
1246−}
1247−
1248−QTEST_MAIN(tst_DirectionalDragArea)
1249−
1250−#include "tst_DirectionalDragArea.moc"
tests/plugins/Ubuntu/Gestures/tst_DirectionalDragArea.qmldeleted−76
@@ -1,76 +0,0 @@
1−/*
2− * Copyright (C) 2013,2015 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.4
18−import Ubuntu.Components 1.3
19−import Unity.Test 0.1
20−
21−Rectangle {
22− width: units.gu(60)
23− height: units.gu(60)
24− color: "white"
25−
26− Binding {
27− target: MouseTouchAdaptor
28− property: "enabled"
29− value: true
30− }
31−
32− MouseArea {
33− id: mouseArea
34− objectName: "mouseArea"
35− anchors.fill: parent
36− onClicked: {
37− hpLauncher.reset()
38− hnLauncher.reset()
39− vpLauncher.reset()
40− vnLauncher.reset()
41− }
42− }
43−
44− Item {
45− id: baseItem
46− objectName: "baseItem"
47− width: parent.width
48− height: parent.height
49−
50− // NB: Do not anchor it as we will move it programmatically from the test
51− RightwardsLauncher {
52− id: hpLauncher;
53− width: parent.width
54− height: parent.height
55− }
56−
57− LeftwardsLauncher { id: hnLauncher; anchors.fill: parent }
58− DownwardsLauncher { id: vpLauncher; anchors.fill: parent }
59− UpwardsLauncher { id: vnLauncher; anchors.fill: parent }
60− }
61−
62− Button {
63− anchors.bottom: parent.bottom
64− anchors.left: parent.left
65− anchors.margins: units.gu(1)
66−
67− text: "rotation: " + baseItem.rotation
68− onClicked: {
69− if (baseItem.rotation === 0.0) {
70− baseItem.rotation = 90.0
71− } else {
72− baseItem.rotation = 0.0
73− }
74− }
75− }
76−}
tests/plugins/Ubuntu/Gestures/tst_FloatingFlickable.cpp+25−18
@@ -17,12 +17,9 @@
17#include <QtTest>
17#include <QtTest>
18#include <QQuickView>
18#include <QQuickView>
19
19
20−// Ubuntu.Gestures plugin
21−#include <DirectionalDragArea.h>
22−#include <FloatingFlickable.h>
23−
24#include "GestureTest.h"
20#include "GestureTest.h"
25#include "TestItem.h"
21#include "TestItem.h"
22+#include "Direction.h"
26
23
27using namespace UbuntuGestures;
24using namespace UbuntuGestures;
28
25
@@ -44,8 +41,8 @@ tst_FloatingFlickable::tst_FloatingFlickable()
44
41
45void tst_FloatingFlickable::tapGoesThrough()
42void tst_FloatingFlickable::tapGoesThrough()
46{
43{
47− FloatingFlickable *floatingFlickable =
44+ QQuickItem *floatingFlickable =
48− m_view->rootObject()->findChild<FloatingFlickable*>("floatingFlickable");
45+ m_view->rootObject()->findChild<QQuickItem*>("floatingFlickable");
49 QVERIFY(floatingFlickable != nullptr);
46 QVERIFY(floatingFlickable != nullptr);
50
47
51 TestItem *testItem = new TestItem;
48 TestItem *testItem = new TestItem;
@@ -62,16 +59,26 @@ void tst_FloatingFlickable::tapGoesThrough()
62 QCOMPARE(testItem->touchEventsReceived.count(), 1);
59 QCOMPARE(testItem->touchEventsReceived.count(), 1);
63}
60}
64
61
62+static void removeTimeConstraints(QQuickItem *floatingFlickable)
63+{
64+ auto children = floatingFlickable->findChildren<QObject*>();
65+ Q_FOREACH(QObject *child, children) {
66+ if (child->metaObject()->className() == QByteArray("UCSwipeAreaPrivate")) {
67+ QMetaObject::invokeMethod(child, "setMaxTime", Q_ARG(int, 60 * 60 * 1000));
68+ QMetaObject::invokeMethod(child, "setCompositionTime", Q_ARG(int, 0));
69+ }
70+ }
71+}
72+
65void tst_FloatingFlickable::flickChangesContentX()
73void tst_FloatingFlickable::flickChangesContentX()
66{
74{
67 QSKIP("This fails due to bug #1564571");
75 QSKIP("This fails due to bug #1564571");
68− FloatingFlickable *floatingFlickable =
76+ QQuickItem *floatingFlickable =
69− m_view->rootObject()->findChild<FloatingFlickable*>("floatingFlickable");
77+ m_view->rootObject()->findChild<QQuickItem*>("floatingFlickable");
70 QVERIFY(floatingFlickable != nullptr);
78 QVERIFY(floatingFlickable != nullptr);
79+ removeTimeConstraints(floatingFlickable);
71
80
72− floatingFlickable->m_dragArea->removeTimeConstraints();
73−
74− qreal startContentX = floatingFlickable->contentX();
81+ qreal startContentX = floatingFlickable->property("contentX").toReal();
75
82
76 QPoint startPos(floatingFlickable->width() - 5, 10);
83 QPoint startPos(floatingFlickable->width() - 5, 10);
77 int stepCount = 20;
84 int stepCount = 20;
@@ -87,20 +94,20 @@ void tst_FloatingFlickable::flickChangesContentX()
87 QTest::qWait(10);
94 QTest::qWait(10);
88 QTest::touchEvent(m_view, m_device).release(0, QPoint(5, 10));
95 QTest::touchEvent(m_view, m_device).release(0, QPoint(5, 10));
89
96
90− QVERIFY(floatingFlickable->contentX() > (startContentX + floatingFlickable->width()/2));
97+ QVERIFY(floatingFlickable->property("contentX").toReal() > (startContentX + floatingFlickable->width()/2));
91}
98}
92
99
93void tst_FloatingFlickable::flickChangesContentY()
100void tst_FloatingFlickable::flickChangesContentY()
94{
101{
95 QSKIP("This fails due to bug #1564571");
102 QSKIP("This fails due to bug #1564571");
96− FloatingFlickable *floatingFlickable =
103+ QQuickItem *floatingFlickable =
97− m_view->rootObject()->findChild<FloatingFlickable*>("floatingFlickable");
104+ m_view->rootObject()->findChild<QQuickItem*>("floatingFlickable");
98 QVERIFY(floatingFlickable != nullptr);
105 QVERIFY(floatingFlickable != nullptr);
99
106
100− floatingFlickable->setDirection(Direction::Vertical);
107+ floatingFlickable->setProperty("direction", Direction::Vertical);
101− floatingFlickable->m_dragArea->removeTimeConstraints();
108+ removeTimeConstraints(floatingFlickable);
102
109
103− qreal startContentY = floatingFlickable->contentY();
110+ qreal startContentY = floatingFlickable->property("contentY").toReal();
104
111
105 QPoint startPos(10, floatingFlickable->height() - 5);
112 QPoint startPos(10, floatingFlickable->height() - 5);
106 int stepCount = 20;
113 int stepCount = 20;
@@ -116,7 +123,7 @@ void tst_FloatingFlickable::flickChangesContentY()
116 QTest::qWait(10);
123 QTest::qWait(10);
117 QTest::touchEvent(m_view, m_device).release(0, QPoint(10, 5));
124 QTest::touchEvent(m_view, m_device).release(0, QPoint(10, 5));
118
125
119− QVERIFY(floatingFlickable->contentY() > (startContentY + floatingFlickable->height()/2));
126+ QVERIFY(floatingFlickable->property("contentY").toReal() > (startContentY + floatingFlickable->height()/2));
120}
127}
121
128
122QTEST_MAIN(tst_FloatingFlickable)
129QTEST_MAIN(tst_FloatingFlickable)
tests/plugins/Ubuntu/Gestures/tst_FloatingFlickable.qml+1
@@ -18,6 +18,7 @@ import QtQuick 2.4
18import Ubuntu.Components 1.3
18import Ubuntu.Components 1.3
19import Ubuntu.Gestures 0.1
19import Ubuntu.Gestures 0.1
20import Unity.Test 0.1
20import Unity.Test 0.1
21+import "../../../../../qml/Components"
21
22
22Rectangle {
23Rectangle {
23 id: root
24 id: root
tests/plugins/Ubuntu/Gestures/tst_TouchGate.cpp+1−1
@@ -25,7 +25,7 @@
25#include <functional>
25#include <functional>
26
26
27#include <TouchGate.h>
27#include <TouchGate.h>
28−#include <TouchRegistry.h>
28+#include <TouchRegistry>
29
29
30#include "TestItem.h"
30#include "TestItem.h"
31
31
tests/plugins/Unity/Indicators/MenuContentActivatorTest.cpp+1
@@ -28,6 +28,7 @@ class FakeTimer : public UnityIndicators::AbstractTimer
28public:
28public:
29 FakeTimer(QObject *parent = 0)
29 FakeTimer(QObject *parent = 0)
30 : UnityIndicators::AbstractTimer(parent)
30 : UnityIndicators::AbstractTimer(parent)
31+ , m_duration(0)
31 {}
32 {}
32
33
33 int interval() const override { return m_duration; }
34 int interval() const override { return m_duration; }
tests/plugins/Unity/Session/sessionbackendtest.cpp−15
@@ -148,21 +148,6 @@ private Q_SLOTS:
148 }
148 }
149 }
149 }
150
150
151− void testLogin1Capabilities() {
152− QSKIP("This test talks to real logind backend, it will fail depending on how the machine is set up");
153− DBusUnitySessionService dbusUnitySessionService;
154− QDBusInterface login1face("org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", QDBusConnection::systemBus());
155− QCoreApplication::processEvents(); // to let the services register on DBus
156−
157− if (login1face.isValid()) {
158− QCOMPARE(dbusUnitySessionService.CanHibernate(), (login1face.call("CanHibernate").arguments().first().toString() != "no"));
159− QCOMPARE(dbusUnitySessionService.CanSuspend(), (login1face.call("CanSuspend").arguments().first().toString() != "no"));
160− QCOMPARE(dbusUnitySessionService.CanReboot(), (login1face.call("CanReboot").arguments().first().toString() != "no"));
161− QCOMPARE(dbusUnitySessionService.CanShutdown(), (login1face.call("CanPowerOff").arguments().first().toString() != "no"));
162− QCOMPARE(dbusUnitySessionService.CanHybridSleep(), (login1face.call("CanHybridSleep").arguments().first().toString() != "no"));
163− }
164− }
165−
166private:
151private:
167 QDBusInterface *dbusUnitySession;
152 QDBusInterface *dbusUnitySession;
168};
153};
tests/plugins/Utils/WindowInputMonitorTest.cpp+52−11
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2015 Canonical, Ltd.
2+ * Copyright (C) 2015-2016 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
@@ -71,6 +71,8 @@ public:
71
71
72using namespace UnityUtil;
72using namespace UnityUtil;
73
73
74+Q_DECLARE_METATYPE(Qt::Key) // because of QTest::addColumn<Qt::Key>
75+
74class WindowInputMonitorTest : public QObject {
76class WindowInputMonitorTest : public QObject {
75 Q_OBJECT
77 Q_OBJECT
76private Q_SLOTS:
78private Q_SLOTS:
@@ -81,6 +83,7 @@ private Q_SLOTS:
81 void touchTapTouch();
83 void touchTapTouch();
82
84
83 void tapWhileTouching();
85 void tapWhileTouching();
86+ void multipleHomeKeys();
84
87
85private:
88private:
86 void passTime(qint64 timeSpanMs);
89 void passTime(qint64 timeSpanMs);
@@ -112,13 +115,15 @@ void WindowInputMonitorTest::touchTapTouch_data()
112 QTest::addColumn<int>("tapDuration");
115 QTest::addColumn<int>("tapDuration");
113 QTest::addColumn<int>("silenceAfterTap");
116 QTest::addColumn<int>("silenceAfterTap");
114 QTest::addColumn<int>("expectedActivatedCount");
117 QTest::addColumn<int>("expectedActivatedCount");
115−
118+ QTest::addColumn<Qt::Key>("key");
119+
116− QTest::newRow("tap followed by touch") << 2000 << 50 << 10 << 0;
120+ QTest::newRow("tap followed by touch") << 2000 << 50 << 10 << 0 << Qt::Key_Super_L;
117− QTest::newRow("touch, tap and touch") << 10 << 50 << 10 << 0;
121+ QTest::newRow("touch, tap and touch") << 10 << 50 << 10 << 0 << Qt::Key_Super_L;
118− QTest::newRow("touch followed by tap") << 10 << 50 << 2000 << 0;
122+ QTest::newRow("touch followed by tap") << 10 << 50 << 2000 << 0 << Qt::Key_Super_L;
119− QTest::newRow("touch followed by long tap") << 10 << 500 << 2000 << 0;
123+ QTest::newRow("touch followed by long tap") << 10 << 500 << 2000 << 0 << Qt::Key_Super_L;
120− QTest::newRow("isolated tap") << 1000 << 50 << 1000 << 1;
124+ QTest::newRow("isolated tap, Super_L") << 1000 << 50 << 1000 << 1 << Qt::Key_Super_L;
125+ QTest::newRow("isolated tap, HomePage") << 1000 << 50 << 1000 << 1 << Qt::Key_HomePage;
121− QTest::newRow("isolated long press") << 1000 << 200 << 1000 << 0;
126+ QTest::newRow("isolated long press") << 1000 << 200 << 1000 << 0 << Qt::Key_Super_L;
122}
127}
123
128
124void WindowInputMonitorTest::touchTapTouch()
129void WindowInputMonitorTest::touchTapTouch()
@@ -127,6 +132,7 @@ void WindowInputMonitorTest::touchTapTouch()
127 QFETCH(int, tapDuration);
132 QFETCH(int, tapDuration);
128 QFETCH(int, silenceAfterTap);
133 QFETCH(int, silenceAfterTap);
129 QFETCH(int, expectedActivatedCount);
134 QFETCH(int, expectedActivatedCount);
135+ QFETCH(Qt::Key, key);
130 WindowInputMonitor homeKeyWatcher(m_fakeTimerFactory->create(), new FakeElapsedTimer);
136 WindowInputMonitor homeKeyWatcher(m_fakeTimerFactory->create(), new FakeElapsedTimer);
131 QSignalSpy activatedSpy(&homeKeyWatcher, &WindowInputMonitor::homeKeyActivated);
137 QSignalSpy activatedSpy(&homeKeyWatcher, &WindowInputMonitor::homeKeyActivated);
132 QVERIFY(activatedSpy.isValid());
138 QVERIFY(activatedSpy.isValid());
@@ -149,7 +155,7 @@ void WindowInputMonitorTest::touchTapTouch()
149 passTime(silenceBeforeTap);
155 passTime(silenceBeforeTap);
150
156
151 {
157 {
152− QKeyEvent keyEvent(QEvent::KeyPress, Qt::Key_Super_L, Qt::NoModifier);
158+ QKeyEvent keyEvent(QEvent::KeyPress, key, Qt::NoModifier);
153 homeKeyWatcher.update(&keyEvent);
159 homeKeyWatcher.update(&keyEvent);
154 }
160 }
155 int tapTime = 0;
161 int tapTime = 0;
@@ -157,10 +163,10 @@ void WindowInputMonitorTest::touchTapTouch()
157 passTime(10);
163 passTime(10);
158 tapTime += 10;
164 tapTime += 10;
159 if (tapTime + 10 >= tapDuration) {
165 if (tapTime + 10 >= tapDuration) {
160− QKeyEvent keyEvent(QEvent::KeyRelease, Qt::Key_Super_L, Qt::NoModifier);
166+ QKeyEvent keyEvent(QEvent::KeyRelease, key, Qt::NoModifier);
161 homeKeyWatcher.update(&keyEvent);
167 homeKeyWatcher.update(&keyEvent);
162 } else {
168 } else {
163− QKeyEvent keyEvent(QEvent::KeyPress, Qt::Key_Super_L, Qt::NoModifier, QString(), true /*autorepeat*/);
169+ QKeyEvent keyEvent(QEvent::KeyPress, key, Qt::NoModifier, QString(), true /*autorepeat*/);
164 homeKeyWatcher.update(&keyEvent);
170 homeKeyWatcher.update(&keyEvent);
165 }
171 }
166 }
172 }
@@ -217,6 +223,41 @@ void WindowInputMonitorTest::tapWhileTouching()
217 QCOMPARE(activatedSpy.count(), 0);
223 QCOMPARE(activatedSpy.count(), 0);
218}
224}
219
225
226+/*
227+ Press multiple of the mapped home keys roughly at the same time.
228+ The first pressed will be recognized and the other ignored
229+ */
230+void WindowInputMonitorTest::multipleHomeKeys()
231+{
232+ WindowInputMonitor homeKeyWatcher(m_fakeTimerFactory->create(), new FakeElapsedTimer);
233+ QSignalSpy activatedSpy(&homeKeyWatcher, &WindowInputMonitor::homeKeyActivated);
234+ QVERIFY(activatedSpy.isValid());
235+
236+ passTime(1000);
237+ {
238+ QKeyEvent keyEvent(QEvent::KeyPress, Qt::Key_HomePage, Qt::NoModifier);
239+ homeKeyWatcher.update(&keyEvent);
240+ }
241+ passTime(50);
242+ {
243+ QKeyEvent keyEvent(QEvent::KeyPress, Qt::Key_Super_L, Qt::NoModifier);
244+ homeKeyWatcher.update(&keyEvent);
245+ }
246+ passTime(50);
247+ {
248+ QKeyEvent keyEvent(QEvent::KeyRelease, Qt::Key_HomePage, Qt::NoModifier);
249+ homeKeyWatcher.update(&keyEvent);
250+ }
251+ passTime(10);
252+ {
253+ QKeyEvent keyEvent(QEvent::KeyRelease, Qt::Key_Super_L, Qt::NoModifier);
254+ homeKeyWatcher.update(&keyEvent);
255+ }
256+ passTime(1000);
257+
258+ QCOMPARE(activatedSpy.count(), 1);
259+}
260+
220/////////////////////////////////// FakeTimer //////////////////////////////////
261/////////////////////////////////// FakeTimer //////////////////////////////////
221
262
222FakeTimer::FakeTimer(QObject *parent)
263FakeTimer::FakeTimer(QObject *parent)
tests/qmltests/Components/CMakeLists.txt+6−3
@@ -1,18 +1,21 @@
1add_definitions(-DTEST_DIR="qmltests/Components")
1add_definitions(-DTEST_DIR="qmltests/Components")
2
2
3+pkg_check_modules(UBUNTUGESTURES REQUIRED UbuntuGestures)
4+
3########## tst_DragHandle
5########## tst_DragHandle
4
6
5include_directories(
7include_directories(
6 ${CMAKE_SOURCE_DIR}/plugins/Ubuntu/Gestures
8 ${CMAKE_SOURCE_DIR}/plugins/Ubuntu/Gestures
7− ${CMAKE_SOURCE_DIR}/libs/UbuntuGestures
9+ ${UBUNTUGESTURES_INCLUDE_DIRS}
8 ${CMAKE_CURRENT_BINARY_DIR}
10 ${CMAKE_CURRENT_BINARY_DIR}
9 ${Qt5Gui_PRIVATE_INCLUDE_DIRS}
11 ${Qt5Gui_PRIVATE_INCLUDE_DIRS}
10 ${Qt5Quick_PRIVATE_INCLUDE_DIRS}
12 ${Qt5Quick_PRIVATE_INCLUDE_DIRS}
13+ ${UBUNTUGESTURES_INCLUDEDIR}/UbuntuGestures/${UBUNTUGESTURES_VERSION}
11 )
14 )
12
15
13add_executable(DragHandleTestExec tst_DragHandle.cpp)
16add_executable(DragHandleTestExec tst_DragHandle.cpp)
14qt5_use_modules(DragHandleTestExec Test Core Qml Gui Quick)
17qt5_use_modules(DragHandleTestExec Test Core Qml Gui Quick)
15−target_link_libraries(DragHandleTestExec UbuntuGesturesQml UbuntuGestures)
18+target_link_libraries(DragHandleTestExec UbuntuGesturesQml ${UBUNTUGESTURES_LIBRARIES})
16install(TARGETS DragHandleTestExec
19install(TARGETS DragHandleTestExec
17 DESTINATION "${SHELL_PRIVATE_LIBDIR}/tests/qmltests/Components"
20 DESTINATION "${SHELL_PRIVATE_LIBDIR}/tests/qmltests/Components"
18 )
21 )
@@ -28,7 +31,7 @@ add_unity8_qmltest_data(. tst_DragHandle)
28########## tst_EdgeDragEvaluator
31########## tst_EdgeDragEvaluator
29add_executable(EdgeDragEvaluatorTestExec tst_EdgeDragEvaluator.cpp)
32add_executable(EdgeDragEvaluatorTestExec tst_EdgeDragEvaluator.cpp)
30qt5_use_modules(EdgeDragEvaluatorTestExec Test Core Qml Gui Quick)
33qt5_use_modules(EdgeDragEvaluatorTestExec Test Core Qml Gui Quick)
31−target_link_libraries(EdgeDragEvaluatorTestExec UbuntuGesturesQml UbuntuGestures)
34+target_link_libraries(EdgeDragEvaluatorTestExec UbuntuGesturesQml ${UBUNTUGESTURES_LIBRARIES})
32install(TARGETS EdgeDragEvaluatorTestExec
35install(TARGETS EdgeDragEvaluatorTestExec
33 DESTINATION "${SHELL_PRIVATE_LIBDIR}/tests/qmltests/Components"
36 DESTINATION "${SHELL_PRIVATE_LIBDIR}/tests/qmltests/Components"
34 )
37 )
tests/qmltests/Components/tst_DragHandle.cpp+28−24
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2013-2014 Canonical, Ltd.
2+ * Copyright (C) 2013-2014,2016 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
@@ -21,11 +21,11 @@
21#include <QtQuick/QQuickView>
21#include <QtQuick/QQuickView>
22#include <QtQml/QQmlEngine>
22#include <QtQml/QQmlEngine>
23#include <private/qquickwindow_p.h>
23#include <private/qquickwindow_p.h>
24+#include <UbuntuGestures/private/ucswipearea_p_p.h>
24
25
25#include <AxisVelocityCalculator.h>
26#include <AxisVelocityCalculator.h>
26−#include <DirectionalDragArea.h>
27−#include <DirectionalDragArea_p.h>
28−#include <Timer.h>
27+#include <Timer>
28+#include "Direction.h"
29
29
30#include <paths.h>
30#include <paths.h>
31
31
@@ -53,11 +53,11 @@ private Q_SLOTS:
53 void hintingAnimation_dontRestartAfterFinishedAndStillPressed();
53 void hintingAnimation_dontRestartAfterFinishedAndStillPressed();
54
54
55private:
55private:
56− void flickAndHold(DirectionalDragArea *dragHandle, qreal distance);
56+ void flickAndHold(QQuickItem *dragHandle, qreal distance);
57 void drag(QPointF &touchPoint, const QPointF& direction, qreal distance,
57 void drag(QPointF &touchPoint, const QPointF& direction, qreal distance,
58 int numSteps, qint64 timeMs = 500);
58 int numSteps, qint64 timeMs = 500);
59− DirectionalDragArea *fetchAndSetupDragHandle(const char *objectName);
59+ QQuickItem *fetchAndSetupDragHandle(const char *objectName);
60− qreal fetchDragThreshold(DirectionalDragArea *dragHandle);
60+ qreal fetchDragThreshold(QQuickItem *dragHandle);
61 void tryCompare(std::function<qreal ()> actualFunc, qreal expectedValue);
61 void tryCompare(std::function<qreal ()> actualFunc, qreal expectedValue);
62
62
63 QQuickView *createView();
63 QQuickView *createView();
@@ -132,11 +132,11 @@ void tst_DragHandle::tryCompare(std::function<qreal ()> actualFunc,
132}
132}
133
133
134namespace {
134namespace {
135−QPointF calculateDirectionVector(DirectionalDragArea *edgeDragArea)
135+QPointF calculateDirectionVector(QQuickItem *edgeDragArea)
136{
136{
137 QPointF localOrigin(0., 0.);
137 QPointF localOrigin(0., 0.);
138 QPointF localDirection;
138 QPointF localDirection;
139− switch (edgeDragArea->direction()) {
139+ switch (edgeDragArea->property("direction").toInt()) {
140 case Direction::Upwards:
140 case Direction::Upwards:
141 localDirection.rx() = 0.;
141 localDirection.rx() = 0.;
142 localDirection.ry() = -1.;
142 localDirection.ry() = -1.;
@@ -160,7 +160,7 @@ QPointF calculateDirectionVector(DirectionalDragArea *edgeDragArea)
160}
160}
161}
161}
162
162
163−void tst_DragHandle::flickAndHold(DirectionalDragArea *dragHandle,
163+void tst_DragHandle::flickAndHold(QQuickItem *dragHandle,
164 qreal distance)
164 qreal distance)
165{
165{
166 QPointF initialTouchPos = dragHandle->mapToScene(
166 QPointF initialTouchPos = dragHandle->mapToScene(
@@ -198,13 +198,17 @@ void tst_DragHandle::drag(QPointF &touchPoint, const QPointF& direction, qreal d
198 }
198 }
199}
199}
200
200
201−DirectionalDragArea *tst_DragHandle::fetchAndSetupDragHandle(const char *objectName)
201+QQuickItem *tst_DragHandle::fetchAndSetupDragHandle(const char *objectName)
202{
202{
203− DirectionalDragArea *dragHandle =
203+ QQuickItem *dragHandle =
204− m_view->rootObject()->findChild<DirectionalDragArea*>(objectName);
204+ m_view->rootObject()->findChild<QQuickItem*>(objectName);
205 Q_ASSERT(dragHandle != 0);
205 Q_ASSERT(dragHandle != 0);
206+ UCSwipeArea *swipeArea = dynamic_cast<UCSwipeArea*>(dragHandle);
207+ if (swipeArea) {
208+ UCSwipeAreaPrivate *swipeAreaPrivate = dynamic_cast<UCSwipeAreaPrivate *>(QQuickItemPrivate::get(swipeArea));
206− dragHandle->d->setRecognitionTimer(m_fakeTimer);
209+ swipeAreaPrivate->setRecognitionTimer(m_fakeTimer);
207− dragHandle->d->setTimeSource(m_fakeTimeSource);
210+ swipeAreaPrivate->setTimeSource(m_fakeTimeSource);
211+ }
208
212
209 AxisVelocityCalculator *edgeDragEvaluator =
213 AxisVelocityCalculator *edgeDragEvaluator =
210 dragHandle->findChild<AxisVelocityCalculator*>("edgeDragEvaluator");
214 dragHandle->findChild<AxisVelocityCalculator*>("edgeDragEvaluator");
@@ -214,7 +218,7 @@ DirectionalDragArea *tst_DragHandle::fetchAndSetupDragHandle(const char *objectN
214 return dragHandle;
218 return dragHandle;
215}
219}
216
220
217−qreal tst_DragHandle::fetchDragThreshold(DirectionalDragArea *dragHandle)
221+qreal tst_DragHandle::fetchDragThreshold(QQuickItem *dragHandle)
218{
222{
219 AxisVelocityCalculator *edgeDragEvaluator =
223 AxisVelocityCalculator *edgeDragEvaluator =
220 dragHandle->findChild<AxisVelocityCalculator*>("edgeDragEvaluator");
224 dragHandle->findChild<AxisVelocityCalculator*>("edgeDragEvaluator");
@@ -235,7 +239,7 @@ void tst_DragHandle::dragThreshold_horizontal()
235 QQuickItem *baseItem = m_view->rootObject()->findChild<QQuickItem*>("baseItem");
239 QQuickItem *baseItem = m_view->rootObject()->findChild<QQuickItem*>("baseItem");
236 baseItem->setRotation(rotation);
240 baseItem->setRotation(rotation);
237
241
238− DirectionalDragArea *dragHandle = fetchAndSetupDragHandle("rightwardsDragHandle");
242+ QQuickItem *dragHandle = fetchAndSetupDragHandle("rightwardsDragHandle");
239 QQuickItem *parentItem = dragHandle->parentItem();
243 QQuickItem *parentItem = dragHandle->parentItem();
240
244
241 qreal dragThreshold = fetchDragThreshold(dragHandle);
245 qreal dragThreshold = fetchDragThreshold(dragHandle);
@@ -288,7 +292,7 @@ void tst_DragHandle::dragThreshold_vertical()
288 QQuickItem *baseItem = m_view->rootObject()->findChild<QQuickItem*>("baseItem");
292 QQuickItem *baseItem = m_view->rootObject()->findChild<QQuickItem*>("baseItem");
289 baseItem->setRotation(rotation);
293 baseItem->setRotation(rotation);
290
294
291− DirectionalDragArea *dragHandle = fetchAndSetupDragHandle("downwardsDragHandle");
295+ QQuickItem *dragHandle = fetchAndSetupDragHandle("topEdgeShowDragHandle");
292
296
293 qreal dragThreshold = fetchDragThreshold(dragHandle);
297 qreal dragThreshold = fetchDragThreshold(dragHandle);
294
298
@@ -307,7 +311,7 @@ void tst_DragHandle::dragThreshold_vertical()
307 tryCompare([&](){ return parentItem->y(); }, 0);
311 tryCompare([&](){ return parentItem->y(); }, 0);
308 QCOMPARE(parentItem->property("shown").toBool(), true);
312 QCOMPARE(parentItem->property("shown").toBool(), true);
309
313
310− dragHandle = fetchAndSetupDragHandle("upwardsDragHandle");
314+ dragHandle = fetchAndSetupDragHandle("topEdgeHideDragHandle");
311
315
312 dragThreshold = fetchDragThreshold(dragHandle);
316 dragThreshold = fetchDragThreshold(dragHandle);
313
317
@@ -340,7 +344,7 @@ void tst_DragHandle::dragThreshold_vertical_data()
340 */
344 */
341void tst_DragHandle::stretch_horizontal()
345void tst_DragHandle::stretch_horizontal()
342{
346{
343− DirectionalDragArea *dragHandle = fetchAndSetupDragHandle("rightwardsDragHandle");
347+ QQuickItem *dragHandle = fetchAndSetupDragHandle("rightwardsDragHandle");
344 qreal totalDragDistance = dragHandle->property("maxTotalDragDistance").toReal();
348 qreal totalDragDistance = dragHandle->property("maxTotalDragDistance").toReal();
345 QQuickItem *parentItem = dragHandle->parentItem();
349 QQuickItem *parentItem = dragHandle->parentItem();
346
350
@@ -370,7 +374,7 @@ void tst_DragHandle::stretch_horizontal()
370
374
371void tst_DragHandle::stretch_vertical()
375void tst_DragHandle::stretch_vertical()
372{
376{
373− DirectionalDragArea *dragHandle = fetchAndSetupDragHandle("downwardsDragHandle");
377+ QQuickItem *dragHandle = fetchAndSetupDragHandle("topEdgeShowDragHandle");
374 qreal totalDragDistance = dragHandle->property("maxTotalDragDistance").toReal();
378 qreal totalDragDistance = dragHandle->property("maxTotalDragDistance").toReal();
375 QQuickItem *parentItem = dragHandle->parentItem();
379 QQuickItem *parentItem = dragHandle->parentItem();
376
380
@@ -387,7 +391,7 @@ void tst_DragHandle::stretch_vertical()
387 tryCompare([&](){ return parentItem->height(); }, totalDragDistance);
391 tryCompare([&](){ return parentItem->height(); }, totalDragDistance);
388 QCOMPARE(parentItem->property("shown").toBool(), true);
392 QCOMPARE(parentItem->property("shown").toBool(), true);
389
393
390− dragHandle = fetchAndSetupDragHandle("upwardsDragHandle");
394+ dragHandle = fetchAndSetupDragHandle("topEdgeHideDragHandle");
391
395
392 // flick all the way
396 // flick all the way
393 flickAndHold(dragHandle, totalDragDistance);
397 flickAndHold(dragHandle, totalDragDistance);
@@ -406,7 +410,7 @@ void tst_DragHandle::stretch_vertical()
406 */
410 */
407void tst_DragHandle::hintingAnimation()
411void tst_DragHandle::hintingAnimation()
408{
412{
409− DirectionalDragArea *dragHandle = fetchAndSetupDragHandle("downwardsDragHandle");
413+ QQuickItem *dragHandle = fetchAndSetupDragHandle("topEdgeShowDragHandle");
410 QQuickItem *parentItem = dragHandle->parentItem();
414 QQuickItem *parentItem = dragHandle->parentItem();
411 qreal hintDisplacement = 100.0;
415 qreal hintDisplacement = 100.0;
412
416
@@ -447,7 +451,7 @@ void tst_DragHandle::hintingAnimation()
447 */
451 */
448void tst_DragHandle::hintingAnimation_dontRestartAfterFinishedAndStillPressed()
452void tst_DragHandle::hintingAnimation_dontRestartAfterFinishedAndStillPressed()
449{
453{
450− DirectionalDragArea *dragHandle = fetchAndSetupDragHandle("downwardsDragHandle");
454+ QQuickItem *dragHandle = fetchAndSetupDragHandle("topEdgeShowDragHandle");
451 QQuickItem *parentItem = dragHandle->parentItem();
455 QQuickItem *parentItem = dragHandle->parentItem();
452 qreal hintDisplacement = 100.0;
456 qreal hintDisplacement = 100.0;
453
457
tests/qmltests/Components/tst_DragHandle.qml+22−4
@@ -64,15 +64,33 @@ Rectangle {
64 onDragHandleRecognizedGesture: { root.dragHandle = dragHandle }
64 onDragHandleRecognizedGesture: { root.dragHandle = dragHandle }
65 }
65 }
66
66
67− VerticalShowable {
67+ TopEdgeShowable {
68+ id: topEdgeShowable
68− visible: !root.bidirectional
69+ visible: !root.bidirectional && !bottomEdgeShowable.shown
69 onDragHandleRecognizedGesture: { root.dragHandle = dragHandle }
70 onDragHandleRecognizedGesture: { root.dragHandle = dragHandle }
70 stretch: root.stretch
71 stretch: root.stretch
71 hintDisplacement: root.hintDisplacement
72 hintDisplacement: root.hintDisplacement
72 }
73 }
73
74
74− HorizontalShowable {
75+ BottomEdgeShowable {
76+ id: bottomEdgeShowable
77+ visible: !root.bidirectional && !topEdgeShowable.shown
78+ onDragHandleRecognizedGesture: { root.dragHandle = dragHandle }
79+ stretch: root.stretch
80+ hintDisplacement: root.hintDisplacement
81+ }
82+
83+ LeftEdgeShowable {
84+ id: leftEdgeShowable
75− visible: !root.bidirectional
85+ visible: !root.bidirectional && !rightEdgeShowable.shown
86+ onDragHandleRecognizedGesture: { root.dragHandle = dragHandle }
87+ stretch: root.stretch
88+ hintDisplacement: root.hintDisplacement
89+ }
90+
91+ RightEdgeShowable {
92+ id: rightEdgeShowable
93+ visible: !root.bidirectional && !leftEdgeShowable.shown
76 onDragHandleRecognizedGesture: { root.dragHandle = dragHandle }
94 onDragHandleRecognizedGesture: { root.dragHandle = dragHandle }
77 stretch: root.stretch
95 stretch: root.stretch
78 hintDisplacement: root.hintDisplacement
96 hintDisplacement: root.hintDisplacement
tests/qmltests/Components/tst_DragHandle/BottomEdgeShowable.qmlnew file+108
@@ -0,0 +1,108 @@
1+/*
2+ * Copyright (C) 2016 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.4
18+import "../../../../qml/Components"
19+import Ubuntu.Components 1.3
20+import Ubuntu.Gestures 0.1
21+
22+Showable {
23+ id: root
24+ y: height
25+ width: parent.width
26+ height: parent.height
27+
28+ property bool stretch
29+ property real hintDisplacement
30+
31+ Binding {
32+ when: stretch
33+ target: root
34+ property: "y"
35+ value: root.parent.height - root.height
36+ }
37+
38+ onStretchChanged: {
39+ // reset
40+ shown = false;
41+ if (stretch) {
42+ height = 0;
43+ } else {
44+ y = parent.height;
45+ height = parent.height;
46+ }
47+ }
48+
49+ shown: false
50+
51+ signal dragHandleRecognizedGesture(var dragHandle)
52+
53+ property string animatedProp: stretch ? "height" : "y"
54+ property real propValueWhenShown: stretch ? parent.height : 0
55+ property real propValueWhenHidden: stretch ? 0 : height
56+
57+ showAnimation: StandardAnimation { property: animatedProp; to: propValueWhenShown }
58+ hideAnimation: StandardAnimation { property: animatedProp; to: propValueWhenHidden }
59+
60+ Image { source: "../../UnityLogo.png"; anchors.fill: parent }
61+
62+ DragHandle {
63+ objectName: "topEdgeHideDragHandle"
64+ id: hideDragHandle
65+ anchors.left: parent.left
66+ anchors.right: parent.right
67+ anchors.top: parent.top
68+
69+ height: units.gu(2)
70+
71+ direction: Direction.Downwards
72+ stretch: root.stretch
73+ maxTotalDragDistance: root.parent.height
74+ hintDisplacement: root.hintDisplacement
75+
76+ onDraggingChanged: {
77+ if (dragging) {
78+ dragHandleRecognizedGesture(hideDragHandle);
79+ }
80+ }
81+
82+ Rectangle { color: "red"; anchors.fill: parent }
83+ }
84+
85+ DragHandle {
86+ objectName: "topEdgeShowDragHandle"
87+ id: showDragHandle
88+ anchors.left: parent.left
89+ anchors.right: parent.right
90+ anchors.bottom: parent.top
91+
92+ height: units.gu(2)
93+
94+ direction: Direction.Upwards
95+ stretch: root.stretch
96+ maxTotalDragDistance: root.parent.height
97+ hintDisplacement: root.hintDisplacement
98+
99+ onDraggingChanged: {
100+ if (dragging) {
101+ dragHandleRecognizedGesture(showDragHandle);
102+ }
103+ }
104+
105+ Rectangle { color: "green"; anchors.fill: parent }
106+ }
107+
108+}
tests/qmltests/Components/tst_DragHandle/HorizontalShowable.qml → tests/qmltests/Components/tst_DragHandle/LeftEdgeShowable.qmlrenamed

The content is the same.

tests/qmltests/Components/tst_DragHandle/RightEdgeShowable.qmlnew file+108
@@ -0,0 +1,108 @@
1+/*
2+ * Copyright (C) 2016 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.4
18+import "../../../../qml/Components"
19+import Ubuntu.Components 1.3
20+import Ubuntu.Gestures 0.1
21+
22+Showable {
23+ id: root
24+ x: parent.width
25+ width: parent.width
26+ height: parent.height
27+
28+ property bool stretch
29+ property real hintDisplacement
30+
31+ Binding {
32+ when: stretch
33+ target: root
34+ property: "x"
35+ value: root.parent.width - root.width
36+ }
37+
38+ onStretchChanged: {
39+ // reset
40+ shown = false;
41+ if (stretch) {
42+ width = 0;
43+ } else {
44+ x = parent.width;
45+ width = parent.width;
46+ }
47+ }
48+
49+ shown: false
50+
51+ signal dragHandleRecognizedGesture(var dragHandle)
52+
53+ property string animatedProp: stretch ? "width" : "x"
54+ property real propValueWhenShown: stretch ? parent.width : 0
55+ property real propValueWhenHidden: stretch ? 0 : parent.width
56+
57+ showAnimation: StandardAnimation { property: animatedProp; to: propValueWhenShown }
58+ hideAnimation: StandardAnimation { property: animatedProp; to: propValueWhenHidden }
59+
60+ Image { source: "../../UnityLogo.png"; anchors.fill: parent }
61+
62+ DragHandle {
63+ objectName: "rightEdgeHideDragHandle"
64+ id: hideDragHandle
65+ anchors.top: parent.top
66+ anchors.bottom: parent.bottom
67+ anchors.left: parent.left
68+
69+ width: units.gu(2)
70+
71+ direction: Direction.Rightwards
72+ stretch: root.stretch
73+ maxTotalDragDistance: root.parent.width
74+ hintDisplacement: root.hintDisplacement
75+
76+ onDraggingChanged: {
77+ if (dragging) {
78+ dragHandleRecognizedGesture(hideDragHandle);
79+ }
80+ }
81+
82+ Rectangle { color: "red"; anchors.fill: parent }
83+ }
84+
85+ DragHandle {
86+ objectName: "rightEdgeShowDragHandle"
87+ id: showDragHandle
88+ anchors.top: parent.top
89+ anchors.bottom: parent.bottom
90+ anchors.right: parent.left
91+
92+ width: units.gu(2)
93+
94+ direction: Direction.Leftwards
95+ stretch: root.stretch
96+ maxTotalDragDistance: root.parent.width
97+ hintDisplacement: root.hintDisplacement
98+
99+ onDraggingChanged: {
100+ if (dragging) {
101+ dragHandleRecognizedGesture(showDragHandle);
102+ }
103+ }
104+
105+ Rectangle { color: "green"; anchors.fill: parent }
106+ }
107+
108+}
tests/qmltests/Components/tst_DragHandle/VerticalShowable.qml → tests/qmltests/Components/tst_DragHandle/TopEdgeShowable.qmlrenamed+7−7
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2013 Canonical, Ltd.
2+ * Copyright (C) 2013,2016 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
@@ -52,8 +52,8 @@ Showable {
52 Image { source: "../../UnityLogo.png"; anchors.fill: parent }
52 Image { source: "../../UnityLogo.png"; anchors.fill: parent }
53
53
54 DragHandle {
54 DragHandle {
55− objectName: "upwardsDragHandle"
55+ objectName: "topEdgeHideDragHandle"
56− id: upwardsDragHandle
56+ id: hideDragHandle
57 anchors.left: parent.left
57 anchors.left: parent.left
58 anchors.right: parent.right
58 anchors.right: parent.right
59 anchors.bottom: parent.bottom
59 anchors.bottom: parent.bottom
@@ -67,7 +67,7 @@ Showable {
67
67
68 onDraggingChanged: {
68 onDraggingChanged: {
69 if (dragging) {
69 if (dragging) {
70− dragHandleRecognizedGesture(upwardsDragHandle);
70+ dragHandleRecognizedGesture(hideDragHandle);
71 }
71 }
72 }
72 }
73
73
@@ -75,8 +75,8 @@ Showable {
75 }
75 }
76
76
77 DragHandle {
77 DragHandle {
78− objectName: "downwardsDragHandle"
78+ objectName: "topEdgeShowDragHandle"
79− id: downwardsDragHandle
79+ id: showDragHandle
80 anchors.left: parent.left
80 anchors.left: parent.left
81 anchors.right: parent.right
81 anchors.right: parent.right
82 anchors.top: parent.bottom
82 anchors.top: parent.bottom
@@ -90,7 +90,7 @@ Showable {
90
90
91 onDraggingChanged: {
91 onDraggingChanged: {
92 if (dragging) {
92 if (dragging) {
93− dragHandleRecognizedGesture(downwardsDragHandle);
93+ dragHandleRecognizedGesture(showDragHandle);
94 }
94 }
95 }
95 }
96
96
tests/qmltests/Components/tst_EdgeDragEvaluator.cpp+1−1
@@ -24,7 +24,7 @@
24// Ubuntu.Gestures plugin
24// Ubuntu.Gestures plugin
25#include <AxisVelocityCalculator.h>
25#include <AxisVelocityCalculator.h>
26#include <Direction.h>
26#include <Direction.h>
27−#include <Timer.h>
27+#include <Timer>
28
28
29#include <paths.h>
29#include <paths.h>
30
30
tests/qmltests/Dash/Previews/tst_Preview.qml−1
@@ -109,7 +109,6 @@ Rectangle {
109 }
109 }
110
110
111 function test_comboEnsureVisible() {
111 function test_comboEnsureVisible() {
112− skip("Flaky in adt but can't reproduce locally. Given the deadline I won't risk this getting stuck in proposed.");
113 waitForRendering(preview);
112 waitForRendering(preview);
114
113
115 // Scroll down
114 // Scroll down
tests/qmltests/Dash/Previews/tst_PreviewRatingEdit.qml+5−1
@@ -50,7 +50,8 @@ Rectangle {
50
50
51 var authorLabel = findChild(previewRatingEdit, "authorLabel");
51 var authorLabel = findChild(previewRatingEdit, "authorLabel");
52 var reviewTextArea = findChild(previewRatingEdit, "reviewTextArea");
52 var reviewTextArea = findChild(previewRatingEdit, "reviewTextArea");
53− var inputRating = findChild(findChild(previewRatingEdit, "input"), "rating");
53+ var ratingInput = findChild(previewRatingEdit, "input");
54+ var inputRating = findChild(ratingInput, "rating");
54 verify(authorLabel.visible)
55 verify(authorLabel.visible)
55 verify(!reviewTextArea.visible)
56 verify(!reviewTextArea.visible)
56
57
@@ -65,6 +66,9 @@ Rectangle {
65 reviewTextArea.text = "Ho Ho";
66 reviewTextArea.text = "Ho Ho";
66 inputRating.value = 3;
67 inputRating.value = 3;
67
68
69+ var reviewContainer = findChild(ratingInput, "reviewContainer");
70+ var reviewSubmitContainer = findChild(ratingInput, "reviewSubmitContainer");
71+ tryCompare(reviewContainer, "implicitHeight", reviewSubmitContainer.implicitHeight + reviewContainer.anchors.topMargin);
68 var submitButton = findChild(previewRatingEdit, "submitButton")
72 var submitButton = findChild(previewRatingEdit, "submitButton")
69 mouseClick(submitButton);
73 mouseClick(submitButton);
70
74
tests/qmltests/Dash/Previews/tst_PreviewRatingInput.qml+18−6
@@ -73,11 +73,10 @@ Rectangle {
73
73
74 function test_labels() {
74 function test_labels() {
75 var ratingLabel = findChild(previewRatingInput, "ratingLabel");
75 var ratingLabel = findChild(previewRatingInput, "ratingLabel");
76− var reviewLabel = findChild(previewRatingInput, "reviewLabel");
77
76
78 previewRatingInput.widgetData = widgetDataNewLabels;
77 previewRatingInput.widgetData = widgetDataNewLabels;
79 compare(ratingLabel.text, widgetDataNewLabels["rating-label"]);
78 compare(ratingLabel.text, widgetDataNewLabels["rating-label"]);
80− compare(reviewLabel.text, widgetDataNewLabels["review-label"]);
79+ compare(reviewTextArea.placeholderText, widgetDataNewLabels["review-label"]);
81 compare(submitButton.text, widgetDataNewLabels["submit-label"]);
80 compare(submitButton.text, widgetDataNewLabels["submit-label"]);
82 }
81 }
83
82
@@ -120,10 +119,17 @@ Rectangle {
120
119
121 previewRatingInput.widgetData = data.widgetData;
120 previewRatingInput.widgetData = data.widgetData;
122
121
122+ if (data.widgetData["visible"] === "both" && data.widgetData["required"] === "both")
123+ compare(reviewTextArea.visible, false);
124+
123 if (data.widgetData["visible"] !== "review") {
125 if (data.widgetData["visible"] !== "review") {
124− verify(rating.visible === true);
126+ compare(rating.visible, true);
125
127
126 rating.value = data.inputRating;
128 rating.value = data.inputRating;
129+
130+ if (data.inputRating > 0 && data.widgetData["visible"] === "both")
131+ compare(reviewTextArea.visible, true);
132+
127 if (data.widgetData["required"] !== "rating" ||
133 if (data.widgetData["required"] !== "rating" ||
128 data.widgetData["visible"] !== "rating" ||
134 data.widgetData["visible"] !== "rating" ||
129 data.inputRating < 0) {
135 data.inputRating < 0) {
@@ -132,13 +138,19 @@ Rectangle {
132 compare(spy.count, 1);
138 compare(spy.count, 1);
133 }
139 }
134 } else {
140 } else {
135− verify(rating.visible === false);
141+ compare(rating.visible, false);
136 }
142 }
137
143
138 if (data.widgetData["visible"] !== "rating") {
144 if (data.widgetData["visible"] !== "rating") {
145+ if (data.widgetData["visible"] === "review" || data.widgetData["required"] === "review")
139− verify(reviewTextArea.visible === true);
146+ compare(reviewTextArea.visible, true);
140
147
141 reviewTextArea.text = data.inputText;
148 reviewTextArea.text = data.inputText;
149+ var reviewContainer = findChild(previewRatingInput, "reviewContainer");
150+ if (reviewContainer.visible) {
151+ var reviewSubmitContainer = findChild(previewRatingInput, "reviewSubmitContainer");
152+ tryCompare(reviewContainer, "implicitHeight", reviewSubmitContainer.implicitHeight + reviewContainer.anchors.topMargin);
153+ }
142 mouseClick(submitButton);
154 mouseClick(submitButton);
143 switch (data.widgetData["required"]) {
155 switch (data.widgetData["required"]) {
144 case "rating": {
156 case "rating": {
@@ -164,7 +176,7 @@ Rectangle {
164 }
176 }
165 }
177 }
166 } else {
178 } else {
167− verify(reviewTextArea.visible === false);
179+ compare(reviewTextArea.visible, false);
168 }
180 }
169
181
170 compare(spy.count === 1, data.emitted);
182 compare(spy.count === 1, data.emitted);
tests/qmltests/Dash/Previews/tst_PreviewWidgetFactory.qml+1−1
@@ -43,7 +43,7 @@ Rectangle {
43 name: "PreviewWidgetFactory"
43 name: "PreviewWidgetFactory"
44 when: windowShown
44 when: windowShown
45
45
46− property Item mockWidget: findChild(factory, "mockPreviewWidget")
46+ property Item mockWidget: findChild(factory, "mockPreviewWidget", 0 /*timeout*/)
47
47
48 function cleanup() {
48 function cleanup() {
49 factory.source = Qt.binding(function() { return factory.widgetSource });
49 factory.source = Qt.binding(function() { return factory.widgetSource });
tests/qmltests/Dash/tst_Card.qml+22−10
@@ -226,16 +226,16 @@ Rectangle {
226
226
227 when: windowShown
227 when: windowShown
228
228
229− property Item title: findChild(loader, "titleLabel")
229+ property Item title: findChild(loader, "titleLabel", 0 /*timeout*/)
230− property Item subtitle: findChild(loader, "subtitleLabel")
230+ property Item subtitle: findChild(loader, "subtitleLabel", 0 /*timeout*/)
231− property var headerRow: findChild(loader, "outerRow")
231+ property var headerRow: findChild(loader, "outerRow", 0 /*timeout*/)
232− property var art: findChild(loader, "artShape")
232+ property var art: findChild(loader, "artShape", 0 /*timeout*/)
233− property Item artImage: findChild(loader, "artImage")
233+ property Item artImage: findChild(loader, "artImage", 0 /*timeout*/)
234− property Item summary: findChild(loader, "summaryLabel")
234+ property Item summary: findChild(loader, "summaryLabel", 0 /*timeout*/)
235− property Item background: findChild(loader, "background")
235+ property Item background: findChild(loader, "background", 0 /*timeout*/)
236− property Item backgroundLoader: findChild(loader, "backgroundLoader")
236+ property Item backgroundLoader: findChild(loader, "backgroundLoader", 0 /*timeout*/)
237− property Item backgroundImage: findChild(loader, "backgroundImage")
237+ property Item backgroundImage: findChild(loader, "backgroundImage", 0 /*timeout*/)
238− property Item mascotImage: findChild(loader, "mascotImage");
238+ property Item mascotImage: findChild(loader, "mascotImage", 0 /*timeout*/)
239
239
240 function init() {
240 function init() {
241 cardTool.components = Qt.binding(function() { return Helpers.update(JSON.parse(Helpers.defaultLayout), Helpers.tryParse(layoutArea.text, layoutError))['components']; });
241 cardTool.components = Qt.binding(function() { return Helpers.update(JSON.parse(Helpers.defaultLayout), Helpers.tryParse(layoutArea.text, layoutError))['components']; });
@@ -496,6 +496,18 @@ Rectangle {
496 tryCompare(art, "visible", true);
496 tryCompare(art, "visible", true);
497 compare(artImage.source, Qt.resolvedUrl("artwork/checkers.png"));
497 compare(artImage.source, Qt.resolvedUrl("artwork/checkers.png"));
498
498
499+ card.cardData["art"] = "somethingbroken";
500+ card.cardDataChanged();
501+ waitForRendering(card);
502+ tryCompare(art, "visible", true);
503+ compare(artImage.source, Qt.resolvedUrl("artwork/checkers.png"));
504+
505+ card.cardData["art"] = Qt.resolvedUrl("artwork/music-player-design.png");
506+ card.cardDataChanged();
507+ waitForRendering(card);
508+ tryCompare(art, "visible", true);
509+ compare(artImage.source, Qt.resolvedUrl("artwork/music-player-design.png"));
510+
499 card.cardData["mascot"] = "somethingbroken2";
511 card.cardData["mascot"] = "somethingbroken2";
500 card.cardDataChanged();
512 card.cardDataChanged();
501 compare(mascotImage.status, Image.Error);
513 compare(mascotImage.status, Image.Error);
tests/qmltests/Dash/tst_CardTool.qml+1−1
@@ -240,7 +240,7 @@ Rectangle {
240 id: testCase
240 id: testCase
241 name: "CardTool"
241 name: "CardTool"
242
242
243− property var internalCard: findChild(cardTool, "cardToolCard")
243+ property var internalCard: findChild(cardTool, "cardToolCard", 0 /*timeout*/)
244
244
245 when: windowShown
245 when: windowShown
246
246
tests/qmltests/Dash/tst_Dash.qml+76−62
@@ -18,6 +18,7 @@ import QtQuick 2.4
18import QtTest 1.0
18import QtTest 1.0
19import "../../../qml/Dash"
19import "../../../qml/Dash"
20import Ubuntu.Components 1.3
20import Ubuntu.Components 1.3
21+import Unity 0.2 // Access the Filters enum
21import Unity.Test 0.1 as UT
22import Unity.Test 0.1 as UT
22
23
23Item {
24Item {
@@ -57,7 +58,7 @@ Item {
57 tryCompare(dashContentList, "count", 0);
58 tryCompare(dashContentList, "count", 0);
58 scopes.load();
59 scopes.load();
59 tryCompare(dashContentList, "currentIndex", 0);
60 tryCompare(dashContentList, "currentIndex", 0);
60− tryCompare(dashContentList, "count", 6);
61+ tryCompare(dashContentList, "count", 7);
61 tryCompare(scopes, "loaded", true);
62 tryCompare(scopes, "loaded", true);
62 tryCompareFunction(function() {
63 tryCompareFunction(function() {
63 var mockScope1Loader = findChild(dash, "scopeLoader0");
64 var mockScope1Loader = findChild(dash, "scopeLoader0");
@@ -106,6 +107,72 @@ Item {
106 mouseClick(tile);
107 mouseClick(tile);
107 }
108 }
108
109
110+ function test_longNavigationFilterList() {
111+ // Select the scope with long navigation
112+ dash.setCurrentScope("LongPrimaryNavigation")
113+ var dashContent = findChild(dash, "dashContent")
114+ tryCompare(dashContent.currentScope, "id", "LongPrimaryNavigation")
115+
116+ var dashContentList = findChild(dashContent, "dashContentList")
117+ var searchButton = findChild(dashContentList.currentItem, "search_button")
118+ var extraPanel = findChild(dashContentList.currentItem, "peExtraPanel")
119+ tryCompare(extraPanel, "visible", false)
120+
121+ // Open the primaryNavigationFilter
122+ dashContent.currentScope.setHasNavigation(false)
123+ mouseClick(searchButton)
124+ tryCompare(extraPanel, "visible", true)
125+
126+ var primaryFilterContainer = findChild(extraPanel, "primaryFilterContainer")
127+ verify(primaryFilterContainer)
128+
129+ var primaryFilter = findChild(extraPanel, "primaryFilter")
130+ verify(primaryFilter)
131+ tryCompare(primaryFilter, "widgetType", Filters.OptionSelectorFilter)
132+
133+ var genericScopeView = dashContentList.currentItem;
134+ var categoryListView = findChild(genericScopeView, "categoryListView")
135+ verify(categoryListView)
136+ tryCompare(categoryListView, "atYBeginning", true)
137+
138+ var expandingItem = findChild(primaryFilter, "expandingItem")
139+ verify(expandingItem)
140+ expandingItem.expanded = true
141+
142+ // Flick the navigation list and ensure the underlying scope didn't move
143+ tryCompareFunction(function() { return expandingItem.height == expandingItem.expandedHeight; }, true);
144+ flickToYEnd(primaryFilterContainer)
145+
146+ tryCompare(categoryListView, "atYBeginning", true)
147+ }
148+
149+ function test_navigationFilterPopupClosesWhenOptionSelected() {
150+ dash.setCurrentScope("LongPrimaryNavigation")
151+
152+ var dashContentList = findChild(dashContent, "dashContentList")
153+ var searchButton = findChild(dashContentList.currentItem, "search_button")
154+ verify(searchButton)
155+ var extraPanel = findChild(dashContentList.currentItem, "peExtraPanel")
156+ verify(extraPanel)
157+
158+ var primaryFilter = findChild(extraPanel, "primaryFilter")
159+ var expandingItem = findChild(primaryFilter, "expandingItem")
160+ verify(expandingItem)
161+ tryCompare(expandingItem, "expanded", false)
162+
163+ mouseClick(searchButton)
164+ expandingItem.expanded = true
165+ tryCompare(expandingItem, "expanded", true)
166+ tryCompareFunction(function() { return expandingItem.height == expandingItem.expandedHeight; }, true);
167+
168+ var optionsRepeater = findChild(expandingItem, "optionsRepeater")
169+ verify(optionsRepeater)
170+ verify(optionsRepeater.itemAt(0))
171+ tryCompare(optionsRepeater.itemAt(0), "visible", true)
172+ mouseClick(optionsRepeater.itemAt(0))
173+ tryCompare(expandingItem, "visible", false)
174+ }
175+
109 function test_manage_dash_clickscope_unfavoritable() {
176 function test_manage_dash_clickscope_unfavoritable() {
110 // Show the manage dash
177 // Show the manage dash
111 touchFlick(dash, dash.width / 2, dash.height - 1, dash.width / 2, units.gu(2));
178 touchFlick(dash, dash.width / 2, dash.height - 1, dash.width / 2, units.gu(2));
@@ -125,7 +192,7 @@ Item {
125 // Go back
192 // Go back
126 var scopesList = findChild(dash, "scopesList");
193 var scopesList = findChild(dash, "scopesList");
127 var scopesListPageHeader = findChild(scopesList, "pageHeader");
194 var scopesListPageHeader = findChild(scopesList, "pageHeader");
128− var backButton = findChild(findChild(scopesListPageHeader, "innerPageHeader"), "customBackButton");
195+ var backButton = findChild(scopesListPageHeader, "innerPageHeader").leadingActionBar;
129 mouseClick(backButton);
196 mouseClick(backButton);
130 tryCompare(bottomEdgeController, "progress", 0);
197 tryCompare(bottomEdgeController, "progress", 0);
131 }
198 }
@@ -200,60 +267,7 @@ Item {
200
267
201 // Go back
268 // Go back
202 var dashTempScopeItemHeader = findChild(dashTempScopeItem, "scopePageHeader");
269 var dashTempScopeItemHeader = findChild(dashTempScopeItem, "scopePageHeader");
203− var backButton = findChild(findChild(dashTempScopeItemHeader, "innerPageHeader"), "customBackButton");
270+ var backButton = findChild(dashTempScopeItemHeader, "innerPageHeader").leadingActionBar;
204− mouseClick(backButton);
205−
206− // Check temp scope is gone
207− tryCompare(dashTempScopeItem, "x", dash.width);
208− tryCompare(dashTempScopeItem, "visible", false);
209−
210− // Original list is still on 0
211− var dashContentList = findChild(dash, "dashContentList");
212− compare(dashContentList.currentIndex, 0);
213− }
214−
215− function test_manage_dash_search_temp_scope() {
216− // TODO Search is disabled for now in manage dash
217− skip();
218−
219− // Show the manage dash
220− touchFlick(dash, dash.width / 2, dash.height - 1, dash.width / 2, units.gu(2));
221− var bottomEdgeController = findInvisibleChild(dash, "bottomEdgeController");
222− tryCompare(bottomEdgeController, "progress", 1);
223−
224− // Do a search
225− var scopesList = findChild(dash, "scopesList");
226− var scopesListPageHeader = findChild(scopesList, "pageHeader");
227− var searchButton = findChild(scopesListPageHeader, "search_header_button");
228− mouseClick(searchButton);
229−
230− // Type something
231− keyClick(Qt.Key_H);
232−
233− // Click on a temp scope in the search
234− tryCompareFunction( function() { return findChild(scopesList, "scopesListCategorysearchA") != null; }, true);
235− var dashCategorysearchA = findChild(scopesList, "scopesListCategorysearchA");
236− tryCompareFunction( function() { return findChild(dashCategorysearchA, "delegate2") != null; }, true);
237− var cardTempScope = findChild(dashCategorysearchA, "delegate2");
238−
239− waitForRendering(cardTempScope);
240− mouseClick(cardTempScope);
241−
242− // Check the bottom edge (overview) is disabled from temp scope
243− var overviewDragHandle = findChild(dash, "overviewDragHandle");
244− compare(overviewDragHandle.enabled, false);
245−
246− // Check temp scope is there
247− var dashTempScopeItem = findChild(dash, "dashTempScopeItem");
248− tryCompare(dashTempScopeItem, "x", 0);
249− tryCompare(dashTempScopeItem, "visible", true);
250−
251− // Check the manage dash is gone
252− tryCompare(bottomEdgeController, "progress", 0);
253−
254− // Go back
255− var dashTempScopeItemHeader = findChild(dashTempScopeItem, "scopePageHeader");
256− var backButton = findChild(findChild(dashTempScopeItemHeader, "innerPageHeader"), "customBackButton");
257 mouseClick(backButton);
271 mouseClick(backButton);
258
272
259 // Check temp scope is gone
273 // Check temp scope is gone
@@ -279,7 +293,7 @@ Item {
279 // Go back
293 // Go back
280 var scopesList = findChild(dash, "scopesList");
294 var scopesList = findChild(dash, "scopesList");
281 var scopesListPageHeader = findChild(scopesList, "pageHeader");
295 var scopesListPageHeader = findChild(scopesList, "pageHeader");
282− var backButton = findChild(findChild(scopesListPageHeader, "innerPageHeader"), "customBackButton");
296+ var backButton = findChild(scopesListPageHeader, "innerPageHeader").leadingActionBar;
283 mouseClick(backButton);
297 mouseClick(backButton);
284 tryCompare(bottomEdgeController, "progress", 0);
298 tryCompare(bottomEdgeController, "progress", 0);
285 }
299 }
@@ -391,7 +405,7 @@ Item {
391 // Exit edit mode and go back
405 // Exit edit mode and go back
392 var scopesList = findChild(dash, "scopesList");
406 var scopesList = findChild(dash, "scopesList");
393 var scopesListPageHeader = findChild(scopesList, "pageHeader");
407 var scopesListPageHeader = findChild(scopesList, "pageHeader");
394− var backButton = findChild(findChild(scopesListPageHeader, "innerPageHeader"), "customBackButton");
408+ var backButton = findChild(scopesListPageHeader, "innerPageHeader").leadingActionBar;
395 mouseClick(backButton);
409 mouseClick(backButton);
396 mouseClick(backButton);
410 mouseClick(backButton);
397 tryCompare(bottomEdgeController, "progress", 0);
411 tryCompare(bottomEdgeController, "progress", 0);
@@ -436,7 +450,7 @@ Item {
436 // Exit edit mode
450 // Exit edit mode
437 var scopesList = findChild(dash, "scopesList");
451 var scopesList = findChild(dash, "scopesList");
438 var scopesListPageHeader = findChild(scopesList, "pageHeader");
452 var scopesListPageHeader = findChild(scopesList, "pageHeader");
439− var backButton = findChild(findChild(scopesListPageHeader, "innerPageHeader"), "customBackButton");
453+ var backButton = findChild(scopesListPageHeader, "innerPageHeader").leadingActionBar;
440 mouseClick(backButton);
454 mouseClick(backButton);
441
455
442 // Click on third scope
456 // Click on third scope
@@ -546,7 +560,7 @@ Item {
546
560
547 // Go back
561 // Go back
548 var dashTempScopeItemHeader = findChild(dashTempScopeItem, "scopePageHeader");
562 var dashTempScopeItemHeader = findChild(dashTempScopeItem, "scopePageHeader");
549− var backButton = findChild(findChild(dashTempScopeItemHeader, "innerPageHeader"), "customBackButton");
563+ var backButton = findChild(dashTempScopeItemHeader, "innerPageHeader").leadingActionBar;
550 mouseClick(backButton);
564 mouseClick(backButton);
551
565
552 // Check temp scope is gone
566 // Check temp scope is gone
@@ -614,7 +628,7 @@ Item {
614
628
615 // Go back
629 // Go back
616 var dashTempScopeItemHeader = findChild(dashTempScopeItem, "scopePageHeader");
630 var dashTempScopeItemHeader = findChild(dashTempScopeItem, "scopePageHeader");
617− var backButton = findChild(findChild(dashTempScopeItemHeader, "innerPageHeader"), "customBackButton");
631+ var backButton = findChild(dashTempScopeItemHeader, "innerPageHeader").leadingActionBar;
618 mouseClick(backButton);
632 mouseClick(backButton);
619
633
620 // Check temp scope is gone
634 // Check temp scope is gone
@@ -646,7 +660,7 @@ Item {
646
660
647 // Go back
661 // Go back
648 var dashTempScopeItemHeader = findChild(dashTempScopeItem, "scopePageHeader");
662 var dashTempScopeItemHeader = findChild(dashTempScopeItem, "scopePageHeader");
649− var backButton = findChild(findChild(dashTempScopeItemHeader, "innerPageHeader"), "customBackButton");
663+ var backButton = findChild(dashTempScopeItemHeader, "innerPageHeader").leadingActionBar;
650 mouseClick(backButton);
664 mouseClick(backButton);
651
665
652 // Check temp scope is gone
666 // Check temp scope is gone
tests/qmltests/Dash/tst_DashContent.qml+63−4
@@ -124,7 +124,7 @@ Item {
124
124
125 loadScopes();
125 loadScopes();
126
126
127− compare(dashContentList.count, 6);
127+ compare(dashContentList.count, 7);
128 verify(dashContentList.currentIndex >= 0 && dashContentList.currentIndex < dashContentList.count);
128 verify(dashContentList.currentIndex >= 0 && dashContentList.currentIndex < dashContentList.count);
129 }
129 }
130
130
@@ -215,7 +215,7 @@ Item {
215 verify(pageHeader, "Could not find the scope page header.");
215 verify(pageHeader, "Could not find the scope page header.");
216 var innerHeader = findChild(pageHeader, "innerPageHeader");
216 var innerHeader = findChild(pageHeader, "innerPageHeader");
217 verify(innerHeader, "Could not find the scope page header.");
217 verify(innerHeader, "Could not find the scope page header.");
218− compare(innerHeader.config.title, scopesModel.getScope(data.index).name);
218+ compare(innerHeader.title, scopesModel.getScope(data.index).name);
219 }
219 }
220
220
221 function test_is_active_data() {
221 function test_is_active_data() {
@@ -515,10 +515,18 @@ Item {
515 }
515 }
516
516
517 function test_navigationShowFilterPopup() {
517 function test_navigationShowFilterPopup() {
518− goToSecondLevel();
519−
520 var dashContentList = findChild(dashContent, "dashContentList");
518 var dashContentList = findChild(dashContent, "dashContentList");
519+ var pageHeader = findChild(dashContentList.currentItem, "scopePageHeader")
521 var settingsButton = findChild(dashContentList.currentItem, "settingsButton");
520 var settingsButton = findChild(dashContentList.currentItem, "settingsButton");
521+ var searchButton = findChild(dashContentList.currentItem, "search_button");
522+ var cancelButton = findChild(dashContentList.currentItem, "cancelButton");
523+ var searchTextField = findChild(pageHeader, "searchTextField");
524+ var peExtraPanel = findChild(dashContentList.currentItem, "peExtraPanel");
525+ var headerContainer = findChild(pageHeader, "headerContainer");
526+
527+ // test that closing the filters popover without a search unfocuses and removes the navigation
528+ mouseClick(searchButton);
529+ tryCompare(peExtraPanel, "visible", true);
522
530
523 var filtersPopover = findChild(shell, "filtersPopover")
531 var filtersPopover = findChild(shell, "filtersPopover")
524 verify(!filtersPopover);
532 verify(!filtersPopover);
@@ -526,8 +534,33 @@ Item {
526 mouseClick(settingsButton);
534 mouseClick(settingsButton);
527
535
528 filtersPopover = findChild(shell, "filtersPopover")
536 filtersPopover = findChild(shell, "filtersPopover")
537+ verify(filtersPopover);
529
538
539+ mouseClick(shell, shell.width - 1, shell.height - 1);
540+
541+ tryCompare(pageHeader.extraPanel, "visible", false);
542+ tryCompare(headerContainer, "showSearch", true);
543+ tryCompare(searchTextField, "focus", false);
544+
545+ mouseClick(cancelButton);
546+ tryCompare(headerContainer, "showSearch", false);
547+ tryCompare(headerContainer, "contentY", headerContainer.height);
548+
549+ // test within a navigation
550+ goToSecondLevel();
551+
552+ filtersPopover = findChild(shell, "filtersPopover")
553+ verify(!filtersPopover);
554+
555+ mouseClick(settingsButton);
556+
557+ filtersPopover = findChild(shell, "filtersPopover")
530 verify(filtersPopover);
558 verify(filtersPopover);
559+
560+ mouseClick(shell, shell.width - 1, shell.height - 1);
561+
562+ tryCompare(pageHeader.extraPanel, "visible", false);
563+ tryCompare(headerContainer, "showSearch", true);
531 }
564 }
532
565
533 function test_primaryFilter() {
566 function test_primaryFilter() {
@@ -625,5 +658,31 @@ Item {
625 tryCompareFunction(function() { return dashContentList.currentItem.item.scope.id == nextScopeId; }, true);
658 tryCompareFunction(function() { return dashContentList.currentItem.item.scope.id == nextScopeId; }, true);
626 compare(dashContentList.currentIndex, 0);
659 compare(dashContentList.currentIndex, 0);
627 }
660 }
661+
662+ function test_extraPanel() {
663+ var dashContentList = findChild(dashContent, "dashContentList");
664+ var pageHeader = findChild(dashContentList.currentItem, "scopePageHeader")
665+ pageHeader.searchEntryEnabled = true;
666+ pageHeader.searchHistory.clear();
667+
668+ pageHeader.searchHistory.addQuery("Search1");
669+ pageHeader.searchHistory.addQuery("Search2");
670+
671+ pageHeader.triggerSearch();
672+ tryCompare(pageHeader.extraPanel, "visible", true);
673+
674+ var searchTextField = findChild(pageHeader, "searchTextField");
675+ compare(searchTextField.focus, true);
676+
677+ var recentSearches = findChild(pageHeader.extraPanel, "recentSearchesRepeater");
678+ verify(recentSearches, "Could not find recent searches");
679+
680+ waitForRendering(recentSearches);
681+
682+ mouseClick(recentSearches.itemAt(0));
683+ compare(pageHeader.searchQuery, "Search2");
684+ tryCompare(pageHeader.extraPanel, "visible", false);
685+ compare(searchTextField.focus, false);
686+ }
628 }
687 }
629}
688}
tests/qmltests/Dash/tst_DashPageHeader.qml−24
@@ -147,30 +147,6 @@ Item {
147 doResetSearch();
147 doResetSearch();
148 }
148 }
149
149
150− function test_extraPanel() {
151− searchEnabled = true;
152− pageHeader.searchHistory.clear();
153−
154− pageHeader.searchHistory.addQuery("Search1");
155− pageHeader.searchHistory.addQuery("Search2");
156−
157− pageHeader.triggerSearch();
158−
159− tryCompare(pageHeader.extraPanel, "visible", true);
160−
161− var searchTextField = findChild(pageHeader, "searchTextField");
162− compare(searchTextField.focus, true);
163−
164− var recentSearches = findChild(pageHeader.extraPanel, "recentSearchesRepeater");
165− verify(recentSearches, "Could not find recent searches");
166− waitForRendering(recentSearches);
167− mouseClick(recentSearches.itemAt(0));
168−
169− compare(pageHeader.searchQuery, "Search2");
170− tryCompare(pageHeader.extraPanel, "visible", false);
171− compare(searchTextField.focus, false);
172− }
173−
174 function test_popup_closing_data() {
150 function test_popup_closing_data() {
175 return [
151 return [
176 { tag: "with search text", searchText: "foobar", hideSearch: false },
152 { tag: "with search text", searchText: "foobar", hideSearch: false },
tests/qmltests/Dash/tst_DashShell.qml+1−1
@@ -60,7 +60,7 @@ Item {
60 tryCompare(dashContentList, "count", 0);
60 tryCompare(dashContentList, "count", 0);
61 scopes.load();
61 scopes.load();
62 tryCompare(dashContentList, "currentIndex", 0);
62 tryCompare(dashContentList, "currentIndex", 0);
63− tryCompare(dashContentList, "count", 6);
63+ tryCompare(dashContentList, "count", 7);
64 tryCompare(scopes, "loaded", true);
64 tryCompare(scopes, "loaded", true);
65 tryCompareFunction(function() {
65 tryCompareFunction(function() {
66 var mockScope1Loader = findChild(dash, "scopeLoader0");
66 var mockScope1Loader = findChild(dash, "scopeLoader0");
tests/qmltests/Dash/tst_GenericScopeView.qml+2−2
@@ -442,8 +442,8 @@ Item {
442
442
443 var innerHeader = findChild(header, "innerPageHeader");
443 var innerHeader = findChild(header, "innerPageHeader");
444 verify(innerHeader, "Could not find the inner header");
444 verify(innerHeader, "Could not find the inner header");
445− verify(Qt.colorEqual(innerHeader.config.foregroundColor, data.foreground),
445+ verify(Qt.colorEqual(innerHeader.__styleInstance.foregroundColor, data.foreground),
446− "Foreground color not equal: %1 != %2".arg(innerHeader.config.foregroundColor).arg(data.foreground));
446+ "Foreground color not equal: %1 != %2".arg(innerHeader.__styleInstance.foregroundColor).arg(data.foreground));
447
447
448 var background = findChild(header, "headerBackground");
448 var background = findChild(header, "headerBackground");
449 verify(background, "Could not find the background");
449 verify(background, "Could not find the background");
tests/qmltests/Dash/tst_PreviewView.qml+3−3
@@ -98,7 +98,7 @@ Rectangle {
98 var header = findChild(view, "innerPageHeader");
98 var header = findChild(view, "innerPageHeader");
99 verify(header, "Could not find the preview header");
99 verify(header, "Could not find the preview header");
100
100
101− compare(header.config.title, "Mock Scope");
101+ compare(header.title, "Mock Scope");
102 }
102 }
103
103
104 function test_header_style() {
104 function test_header_style() {
@@ -107,8 +107,8 @@ Rectangle {
107
107
108 var innerHeader = findChild(header, "innerPageHeader");
108 var innerHeader = findChild(header, "innerPageHeader");
109 verify(innerHeader, "Could not find the inner header");
109 verify(innerHeader, "Could not find the inner header");
110− verify(Qt.colorEqual(innerHeader.config.foregroundColor, UbuntuColors.darkGrey),
110+ verify(Qt.colorEqual(innerHeader.__styleInstance.foregroundColor, UbuntuColors.darkGrey),
111− "Foreground color not equal: %1 != %2".arg(innerHeader.config.foregroundColor).arg(UbuntuColors.darkGrey));
111+ "Foreground color not equal: %1 != %2".arg(innerHeader.__styleInstance.foregroundColor).arg(UbuntuColors.darkGrey));
112
112
113 var background = findChild(header, "headerBackground");
113 var background = findChild(header, "headerBackground");
114 verify(background, "Could not find the background");
114 verify(background, "Could not find the background");
tests/qmltests/Greeter/tst_Greeter.qml+1−1
@@ -166,7 +166,7 @@ Item {
166 tryCompare(loader, "itemDestroyed", true);
166 tryCompare(loader, "itemDestroyed", true);
167 loader.active = true;
167 loader.active = true;
168 tryCompare(loader, "status", Loader.Ready);
168 tryCompare(loader, "status", Loader.Ready);
169− removeTimeConstraintsFromDirectionalDragAreas(loader.item);
169+ removeTimeConstraintsFromSwipeAreas(loader.item);
170 }
170 }
171
171
172 function getIndexOf(name) {
172 function getIndexOf(name) {
tests/qmltests/Greeter/tst_NarrowView.qml+1−1
@@ -302,7 +302,7 @@ Item {
302 tryCompare(loader, "itemDestroyed", true);
302 tryCompare(loader, "itemDestroyed", true);
303 loader.active = true;
303 loader.active = true;
304 tryCompare(loader, "status", Loader.Ready);
304 tryCompare(loader, "status", Loader.Ready);
305− removeTimeConstraintsFromDirectionalDragAreas(loader.item);
305+ removeTimeConstraintsFromSwipeAreas(loader.item);
306 }
306 }
307
307
308 function swipeAwayCover(toTheRight) {
308 function swipeAwayCover(toTheRight) {
tests/qmltests/Greeter/tst_WideView.qml+1−1
@@ -330,7 +330,7 @@ Item {
330 tryCompare(loader, "itemDestroyed", true);
330 tryCompare(loader, "itemDestroyed", true);
331 loader.active = true;
331 loader.active = true;
332 tryCompare(loader, "status", Loader.Ready);
332 tryCompare(loader, "status", Loader.Ready);
333− removeTimeConstraintsFromDirectionalDragAreas(loader.item);
333+ removeTimeConstraintsFromSwipeAreas(loader.item);
334 }
334 }
335
335
336 function getIndexOf(name) {
336 function getIndexOf(name) {
tests/qmltests/Launcher/tst_Launcher.qml+13−1
@@ -34,6 +34,14 @@ Rectangle {
34
34
35 Component.onCompleted: theme.name = "Ubuntu.Components.Themes.SuruDark"
35 Component.onCompleted: theme.name = "Ubuntu.Components.Themes.SuruDark"
36
36
37+ MouseArea {
38+ id: clickThroughTester
39+ anchors.fill: parent
40+ // SignalSpy does not seem to want to connect to the pressed signal. let's count them ourselves.
41+ property int pressCount: 0
42+ onPressed: pressCount++;
43+ }
44+
37 Loader {
45 Loader {
38 id: launcherLoader
46 id: launcherLoader
39 anchors.fill: parent
47 anchors.fill: parent
@@ -254,7 +262,7 @@ Rectangle {
254 // Now do check that snapping is in fact enabled
262 // Now do check that snapping is in fact enabled
255 compare(listView.snapMode, ListView.SnapToItem, "Snapping is not enabled");
263 compare(listView.snapMode, ListView.SnapToItem, "Snapping is not enabled");
256
264
257− removeTimeConstraintsFromDirectionalDragAreas(root);
265+ removeTimeConstraintsFromSwipeAreas(root);
258 }
266 }
259
267
260 function dragLauncherIntoView() {
268 function dragLauncherIntoView() {
@@ -836,16 +844,20 @@ Rectangle {
836 dragLauncherIntoView();
844 dragLauncherIntoView();
837 verify(launcher.state == "visible");
845 verify(launcher.state == "visible");
838
846
847+ clickThroughTester.pressCount = 0;
839 mouseClick(root, root.width / 2, units.gu(1));
848 mouseClick(root, root.width / 2, units.gu(1));
840 waitUntilLauncherDisappears();
849 waitUntilLauncherDisappears();
841 verify(launcher.state == "");
850 verify(launcher.state == "");
851+ compare(clickThroughTester.pressCount, 1);
842
852
843 // and repeat, as a test for regression in lpbug#1531339
853 // and repeat, as a test for regression in lpbug#1531339
844 dragLauncherIntoView();
854 dragLauncherIntoView();
845 verify(launcher.state == "visible");
855 verify(launcher.state == "visible");
856+ clickThroughTester.pressCount = 0;
846 mouseClick(root, root.width / 2, units.gu(1));
857 mouseClick(root, root.width / 2, units.gu(1));
847 waitUntilLauncherDisappears();
858 waitUntilLauncherDisappears();
848 verify(launcher.state == "");
859 verify(launcher.state == "");
860+ compare(clickThroughTester.pressCount, 1);
849 }
861 }
850
862
851 function test_quicklist_positioning_data() {
863 function test_quicklist_positioning_data() {
tests/qmltests/Notifications/tst_Notifications.qml+89
@@ -725,6 +725,95 @@ Item {
725 tryCompare(mockModel, "count", before - 1)
725 tryCompare(mockModel, "count", before - 1)
726 }
726 }
727
727
728+ function expansionLogic_data() {
729+ return [{
730+ tag: "Snap Decision without secondary icon and no button-tint",
731+ n: nlist[3],
732+ summaryVisible: true,
733+ bodyVisible: true,
734+ iconVisible: true,
735+ centeredIconVisible: false,
736+ shaped: true,
737+ secondaryIconVisible: false,
738+ buttonRowVisible: true,
739+ buttonTinted: false,
740+ hasSound: true,
741+ valueVisible: false,
742+ valueLabelVisible: false,
743+ valueTinted: false
744+ },
745+ {
746+ tag: "2-over-1 Snap Decision with button-tint",
747+ n: nlist[8],
748+ summaryVisible: true,
749+ bodyVisible: true,
750+ iconVisible: false,
751+ centeredIconVisible: false,
752+ shaped: false,
753+ secondaryIconVisible: false,
754+ buttonRowVisible: false,
755+ buttonTinted: true,
756+ hasSound: false,
757+ valueVisible: false,
758+ valueLabelVisible: false,
759+ valueTinted: false
760+ },
761+ {
762+ tag: "Snap Decision without secondary icon and no button-tint",
763+ n: nlist[3],
764+ summaryVisible: true,
765+ bodyVisible: true,
766+ iconVisible: true,
767+ centeredIconVisible: false,
768+ shaped: true,
769+ secondaryIconVisible: false,
770+ buttonRowVisible: true,
771+ buttonTinted: false,
772+ hasSound: true,
773+ valueVisible: false,
774+ valueLabelVisible: false,
775+ valueTinted: false
776+ }
777+ ]
778+ }
779+
780+ function test_expansionLogic() {
781+ var data = expansionLogic_data();
782+
783+ // fill the model
784+ data.forEach(function(notification) {
785+ mockModel.append(notification.n);
786+ notification.n.completed.connect(mockModel.onCompleted)
787+ })
788+
789+ // make sure the view is properly updated before going on
790+ notifications.forceLayout();
791+ waitForRendering(notifications);
792+
793+ // first one should be expanded by default
794+ var notification1 = findChild(notifications, "notification1") // 0 is placeholder...
795+ verify(!!notification1, "notification wasn't found");
796+ waitForRendering(notification1);
797+ verify(notification1.expanded);
798+
799+ // click the 2nd one, verify it's now expanded
800+ var notification2 = findChild(notifications, "notification2") // 0 is placeholder...
801+ verify(!!notification2, "notification wasn't found");
802+ waitForRendering(notification2);
803+ mouseClick(notification2);
804+ verify(notification2.expanded);
805+ verify(!notification1.expanded);
806+
807+ // now close the 2nd one, verify 1st is again expanded, 2nd is gone
808+ var dragStart = notification2.width * 0.25;
809+ var dragEnd = notification2.width;
810+ var dragY = notification2.height / 2;
811+ touchFlick(notification2, dragStart, dragY, dragEnd, dragY);
812+ waitForRendering(notifications);
813+ tryCompareFunction(function() { return notification1.expanded; }, true);
814+ tryCompareFunction(function() { return notification2.expanded; }, undefined);
815+ }
816+
728 function cleanupTestCase() {
817 function cleanupTestCase() {
729 notifications.hasMouse = false;
818 notifications.hasMouse = false;
730 }
819 }
tests/qmltests/Panel/Indicators/tst_MessageMenuItemFactory.qml+1
@@ -30,6 +30,7 @@ Item {
30 id: factory
30 id: factory
31 menuModel: UnityMenuModel {}
31 menuModel: UnityMenuModel {}
32 menuIndex: 0
32 menuIndex: 0
33+ width: parent.width
33 }
34 }
34
35
35 UT.UnityTestCase {
36 UT.UnityTestCase {
tests/qmltests/Stages/tst_DesktopStage.qml+31−1
@@ -462,6 +462,36 @@ Item {
462 verify(topSurfaceList.indexForId(dialerSurfaceId) === -1);
462 verify(topSurfaceList.indexForId(dialerSurfaceId) === -1);
463 }
463 }
464
464
465+ function test_windowMaximizeHorizontally() {
466+ var dialerDelegate = startApplication("dialer-app");
467+
468+ var dialerMaximizeButton = findChild(dialerDelegate, "maximizeWindowButton");
469+ verify(dialerMaximizeButton);
470+
471+ // RMB to maximize horizontally
472+ mouseClick(dialerMaximizeButton, dialerMaximizeButton.width/2, dialerMaximizeButton.height/2, Qt.RightButton);
473+ tryCompare(dialerDelegate, "windowState", WindowStateStorage.WindowStateMaximizedHorizontally);
474+
475+ // click again to restore
476+ mouseClick(dialerMaximizeButton);
477+ tryCompare(dialerDelegate, "windowState", WindowStateStorage.WindowStateNormal);
478+ }
479+
480+ function test_windowMaximizeVertically() {
481+ var dialerDelegate = startApplication("dialer-app");
482+
483+ var dialerMaximizeButton = findChild(dialerDelegate, "maximizeWindowButton");
484+ verify(dialerMaximizeButton);
485+
486+ // MMB to maximize vertically
487+ mouseClick(dialerMaximizeButton, dialerMaximizeButton.width/2, dialerMaximizeButton.height/2, Qt.MiddleButton);
488+ tryCompare(dialerDelegate, "windowState", WindowStateStorage.WindowStateMaximizedVertically);
489+
490+ // click again to restore
491+ mouseClick(dialerMaximizeButton);
492+ tryCompare(dialerDelegate, "windowState", WindowStateStorage.WindowStateNormal);
493+ }
494+
465 function test_smashCursorKeys() {
495 function test_smashCursorKeys() {
466 var apps = ["dialer-app", "gmail-webapp"];
496 var apps = ["dialer-app", "gmail-webapp"];
467 apps.forEach(startApplication);
497 apps.forEach(startApplication);
@@ -483,7 +513,7 @@ Item {
483 verify(decoratedWindow);
513 verify(decoratedWindow);
484
514
485 tryCompare(dashSurface, "visible", true);
515 tryCompare(dashSurface, "visible", true);
486− decoratedWindow.minimize();
516+ decoratedWindow.minimizeClicked();
487 tryCompare(dashSurface, "visible", false);
517 tryCompare(dashSurface, "visible", false);
488 }
518 }
489
519
tests/qmltests/Stages/tst_TabletStage.qml+66−2
@@ -129,6 +129,12 @@ Rectangle {
129 }
129 }
130 }
130 }
131
131
132+ SignalSpy {
133+ id: stageSaver
134+ target: WindowStateStorage
135+ signalName: "stageSaved"
136+ }
137+
132 UnityTestCase {
138 UnityTestCase {
133 id: testCase
139 id: testCase
134 name: "TabletStage"
140 name: "TabletStage"
@@ -138,6 +144,7 @@ Rectangle {
138 property Item sideStage: tabletStage ? findChild(tabletStage, "sideStage") : null
144 property Item sideStage: tabletStage ? findChild(tabletStage, "sideStage") : null
139
145
140 function init() {
146 function init() {
147+ stageSaver.clear();
141 tabletStageLoader.active = true;
148 tabletStageLoader.active = true;
142 tryCompare(tabletStageLoader, "status", Loader.Ready);
149 tryCompare(tabletStageLoader, "status", Loader.Ready);
143
150
@@ -510,7 +517,35 @@ Rectangle {
510 tryCompare(stagesPriv, "sideStageAppId", data.sideStageAppId);
517 tryCompare(stagesPriv, "sideStageAppId", data.sideStageAppId);
511 }
518 }
512
519
513− function test_loadSideStageByDragginFromMainStage() {
520+ function test_applicationSavesLastStage_data() {
521+ return [
522+ { tag: "MainStage", stage: ApplicationInfoInterface.MainStage},
523+ { tag: "SideStage", stage: ApplicationInfoInterface.SideStage},
524+ ];
525+ }
526+
527+ function test_applicationSavesLastStage(data) {
528+ WindowStateStorage.saveStage(webbrowserCheckBox.appId, data.stage);
529+ stageSaver.clear();
530+
531+ var stagesPriv = findInvisibleChild(tabletStage, "stagesPriv");
532+ verify(stagesPriv);
533+
534+ tryCompare(stagesPriv, "mainStageAppId", "unity8-dash");
535+ tryCompare(stagesPriv, "sideStageAppId", "");
536+
537+ var webbrowserSurfaceId = topSurfaceList.nextId;
538+ webbrowserCheckBox.checked = true;
539+ waitUntilAppSurfaceShowsUp(webbrowserSurfaceId);
540+
541+ webbrowserCheckBox.checked = false;
542+
543+ tryCompare(stageSaver, "count", 1);
544+ compare(stageSaver.signalArguments[0][0], "webbrowser-app")
545+ compare(stageSaver.signalArguments[0][1], data.stage)
546+ }
547+
548+ function test_loadSideStageByDraggingFromMainStage() {
514 sideStage.showNow();
549 sideStage.showNow();
515 var webbrowserSurfaceId = topSurfaceList.nextId;
550 var webbrowserSurfaceId = topSurfaceList.nextId;
516 webbrowserCheckBox.checked = true;
551 webbrowserCheckBox.checked = true;
@@ -538,7 +573,7 @@ Rectangle {
538 tryCompare(appDelegate, "stage", ApplicationInfoInterface.SideStage);
573 tryCompare(appDelegate, "stage", ApplicationInfoInterface.SideStage);
539 }
574 }
540
575
541− function test_unloadSideStageByDragginFromStageStage() {
576+ function test_unloadSideStageByDraggingFromStageStage() {
542 sideStage.showNow();
577 sideStage.showNow();
543 WindowStateStorage.saveStage(webbrowserCheckBox.appId, ApplicationInfoInterface.SideStage)
578 WindowStateStorage.saveStage(webbrowserCheckBox.appId, ApplicationInfoInterface.SideStage)
544 var webbrowserSurfaceId = topSurfaceList.nextId;
579 var webbrowserSurfaceId = topSurfaceList.nextId;
@@ -690,5 +725,34 @@ Rectangle {
690 // only unity8-dash surface is left
725 // only unity8-dash surface is left
691 compare(topSurfaceList.count, 1);
726 compare(topSurfaceList.count, 1);
692 }
727 }
728+
729+ function test_draggingSurfaceKeepsSurfaceFocus() {
730+ var webbrowserSurfaceId = topSurfaceList.nextId;
731+ webbrowserCheckBox.checked = true;
732+ waitUntilAppSurfaceShowsUp(webbrowserSurfaceId);
733+
734+ var appDelegate = findChild(tabletStage, "spreadDelegate_" + webbrowserSurfaceId);
735+ verify(appDelegate);
736+ compare(appDelegate.stage, ApplicationInfoInterface.MainStage);
737+
738+ tryCompare(appDelegate.surface, "activeFocus", true);
739+
740+ var pos = tabletStage.width - sideStage.width - (tabletStage.width - sideStage.width) / 2;
741+ var end_pos = tabletStage.width - sideStage.width / 2;
742+
743+ multiTouchDragUntil([0,1,2],
744+ tabletStage,
745+ pos,
746+ tabletStage.height / 2,
747+ units.gu(3),
748+ 0,
749+ function() {
750+ pos += units.gu(3);
751+ return sideStage.shown && !sideStage.showAnimation.running &&
752+ pos >= end_pos;
753+ });
754+
755+ tryCompare(appDelegate.surface, "activeFocus", true);
756+ }
693 }
757 }
694}
758}
tests/qmltests/Stages/tst_WindowResizeArea.qml+16−5
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright 2014-2015 Canonical Ltd.
2+ * Copyright 2014-2016 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
@@ -24,6 +24,7 @@ import "../../../qml/Stages"
24import Ubuntu.Components 1.3
24import Ubuntu.Components 1.3
25import Ubuntu.Components.ListItems 1.3 as ListItem
25import Ubuntu.Components.ListItems 1.3 as ListItem
26import Unity.Application 0.1
26import Unity.Application 0.1
27+import Utils 0.1
27
28
28Item {
29Item {
29 id: root
30 id: root
@@ -55,10 +56,20 @@ Item {
55 property real maximumHeight: 0
56 property real maximumHeight: 0
56 property real widthIncrement: 0
57 property real widthIncrement: 0
57 property real heightIncrement: 0
58 property real heightIncrement: 0
58− state: "normal"
59+
60+ property int windowState: WindowStateStorage.WindowStateNormal
61+
62+ states: [
63+ State { name: "normal"; when: windowState == WindowStateStorage.WindowStateNormal },
64+ State { name: "maximized"; when: windowState == WindowStateStorage.WindowStateMaximized }
65+ ]
59
66
60 function maximize() {
67 function maximize() {
61− state = "maximized"
68+ windowState = WindowStateStorage.WindowStateMaximized
69+ }
70+
71+ function restoreFromMaximized() {
72+ windowState = WindowStateStorage.WindowStateNormal
62 }
73 }
63
74
64 WindowResizeArea {
75 WindowResizeArea {
@@ -346,7 +357,7 @@ Item {
346 fakeWindow.y = initialWindowY + moveDelta
357 fakeWindow.y = initialWindowY + moveDelta
347
358
348 // Now change the state to maximized. The window should not keep updating the stored values
359 // Now change the state to maximized. The window should not keep updating the stored values
349− fakeWindow.state = "maximized"
360+ fakeWindow.maximize()
350 fakeWindow.x = 31415 // 0 is too risky to pass the test even when broken
361 fakeWindow.x = 31415 // 0 is too risky to pass the test even when broken
351 fakeWindow.y = 31415
362 fakeWindow.y = 31415
352
363
@@ -363,7 +374,7 @@ Item {
363 tryCompare(fakeWindow, "state", "maximized")
374 tryCompare(fakeWindow, "state", "maximized")
364
375
365 // clean up
376 // clean up
366− fakeWindow.state = "normal"
377+ fakeWindow.restoreFromMaximized()
367 }
378 }
368
379
369 function test_restoreMovesIntoBounds_data() {
380 function test_restoreMovesIntoBounds_data() {
tests/qmltests/Tutorial/tst_Tutorial.qml+2−2
@@ -261,7 +261,7 @@ Rectangle {
261 shellLoader.active = true;
261 shellLoader.active = true;
262
262
263 tryCompare(shellLoader, "status", Loader.Ready);
263 tryCompare(shellLoader, "status", Loader.Ready);
264− removeTimeConstraintsFromDirectionalDragAreas(shellLoader.item);
264+ removeTimeConstraintsFromSwipeAreas(shellLoader.item);
265 }
265 }
266
266
267 function prepareShell() {
267 function prepareShell() {
@@ -465,7 +465,7 @@ Rectangle {
465 // compare opacity with a bound rather than hard 0.6 because progress doesn't
465 // compare opacity with a bound rather than hard 0.6 because progress doesn't
466 // always match the drag perfectly (takes a moment for drag to kick in)
466 // always match the drag perfectly (takes a moment for drag to kick in)
467 tryCompareFunction(function() {
467 tryCompareFunction(function() {
468− return tutorialTop.opacity >= 0.6 && tutorialTop.opacity < 0.7;
468+ return tutorialTop.opacity >= 0.5 && tutorialTop.opacity < 0.7;
469 }, true);
469 }, true);
470 touchFlick(shell, halfWidth, 0, halfWidth, shell.height * 0.4, false, true);
470 touchFlick(shell, halfWidth, 0, halfWidth, shell.height * 0.4, false, true);
471
471
tests/qmltests/Wizard/tst_Wizard.qml+7−15
@@ -21,7 +21,7 @@ import MeeGo.QOfono 0.2
21import QMenuModel 0.1
21import QMenuModel 0.1
22import Ubuntu.Components 1.3
22import Ubuntu.Components 1.3
23import Ubuntu.SystemSettings.SecurityPrivacy 1.0
23import Ubuntu.SystemSettings.SecurityPrivacy 1.0
24−import Ubuntu.SystemSettings.TimeDate 1.0
24+import Ubuntu.SystemSettings.TimeDate 1.1
25import Unity.Test 0.1 as UT
25import Unity.Test 0.1 as UT
26import Wizard 0.1
26import Wizard 0.1
27import "../../../qml/Wizard"
27import "../../../qml/Wizard"
@@ -144,7 +144,9 @@ Item {
144 var pages = findChild(wizard, "wizardPages");
144 var pages = findChild(wizard, "wizardPages");
145 var stack = findChild(pages, "pageStack");
145 var stack = findChild(pages, "pageStack");
146 // don't simply call tryCompare here, because stack.currentPage will be swapped out itself
146 // don't simply call tryCompare here, because stack.currentPage will be swapped out itself
147− tryCompareFunction(function() { return stack.currentPage.objectName; }, name);
147+ tryCompareFunction(function() { return stack.currentPage.objectName; }, name, 15000);
148+ var contentAnimation = findInvisibleChild(stack.currentPage, "contentAnimation");
149+ tryCompareFunction(function() { return contentAnimation.running; }, false);
148 tryCompare(stack.currentPage, "opacity", 1.0);
150 tryCompare(stack.currentPage, "opacity", 1.0);
149 tryCompare(stack.currentPage, "enabled", true);
151 tryCompare(stack.currentPage, "enabled", true);
150 tryCompare(stack.currentPage, "skipValid", true);
152 tryCompare(stack.currentPage, "skipValid", true);
@@ -153,17 +155,6 @@ Item {
153 return stack.currentPage;
155 return stack.currentPage;
154 }
156 }
155
157
156− function verifyPageIsBlocked(name) {
157− var pages = findChild(wizard, "wizardPages");
158− var stack = findChild(pages, "pageStack");
159− // don't simply call tryCompare here, because stack.currentPage will be swapped out itself
160− tryCompareFunction(function() { return stack.currentPage.objectName; }, name);
161− tryCompare(stack.currentPage, "enabled", false);
162− tryCompare(stack.currentPage, "skipValid", false);
163− waitForRendering(stack.currentPage);
164− return stack.currentPage;
165− }
166−
167 function goToPage(name, skipSim, skipLocation, skipReporting) {
158 function goToPage(name, skipSim, skipLocation, skipReporting) {
168 if (skipSim === undefined) {
159 if (skipSim === undefined) {
169 skipSim = false;
160 skipSim = false;
@@ -464,7 +455,7 @@ Item {
464 var tzFilter = findChild(page, "tzFilter");
455 var tzFilter = findChild(page, "tzFilter");
465 verify(tzFilter);
456 verify(tzFilter);
466 tap(tzFilter);
457 tap(tzFilter);
467− typeString("London");
458+ typeString("Belfa");
468
459
469 var tzList = findChild(page, "tzList");
460 var tzList = findChild(page, "tzList");
470 verify(tzList);
461 verify(tzList);
@@ -478,7 +469,8 @@ Item {
478 // go next and verify the (mock) signal got fired
469 // go next and verify the (mock) signal got fired
479 tap(findChild(page, "forwardButton"));
470 tap(findChild(page, "forwardButton"));
480 tryCompare(timezoneSpy, "count", 1);
471 tryCompare(timezoneSpy, "count", 1);
472+ compare(timezoneSpy.signalArguments[0][0], "Europe/London");
481− tryCompare(page.tdModule, "timeZone", timezoneSpy.signalArguments[0][0]);
473+ compare(timezoneSpy.signalArguments[0][1], "Belfast");
482 }
474 }
483
475
484 function test_accountPage() {
476 function test_accountPage() {
tests/qmltests/tst_OrientedShell.qml+1−1
@@ -1551,7 +1551,7 @@ Rectangle {
1551 orientedShellLoader.active = true;
1551 orientedShellLoader.active = true;
1552
1552
1553 tryCompare(orientedShellLoader, "status", Loader.Ready);
1553 tryCompare(orientedShellLoader, "status", Loader.Ready);
1554− removeTimeConstraintsFromDirectionalDragAreas(orientedShellLoader.item);
1554+ removeTimeConstraintsFromSwipeAreas(orientedShellLoader.item);
1555
1555
1556 shell = findChild(orientedShell, "shell");
1556 shell = findChild(orientedShell, "shell");
1557
1557
tests/qmltests/tst_Shell.qml+32−5
@@ -436,7 +436,7 @@ Rectangle {
436 shellLoader.state = formFactor;
436 shellLoader.state = formFactor;
437 shellLoader.active = true;
437 shellLoader.active = true;
438 tryCompare(shellLoader, "status", Loader.Ready);
438 tryCompare(shellLoader, "status", Loader.Ready);
439− removeTimeConstraintsFromDirectionalDragAreas(shellLoader.item);
439+ removeTimeConstraintsFromSwipeAreas(shellLoader.item);
440 tryCompare(shell, "enabled", true); // enabled by greeter when ready
440 tryCompare(shell, "enabled", true); // enabled by greeter when ready
441
441
442 sessionSpy.target = findChild(shell, "greeter")
442 sessionSpy.target = findChild(shell, "greeter")
@@ -749,8 +749,9 @@ Rectangle {
749 // greeter unloads its internal components when hidden
749 // greeter unloads its internal components when hidden
750 // and reloads them when shown. Thus we have to do this
750 // and reloads them when shown. Thus we have to do this
751 // again before interacting with it otherwise any
751 // again before interacting with it otherwise any
752− // DirectionalDragAreas in there won't be easily fooled by
752+ // SwipeAreas in there won't be easily fooled by
753 // fake swipes.
753 // fake swipes.
754+ removeTimeConstraintsFromSwipeAreas(greeter);
754 swipeAwayGreeter();
755 swipeAwayGreeter();
755
756
756 compare(mainApp.requestedState, ApplicationInfoInterface.RequestedRunning);
757 compare(mainApp.requestedState, ApplicationInfoInterface.RequestedRunning);
@@ -761,7 +762,7 @@ Rectangle {
761 var greeter = findChild(shell, "greeter");
762 var greeter = findChild(shell, "greeter");
762 tryCompare(greeter, "fullyShown", true);
763 tryCompare(greeter, "fullyShown", true);
763 waitForGreeterToStabilize();
764 waitForGreeterToStabilize();
764− removeTimeConstraintsFromDirectionalDragAreas(greeter);
765+ removeTimeConstraintsFromSwipeAreas(greeter);
765
766
766 var touchX = shell.width - (shell.edgeSize / 2);
767 var touchX = shell.width - (shell.edgeSize / 2);
767 var touchY = shell.height / 2;
768 var touchY = shell.height / 2;
@@ -1069,9 +1070,9 @@ Rectangle {
1069 // greeter unloads its internal components when hidden
1070 // greeter unloads its internal components when hidden
1070 // and reloads them when shown. Thus we have to do this
1071 // and reloads them when shown. Thus we have to do this
1071 // again before interacting with it otherwise any
1072 // again before interacting with it otherwise any
1072− // DirectionalDragAreas in there won't be easily fooled by
1073+ // SwipeAreas in there won't be easily fooled by
1073 // fake swipes.
1074 // fake swipes.
1074− removeTimeConstraintsFromDirectionalDragAreas(greeter);
1075+ removeTimeConstraintsFromSwipeAreas(greeter);
1075 }
1076 }
1076
1077
1077 function revealLauncherByEdgePushWithMouse() {
1078 function revealLauncherByEdgePushWithMouse() {
@@ -2203,6 +2204,7 @@ Rectangle {
2203 compare(ApplicationManager.focusedApplicationId, "unity8-dash");
2204 compare(ApplicationManager.focusedApplicationId, "unity8-dash");
2204
2205
2205 // Use Super + Tab Tab to cycle to the first entry in the launcher
2206 // Use Super + Tab Tab to cycle to the first entry in the launcher
2207+ wait(1000);
2206 keyPress(Qt.Key_Super_L, Qt.MetaModifier);
2208 keyPress(Qt.Key_Super_L, Qt.MetaModifier);
2207 keyClick(Qt.Key_Tab);
2209 keyClick(Qt.Key_Tab);
2208 tryCompare(launcher, "state", "visible");
2210 tryCompare(launcher, "state", "visible");
@@ -2427,5 +2429,30 @@ Rectangle {
2427 ApplicationManager.requestFocusApplication("calendar-app");
2429 ApplicationManager.requestFocusApplication("calendar-app");
2428 tryCompare(app2Surface, "keymap", "fr");
2430 tryCompare(app2Surface, "keymap", "fr");
2429 }
2431 }
2432+
2433+ function test_dragPanelToRestoreMaximizedWindow() {
2434+ loadShell("desktop");
2435+ shell.usageScenario = "desktop";
2436+ waitForRendering(shell);
2437+ var panel = findChild(shell, "windowControlArea");
2438+ verify(panel);
2439+
2440+ var appSurfaceId = topLevelSurfaceList.nextId;
2441+ var app = ApplicationManager.startApplication("dialer-app")
2442+ waitUntilAppWindowIsFullyLoaded(appSurfaceId);
2443+
2444+ // start dialer, maximize it
2445+ var appContainer = findChild(shell, "appContainer");
2446+ var appDelegate = findChild(appContainer, "appDelegate_" + appSurfaceId);
2447+ verify(appDelegate);
2448+ appDelegate.maximize();
2449+ tryCompare(appDelegate, "state", "maximized");
2450+
2451+ mousePress(panel);
2452+ mouseMove(shell, shell.width/2, shell.height/2);
2453+ mouseRelease(shell);
2454+
2455+ tryCompare(appDelegate, "state", "normal");
2456+ }
2430 }
2457 }
2431}
2458}
tests/qmltests/tst_ShellWithPin.qml+1−1
@@ -194,7 +194,7 @@ Item {
194 shellLoader.active = true
194 shellLoader.active = true
195
195
196 tryCompare(shellLoader, "status", Loader.Ready)
196 tryCompare(shellLoader, "status", Loader.Ready)
197− removeTimeConstraintsFromDirectionalDragAreas(shellLoader.item)
197+ removeTimeConstraintsFromSwipeAreas(shellLoader.item)
198 }
198 }
199
199
200 function swipeAwayGreeter(waitForCoverPage) {
200 function swipeAwayGreeter(waitForCoverPage) {
tests/uqmlscene/main.cpp−1
@@ -159,7 +159,6 @@ struct Options
159 bool maximized;
159 bool maximized;
160 bool fullscreen;
160 bool fullscreen;
161 bool transparent;
161 bool transparent;
162− bool scenegraphOnGraphicsview;
163 bool clip;
162 bool clip;
164 bool versionDetection;
163 bool versionDetection;
165 bool quitImmediately;
164 bool quitImmediately;
tests/utils/modules/Unity/Test/CMakeLists.txt+4−2
@@ -2,10 +2,12 @@ include(QmlPlugins)
2
2
3add_definitions(-DQT_NO_KEYWORDS)
3add_definitions(-DQT_NO_KEYWORDS)
4
4
5+pkg_check_modules(UBUNTUGESTURES REQUIRED UbuntuGestures)
6+
5include_directories(
7include_directories(
6 ${Qt5Gui_PRIVATE_INCLUDE_DIRS}
8 ${Qt5Gui_PRIVATE_INCLUDE_DIRS}
7 ${Qt5Quick_PRIVATE_INCLUDE_DIRS}
9 ${Qt5Quick_PRIVATE_INCLUDE_DIRS}
8− ${CMAKE_SOURCE_DIR}/libs/UbuntuGestures
10+ ${UBUNTUGESTURES_INCLUDE_DIRS}
9 ${CMAKE_SOURCE_DIR}/src
11 ${CMAKE_SOURCE_DIR}/src
10)
12)
11
13
@@ -20,7 +22,7 @@ if (ENABLE_TOUCH_EMULATION)
20endif()
22endif()
21
23
22add_library(UnityTestQml MODULE ${UnityTestQML_SOURCES})
24add_library(UnityTestQml MODULE ${UnityTestQML_SOURCES})
23−target_link_libraries(UnityTestQml UbuntuGestures)
25+target_link_libraries(UnityTestQml ${UBUNTUGESTURES_LIBRARIES})
24
26
25if (ENABLE_TOUCH_EMULATION)
27if (ENABLE_TOUCH_EMULATION)
26 target_link_libraries(UnityTestQml ${MOUSETOUCHADAPTOR_LIBS_LDFLAGS})
28 target_link_libraries(UnityTestQml ${MOUSETOUCHADAPTOR_LIBS_LDFLAGS})
tests/utils/modules/Unity/Test/UnityTestCase.qml+31−12
@@ -18,6 +18,7 @@ import QtQuick 2.4
18import QtTest 1.0
18import QtTest 1.0
19import Unity.Application 0.1
19import Unity.Application 0.1
20import Ubuntu.Components 1.3
20import Ubuntu.Components 1.3
21+import Ubuntu.Test 1.0 as UbuntuTest
21import Unity.Test 0.1 as UT
22import Unity.Test 0.1 as UT
22import Utils 0.1
23import Utils 0.1
23
24
@@ -175,11 +176,11 @@ TestCase {
175
176
176
177
177 // Find an object with the given name in the children tree of "obj"
178 // Find an object with the given name in the children tree of "obj"
178− function findChild(obj, objectName) {
179+ function findChild(obj, objectName, timeout) {
179 if (!obj)
180 if (!obj)
180 qtest_fail("no obj given", 1);
181 qtest_fail("no obj given", 1);
181
182
182− return findChildIn(obj, "children", objectName);
183+ return findChildInWithTimeout(obj, "children", objectName, timeout);
183 }
184 }
184
185
185 // Find an object with the given name in the children tree of "obj"
186 // Find an object with the given name in the children tree of "obj"
@@ -187,11 +188,30 @@ TestCase {
187 // Note: you should use findChild if you're not sure you need this
188 // Note: you should use findChild if you're not sure you need this
188 // as this tree is much bigger and might contain stuff that goes
189 // as this tree is much bigger and might contain stuff that goes
189 // away randomly.
190 // away randomly.
190− function findInvisibleChild(obj, objectName) {
191+ function findInvisibleChild(obj, objectName, timeout) {
191 if (!obj)
192 if (!obj)
192 qtest_fail("no obj given", 1);
193 qtest_fail("no obj given", 1);
193
194
194− return findChildIn(obj, "data", objectName);
195+ return findChildInWithTimeout(obj, "data", objectName, timeout);
196+ }
197+
198+ // Find a child in the named property with timeout
199+ function findChildInWithTimeout(obj, prop, objectName, timeout) {
200+ if (!obj)
201+ qtest_fail("no obj given", 1);
202+
203+ var timeSpent = 0
204+ if (timeout === undefined)
205+ timeout = 5000;
206+
207+ var child = findChildIn(obj, prop, objectName);
208+
209+ while (timeSpent < timeout && !child) {
210+ wait(50)
211+ timeSpent += 50
212+ child = findChildIn(obj, prop, objectName);
213+ }
214+ return child;
195 }
215 }
196
216
197 // Find a child in the named property
217 // Find a child in the named property
@@ -572,28 +592,27 @@ TestCase {
572 while (rootItem.parent != undefined) {
592 while (rootItem.parent != undefined) {
573 rootItem = rootItem.parent;
593 rootItem = rootItem.parent;
574 }
594 }
575− removeTimeConstraintsFromDirectionalDragAreas(rootItem);
595+ removeTimeConstraintsFromSwipeAreas(rootItem);
576 }
596 }
577
597
578 /*
598 /*
579 In qmltests, sequences of touch events are sent all at once, unlike in "real life".
599 In qmltests, sequences of touch events are sent all at once, unlike in "real life".
580 Also qmltests might run really slowly, e.g. when run from inside virtual machines.
600 Also qmltests might run really slowly, e.g. when run from inside virtual machines.
581 Thus to remove a variable that qmltests cannot really control, namely time, this
601 Thus to remove a variable that qmltests cannot really control, namely time, this
582− function removes all constraints from DirectionalDragAreas that are sensible to
602+ function removes all constraints from SwipeAreas that are sensible to
583 elapsed time.
603 elapsed time.
584
604
585− This effectively makes DirectionalDragAreas easier to fool.
605+ This effectively makes SwipeAreas easier to fool.
586 */
606 */
587− function removeTimeConstraintsFromDirectionalDragAreas(item) {
607+ function removeTimeConstraintsFromSwipeAreas(item) {
588 if (!item)
608 if (!item)
589 qtest_fail("no item given", 1);
609 qtest_fail("no item given", 1);
590
610
591− // use duck-typing to identify a DirectionalDragArea
611+ if (UT.Util.isInstanceOf(item, "UCSwipeArea")) {
592− if (item.removeTimeConstraints != undefined) {
612+ UbuntuTest.TestExtras.removeTimeConstraintsFromSwipeArea(item);
593− item.removeTimeConstraints();
594 } else {
613 } else {
595 for (var i in item.children) {
614 for (var i in item.children) {
596− removeTimeConstraintsFromDirectionalDragAreas(item.children[i]);
615+ removeTimeConstraintsFromSwipeAreas(item.children[i]);
597 }
616 }
598 }
617 }
599 }
618 }
tests/utils/modules/Unity/Test/testutil.cpp+2−2
@@ -22,8 +22,8 @@
22#include <QQuickView>
22#include <QQuickView>
23
23
24// UbuntuGestures lib
24// UbuntuGestures lib
25−#include <TouchRegistry.h>
25+#include <TouchRegistry>
26−#include <Timer.h>
26+#include <Timer>
27
27
28using namespace UbuntuGestures;
28using namespace UbuntuGestures;
29
29
tools/CMakeLists.txt+1−1
@@ -1,7 +1,7 @@
1add_executable(${SCOPE_TOOL}
1add_executable(${SCOPE_TOOL}
2 scopetool.cpp
2 scopetool.cpp
3 registry-tracker.cpp
3 registry-tracker.cpp
4− unix-signal-handler.cpp
4+ ../src/UnixSignalHandler.cpp
5 )
5 )
6
6
7qt5_use_modules(${SCOPE_TOOL} Qml Quick)
7qt5_use_modules(${SCOPE_TOOL} Qml Quick)
tools/scopetool.cpp+1−1
@@ -32,7 +32,7 @@
32// local
32// local
33#include <paths.h>
33#include <paths.h>
34#include "registry-tracker.h"
34#include "registry-tracker.h"
35−#include "unix-signal-handler.h"
35+#include "../src/UnixSignalHandler.h"
36
36
37
37
38int main(int argc, char *argv[])
38int main(int argc, char *argv[])