on xenial help sign in
Merge lp:~unity-team/unity8/dash-as-app
commit6743bb37f413e228eee57f9d6eb7828f736fc225 authorAlbert Astals <albert.astals@canonical.com> dateTue 5 Aug 2014, 18:07 (12 years ago) parent053bf796836fab
62 files changed+1174−908
CMakeLists.txt+1 data/CMakeLists.txt+5−2 data/unity8-dash.conf+22 data/unity8-dash.desktop.in+9 data/unity8.conf+1−7 debian/unity8.install+3 plugins/Unity/CMakeLists.txt+1 plugins/Unity/DashCommunicator/CMakeLists.txt+19 plugins/Unity/DashCommunicator/dashcommunicator.cpp+43 plugins/Unity/DashCommunicator/dashcommunicator.h+35 plugins/Unity/DashCommunicator/dashcommunicatorservice.cpp+30 plugins/Unity/DashCommunicator/dashcommunicatorservice.h+38 plugins/Unity/DashCommunicator/dbusdashcommunicatorservice.cpp+39 plugins/Unity/DashCommunicator/dbusdashcommunicatorservice.h+39 plugins/Unity/DashCommunicator/plugin.cpp+31 plugins/Unity/DashCommunicator/plugin.h+34 plugins/Unity/DashCommunicator/qmldir+3 plugins/Unity/Launcher/launchermodel.cpp+5 po/am.po+10−10 po/el.po+6−6 po/fa.po+51−49 po/hu.po+7−7 po/is.po+6−6 po/km.po+7−7 po/pl.po+7−7 po/pt_BR.po+11−11 po/ru.po+8−8 po/sv.po+6−6 qml/Components/EdgeDemo.qml+5−6 qml/Dash/Dash.qml+7−1 qml/Dash/DashApplication.qml+29 qml/Dash/GenericScopeView.qml+1−1 qml/Dash/ScopeListView.qml−5 qml/Dash/graphics/phone/screenshots/unity8-dash@12.png qml/Launcher/Launcher.qml+2−3 qml/Shell.qml+25−144 qml/Stages/PhoneStage.qml+59−26 qml/Stages/SpreadDelegate.qml+6 qml/Stages/TabletStage.qml+85−41 qml/Stages/TransformedSpreadDelegate.qml+6−5 qml/Stages/TransformedTabletSpreadDelegate.qml+28 src/CMakeLists.txt+1 src/Dash/CMakeLists.txt+13 src/Dash/main.cpp+92 tests/mocks/Unity/Application/ApplicationInfo.cpp−62 tests/mocks/Unity/Application/ApplicationInfo.h−10 tests/mocks/Unity/Application/ApplicationManager.cpp+17−147 tests/mocks/Unity/Application/ApplicationManager.h−16 tests/mocks/Unity/Application/ApplicationScreenshotProvider.cpp+1−1 tests/mocks/Unity/CMakeLists.txt+1 tests/mocks/Unity/DashCommunicator/CMakeLists.txt+18 tests/mocks/Unity/DashCommunicator/dashcommunicator.cpp+37 tests/mocks/Unity/DashCommunicator/dashcommunicator.h+39 tests/mocks/Unity/DashCommunicator/dashcommunicatorservice.cpp+33 tests/mocks/Unity/DashCommunicator/dashcommunicatorservice.h+36 tests/mocks/Unity/DashCommunicator/plugin.cpp+31 tests/mocks/Unity/DashCommunicator/plugin.h+34 tests/mocks/Unity/DashCommunicator/qmldir+3 tests/qmltests/Dash/tst_Dash.qml+19 tests/qmltests/Stages/tst_PhoneStage.qml+3−2 tests/qmltests/tst_Shell.qml+62−275 tests/qmltests/tst_ShellWithPin.qml+4−37
CMakeLists.txt+1
@@ -96,6 +96,7 @@ include(autopilot)
9696declare_autopilot_test(shell unity8.shell ${CMAKE_SOURCE_DIR}/tests/autopilot/)
9797
9898set(SHELL_APP unity8)
99+set(DASH_APP unity8-dash)
99100set(SCOPE_TOOL unity-scope-tool)
100101
101102include_directories(
data/CMakeLists.txt+5−2
@@ -1,7 +1,10 @@
1−# generate desktop file
1+# generate desktop files
22configure_file(${SHELL_APP}.desktop.in ${CMAKE_CURRENT_BINARY_DIR}/${SHELL_APP}.desktop @ONLY)
3+configure_file(${DASH_APP}.desktop.in ${CMAKE_CURRENT_BINARY_DIR}/${DASH_APP}.desktop @ONLY)
34
45# install desktop files
5−install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${SHELL_APP}.desktop
6+install(FILES
7+ ${CMAKE_CURRENT_BINARY_DIR}/${SHELL_APP}.desktop
8+ ${CMAKE_CURRENT_BINARY_DIR}/${DASH_APP}.desktop
69 DESTINATION ${CMAKE_INSTALL_DATADIR}/applications
710 )
data/unity8-dash.confnew file+22
@@ -0,0 +1,22 @@
1+description "Unity Shell v8 Dash"
2+author "Michael Zanetti <michael.zanetti@canonical.com>"
3+
4+emits scope-ui-starting
5+
6+start on started unity8
7+stop on stopping unity8
8+
9+kill timeout 120
10+
11+respawn
12+
13+pre-start script
14+ if [ -z "$UNITY_SCOPES_LIST" ]; then
15+ # FIXME: remove once we have this in dconf
16+ initctl set-env UNITY_SCOPES_LIST="clickscope;musicaggregator;videoaggregator"
17+ fi
18+
19+ initctl emit scope-ui-starting
20+end script
21+
22+exec ${BINARY:-unity8-dash} $ARGS --desktop_file_hint=/usr/share/applications/unity8-dash.desktop
data/unity8-dash.desktop.innew file+9
@@ -0,0 +1,9 @@
1+[Desktop Entry]
2+Type=Application
3+Name=Unity 8 Dash
4+Comment=The converged Unity shell dash
5+Exec=@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_BINDIR@/unity8-dash
6+Terminal=false
7+Icon=unity8
8+NoDisplay=true
9+X-Ubuntu-Touch=true
data/unity8.conf+1−7
@@ -1,7 +1,7 @@
11description "Unity Shell v8"
22author "Ricardo Mendoza <ricmm@ubuntu.com>"
33
4−emits scope-ui-starting indicator-services-start
4+emits indicator-services-start
55
66start on ((xsession SESSION=ubuntu-touch) or (xsession SESSION=ubuntu-touch-surfaceflinger)) and started dbus
77stop on desktop-end
@@ -34,11 +34,6 @@ pre-start script
3434 gdbus call --session --dest org.freedesktop.DBus --object-path /org/freedesktop/DBus --method org.freedesktop.DBus.UpdateActivationEnvironment "@a{ss} {'MIR_SOCKET': '$MIR_SERVER_FILE'}"
3535 fi
3636
37− if [ -z "$UNITY_SCOPES_LIST" ]; then
38− # FIXME: remove once we have this in dconf
39− initctl set-env UNITY_SCOPES_LIST="clickscope;musicaggregator;videoaggregator"
40− fi
41−
4237 # Remove the socket if still there
4338 if [ -S "$MIR_SERVER_FILE" ]; then
4439 rm "$MIR_SERVER_FILE"
@@ -46,7 +41,6 @@ pre-start script
4641
4742 initctl set-env --global MIR_SERVER_PROMPT_FILE=1
4843
49− initctl emit scope-ui-starting
5044 initctl emit --no-wait indicator-services-start
5145end script
5246
debian/unity8.install+3
@@ -1,6 +1,9 @@
11data/unity8.conf usr/share/upstart/sessions/
2+data/unity8-dash.conf usr/share/upstart/sessions/
23usr/bin/unity8
4+usr/bin/unity8-dash
35usr/share/applications/unity8.desktop
6+usr/share/applications/unity8-dash.desktop
47usr/share/unity8/Greeter
58usr/share/unity8/Hud
69usr/share/unity8/Launcher
plugins/Unity/CMakeLists.txt+1
@@ -1,3 +1,4 @@
11add_subdirectory(Indicators)
22add_subdirectory(Launcher)
33add_subdirectory(Session)
4+add_subdirectory(DashCommunicator)
plugins/Unity/DashCommunicator/CMakeLists.txtnew file+19
@@ -0,0 +1,19 @@
1+include_directories(
2+ ${CMAKE_CURRENT_SOURCE_DIR}
3+)
4+
5+set(QMLDASHCOMMUNICATORPLUGIN_SRC
6+ plugin.cpp
7+ dbusdashcommunicatorservice.cpp
8+ dashcommunicatorservice.cpp
9+ dashcommunicator.cpp
10+ )
11+
12+add_library(DashCommunicator-qml MODULE
13+ ${QMLDASHCOMMUNICATORPLUGIN_SRC}
14+ )
15+
16+qt5_use_modules(DashCommunicator-qml DBus Qml)
17+
18+# export the qmldir and qmltypes files
19+add_unity8_plugin(Unity.DashCommunicator 0.1 Unity/DashCommunicator TARGETS DashCommunicator-qml)
plugins/Unity/DashCommunicator/dashcommunicator.cppnew file+43
@@ -0,0 +1,43 @@
1+/*
2+ * Copyright (C) 2014 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+#include "dashcommunicator.h"
18+
19+#include <QObject>
20+#include <QDBusConnection>
21+#include <QDBusInterface>
22+#include <QDebug>
23+
24+DashCommunicator::DashCommunicator(QObject *parent):
25+ QObject(parent)
26+{
27+}
28+
29+DashCommunicator::~DashCommunicator()
30+{
31+}
32+
33+
34+void DashCommunicator::setCurrentScope(const QString &scopeId, bool animate, bool reset)
35+{
36+ QDBusConnection connection = QDBusConnection::sessionBus();
37+ QDBusInterface dashIface ("com.canonical.UnityDash",
38+ "/com/canonical/UnityDash",
39+ "",
40+ connection);
41+
42+ dashIface.call("SetCurrentScope", scopeId, animate, reset);
43+}
plugins/Unity/DashCommunicator/dashcommunicator.hnew file+35
@@ -0,0 +1,35 @@
1+/*
2+ * Copyright (C) 2014 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+#ifndef DASHCOMMUNICATOR_H
18+#define DASHCOMMUNICATOR_H
19+
20+#include <QObject>
21+
22+class DashCommunicator: public QObject
23+{
24+ Q_OBJECT
25+ Q_CLASSINFO("D-Bus Interface", "com.canonical.Unity.DashCommunicator")
26+
27+public:
28+ DashCommunicator(QObject *parent = 0);
29+ ~DashCommunicator();
30+
31+public Q_SLOTS:
32+ void setCurrentScope(const QString &scopeId, bool animate, bool reset);
33+};
34+
35+#endif
plugins/Unity/DashCommunicator/dashcommunicatorservice.cppnew file+30
@@ -0,0 +1,30 @@
1+/*
2+ * Copyright (C) 2014 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+#include "dashcommunicatorservice.h"
18+
19+DashCommunicatorService::DashCommunicatorService(QObject *parent):
20+ QObject(parent),
21+ m_dbusService(new DBusDashCommunicatorService(this))
22+{
23+ connect(m_dbusService, &DBusDashCommunicatorService::setCurrentScopeRequested, this, &DashCommunicatorService::setCurrentScopeRequested);
24+}
25+
26+
27+DashCommunicatorService::~DashCommunicatorService()
28+{
29+
30+}
plugins/Unity/DashCommunicator/dashcommunicatorservice.hnew file+38
@@ -0,0 +1,38 @@
1+/*
2+ * Copyright (C) 2014 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+#ifndef DASHCOMMUNICATORSERVICE_H
18+#define DASHCOMMUNICATORSERVICE_H
19+
20+#include "dbusdashcommunicatorservice.h"
21+
22+#include <QObject>
23+
24+class DashCommunicatorService: public QObject
25+{
26+ Q_OBJECT
27+public:
28+ DashCommunicatorService(QObject *parent = 0);
29+ ~DashCommunicatorService();
30+
31+Q_SIGNALS:
32+ void setCurrentScopeRequested(const QString &scopeId, bool animate, bool reset);
33+
34+private:
35+ DBusDashCommunicatorService *m_dbusService;
36+};
37+
38+#endif // DBUSUNITYSESSIONSERVICE_H
plugins/Unity/DashCommunicator/dbusdashcommunicatorservice.cppnew file+39
@@ -0,0 +1,39 @@
1+/*
2+ * Copyright (C) 2014 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+#include "dbusdashcommunicatorservice.h"
18+
19+#include <QDBusConnection>
20+#include <QDBusInterface>
21+#include <QDebug>
22+
23+DBusDashCommunicatorService::DBusDashCommunicatorService(QObject *parent):
24+ QObject(parent)
25+{
26+ QDBusConnection connection = QDBusConnection::sessionBus();
27+
28+ connection.registerService("com.canonical.UnityDash");
29+ connection.registerObject("/com/canonical/UnityDash", this, QDBusConnection::ExportScriptableSlots);
30+}
31+
32+DBusDashCommunicatorService::~DBusDashCommunicatorService()
33+{
34+}
35+
36+void DBusDashCommunicatorService::SetCurrentScope(const QString &scopeId, bool animate, bool reset)
37+{
38+ Q_EMIT setCurrentScopeRequested(scopeId, animate, reset);
39+}
plugins/Unity/DashCommunicator/dbusdashcommunicatorservice.hnew file+39
@@ -0,0 +1,39 @@
1+/*
2+ * Copyright (C) 2014 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+#ifndef DBUSDASHCOMMUNICATORSERVICE_H
18+#define DBUSDASHCOMMUNICATORSERVICE_H
19+
20+#include <QObject>
21+
22+class DBusDashCommunicatorService: public QObject
23+{
24+ Q_OBJECT
25+ Q_CLASSINFO("D-Bus Interface", "com.canonical.Unity.DashCommunicator")
26+
27+public:
28+ DBusDashCommunicatorService(QObject *parent = 0);
29+ ~DBusDashCommunicatorService();
30+
31+Q_SIGNALS:
32+ void setCurrentScopeRequested(const QString &scopeId, bool animate, bool reset);
33+
34+public Q_SLOTS:
35+ Q_SCRIPTABLE void SetCurrentScope(const QString &scopeId, bool animate, bool reset);
36+
37+};
38+
39+#endif // DBUSUNITYSESSIONSERVICE_H
plugins/Unity/DashCommunicator/plugin.cppnew file+31
@@ -0,0 +1,31 @@
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+ * Authors: Michael Zanetti <michael.zanetti@canonical.com>
17+ */
18+
19+#include "plugin.h"
20+#include "dashcommunicator.h"
21+#include "dashcommunicatorservice.h"
22+
23+#include <QDBusConnection>
24+#include <QtQml/qqml.h>
25+
26+void DashCommunicatorPlugin::registerTypes(const char *uri)
27+{
28+ Q_ASSERT(uri == QStringLiteral("Unity.DashCommunicator"));
29+ qmlRegisterType<DashCommunicatorService>(uri, 0, 1, "DashCommunicatorService");
30+ qmlRegisterType<DashCommunicator>(uri, 0, 1, "DashCommunicator");
31+}
plugins/Unity/DashCommunicator/plugin.hnew file+34
@@ -0,0 +1,34 @@
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+ * Authors: Michael Zanetti <michael.zanetti@canonical.com>
17+ */
18+
19+#ifndef DASHCOMMUNICATOR_PLUGIN_H
20+#define DASHCOMMUNICATOR_PLUGIN_H
21+
22+#include <QtQml/QQmlEngine>
23+#include <QtQml/QQmlExtensionPlugin>
24+
25+class DashCommunicatorPlugin : public QQmlExtensionPlugin
26+{
27+ Q_OBJECT
28+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
29+
30+public:
31+ void registerTypes(const char *uri);
32+};
33+
34+#endif
plugins/Unity/DashCommunicator/qmldirnew file+3
@@ -0,0 +1,3 @@
1+module Unity.DashCommunicator
2+plugin DashCommunicator-qml
3+typeinfo DashCommunicator.qmltypes
plugins/Unity/Launcher/launchermodel.cpp+5
@@ -317,6 +317,11 @@ void LauncherModel::applicationAdded(const QModelIndex &parent, int row)
317317 return;
318318 }
319319
320+ if (app->appId() == "unity8-dash") {
321+ // Not adding the dash app
322+ return;
323+ }
324+
320325 bool found = false;
321326 Q_FOREACH(LauncherItem *item, m_list) {
322327 if (app->appId() == item->appId()) {
po/am.po+10−10
@@ -8,14 +8,14 @@ msgstr ""
88"Project-Id-Version: unity8\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
1010"POT-Creation-Date: 2014-07-11 14:59+0200\n"
11−"PO-Revision-Date: 2014-07-27 01:25+0000\n"
11+"PO-Revision-Date: 2014-08-04 16:30+0000\n"
1212"Last-Translator: samson <Unknown>\n"
1313"Language-Team: Amharic <am@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-28 06:44+0000\n"
18−"X-Generator: Launchpad (build 17131)\n"
17+"X-Launchpad-Export-Date: 2014-08-05 06:45+0000\n"
18+"X-Generator: Launchpad (build 17147)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -36,7 +36,7 @@ msgstr "የቀኝ ጠርዝ"
3636
3737#: qml/Components/EdgeDemo.qml:114
3838msgid "Try swiping from the right edge to unlock the phone"
39−msgstr ""
39+msgstr "ስልኩን ለመክፈት ከ ቀኝ ጠርዝ በኩል ወደ ግራ ይጥረጉ"
4040
4141#: qml/Components/EdgeDemo.qml:145
4242msgid "Top edge"
@@ -44,7 +44,7 @@ msgstr "የላይ ጠርዝ"
4444
4545#: qml/Components/EdgeDemo.qml:146
4646msgid "Try swiping from the top edge to access the indicators"
47−msgstr ""
47+msgstr "ጠቋሚዎች ጋር ለመድረስ ከ ላይ ጠርዝ በኩል ወደ ታች ይጥረጉ"
4848
4949#: qml/Components/EdgeDemo.qml:171
5050msgid "Close"
@@ -52,7 +52,7 @@ msgstr "መዝጊያ"
5252
5353#: qml/Components/EdgeDemo.qml:172
5454msgid "Swipe up again to close the settings screen"
55−msgstr ""
55+msgstr "የማሰናጃውን መመልከቻ ለመዝጋት እንደገና ወደ ላይ ይጥረጉ"
5656
5757#: qml/Components/EdgeDemo.qml:199
5858msgid "Left edge"
@@ -60,11 +60,11 @@ msgstr "የግራ ጠርዝ"
6060
6161#: qml/Components/EdgeDemo.qml:200
6262msgid "Swipe from the left to reveal the launcher for quick access to apps"
63−msgstr ""
63+msgstr "ከ ግራ በኩል ወደ ቀኝ ይጥረጉ በፍጥነት መተግበሪያዎች ጋር ለመድረስ እና ለማስጀመር"
6464
6565#: qml/Components/EdgeDemo.qml:227
6666msgid "Well done"
67−msgstr ""
67+msgstr "ጥሩ አድረገዋል"
6868
6969#: qml/Components/EdgeDemo.qml:228
7070msgid ""
@@ -123,7 +123,7 @@ msgstr "አነስተኛ..."
123123
124124#: qml/Dash/Previews/PreviewRatingInput.qml:81
125125msgid "Rate this"
126−msgstr ""
126+msgstr "ለዚህ ደረጃ ይስጡ"
127127
128128#: qml/Dash/Previews/PreviewRatingInput.qml:126
129129msgid "Add a review"
@@ -135,7 +135,7 @@ msgstr "መላኪያ"
135135
136136#: qml/Greeter/Greeter.qml:157
137137msgid "Swipe to unlock"
138−msgstr ""
138+msgstr "ለመክፈት ይጥረጉ"
139139
140140#: qml/Hud/HudParametrizedActionsPage.qml:132
141141msgid "Confirm"
po/el.po+6−6
@@ -8,14 +8,14 @@ msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
1010"POT-Creation-Date: 2014-07-11 14:59+0200\n"
11−"PO-Revision-Date: 2014-07-28 16:06+0000\n"
12−"Last-Translator: Chris Taklis (aka Kailor) <ctaklis@gmail.com>\n"
11+"PO-Revision-Date: 2014-08-04 18:44+0000\n"
12+"Last-Translator: madvinegar <madvinegar@hotmail.com>\n"
1313"Language-Team: Greek <el@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-29 06:54+0000\n"
18−"X-Generator: Launchpad (build 17131)\n"
17+"X-Launchpad-Export-Date: 2014-08-05 06:45+0000\n"
18+"X-Generator: Launchpad (build 17147)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -171,7 +171,7 @@ msgstr "Παρακαλώ εισάγετε το PIN της κάρτας SIM"
171171
172172#: qml/Panel/ActiveCallHint.qml:77
173173msgid "Tap to return to call..."
174−msgstr ""
174+msgstr "Πατήστε για να γυρίσετε στην κλήση..."
175175
176176#: qml/Panel/ActiveCallHint.qml:90
177177msgid "Conference"
@@ -199,7 +199,7 @@ msgstr "Ολοκληρώθηκε"
199199
200200#: qml/Panel/Indicators/MenuItemFactory.qml:595
201201msgid "Failed, tap to retry"
202−msgstr ""
202+msgstr "Αποτυχία, πατήστε για να ξαναπροσπαθήσετε"
203203
204204#: qml/Panel/SearchIndicator.qml:27
205205msgid "Search"
po/fa.po+51−49
@@ -8,200 +8,202 @@ msgstr ""
88"Project-Id-Version: unity8\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
1010"POT-Creation-Date: 2014-07-11 14:59+0200\n"
11−"PO-Revision-Date: 2013-10-31 19:02+0000\n"
12−"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
11+"PO-Revision-Date: 2014-08-03 13:00+0000\n"
12+"Last-Translator: Arash Badie Modiri <arashbm@gmail.com>\n"
1313"Language-Team: Persian <fa@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-26 07:17+0000\n"
18−"X-Generator: Launchpad (build 17131)\n"
17+"X-Launchpad-Export-Date: 2014-08-04 06:32+0000\n"
18+"X-Generator: Launchpad (build 17147)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
2222msgid "Pin shortcut"
23−msgstr ""
23+msgstr "سنجاق کردن میانبر"
2424
2525#: plugins/Unity/Launcher/launcheritem.cpp:73
2626msgid "Unpin shortcut"
27−msgstr ""
27+msgstr "برداشتن سنجاق میانبر"
2828
2929#: qml/Components/EdgeDemoOverlay.qml:151
3030msgid "Skip intro"
31−msgstr ""
31+msgstr "پرش از مقدّمه"
3232
3333#: qml/Components/EdgeDemo.qml:113
3434msgid "Right edge"
35−msgstr ""
35+msgstr "لبه‌ی راست"
3636
3737#: qml/Components/EdgeDemo.qml:114
3838msgid "Try swiping from the right edge to unlock the phone"
39−msgstr ""
39+msgstr "برای باز کردن قفل تلفن، از لبه‌ی راست بکشید"
4040
4141#: qml/Components/EdgeDemo.qml:145
4242msgid "Top edge"
43−msgstr ""
43+msgstr "لبه‌ی بالا"
4444
4545#: qml/Components/EdgeDemo.qml:146
4646msgid "Try swiping from the top edge to access the indicators"
47−msgstr ""
47+msgstr "برای دست‌رسی به نشانگرها، از لبه‌ی بالا بکشید"
4848
4949#: qml/Components/EdgeDemo.qml:171
5050msgid "Close"
51−msgstr ""
51+msgstr "بستن"
5252
5353#: qml/Components/EdgeDemo.qml:172
5454msgid "Swipe up again to close the settings screen"
55−msgstr ""
55+msgstr "برای بستن صفحه‌ی تنظیمات، دوباره به بالا بکشپد"
5656
5757#: qml/Components/EdgeDemo.qml:199
5858msgid "Left edge"
59−msgstr ""
59+msgstr "لبه‌ی چپ"
6060
6161#: qml/Components/EdgeDemo.qml:200
6262msgid "Swipe from the left to reveal the launcher for quick access to apps"
63−msgstr ""
63+msgstr "برای آشکار شدن اجراگر به منظور دست‌رسی سریع به اپ‌ها از سمت چپ بکشید"
6464
6565#: qml/Components/EdgeDemo.qml:227
6666msgid "Well done"
67−msgstr ""
67+msgstr "عالی بود"
6868
6969#: qml/Components/EdgeDemo.qml:228
7070msgid ""
7171"You have now mastered the edge gestures and can start using the "
7272"phone<br><br>Tap on the screen to start"
7373msgstr ""
74+"هم اکنون در استفاده از ژست های حرکتی مهارت لازم را دارید و می‌توانید استفاده "
75+"از تلفن را آغاز کنید<br><br>برای شروع صفحه را لمس کنید"
7476
7577#: qml/Components/Lockscreen.qml:214
7678msgid "Emergency Call"
77−msgstr ""
79+msgstr "تماس اضطراری"
7880
7981#: qml/Components/Lockscreen.qml:231
8082msgid "OK"
81−msgstr ""
83+msgstr "قبول"
8284
8385#: qml/Components/PassphraseLockscreen.qml:60
8486#, qt-format
8587msgid "Hello %1"
86−msgstr ""
88+msgstr "سلام %1"
8789
8890#: qml/Components/PassphraseLockscreen.qml:60
8991msgid "Hello"
90−msgstr ""
92+msgstr "سلام"
9193
9294#: qml/Components/PinLockscreen.qml:198
9395msgid "CANCEL"
94−msgstr ""
96+msgstr "لغو"
9597
9698#: qml/Components/PinLockscreen.qml:216
9799msgid "DONE"
98−msgstr ""
100+msgstr "انجام شد"
99101
100102#: qml/Components/SeeMore.qml:35
101103msgid "See more"
102−msgstr ""
104+msgstr "بیش‌تر ببینید"
103105
104106#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
105107msgid "See less"
106−msgstr ""
108+msgstr "کم‌تر ببینید"
107109
108110#: qml/Dash/DashApps.qml:37
109111msgid "Recent"
110−msgstr ""
112+msgstr "موارد اخیر"
111113
112114#: qml/Dash/GenericScopeView.qml:330
113115msgid "See all"
114−msgstr ""
116+msgstr "دیدن همه"
115117
116118#: qml/Dash/Previews/PreviewActionCombo.qml:34
117119msgid "More..."
118−msgstr ""
120+msgstr "بیش‌تر…"
119121
120122#: qml/Dash/Previews/PreviewActionCombo.qml:34
121123msgid "Less..."
122−msgstr ""
124+msgstr "کم‌تر…"
123125
124126#: qml/Dash/Previews/PreviewRatingInput.qml:81
125127msgid "Rate this"
126−msgstr ""
128+msgstr "امتیاز دادن"
127129
128130#: qml/Dash/Previews/PreviewRatingInput.qml:126
129131msgid "Add a review"
130−msgstr ""
132+msgstr "افزودن یک بازبینی"
131133
132134#: qml/Dash/Previews/PreviewRatingInput.qml:166
133135msgid "Send"
134−msgstr ""
136+msgstr "ارسال"
135137
136138#: qml/Greeter/Greeter.qml:157
137139msgid "Swipe to unlock"
138−msgstr ""
140+msgstr "برای باز کردن قفل بکشد"
139141
140142#: qml/Hud/HudParametrizedActionsPage.qml:132
141143msgid "Confirm"
142−msgstr ""
144+msgstr "تأیید"
143145
144146#: qml/Hud/Hud.qml:61 qml/Hud/Hud.qml:99 qml/Hud/Hud.qml:372
145147msgid "Type or say a command"
146−msgstr ""
148+msgstr "دستوری را بنویسید یا بگویید"
147149
148150#: qml/Hud/Hud.qml:84
149151msgid "Loading. Please Wait..."
150−msgstr ""
152+msgstr "در حال بار کردن. لطفاً صبر کنید…"
151153
152154#: qml/Hud/Hud.qml:89
153155msgid "Speak Now..."
154−msgstr ""
156+msgstr "اکنون صحبت کنید…"
155157
156158#: qml/Hud/Hud.qml:94
157159msgid "Speaking..."
158−msgstr ""
160+msgstr "در حال صحبت کردن…"
159161
160162#: qml/Notifications/NotificationMenuItemFactory.qml:91
161163msgid "Show password"
162−msgstr ""
164+msgstr "نمایش گذرواژه"
163165
164166#: qml/Notifications/NotificationMenuItemFactory.qml:103
165167msgid "Please enter SIM PIN"
166−msgstr ""
168+msgstr "لطفاً PIN سیم‌کارت را وارد کنید"
167169
168170#: qml/Panel/ActiveCallHint.qml:77
169171msgid "Tap to return to call..."
170−msgstr ""
172+msgstr "برای بازگشت به تماس ضربه بزنید…"
171173
172174#: qml/Panel/ActiveCallHint.qml:90
173175msgid "Conference"
174−msgstr ""
176+msgstr "کنفرانس"
175177
176178#: qml/Panel/Indicators/MenuItemFactory.qml:583
177179msgid "In queue…"
178−msgstr ""
180+msgstr "در صف…"
179181
180182#: qml/Panel/Indicators/MenuItemFactory.qml:587
181183msgid "Downloading"
182−msgstr ""
184+msgstr "در حال بارگیری"
183185
184186#: qml/Panel/Indicators/MenuItemFactory.qml:589
185187msgid "Paused, tap to resume"
186−msgstr ""
188+msgstr "مکث شد، برای از سر گیری ضربه بزنید"
187189
188190#: qml/Panel/Indicators/MenuItemFactory.qml:591
189191msgid "Canceled"
190−msgstr ""
192+msgstr "لغو شد"
191193
192194#: qml/Panel/Indicators/MenuItemFactory.qml:593
193195msgid "Finished"
194−msgstr ""
196+msgstr "پایان یافت"
195197
196198#: qml/Panel/Indicators/MenuItemFactory.qml:595
197199msgid "Failed, tap to retry"
198−msgstr ""
200+msgstr "شکست خورد، برای تلاش دوباره ضربه بزنید"
199201
200202#: qml/Panel/SearchIndicator.qml:27
201203msgid "Search"
202−msgstr ""
204+msgstr "جست‌وجو"
203205
204206#: qml/Shell.qml:359
205207#, qt-format
206208msgid "Please enter %1"
207−msgstr ""
209+msgstr "لطفا %1 را وارد کنید"
po/hu.po+7−7
@@ -8,14 +8,14 @@ msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
1010"POT-Creation-Date: 2014-07-11 14:59+0200\n"
11−"PO-Revision-Date: 2014-07-30 18:42+0000\n"
11+"PO-Revision-Date: 2014-08-04 09:10+0000\n"
1212"Last-Translator: Richard Somlói <ricsipontaz@gmail.com>\n"
1313"Language-Team: Hungarian <hu@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-31 07:15+0000\n"
18−"X-Generator: Launchpad (build 17131)\n"
17+"X-Launchpad-Export-Date: 2014-08-05 06:45+0000\n"
18+"X-Generator: Launchpad (build 17147)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -44,7 +44,7 @@ msgstr "Felső szél"
4444
4545#: qml/Components/EdgeDemo.qml:146
4646msgid "Try swiping from the top edge to access the indicators"
47−msgstr "A jelzők eléréséhez csúsztassa ujját a felső szélről"
47+msgstr "Az állapotmenük eléréséhez csúsztassa ujját a felső szélről"
4848
4949#: qml/Components/EdgeDemo.qml:171
5050msgid "Close"
@@ -82,16 +82,16 @@ msgstr "Vészhívás"
8282
8383#: qml/Components/Lockscreen.qml:231
8484msgid "OK"
85−msgstr "Oké"
85+msgstr "Ok"
8686
8787#: qml/Components/PassphraseLockscreen.qml:60
8888#, qt-format
8989msgid "Hello %1"
90−msgstr "Szia %1"
90+msgstr "Üdv %1"
9191
9292#: qml/Components/PassphraseLockscreen.qml:60
9393msgid "Hello"
94−msgstr "Szia"
94+msgstr "Üdv"
9595
9696#: qml/Components/PinLockscreen.qml:198
9797msgid "CANCEL"
po/is.po+6−6
@@ -10,14 +10,14 @@ msgstr ""
1010"Project-Id-Version: po_unity8-is\n"
1111"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
1212"POT-Creation-Date: 2014-07-11 14:59+0200\n"
13−"PO-Revision-Date: 2014-07-23 05:57+0000\n"
13+"PO-Revision-Date: 2014-07-31 16:10+0000\n"
1414"Last-Translator: Sveinn í Felli <sv1@fellsnet.is>\n"
1515"Language-Team: Icelandic <translation-team-is@lists.sourceforge.net>\n"
1616"MIME-Version: 1.0\n"
1717"Content-Type: text/plain; charset=UTF-8\n"
1818"Content-Transfer-Encoding: 8bit\n"
19−"X-Launchpad-Export-Date: 2014-07-26 07:16+0000\n"
20−"X-Generator: Launchpad (build 17131)\n"
19+"X-Launchpad-Export-Date: 2014-08-01 07:14+0000\n"
20+"X-Generator: Launchpad (build 17141)\n"
2121"Language: is\n"
2222
2323#: plugins/Unity/Launcher/launcheritem.cpp:43
@@ -117,7 +117,7 @@ msgstr "Nýlegt"
117117
118118#: qml/Dash/GenericScopeView.qml:330
119119msgid "See all"
120−msgstr ""
120+msgstr "Sjá allt"
121121
122122#: qml/Dash/Previews/PreviewActionCombo.qml:34
123123msgid "More..."
@@ -173,11 +173,11 @@ msgstr "Settu inn PIN fyrir SIM"
173173
174174#: qml/Panel/ActiveCallHint.qml:77
175175msgid "Tap to return to call..."
176−msgstr ""
176+msgstr "Slá til að svara símtali..."
177177
178178#: qml/Panel/ActiveCallHint.qml:90
179179msgid "Conference"
180−msgstr ""
180+msgstr "Ráðstefna"
181181
182182#: qml/Panel/Indicators/MenuItemFactory.qml:583
183183msgid "In queue…"
po/km.po+7−7
@@ -8,14 +8,14 @@ msgstr ""
88"Project-Id-Version: unity8\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
1010"POT-Creation-Date: 2014-07-11 14:59+0200\n"
11−"PO-Revision-Date: 2014-07-16 01:37+0000\n"
12−"Last-Translator: Khoem Sokhem <khoemsokhem@khmeros.info>\n"
11+"PO-Revision-Date: 2014-08-01 04:02+0000\n"
12+"Last-Translator: Sok Sophea <sksophea@gmail.com>\n"
1313"Language-Team: Khmer <km@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-26 07:16+0000\n"
18−"X-Generator: Launchpad (build 17131)\n"
17+"X-Launchpad-Export-Date: 2014-08-02 06:39+0000\n"
18+"X-Generator: Launchpad (build 17147)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -115,7 +115,7 @@ msgstr "បច្ចុប្បន្ន"
115115
116116#: qml/Dash/GenericScopeView.qml:330
117117msgid "See all"
118−msgstr ""
118+msgstr "មើល​ទាំងអស់"
119119
120120#: qml/Dash/Previews/PreviewActionCombo.qml:34
121121msgid "More..."
@@ -171,11 +171,11 @@ msgstr "បញ្ចូល​កូដ PIN របស់​ស៊ីមកាត"
171171
172172#: qml/Panel/ActiveCallHint.qml:77
173173msgid "Tap to return to call..."
174−msgstr ""
174+msgstr "ប៉ះ​ដើម្បី​ត្រឡប់​ទៅ​ការ​ហៅ..."
175175
176176#: qml/Panel/ActiveCallHint.qml:90
177177msgid "Conference"
178−msgstr ""
178+msgstr "សន្និសីទ"
179179
180180#: qml/Panel/Indicators/MenuItemFactory.qml:583
181181msgid "In queue…"
po/pl.po+7−7
@@ -8,14 +8,14 @@ msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
1010"POT-Creation-Date: 2014-07-11 14:59+0200\n"
11−"PO-Revision-Date: 2014-07-19 14:10+0000\n"
12−"Last-Translator: GTriderXC <gtriderxc@yahoo.com>\n"
11+"PO-Revision-Date: 2014-07-31 13:51+0000\n"
12+"Last-Translator: Michał Radwański <radwanski.michal@outlook.com>\n"
1313"Language-Team: Polish <pl@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-26 07:17+0000\n"
18−"X-Generator: Launchpad (build 17131)\n"
17+"X-Launchpad-Export-Date: 2014-08-01 07:14+0000\n"
18+"X-Generator: Launchpad (build 17141)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -115,7 +115,7 @@ msgstr "Ostatnio używane"
115115
116116#: qml/Dash/GenericScopeView.qml:330
117117msgid "See all"
118−msgstr ""
118+msgstr "Zobacz wszystko"
119119
120120#: qml/Dash/Previews/PreviewActionCombo.qml:34
121121msgid "More..."
@@ -171,11 +171,11 @@ msgstr "Wprowadź kod PIN karty SIM"
171171
172172#: qml/Panel/ActiveCallHint.qml:77
173173msgid "Tap to return to call..."
174−msgstr ""
174+msgstr "Dotknij aby powrócić do połączenia..."
175175
176176#: qml/Panel/ActiveCallHint.qml:90
177177msgid "Conference"
178−msgstr ""
178+msgstr "Konferencja"
179179
180180#: qml/Panel/Indicators/MenuItemFactory.qml:583
181181msgid "In queue…"
po/pt_BR.po+11−11
@@ -8,14 +8,14 @@ msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
1010"POT-Creation-Date: 2014-07-11 14:59+0200\n"
11−"PO-Revision-Date: 2014-07-17 05:46+0000\n"
12−"Last-Translator: Tiago Hillebrandt <tiagohillebrandt@gmail.com>\n"
11+"PO-Revision-Date: 2014-08-04 18:33+0000\n"
12+"Last-Translator: Rafael Neri <Unknown>\n"
1313"Language-Team: Brazilian Portuguese <pt_BR@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-26 07:17+0000\n"
18−"X-Generator: Launchpad (build 17131)\n"
17+"X-Launchpad-Export-Date: 2014-08-05 06:45+0000\n"
18+"X-Generator: Launchpad (build 17147)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -99,7 +99,7 @@ msgstr "CANCELAR"
9999
100100#: qml/Components/PinLockscreen.qml:216
101101msgid "DONE"
102−msgstr ""
102+msgstr "FEITO"
103103
104104#: qml/Components/SeeMore.qml:35
105105msgid "See more"
@@ -115,7 +115,7 @@ msgstr "Recentes"
115115
116116#: qml/Dash/GenericScopeView.qml:330
117117msgid "See all"
118−msgstr ""
118+msgstr "Ver todos"
119119
120120#: qml/Dash/Previews/PreviewActionCombo.qml:34
121121msgid "More..."
@@ -171,11 +171,11 @@ msgstr "Por favor, digite o PIN do cartão SIM"
171171
172172#: qml/Panel/ActiveCallHint.qml:77
173173msgid "Tap to return to call..."
174−msgstr ""
174+msgstr "Toque para retornar para a chamada..."
175175
176176#: qml/Panel/ActiveCallHint.qml:90
177177msgid "Conference"
178−msgstr ""
178+msgstr "Conferência"
179179
180180#: qml/Panel/Indicators/MenuItemFactory.qml:583
181181msgid "In queue…"
@@ -187,7 +187,7 @@ msgstr "Baixando"
187187
188188#: qml/Panel/Indicators/MenuItemFactory.qml:589
189189msgid "Paused, tap to resume"
190−msgstr ""
190+msgstr "Em pausa, toque para continuar"
191191
192192#: qml/Panel/Indicators/MenuItemFactory.qml:591
193193msgid "Canceled"
@@ -195,11 +195,11 @@ msgstr "Cancelado"
195195
196196#: qml/Panel/Indicators/MenuItemFactory.qml:593
197197msgid "Finished"
198−msgstr ""
198+msgstr "Finalizado"
199199
200200#: qml/Panel/Indicators/MenuItemFactory.qml:595
201201msgid "Failed, tap to retry"
202−msgstr ""
202+msgstr "Falhou, toque para tentar novamente"
203203
204204#: qml/Panel/SearchIndicator.qml:27
205205msgid "Search"
po/ru.po+8−8
@@ -8,23 +8,23 @@ msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
1010"POT-Creation-Date: 2014-07-11 14:59+0200\n"
11−"PO-Revision-Date: 2014-07-30 12:49+0000\n"
11+"PO-Revision-Date: 2014-07-31 09:39+0000\n"
1212"Last-Translator: Jay ZDLin <Unknown>\n"
1313"Language-Team: Russian <ru@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-31 07:15+0000\n"
18−"X-Generator: Launchpad (build 17131)\n"
17+"X-Launchpad-Export-Date: 2014-08-01 07:14+0000\n"
18+"X-Generator: Launchpad (build 17141)\n"
1919
2020#: plugins/Unity/Launcher/launcheritem.cpp:43
2121#: plugins/Unity/Launcher/launcheritem.cpp:73
2222msgid "Pin shortcut"
23−msgstr ""
23+msgstr "Закрепить ярлык"
2424
2525#: plugins/Unity/Launcher/launcheritem.cpp:73
2626msgid "Unpin shortcut"
27−msgstr ""
27+msgstr "Изъять ярлык"
2828
2929#: qml/Components/EdgeDemoOverlay.qml:151
3030msgid "Skip intro"
@@ -174,7 +174,7 @@ msgstr "Введите PIN код"
174174
175175#: qml/Panel/ActiveCallHint.qml:77
176176msgid "Tap to return to call..."
177−msgstr ""
177+msgstr "Коснитесь для возврата к вызову..."
178178
179179#: qml/Panel/ActiveCallHint.qml:90
180180msgid "Conference"
@@ -190,7 +190,7 @@ msgstr "Загрузка"
190190
191191#: qml/Panel/Indicators/MenuItemFactory.qml:589
192192msgid "Paused, tap to resume"
193−msgstr ""
193+msgstr "Приостановлено, коснитесь для возобновления"
194194
195195#: qml/Panel/Indicators/MenuItemFactory.qml:591
196196msgid "Canceled"
@@ -202,7 +202,7 @@ msgstr "Завершено"
202202
203203#: qml/Panel/Indicators/MenuItemFactory.qml:595
204204msgid "Failed, tap to retry"
205−msgstr ""
205+msgstr "Сбой, коснитесь для повтора"
206206
207207#: qml/Panel/SearchIndicator.qml:27
208208msgid "Search"
po/sv.po+6−6
@@ -8,14 +8,14 @@ msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
1010"POT-Creation-Date: 2014-07-11 14:59+0200\n"
11−"PO-Revision-Date: 2014-07-25 14:27+0000\n"
12−"Last-Translator: Josef Andersson <Unknown>\n"
11+"PO-Revision-Date: 2014-07-31 08:10+0000\n"
12+"Last-Translator: Peter Hultqvist <phq@silentorbit.com>\n"
1313"Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-07-26 07:17+0000\n"
18−"X-Generator: Launchpad (build 17131)\n"
17+"X-Launchpad-Export-Date: 2014-08-01 07:14+0000\n"
18+"X-Generator: Launchpad (build 17141)\n"
1919"Language: sv\n"
2020
2121#: plugins/Unity/Launcher/launcheritem.cpp:43
@@ -102,11 +102,11 @@ msgstr "KLAR"
102102
103103#: qml/Components/SeeMore.qml:35
104104msgid "See more"
105−msgstr "Se mer"
105+msgstr "Visa mer"
106106
107107#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
108108msgid "See less"
109−msgstr "Se mindre"
109+msgstr "Visa mindre"
110110
111111#: qml/Dash/DashApps.qml:37
112112msgid "Recent"
qml/Components/EdgeDemo.qml+5−6
@@ -22,7 +22,6 @@ Item {
2222 id: demo
2323
2424 property Item greeter
25− property Item dash
2625 property Item launcher
2726 property Item indicators
2827 property Item underlay
@@ -144,7 +143,7 @@ Item {
144143 "edge": "top",
145144 "title": i18n.tr("Top edge"),
146145 "text": i18n.tr("Try swiping from the top edge to access the indicators"),
147− "anchors.fill": demo.dash,
146+ "anchors.fill": demo.underlay,
148147 });
149148 }
150149 if (d.topEdgeDemo) {
@@ -193,12 +192,12 @@ Item {
193192 function startLeftEdgeDemo() {
194193 demo.panelEnabled = false;
195194 demo.launcherEnabled = true;
196− if (demo.dash && demo.underlay) {
195+ if (demo.underlay) {
197196 d.leftEdgeDemo = d.overlay.createObject(demo.underlay, {
198197 "edge": "left",
199198 "title": i18n.tr("Left edge"),
200199 "text": i18n.tr("Swipe from the left to reveal the launcher for quick access to apps"),
201− "anchors.fill": demo.dash,
200+ "anchors.fill": demo.underlay,
202201 });
203202 }
204203 if (d.leftEdgeDemo) {
@@ -221,12 +220,12 @@ Item {
221220
222221 function startFinalEdgeDemo() {
223222 demo.launcherEnabled = false;
224− if (demo.dash && demo.underlay) {
223+ if (demo.underlay) {
225224 d.finalEdgeDemo = d.overlay.createObject(demo.underlay, {
226225 "edge": "none",
227226 "title": i18n.tr("Well done"),
228227 "text": i18n.tr("You have now mastered the edge gestures and can start using the phone<br><br>Tap on the screen to start"),
229− "anchors.fill": demo.dash,
228+ "anchors.fill": demo.underlay,
230229 "showSkip": false,
231230 });
232231 }
qml/Dash/Dash.qml+7−1
@@ -19,6 +19,7 @@ import Ubuntu.Components 0.1
1919import Ubuntu.Gestures 0.1
2020import Unity 0.2
2121import Utils 0.1
22+import Unity.DashCommunicator 0.1
2223import "../Components"
2324
2425Showable {
@@ -30,7 +31,12 @@ Showable {
3031 property string showScopeOnLoaded: "clickscope"
3132 property real contentScale: 1.0
3233
33− property alias overviewHandleHeight: overviewDragHandle.height
34+ DashCommunicatorService {
35+ objectName: "dashCommunicatorService"
36+ onSetCurrentScopeRequested: {
37+ dash.setCurrentScope(scopeId, animate, reset)
38+ }
39+ }
3440
3541 function setCurrentScope(scopeId, animate, reset) {
3642 var scopeIndex = filteredScopes.findFirst(Scopes.RoleId, scopeId)
qml/Dash/DashApplication.qmlnew file+29
@@ -0,0 +1,29 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.2
18+import Ubuntu.Components 1.0
19+
20+MainView {
21+ width: units.gu(40)
22+ height: units.gu(71)
23+
24+ useDeprecatedToolbar: false
25+
26+ Dash {
27+ anchors.fill: parent
28+ }
29+}
qml/Dash/GenericScopeView.qml+1−1
@@ -48,7 +48,7 @@ FocusScope {
4848 }
4949
5050 function activateApp(appId) {
51− shell.activateApplication(appId);
51+ Qt.openUrlExternally(appId);
5252 }
5353
5454 function positionAtBeginning() {
qml/Dash/ScopeListView.qml−5
@@ -20,9 +20,4 @@ import Dash 0.1
2020ListViewWithPageHeader {
2121 maximumFlickVelocity: height * 10
2222 flickDeceleration: height * 2
23−
24− Connections {
25− target: greeter
26− onShownChanged: if (greeter.shown) showHeader()
27− }
2823}
qml/Dash/graphics/phone/screenshots/unity8-dash@12.pngnew file

Binary file not shown.

qml/Launcher/Launcher.qml+2−3
@@ -29,8 +29,7 @@ Item {
2929 property int dragAreaWidth: units.gu(1)
3030 property int minimizeDistance: units.gu(26)
3131 property real progress: dragArea.dragging && dragArea.touchX > panelWidth ?
32− (width * (dragArea.touchX-panelWidth) / (width - panelWidth)) :
33− (dragArea.dragging ? 0.001 : 0)
32+ (width * (dragArea.touchX-panelWidth) / (width - panelWidth)) : 0
3433
3534 readonly property bool shown: panel.x > -panel.width
3635
@@ -245,7 +244,7 @@ Item {
245244 if (!dragging) {
246245 if (distance > panel.width / 2) {
247246 if (distance > minimizeDistance) {
248− root.dash()
247+ root.dash();
249248 } else {
250249 root.switchToNextState("visible")
251250 }
qml/Shell.qml+25−144
@@ -25,7 +25,6 @@ import Utils 0.1
2525import LightDM 0.1 as LightDM
2626import Powerd 0.1
2727import SessionBroadcast 0.1
28−import "Dash"
2928import "Greeter"
3029import "Launcher"
3130import "Panel"
@@ -34,6 +33,7 @@ import "Notifications"
3433import "Stages"
3534import Unity.Notifications 1.0 as NotificationBackend
3635import Unity.Session 0.1
36+import Unity.DashCommunicator 0.1
3737
3838Item {
3939 id: shell
@@ -48,8 +48,6 @@ Item {
4848 property url background
4949 readonly property real panelHeight: panel.panelHeight
5050
51− property bool dashShown: dash.shown && dash.available && underlay.visible
52−
5351 property bool sideStageEnabled: shell.width >= units.gu(100)
5452 readonly property string focusedApplicationId: ApplicationManager.focusedApplicationId
5553
@@ -59,7 +57,6 @@ Item {
5957 } else {
6058 var execFlags = shell.sideStageEnabled ? ApplicationManager.NoFlag : ApplicationManager.ForceMainStage;
6159 ApplicationManager.startApplication(appId, execFlags);
62− stages.show();
6360 }
6461 }
6562
@@ -86,6 +83,11 @@ Item {
8683 id: volumeControl
8784 }
8885
86+ DashCommunicator {
87+ id: dash
88+ objectName: "dashCommunicator"
89+ }
90+
8991 WindowKeysFilter {
9092 // Handle but do not filter out volume keys
9193 Keys.onVolumeUpPressed: { volumeControl.volumeUp(); event.accepted = false; }
@@ -110,125 +112,12 @@ Item {
110112 }
111113 }
112114
113− Item {
114− id: underlay
115− objectName: "underlay"
116− anchors.fill: parent
117−
118− // Whether the underlay is fully covered by opaque UI elements.
119− property bool fullyCovered: (panel.indicators.fullyOpened && shell.width <= panel.indicatorsMenuWidth)
120− || stages.fullyShown || greeterWrapper.fullyShown
121− visible: !fullyCovered
122−
123− Dash {
124− id: dash
125− objectName: "dash"
126−
127− available: !LightDM.Greeter.active
128− hides: [stages, launcher, panel.indicators]
129− shown: disappearingAnimationProgress !== 1.0 && greeterWrapper.showProgress !== 1.0 &&
130− !(panel.indicators.fullyOpened && !sideStageEnabled)
131− enabled: disappearingAnimationProgress === 0.0 && greeterWrapper.showProgress === 0.0 && edgeDemo.dashEnabled
132−
133− overviewHandleHeight: shell.edgeSize
134−
135− anchors {
136− fill: parent
137− topMargin: panel.panelHeight
138− }
139−
140− contentScale: 1.0 - 0.2 * disappearingAnimationProgress
141− opacity: 1.0 - disappearingAnimationProgress
142− property real disappearingAnimationProgress: stages.showProgress
143−
144− // FIXME: only necessary because stages.showProgress is not animated
145− Behavior on disappearingAnimationProgress { SmoothedAnimation { velocity: 5 }}
146− }
147− }
148−
149− EdgeDragArea {
150− id: stagesDragArea
151− direction: Direction.Leftwards
152−
153− anchors { top: parent.top; right: parent.right; bottom: parent.bottom }
154− width: shell.edgeSize
155−
156− property real progress: stages.width
157−
158− onTouchXChanged: {
159− if (status == DirectionalDragArea.Recognized) {
160− if (ApplicationManager.empty) {
161− progress = Math.max(stages.width - stagesDragArea.width + touchX, stages.width * .3);
162− } else {
163− progress = stages.width - stagesDragArea.width + touchX;
164− }
165− }
166− }
167−
168− onDraggingChanged: {
169− if (!dragging) {
170− if (!ApplicationManager.empty && progress < stages.width - units.gu(10)) {
171− stages.show();
172− }
173− stagesDragArea.progress = Qt.binding(function () { return stages.width; });
174− }
175− }
176− }
177−
178115 Item {
179116 id: stages
180117 objectName: "stages"
181118 width: parent.width
182119 height: parent.height
183−
184− visible: !fullyHidden && !ApplicationManager.empty
185−
186− x: {
187− if (shown) {
188− if (locked || greeter.fakeActiveForApp !== "") {
189− return 0;
190− }
191− return launcher.progress;
192− } else {
193− return stagesDragArea.progress
194− }
195− }
196− Behavior on x { SmoothedAnimation { velocity: 600; duration: UbuntuAnimation.FastDuration } }
197−
198− property bool shown: false
199− onShownChanged: {
200− if (shown) {
201− if (ApplicationManager.count > 0) {
202− ApplicationManager.focusApplication(ApplicationManager.get(0).appId);
203− }
204− } else {
205− if (ApplicationManager.focusedApplicationId) {
206− ApplicationManager.updateScreenshot(ApplicationManager.focusedApplicationId);
207− ApplicationManager.unfocusCurrentApplication();
208− }
209− }
210− }
211−
212− // Avoid a silent "divide by zero -> NaN" situation during init as shell.width will be
213− // zero. That breaks the property binding and the function won't be reevaluated once
214− // shell.width is set, with the NaN result staying there for good.
215− property real showProgress: shell.width ? MathUtils.clamp(1 - x / shell.width, 0, 1) : 0
216−
217− property bool fullyShown: x == 0
218− property bool fullyHidden: x == width
219−
220− property bool locked: applicationsDisplayLoader.item ? applicationsDisplayLoader.item.locked : false
221−
222− // It might technically not be fullyShown but visually it just looks so.
223− property bool roughlyFullyShown: x >= 0 && x <= units.gu(1)
224−
225− function show() {
226− shown = true;
227− }
228−
229− function hide() {
230− shown = false;
231− }
120+ visible: !ApplicationManager.empty
232121
233122 Connections {
234123 target: ApplicationManager
@@ -237,7 +126,6 @@ Item {
237126 lockscreen.show();
238127 }
239128 greeter.hide();
240− stages.show();
241129 }
242130
243131 onFocusedApplicationIdChanged: {
@@ -248,18 +136,9 @@ Item {
248136 }
249137
250138 onApplicationAdded: {
251− if (greeter.shown) {
139+ if (greeter.shown && appId != "unity8-dash") {
252140 greeter.hide();
253141 }
254− if (!stages.shown) {
255− stages.show();
256− }
257− }
258−
259− onEmptyChanged: {
260− if (ApplicationManager.empty) {
261− stages.hide();
262− }
263142 }
264143 }
265144
@@ -288,14 +167,18 @@ Item {
288167 Binding {
289168 target: applicationsDisplayLoader.item
290169 property: "interactive"
291− value: stages.roughlyFullyShown && !greeter.shown && !lockscreen.shown
292− && panel.indicators.fullyClosed
170+ value: !greeter.shown && !lockscreen.shown && panel.indicators.fullyClosed && launcher.progress == 0
293171 }
294172 Binding {
295173 target: applicationsDisplayLoader.item
296174 property: "spreadEnabled"
297175 value: greeter.fakeActiveForApp === "" // to support emergency dialer hack
298176 }
177+ Binding {
178+ target: applicationsDisplayLoader.item
179+ property: "inverseProgress"
180+ value: launcher.progress
181+ }
299182 }
300183 }
301184
@@ -525,25 +408,20 @@ Item {
525408
526409 var animate = !LightDM.Greeter.active && !stages.shown
527410 dash.setCurrentScope("clickscope", animate, false)
528− stages.hide()
411+ ApplicationManager.requestFocusApplication("unity8-dash")
529412 }
530413
531414 function showDash() {
532415 if (LightDM.Greeter.active && !LightDM.Greeter.promptless) {
533416 return;
534417 }
535−
536− if (!stages.locked) {
537− stages.hide();
538− launcher.fadeOut();
539− } else {
540− launcher.switchToNextState("visible");
541− }
542−
543418 if (greeter.shown) {
544419 greeter.hideRight();
545420 launcher.fadeOut();
546421 }
422+
423+ ApplicationManager.requestFocusApplication("unity8-dash")
424+ launcher.fadeOut();
547425 }
548426
549427 Item {
@@ -568,8 +446,8 @@ Item {
568446 ApplicationManager.focusedApplicationId &&
569447 ApplicationManager.findApplication(ApplicationManager.focusedApplicationId).fullscreen
570448
571− fullscreenMode: (stages.roughlyFullyShown && topmostApplicationIsFullscreen
572− && !LightDM.Greeter.active) || greeter.fakeActiveForApp !== ""
449+ fullscreenMode: (topmostApplicationIsFullscreen && !LightDM.Greeter.active && launcher.progress == 0)
450+ || greeter.fakeActiveForApp !== ""
573451 }
574452
575453 Launcher {
@@ -586,7 +464,11 @@ Item {
586464
587465 onShowDashHome: showHome()
588466 onDash: showDash()
589− onDashSwipeChanged: if (dashSwipe && stages.shown) dash.setCurrentScope("clickscope", false, true)
467+ onDashSwipeChanged: {
468+ if (dashSwipe && ApplicationManager.focusedApplicationId !== "unity8-dash") {
469+ dash.setCurrentScope("clickscope", false, true)
470+ }
471+ }
590472 onLauncherApplicationSelected: {
591473 if (greeter.fakeActiveForApp !== "") {
592474 lockscreen.show()
@@ -678,7 +560,6 @@ Item {
678560 z: alphaDisclaimerLabel.z + 10
679561 greeter: greeter
680562 launcher: launcher
681− dash: dash
682563 indicators: panel.indicators
683564 underlay: underlay
684565 }
qml/Stages/PhoneStage.qml+59−26
@@ -21,7 +21,7 @@ import Unity.Application 0.1
2121import Utils 0.1
2222import "../Components"
2323
24−Item {
24+Rectangle {
2525 id: root
2626
2727 // Controls to be set from outside
@@ -29,9 +29,9 @@ Item {
2929 property real maximizedAppTopMargin
3030 property bool interactive
3131 property bool spreadEnabled: true // If false, animations and right edge will be disabled
32+ property real inverseProgress: 0 // This is the progress for left edge drags, in pixels.
3233
33− // State information propagated to the outside
34− readonly property bool locked: spreadView.phase == 2
34+ color: "black"
3535
3636 function select(appId) {
3737 spreadView.snapTo(priv.indexOf(appId));
@@ -43,6 +43,16 @@ Item {
4343 spreadView.contentX = -spreadView.shift;
4444 }
4545
46+ onInverseProgressChanged: {
47+ if (inverseProgress == 0 && priv.oldInverseProgress > 0) {
48+ // left edge drag released. Minimum distance is given by design.
49+ if (priv.oldInverseProgress > units.gu(22)) {
50+ ApplicationManager.focusApplication("unity8-dash");
51+ }
52+ }
53+ priv.oldInverseProgress = inverseProgress;
54+ }
55+
4656 Connections {
4757 target: ApplicationManager
4858
@@ -50,7 +60,7 @@ Item {
5060 if (spreadView.phase > 0) {
5161 spreadView.snapTo(priv.indexOf(appId));
5262 } else {
53− priv.switchToApp(appId);
63+ ApplicationManager.focusApplication(appId);
5464 }
5565 }
5666
@@ -60,7 +70,7 @@ Item {
6070 } else {
6171 spreadView.phase = 0;
6272 spreadView.contentX = -spreadView.shift;
63− priv.switchToApp(appId);
73+ ApplicationManager.focusApplication(appId);
6474 }
6575 }
6676
@@ -79,15 +89,11 @@ Item {
7989
8090 property string focusedAppId: ApplicationManager.focusedApplicationId
8191 property var focusedApplication: ApplicationManager.findApplication(focusedAppId)
92+ property var focusedAppDelegate: null
8293
83− function switchToApp(appId) {
84− if (priv.focusedAppId) {
85− spreadView.focusChanging = true;
86− ApplicationManager.focusApplication(appId);
87− } else {
88− ApplicationManager.focusApplication(appId);
89− }
90− }
94+ property real oldInverseProgress: 0
95+
96+ onFocusedAppIdChanged: focusedAppDelegate = spreadRepeater.itemAt(0);
9197
9298 function indexOf(appId) {
9399 for (var i = 0; i < ApplicationManager.count; i++) {
@@ -100,14 +106,6 @@ Item {
100106
101107 }
102108
103− Rectangle {
104− id: coverFlipBackground
105− anchors.fill: parent
106− color: "black"
107− visible: spreadView.visible
108− }
109−
110−
111109 Flickable {
112110 id: spreadView
113111 objectName: "spreadView"
@@ -116,6 +114,10 @@ Item {
116114 contentWidth: spreadRow.width - shift
117115 contentX: -shift
118116
117+ // This indicates when the spreadView is active. That means, all the animations
118+ // are activated and tiles need to line up for the spread.
119+ readonly property bool active: shiftedContentX > 0 || spreadDragArea.dragging
120+
119121 // The flickable needs to fill the screen in order to get touch events all over.
120122 // However, we don't want to the user to be able to scroll back all the way. For
121123 // that, the beginning of the gesture starts with a negative value for contentX
@@ -198,6 +200,12 @@ Item {
198200 snapAnimation.start();
199201 }
200202
203+ // In case the ApplicationManager already holds an app when starting up we're missing animations
204+ // Make sure we end up in the same state
205+ Component.onCompleted: {
206+ spreadView.contentX = -spreadView.shift
207+ }
208+
201209 SequentialAnimation {
202210 id: snapAnimation
203211 property int targetContentX: -spreadView.shift
@@ -260,14 +268,33 @@ Item {
260268 && spreadView.shiftedContentX === 0 && root.interactive && index === 0
261269 swipeToCloseEnabled: spreadView.interactive
262270 maximizedAppTopMargin: root.maximizedAppTopMargin
263− dropShadow: spreadView.shiftedContentX > 0 || spreadDragArea.status == DirectionalDragArea.Undecided
271+ dropShadow: spreadView.active ||
272+ priv.focusedAppDelegate.x !== 0
273+
274+ readonly property bool isDash: model.appId == "unity8-dash"
275+
276+ z: isDash && !spreadView.active ? -1 : behavioredIndex
264277
265− z: behavioredIndex
266− x: index == 0 ? 0 : spreadView.width + (index - 1) * spreadView.tileDistance
278+ x: {
279+ // focused app is always positioned at 0 except when following left edge drag
280+ if (index == 0) {
281+ if (!isDash && root.inverseProgress > 0) {
282+ return root.inverseProgress;
283+ }
284+ return 0;
285+ }
286+ if (isDash && !spreadView.active && !spreadDragArea.dragging) {
287+ return 0;
288+ }
289+
290+ // Otherwise line up for the spread
291+ return spreadView.width + (index - 1) * spreadView.tileDistance;
292+ }
267293 property real behavioredIndex: index
268294 Behavior on behavioredIndex {
269295 enabled: spreadView.closingIndex >= 0
270296 UbuntuNumberAnimation {
297+ id: appXAnimation
271298 onRunningChanged: {
272299 if (!running) {
273300 spreadView.closingIndex = -1;
@@ -277,11 +304,13 @@ Item {
277304 }
278305
279306 Behavior on x {
280− enabled: spreadView.focusChanging && index == 0 && root.spreadEnabled
307+ enabled: root.spreadEnabled &&
308+ !spreadView.active &&
309+ !snapAnimation.running
281310 UbuntuNumberAnimation {
282311 duration: UbuntuAnimation.FastDuration
283312 onRunningChanged: {
284− if (!running) {
313+ if (!running && root.inverseProgress == 0) {
285314 spreadView.focusChanging = false;
286315 }
287316 }
@@ -322,6 +351,10 @@ Item {
322351 return progress;
323352 }
324353
354+ // Hiding tiles when their progress is negative or reached the maximum
355+ visible: (progress >= 0 && progress < 1.7) ||
356+ (isDash && priv.focusedAppDelegate.x !== 0)
357+
325358 EasingCurve {
326359 id: snappingCurve
327360 type: EasingCurve.Linear
qml/Stages/SpreadDelegate.qml+6
@@ -37,6 +37,7 @@ Item {
3737
3838 SurfaceContainer {
3939 id: surfaceContainer
40+ objectName: "surfaceContainer"
4041 anchors.fill: parent
4142 surface: model.surface
4243 property bool appHasCreatedASurface: false
@@ -172,6 +173,11 @@ Item {
172173 }
173174
174175 onDragEnd: {
176+ if (model.appId == "unity8-dash") {
177+ animation.animate("center")
178+ return;
179+ }
180+
175181 // velocity and distance values specified by design prototype
176182 if ((dragVelocity < -units.gu(40) && distance < -units.gu(8)) || distance < -root.height / 2) {
177183 animation.animate("up")
qml/Stages/TabletStage.qml+85−41
@@ -21,10 +21,11 @@ import Unity.Application 0.1
2121import Utils 0.1
2222import "../Components"
2323
24−Item {
24+Rectangle {
2525 id: root
2626 objectName: "stages"
2727 anchors.fill: parent
28+ color: "black"
2829
2930 // Controls to be set from outside
3031 property bool shown: false
@@ -32,9 +33,17 @@ Item {
3233 property int dragAreaWidth
3334 property real maximizedAppTopMargin
3435 property bool interactive
36+ property real inverseProgress: 0 // This is the progress for left edge drags, in pixels.
3537
36− // State information propagated to the outside
37− readonly property bool locked: spreadView.phase == 2
38+ onInverseProgressChanged: {
39+ if (inverseProgress == 0 && priv.oldInverseProgress > 0) {
40+ // left edge drag released. Minimum distance is given by design.
41+ if (priv.oldInverseProgress > units.gu(22)) {
42+ ApplicationManager.focusApplication("unity8-dash");
43+ }
44+ }
45+ priv.oldInverseProgress = inverseProgress;
46+ }
3847
3948 QtObject {
4049 id: priv
@@ -49,6 +58,8 @@ Item {
4958 property string appId0
5059 property string appId1
5160
61+ property int oldInverseProgress: 0
62+
5263 onFocusedAppIdChanged: {
5364 if (priv.focusedAppId.length > 0) {
5465 var focusedApp = ApplicationManager.findApplication(focusedAppId);
@@ -107,16 +118,26 @@ Item {
107118 }
108119 }
109120
121+ onApplicationAdded: {
122+ if (spreadView.phase == 2) {
123+ spreadView.snapTo(ApplicationManager.count - 1);
124+ } else {
125+ spreadView.phase = 0;
126+ spreadView.contentX = -spreadView.shift;
127+ ApplicationManager.focusApplication(appId);
128+ }
129+ }
130+
110131 onApplicationRemoved: {
111132 if (priv.mainStageAppId == appId) {
112− priv.mainStageAppId = "";
133+ ApplicationManager.focusApplication("unity8-dash")
113134 }
114135 if (priv.sideStageAppId == appId) {
115136 priv.sideStageAppId = "";
116137 }
117138 if (ApplicationManager.count == 0) {
118139 spreadView.phase = 0;
119− spreadView.contentX = 0;
140+ spreadView.contentX = -spreadView.shift;
120141 }
121142 }
122143 }
@@ -124,13 +145,26 @@ Item {
124145 Flickable {
125146 id: spreadView
126147 anchors.fill: parent
127− contentWidth: spreadRow.width
128148 interactive: (spreadDragArea.status == DirectionalDragArea.Recognized || phase > 1) && draggedIndex == -1
149+ contentWidth: spreadRow.width - shift
150+ contentX: -shift
129151
130152 property int tileDistance: units.gu(20)
131153 property int sideStageWidth: units.gu(40)
132154 property bool sideStageVisible: priv.sideStageAppId
133155
156+ // This indicates when the spreadView is active. That means, all the animations
157+ // are activated and tiles need to line up for the spread.
158+ readonly property bool active: shiftedContentX > 0 || spreadDragArea.dragging
159+
160+ // The flickable needs to fill the screen in order to get touch events all over.
161+ // However, we don't want to the user to be able to scroll back all the way. For
162+ // that, the beginning of the gesture starts with a negative value for contentX
163+ // so the flickable wants to pull it into the view already. "shift" tunes the
164+ // distance where to "lock" the content.
165+ readonly property real shift: width / 2
166+ readonly property real shiftedContentX: contentX + shift
167+
134168 // Phase of the animation:
135169 // 0: Starting from right edge, a new app (index 1) comes in from the right
136170 // 1: The app has reached the first snap position.
@@ -168,6 +202,12 @@ Item {
168202 }
169203 }
170204
205+ // In case the ApplicationManager already holds an app when starting up we're missing animations
206+ // Make sure we end up in the same state
207+ Component.onCompleted: {
208+ spreadView.contentX = -spreadView.shift
209+ }
210+
171211 property int nextInStack: {
172212 switch (state) {
173213 case "main":
@@ -224,31 +264,31 @@ Item {
224264 return "empty";
225265 }
226266
227− onContentXChanged: {
228− if (spreadView.phase == 0 && spreadView.contentX > spreadView.width * spreadView.positionMarker2) {
267+ onShiftedContentXChanged: {
268+ if (spreadView.phase == 0 && spreadView.shiftedContentX > spreadView.width * spreadView.positionMarker2) {
229269 spreadView.phase = 1;
230− } else if (spreadView.phase == 1 && spreadView.contentX > spreadView.width * spreadView.positionMarker4) {
270+ } else if (spreadView.phase == 1 && spreadView.shiftedContentX > spreadView.width * spreadView.positionMarker4) {
231271 spreadView.phase = 2;
232− } else if (spreadView.phase == 1 && spreadView.contentX < spreadView.width * spreadView.positionMarker2) {
272+ } else if (spreadView.phase == 1 && spreadView.shiftedContentX < spreadView.width * spreadView.positionMarker2) {
233273 spreadView.phase = 0;
234274 }
235275 }
236276
237277 function snap() {
238− if (contentX < phase0Width) {
239− snapAnimation.targetContentX = 0;
278+ if (shiftedContentX < phase0Width) {
279+ snapAnimation.targetContentX = -shift;
240280 snapAnimation.start();
241− } else if (contentX < phase1Width) {
281+ } else if (shiftedContentX < phase1Width) {
242282 snapTo(1);
243283 } else {
244284 // Add 1 pixel to make sure we definitely hit positionMarker4 even with rounding errors of the animation.
245− snapAnimation.targetContentX = spreadView.width * spreadView.positionMarker4 + 1;
285+ snapAnimation.targetContentX = spreadView.width * spreadView.positionMarker4 + 1 - shift;
246286 snapAnimation.start();
247287 }
248288 }
249289 function snapTo(index) {
250290 spreadView.selectedIndex = index;
251− snapAnimation.targetContentX = 0;
291+ snapAnimation.targetContentX = -shift;
252292 snapAnimation.start();
253293 }
254294
@@ -261,12 +301,12 @@ Item {
261301 return index;
262302 }
263303
264− var isActive = app.appId == priv.mainStageAppId || app.appId == priv.sideStageAppId;
265− if (isActive && app.stage == ApplicationInfoInterface.MainStage) {
304+ var active = app.appId == priv.mainStageAppId || app.appId == priv.sideStageAppId;
305+ if (active && app.stage == ApplicationInfoInterface.MainStage) {
266306 // if this app is active, and its the MainStage, always put it to index 0
267307 return 0;
268308 }
269− if (isActive && app.stage == ApplicationInfoInterface.SideStage) {
309+ if (active && app.stage == ApplicationInfoInterface.SideStage) {
270310 if (!priv.mainStageAppId) {
271311 // Only have SS apps running. Put the active one at 0
272312 return 0;
@@ -309,7 +349,7 @@ Item {
309349
310350 SequentialAnimation {
311351 id: snapAnimation
312− property int targetContentX: 0
352+ property int targetContentX: -spreadView.shift
313353
314354 UbuntuNumberAnimation {
315355 target: spreadView
@@ -325,15 +365,14 @@ Item {
325365 spreadView.selectedIndex = -1;
326366 ApplicationManager.focusApplication(ApplicationManager.get(newIndex).appId);
327367 spreadView.phase = 0;
328− spreadView.contentX = 0;
368+ spreadView.contentX = -spreadView.shift;
329369 }
330370 }
331371 }
332372 }
333373
334− Rectangle {
374+ Item {
335375 id: spreadRow
336− color: "black"
337376 x: spreadView.contentX
338377 height: root.height
339378 width: spreadView.width + Math.max(spreadView.width, ApplicationManager.count * spreadView.tileDistance)
@@ -380,7 +419,7 @@ Item {
380419 MouseArea {
381420 id: sideStageDragHandleMouseArea
382421 anchors.fill: parent
383− enabled: spreadView.contentX == 0
422+ enabled: spreadView.shiftedContentX == 0
384423 property int startX
385424 property var gesturePoints: new Array()
386425
@@ -413,7 +452,7 @@ Item {
413452
414453 onRunningChanged: {
415454 if (!running) {
416− sideStageDragHandle.dragging = false;;
455+ sideStageDragHandle.dragging = false;
417456 }
418457 }
419458 }
@@ -427,17 +466,26 @@ Item {
427466 id: spreadTile
428467 height: spreadView.height
429468 width: model.stage == ApplicationInfoInterface.MainStage ? spreadView.width : spreadView.sideStageWidth
430− x: spreadView.width
431− z: spreadView.indexToZIndex(index)
432469 active: model.appId == priv.mainStageAppId || model.appId == priv.sideStageAppId
433− zIndex: z
470+ zIndex: spreadView.indexToZIndex(index)
434471 selected: spreadView.selectedIndex == index
435472 otherSelected: spreadView.selectedIndex >= 0 && !selected
436473 isInSideStage: priv.sideStageAppId == model.appId
437474 interactive: !spreadView.interactive && spreadView.phase === 0 && root.interactive
438475 swipeToCloseEnabled: spreadView.interactive
439476 maximizedAppTopMargin: root.maximizedAppTopMargin
440− dropShadow: spreadView.contentX > 0 || spreadDragArea.status == DirectionalDragArea.Undecided
477+ dragOffset: !isDash && model.appId == priv.mainStageAppId && root.inverseProgress > 0 ? root.inverseProgress : 0
478+
479+ readonly property bool isDash: model.appId == "unity8-dash"
480+
481+ // FIXME: A regular binding doesn't update any more after closing an app.
482+ // Using a Binding for now.
483+ Binding {
484+ target: spreadTile
485+ property: "z"
486+ value: (!spreadView.active && isDash && !active) ? -1 : spreadTile.zIndex
487+ }
488+ x: spreadView.width
441489
442490 property real behavioredZIndex: zIndex
443491 Behavior on behavioredZIndex {
@@ -458,7 +506,7 @@ Item {
458506 }
459507
460508 progress: {
461− var tileProgress = (spreadView.contentX - behavioredZIndex * spreadView.tileDistance) / spreadView.width;
509+ var tileProgress = (spreadView.shiftedContentX - behavioredZIndex * spreadView.tileDistance) / spreadView.width;
462510 // Some tiles (nextInStack, active) need to move directly from the beginning, normalize progress to immediately start at 0
463511 if ((index == spreadView.nextInStack && spreadView.phase < 2) || (active && spreadView.phase < 1)) {
464512 tileProgress += behavioredZIndex * spreadView.tileDistance / spreadView.width;
@@ -481,11 +529,7 @@ Item {
481529
482530 onClicked: {
483531 if (spreadView.phase == 2) {
484− if (ApplicationManager.focusedApplicationId == ApplicationManager.get(index).appId) {
485− spreadView.snapTo(index);
486− } else {
487− ApplicationManager.requestFocusApplication(ApplicationManager.get(index).appId);
488− }
532+ spreadView.snapTo(index);
489533 }
490534 }
491535
@@ -518,12 +562,12 @@ Item {
518562 onTouchXChanged: {
519563 if (!dragging) {
520564 spreadView.phase = 0;
521− spreadView.contentX = 0;
565+ spreadView.contentX = -spreadView.shift;
522566 }
523567
524− if (attachedToView) {
525− spreadView.contentX = -touchX + spreadDragArea.width;
526− if (spreadView.contentX > spreadView.phase0Width + spreadView.phase1Width / 2) {
568+ if (dragging && attachedToView) {
569+ spreadView.contentX = -touchX + spreadDragArea.width - spreadView.shift;
570+ if (spreadView.shiftedContentX > spreadView.phase0Width + spreadView.phase1Width / 2) {
527571 attachedToView = false;
528572 spreadView.snap();
529573 }
@@ -548,14 +592,14 @@ Item {
548592 var oneWayFlick = priv.evaluateOneWayFlick(gesturePoints);
549593 gesturePoints = [];
550594
551− if (oneWayFlick && spreadView.contentX < spreadView.positionMarker1 * spreadView.width) {
595+ if (oneWayFlick && spreadView.shiftedContentX < spreadView.positionMarker1 * spreadView.width) {
552596 // If it was a short one-way movement, do the Alt+Tab switch
553597 // no matter if we didn't cross positionMarker1 yet.
554598 spreadView.snapTo(spreadView.nextInStack);
555599 } else if (!dragging && attachedToView) {
556− if (spreadView.contentX < spreadView.width * spreadView.positionMarker1) {
600+ if (spreadView.shiftedContentX < spreadView.width * spreadView.positionMarker1) {
557601 spreadView.snap();
558− } else if (spreadView.contentX < spreadView.width * spreadView.positionMarker2) {
602+ } else if (spreadView.shiftedContentX < spreadView.width * spreadView.positionMarker2) {
559603 spreadView.snapTo(spreadView.nextInStack);
560604 } else {
561605 // otherwise snap to the closest snap position we can find
qml/Stages/TransformedSpreadDelegate.qml+6−5
@@ -46,9 +46,6 @@ SpreadDelegate {
4646 property real startDistance: units.gu(5)
4747 property real endDistance: units.gu(.5)
4848
49− // Hiding tiles when their progress is negative or reached the maximum
50− visible: progress >= 0 && progress < 1.7
51−
5249 onSelectedChanged: {
5350 if (selected) {
5451 priv.snapshot();
@@ -132,6 +129,10 @@ SpreadDelegate {
132129 // the selected tile, which is animated from the snapshotted position to be fullscreen.
133130
134131 readonly property real xTranslate: {
132+ if (!spreadView.active) {
133+ return 0;
134+ }
135+
135136 if (otherSelected) {
136137 if (spreadView.phase < 2 && index == 0) {
137138 return linearAnimation(selectedProgress, 0, selectedXTranslate,
@@ -183,7 +184,7 @@ SpreadDelegate {
183184 }
184185
185186 readonly property real angle: {
186− if (spreadView.focusChanging) {
187+ if (!spreadView.active) {
187188 return 0;
188189 }
189190
@@ -216,7 +217,7 @@ SpreadDelegate {
216217 }
217218
218219 readonly property real scale: {
219− if (spreadView.focusChanging) {
220+ if (!spreadView.active) {
220221 return 1;
221222 }
222223 if (priv.otherSelected) {
qml/Stages/TransformedTabletSpreadDelegate.qml+28
@@ -47,6 +47,11 @@ SpreadDelegate {
4747
4848 property bool isInSideStage: false
4949
50+ property int dragOffset: 0
51+
52+ dropShadow: spreadView.active ||
53+ (active && model.stage == ApplicationInfoInterface.MainStage && priv.xTranslate != 0)
54+
5055 onSelectedChanged: {
5156 if (selected) {
5257 priv.snapshot();
@@ -129,6 +134,16 @@ SpreadDelegate {
129134 return helperEasingCurve.value * (endValue - startValue) + startValue;
130135 }
131136
137+ Behavior on xTranslate {
138+ enabled: !spreadView.active &&
139+ !snapAnimation.running &&
140+ model.appId !== "unity8-dash" &&
141+ !spreadView.sideStageDragging
142+ UbuntuNumberAnimation {
143+ duration: UbuntuAnimation.FastDuration
144+ }
145+ }
146+
132147 property real xTranslate: {
133148 var newTranslate = 0;
134149
@@ -155,7 +170,12 @@ SpreadDelegate {
155170 if (spreadView.phase == 0 && shouldMoveAway) {
156171 newTranslate += linearAnimation(0, spreadView.positionMarker2, 0, -units.gu(4), root.animatedProgress);
157172 }
173+ newTranslate += root.dragOffset;
174+ }
175+ if (!spreadView.active && model.appId == "unity8-dash" && !root.active) {
176+ newTranslate -= root.width;
158177 }
178+
159179 if (nextInStack && spreadView.phase == 0) {
160180 if (model.stage == ApplicationInfoInterface.MainStage) {
161181 if (spreadView.sideStageVisible && root.progress > 0) {
@@ -205,6 +225,10 @@ SpreadDelegate {
205225 }
206226
207227 property real scale: {
228+ if (!spreadView.active) {
229+ return 1;
230+ }
231+
208232 if (otherSelected) {
209233 return selectedScale;
210234 }
@@ -249,6 +273,10 @@ SpreadDelegate {
249273 }
250274
251275 property real angle: {
276+ if (!spreadView.active) {
277+ return 0;
278+ }
279+
252280 if (otherSelected) {
253281 return selectedAngle;
254282 }
src/CMakeLists.txt+1
@@ -35,3 +35,4 @@ install(TARGETS ${SHELL_APP}
3535 )
3636
3737add_subdirectory(Panel)
38+add_subdirectory(Dash)
src/Dash/CMakeLists.txtnew file+13
@@ -0,0 +1,13 @@
1+set(DASH_SRCS
2+ main.cpp
3+ ../MouseTouchAdaptor.cpp
4+)
5+
6+add_executable(unity8-dash ${DASH_SRCS})
7+
8+qt5_use_modules(unity8-dash Gui Qml Quick Test)
9+
10+# install binaries
11+install(TARGETS ${DASH_APP}
12+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
13+)
src/Dash/main.cppnew file+92
@@ -0,0 +1,92 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
4+ * Authors:
5+ * Michael Zanetti <michael.zanetti@canonical.com>
6+ *
7+ * This program is free software; you can redistribute it and/or modify
8+ * it under the terms of the GNU General Public License as published by
9+ * the Free Software Foundation; version 3.
10+ *
11+ * This program is distributed in the hope that it will be useful,
12+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ * GNU General Public License for more details.
15+ *
16+ * You should have received a copy of the GNU General Public License
17+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
18+ */
19+
20+#include <QtQuick/QQuickView>
21+#include <QtGui/QGuiApplication>
22+#include <QtQml/QQmlEngine>
23+#include <QtQml/QQmlContext>
24+#include <QDebug>
25+#include <QCommandLineParser>
26+#include <QLibrary>
27+
28+#include <paths.h>
29+#include "../MouseTouchAdaptor.h"
30+
31+int main(int argc, const char *argv[])
32+{
33+ QGuiApplication *application = new QGuiApplication(argc, (char**)argv);
34+
35+ QCommandLineParser parser;
36+ parser.setApplicationDescription("Description: Unity 8 Shell Dash");
37+ parser.addHelpOption();
38+
39+ QCommandLineOption mousetouchOption("mousetouch",
40+ "Allow the mouse to provide touch input");
41+ parser.addOption(mousetouchOption);
42+
43+ QCommandLineOption testabilityOption("testability",
44+ "Load the testability driver (Alternatively export QT_LOAD_TESTABILITY");
45+ parser.addOption(testabilityOption);
46+
47+ // Treat args with single dashes the same as arguments with two dashes
48+ // Ex: -fullscreen == --fullscreen
49+ parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions);
50+ parser.process(*application);
51+
52+ if (parser.isSet(testabilityOption) || getenv("QT_LOAD_TESTABILITY")) {
53+ QLibrary testLib(QLatin1String("qttestability"));
54+ if (testLib.load()) {
55+ typedef void (*TasInitialize)(void);
56+ TasInitialize initFunction = (TasInitialize)testLib.resolve("qt_testability_init");
57+ if (initFunction) {
58+ initFunction();
59+ } else {
60+ qCritical("Library qttestability resolve failed!");
61+ }
62+ } else {
63+ qCritical("Library qttestability load failed!");
64+ }
65+ }
66+
67+ QQuickView* view = new QQuickView();
68+ view->setResizeMode(QQuickView::SizeRootObjectToView);
69+ view->setTitle("Unity Dash");
70+
71+ // You will need this if you want to interact with touch-only components using a mouse
72+ // Needed only when manually testing on a desktop.
73+ MouseTouchAdaptor *mouseTouchAdaptor = 0;
74+ if (parser.isSet(mousetouchOption)) {
75+ mouseTouchAdaptor = new MouseTouchAdaptor;
76+ application->installNativeEventFilter(mouseTouchAdaptor);
77+ }
78+
79+ QUrl source(::qmlDirectory()+"Dash/DashApplication.qml");
80+ prependImportPaths(view->engine(), ::overrideImportPaths());
81+ appendImportPaths(view->engine(), ::fallbackImportPaths());
82+
83+ view->setSource(source);
84+ view->show();
85+
86+ int result = application->exec();
87+
88+ delete view;
89+ delete application;
90+
91+ return result;
92+}
tests/mocks/Unity/Application/ApplicationInfo.cpp−62
@@ -31,8 +31,6 @@ ApplicationInfo::ApplicationInfo(const QString &appId, QObject *parent)
3131 , m_state(Starting)
3232 , m_focused(false)
3333 , m_fullscreen(false)
34− , m_windowItem(0)
35− , m_windowComponent(0)
3634 , m_parentItem(0)
3735 , m_surface(0)
3836{
@@ -45,8 +43,6 @@ ApplicationInfo::ApplicationInfo(QObject *parent)
4543 , m_state(Starting)
4644 , m_focused(false)
4745 , m_fullscreen(false)
48− , m_windowItem(0)
49− , m_windowComponent(0)
5046 , m_parentItem(0)
5147 , m_surface(0)
5248{
@@ -61,12 +57,6 @@ ApplicationInfo::~ApplicationInfo()
6157 }
6258}
6359
64−void ApplicationInfo::onWindowComponentStatusChanged(QQmlComponent::Status status)
65−{
66− if (status == QQmlComponent::Ready && !m_windowItem)
67− doCreateWindowItem();
68−}
69−
7060void ApplicationInfo::onStateChanged(State state)
7161{
7262 if (state == ApplicationInfo::Running) {
@@ -108,55 +98,3 @@ void ApplicationInfo::setSurface(MirSurfaceItem* surface)
10898 Q_EMIT surfaceChanged(m_surface);
10999 SurfaceManager::singleton()->registerSurface(m_surface);
110100}
111−
112−void ApplicationInfo::createWindowComponent()
113−{
114− // The assumptions I make here really should hold.
115− QQuickView *quickView =
116− qobject_cast<QQuickView*>(QGuiApplication::topLevelWindows()[0]);
117−
118− QQmlEngine *engine = quickView->engine();
119−
120− m_windowComponent = new QQmlComponent(engine, this);
121− m_windowComponent->setData(m_windowQml.toLatin1(), QUrl());
122−}
123−
124−void ApplicationInfo::doCreateWindowItem()
125−{
126− m_windowItem = qobject_cast<QQuickItem *>(m_windowComponent->create());
127− m_windowItem->setParentItem(m_parentItem);
128−}
129−
130−void ApplicationInfo::createWindowItem()
131−{
132− if (!m_windowComponent)
133− createWindowComponent();
134−
135− // only create the windowItem once the component is ready
136− if (!m_windowComponent->isReady()) {
137− connect(m_windowComponent, &QQmlComponent::statusChanged,
138− this, &ApplicationInfo::onWindowComponentStatusChanged);
139− } else {
140− doCreateWindowItem();
141− }
142−}
143−
144−void ApplicationInfo::showWindow(QQuickItem *parent)
145−{
146− m_parentItem = parent;
147−
148− if (!m_windowItem)
149− createWindowItem();
150−
151− if (m_windowItem) {
152− m_windowItem->setVisible(true);
153− }
154−}
155−
156−void ApplicationInfo::hideWindow()
157−{
158− if (!m_windowItem)
159− return;
160−
161− m_windowItem->setVisible(false);
162−}
tests/mocks/Unity/Application/ApplicationInfo.h−10
@@ -88,22 +88,12 @@ public:
8888Q_SIGNALS:
8989 void surfaceChanged(MirSurfaceItem*);
9090
91−public:
92− void showWindow(QQuickItem *parent);
93− void hideWindow();
94−
9591private Q_SLOTS:
96− void onWindowComponentStatusChanged(QQmlComponent::Status status);
9792 void onStateChanged(State state);
9893
9994 void createSurface();
10095
10196private:
102− void createWindowItem();
103− void doCreateWindowItem();
104− void createWindowComponent();
105− QQuickItem *m_windowItem;
106− QQmlComponent *m_windowComponent;
10797 QQuickItem *m_parentItem;
10898 MirSurfaceItem* m_surface;
10999};
tests/mocks/Unity/Application/ApplicationManager.cpp+17−147
@@ -48,16 +48,14 @@ ApplicationManager *ApplicationManager::singleton()
4848ApplicationManager::ApplicationManager(QObject *parent)
4949 : ApplicationManagerInterface(parent)
5050 , m_suspended(false)
51− , m_mainStageComponent(0)
52− , m_mainStage(0)
53− , m_sideStageComponent(0)
54− , m_sideStage(0)
55− , m_rightMargin(0)
5651{
5752 m_roleNames.insert(RoleSurface, "surface");
5853 m_roleNames.insert(RoleFullscreen, "fullscreen");
5954
6055 buildListOfAvailableApplications();
56+
57+ startApplication("unity8-dash");
58+ focusApplication("unity8-dash");
6159}
6260
6361ApplicationManager::~ApplicationManager()
@@ -136,7 +134,6 @@ void ApplicationManager::add(ApplicationInfo *application) {
136134 Q_EMIT applicationAdded(application->appId());
137135 Q_EMIT countChanged();
138136 if (count() == 1) Q_EMIT emptyChanged(isEmpty()); // was empty but not anymore
139− Q_EMIT focusRequested(application->appId());
140137
141138 connect(application, &ApplicationInfo::surfaceChanged, this, [application, this]() {
142139 QModelIndex appIndex = findIndex(application);
@@ -222,6 +219,10 @@ ApplicationInfo* ApplicationManager::startApplication(const QString &appId,
222219
223220bool ApplicationManager::stopApplication(const QString &appId)
224221{
222+ if (appId == "unity8-dash") {
223+ return false;
224+ }
225+
225226 ApplicationInfo *application = findApplication(appId);
226227 if (application == nullptr)
227228 return false;
@@ -294,39 +295,25 @@ bool ApplicationManager::focusApplication(const QString &appId)
294295 for (ApplicationInfo *app : m_runningApplications) {
295296 if (app->focused() && app->stage() == ApplicationInfo::MainStage) {
296297 app->setFocused(false);
297− app->hideWindow();
298298 app->setState(ApplicationInfo::Suspended);
299299 }
300300 }
301301
302302 // focus this app
303303 application->setFocused(true);
304− if (!m_mainStage)
305− createMainStage();
306304 application->setState(ApplicationInfo::Running);
307− application->showWindow(m_mainStage);
308− m_mainStage->setZ(-1000);
309− if (m_sideStage)
310− m_sideStage->setZ(-2000);
311305 } else if (application->stage() == ApplicationInfo::SideStage) {
312306 // unfocus currently focused sidestage app
313307 for (ApplicationInfo *app : m_runningApplications) {
314308 if (app->focused() && app->stage() == ApplicationInfo::SideStage) {
315309 app->setFocused(false);
316− app->hideWindow();
317310 app->setState(ApplicationInfo::Suspended);
318311 }
319312 }
320313
321314 // focus this app
322315 application->setFocused(true);
323− if (!m_sideStage)
324− createSideStage();
325316 application->setState(ApplicationInfo::Running);
326− application->showWindow(m_sideStage);
327− m_sideStage->setZ(-1000);
328− if (m_mainStage)
329− m_mainStage->setZ(-2000);
330317 }
331318
332319 // move app to top of stack
@@ -337,18 +324,14 @@ bool ApplicationManager::focusApplication(const QString &appId)
337324
338325bool ApplicationManager::requestFocusApplication(const QString &appId)
339326{
340− if (appId != focusedApplicationId()) {
341− QMetaObject::invokeMethod(this, "focusRequested", Qt::QueuedConnection, Q_ARG(QString, appId));
342− return true;
343− }
344− return false;
327+ QMetaObject::invokeMethod(this, "focusRequested", Qt::QueuedConnection, Q_ARG(QString, appId));
328+ return true;
345329}
346330
347331void ApplicationManager::unfocusCurrentApplication()
348332{
349333 for (ApplicationInfo *app : m_runningApplications) {
350334 if (app->focused()) {
351− app->hideWindow();
352335 app->setFocused(false);
353336 }
354337 }
@@ -357,42 +340,6 @@ void ApplicationManager::unfocusCurrentApplication()
357340
358341void ApplicationManager::generateQmlStrings(ApplicationInfo *application)
359342{
360− // TODO: Is there a better way of solving this fullscreen vs. regular
361− // application height?
362− QString topMargin;
363− if (application->fullscreen()) {
364− topMargin.append("0");
365− } else {
366− // Taken from Panel.panelHeight
367− topMargin.append("units.gu(3) + units.dp(2)");
368− }
369−
370− QString windowQml = QString(
371− "import QtQuick 2.0\n"
372− "Image {\n"
373− " anchors.fill: parent\n"
374− " anchors.topMargin: %1\n"
375− " anchors.rightMargin: %2\n"
376− " source: \"file://%3/Dash/graphics/phone/screenshots/%4.png\"\n"
377− " smooth: true\n"
378− " fillMode: Image.PreserveAspectCrop\n"
379− "}").arg(topMargin)
380− .arg(m_rightMargin)
381− .arg(qmlDirectory())
382− .arg(application->icon().toString());
383− application->setWindowQml(windowQml);
384−
385− QString imageQml = QString(
386− "import QtQuick 2.0\n"
387− "Image {\n"
388− " anchors.fill: parent\n"
389− " source: \"file://%1/Dash/graphics/phone/screenshots/%2.png\"\n"
390− " smooth: true\n"
391− " fillMode: Image.PreserveAspectCrop\n"
392− "}").arg(qmlDirectory())
393− .arg(application->icon().toString());
394− application->setImageQml(imageQml);
395−
396343 application->setScreenshot(QString("file://%1/Dash/graphics/phone/screenshots/%2@12.png").arg(qmlDirectory())
397344 .arg(application->icon().toString()));
398345}
@@ -401,6 +348,14 @@ void ApplicationManager::buildListOfAvailableApplications()
401348{
402349 ApplicationInfo *application;
403350
351+ application = new ApplicationInfo(this);
352+ application->setAppId("unity8-dash");
353+ application->setName("Unity 8 Mock Dash");
354+ application->setIcon(QUrl("unity8-dash"));
355+ application->setStage(ApplicationInfo::MainStage);
356+ generateQmlStrings(application);
357+ m_availableApplications.append(application);
358+
404359 application = new ApplicationInfo(this);
405360 application->setAppId("dialer-app");
406361 application->setName("Dialer");
@@ -521,78 +476,6 @@ void ApplicationManager::buildListOfAvailableApplications()
521476 m_availableApplications.append(application);
522477}
523478
524−void ApplicationManager::createMainStageComponent()
525−{
526− // The assumptions I make here really should hold.
527− QQuickView *quickView =
528− qobject_cast<QQuickView*>(QGuiApplication::topLevelWindows()[0]);
529−
530− QQmlEngine *engine = quickView->engine();
531−
532− m_mainStageComponent = new QQmlComponent(engine, this);
533− QString mainStageQml =
534− "import QtQuick 2.0\n"
535− "Rectangle {\n"
536− " anchors.fill: parent\n"
537− " color: 'black'\n"
538− " z: -2000\n"
539− "}\n";
540− m_mainStageComponent->setData(mainStageQml.toLatin1(), QUrl());
541−}
542−
543−void ApplicationManager::createMainStage()
544−{
545− if (!m_mainStageComponent)
546− createMainStageComponent();
547−
548− // The assumptions I make here really should hold.
549− QQuickView *quickView =
550− qobject_cast<QQuickView*>(QGuiApplication::topLevelWindows()[0]);
551−
552− QQuickItem *shell = quickView->rootObject();
553−
554− m_mainStage = qobject_cast<QQuickItem *>(m_mainStageComponent->create());
555− m_mainStage->setParentItem(shell);
556−}
557−
558−void ApplicationManager::createSideStageComponent()
559−{
560− // The assumptions I make here really should hold.
561− QQuickView *quickView =
562− qobject_cast<QQuickView*>(QGuiApplication::topLevelWindows()[0]);
563−
564− QQmlEngine *engine = quickView->engine();
565−
566− m_sideStageComponent = new QQmlComponent(engine, this);
567− QString sideStageQml =
568− "import QtQuick 2.0\n"
569− "import Ubuntu.Components 0.1\n"
570− "Item {\n"
571− " width: units.gu(40)\n" // from SideStage in Shell.qml
572− " anchors.top: parent.top\n"
573− " anchors.bottom: parent.bottom\n"
574− " anchors.right: parent.right\n"
575− " z: -1000\n"
576− "}\n";
577− m_sideStageComponent->setData(sideStageQml.toLatin1(), QUrl());
578−}
579−
580−void ApplicationManager::createSideStage()
581−{
582− if (!m_sideStageComponent)
583− createSideStageComponent();
584−
585− // The assumptions I make here really should hold.
586− QQuickView *quickView =
587− qobject_cast<QQuickView*>(QGuiApplication::topLevelWindows()[0]);
588−
589− QQuickItem *shell = quickView->rootObject();
590−
591− m_sideStage = qobject_cast<QQuickItem *>(m_sideStageComponent->create());
592− m_sideStage->setParentItem(shell);
593− m_sideStage->setFlag(QQuickItem::ItemHasContents, false);
594−}
595−
596479QStringList ApplicationManager::availableApplications()
597480{
598481 QStringList appIds;
@@ -602,19 +485,6 @@ QStringList ApplicationManager::availableApplications()
602485 return appIds;
603486}
604487
605−int ApplicationManager::rightMargin() const
606−{
607− return m_rightMargin;
608−}
609−
610−void ApplicationManager::setRightMargin(int rightMargin)
611−{
612− m_rightMargin = rightMargin;
613− Q_FOREACH(ApplicationInfo *app, m_availableApplications) {
614− generateQmlStrings(app);
615− }
616−}
617−
618488bool ApplicationManager::isEmpty() const
619489{
620490 return m_runningApplications.isEmpty();
tests/mocks/Unity/Application/ApplicationManager.h−16
@@ -44,10 +44,6 @@ class ApplicationManager : public ApplicationManagerInterface {
4444
4545 Q_PROPERTY(bool fake READ fake CONSTANT)
4646
47− // Only for testing
48− // This can be used to place some controls to right, like make tryPhoneStage for example
49− Q_PROPERTY(int rightMargin READ rightMargin WRITE setRightMargin)
50−
5147 public:
5248 ApplicationManager(QObject *parent = NULL);
5349 virtual ~ApplicationManager();
@@ -108,8 +104,6 @@ class ApplicationManager : public ApplicationManagerInterface {
108104
109105 // Only for testing
110106 Q_INVOKABLE QStringList availableApplications();
111− int rightMargin() const;
112− void setRightMargin(int rightMargin);
113107
114108 QModelIndex findIndex(ApplicationInfo* application);
115109
@@ -126,19 +120,9 @@ class ApplicationManager : public ApplicationManagerInterface {
126120 void showApplicationWindow(ApplicationInfo *application);
127121 void buildListOfAvailableApplications();
128122 void generateQmlStrings(ApplicationInfo *application);
129− void createMainStageComponent();
130− void createMainStage();
131− void createSideStageComponent();
132− void createSideStage();
133123 bool m_suspended;
134124 QList<ApplicationInfo*> m_runningApplications;
135125 QList<ApplicationInfo*> m_availableApplications;
136− QQmlComponent *m_mainStageComponent;
137− QQuickItem *m_mainStage;
138− QQmlComponent *m_sideStageComponent;
139− QQuickItem *m_sideStage;
140−
141− int m_rightMargin;
142126
143127 static ApplicationManager *the_application_manager;
144128};
tests/mocks/Unity/Application/ApplicationScreenshotProvider.cpp+1−1
@@ -64,7 +64,7 @@ QImage ApplicationScreenshotProvider::requestImage(const QString &imageId, QSize
6464 Q_FOREACH (QWindow *win, unity->allWindows()) {
6565 QQuickWindow *quickWin = qobject_cast<QQuickWindow*>(win);
6666 if (quickWin) {
67− image = image.scaledToWidth(quickWin->width() - m_appManager->rightMargin());
67+ image = image.scaledToWidth(quickWin->width());
6868 break;
6969 }
7070 }
tests/mocks/Unity/CMakeLists.txt+1
@@ -2,6 +2,7 @@ add_subdirectory(Application)
22add_subdirectory(Indicators)
33add_subdirectory(Launcher)
44add_subdirectory(Notifications)
5+add_subdirectory(DashCommunicator)
56
67pkg_search_module(DEE dee-1.0 REQUIRED)
78pkg_search_module(GOBJECT gobject-2.0 REQUIRED)
tests/mocks/Unity/DashCommunicator/CMakeLists.txtnew file+18
@@ -0,0 +1,18 @@
1+include_directories(
2+ ${CMAKE_CURRENT_SOURCE_DIR}
3+)
4+
5+set(QMLDASHCOMMUNICATORPLUGIN_SRC
6+ plugin.cpp
7+ dashcommunicatorservice.cpp
8+ dashcommunicator.cpp
9+ )
10+
11+add_library(MockDashCommunicator-qml MODULE
12+ ${QMLDASHCOMMUNICATORPLUGIN_SRC}
13+ )
14+
15+qt5_use_modules(MockDashCommunicator-qml DBus Qml)
16+
17+# export the qmldir and qmltypes files
18+add_unity8_mock(Unity.DashCommunicator 0.1 Unity/DashCommunicator TARGETS MockDashCommunicator-qml)
tests/mocks/Unity/DashCommunicator/dashcommunicator.cppnew file+37
@@ -0,0 +1,37 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify 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+#include "dashcommunicator.h"
18+
19+#include <QObject>
20+#include <QDBusConnection>
21+#include <QDBusInterface>
22+#include <QDebug>
23+
24+DashCommunicator::DashCommunicator(QObject *parent):
25+ QObject(parent)
26+{
27+}
28+
29+DashCommunicator::~DashCommunicator()
30+{
31+}
32+
33+
34+void DashCommunicator::setCurrentScope(const QString &scopeId, bool animate, bool reset)
35+{
36+ Q_EMIT setCurrentScopeCalled(scopeId, animate, reset);
37+}
tests/mocks/Unity/DashCommunicator/dashcommunicator.hnew file+39
@@ -0,0 +1,39 @@
1+/*
2+ * Copyright (C) 2014 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+#ifndef DASHCOMMUNICATOR_H
18+#define DASHCOMMUNICATOR_H
19+
20+#include <QObject>
21+
22+class DashCommunicator: public QObject
23+{
24+ Q_OBJECT
25+ Q_CLASSINFO("D-Bus Interface", "com.canonical.Unity.DashCommunicator")
26+
27+public:
28+ DashCommunicator(QObject *parent = 0);
29+ ~DashCommunicator();
30+
31+public Q_SLOTS:
32+ void setCurrentScope(const QString &scopeId, bool animate, bool reset);
33+
34+Q_SIGNALS:
35+ // This mock just emits calls back to the QML api for the plugin to verify calls
36+ void setCurrentScopeCalled(const QString &scopeId, bool animate, bool reset);
37+};
38+
39+#endif
tests/mocks/Unity/DashCommunicator/dashcommunicatorservice.cppnew file+33
@@ -0,0 +1,33 @@
1+/*
2+ * Copyright (C) 2014 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+#include "dashcommunicatorservice.h"
18+
19+DashCommunicatorService::DashCommunicatorService(QObject *parent):
20+ QObject(parent)
21+{
22+}
23+
24+
25+DashCommunicatorService::~DashCommunicatorService()
26+{
27+
28+}
29+
30+void DashCommunicatorService::mockSetCurrentScope(const QString &scopeId, bool animate, bool reset)
31+{
32+ Q_EMIT setCurrentScopeRequested(scopeId, animate, reset);
33+}
tests/mocks/Unity/DashCommunicator/dashcommunicatorservice.hnew file+36
@@ -0,0 +1,36 @@
1+/*
2+ * Copyright (C) 2014 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+#ifndef DASHCOMMUNICATORSERVICE_H
18+#define DASHCOMMUNICATORSERVICE_H
19+
20+#include <QObject>
21+
22+class DashCommunicatorService: public QObject
23+{
24+ Q_OBJECT
25+public:
26+ DashCommunicatorService(QObject *parent = 0);
27+ ~DashCommunicatorService();
28+
29+Q_SIGNALS:
30+ void setCurrentScopeRequested(const QString &scopeId, bool animate, bool reset);
31+
32+public Q_SLOTS:
33+ void mockSetCurrentScope(const QString &scopeId, bool animate, bool reset);
34+};
35+
36+#endif // DBUSUNITYSESSIONSERVICE_H
tests/mocks/Unity/DashCommunicator/plugin.cppnew file+31
@@ -0,0 +1,31 @@
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+ * Authors: Michael Zanetti <michael.zanetti@canonical.com>
17+ */
18+
19+#include "plugin.h"
20+#include "dashcommunicator.h"
21+#include "dashcommunicatorservice.h"
22+
23+#include <QDBusConnection>
24+#include <QtQml/qqml.h>
25+
26+void DashCommunicatorPlugin::registerTypes(const char *uri)
27+{
28+ Q_ASSERT(uri == QStringLiteral("Unity.DashCommunicator"));
29+ qmlRegisterType<DashCommunicatorService>(uri, 0, 1, "DashCommunicatorService");
30+ qmlRegisterType<DashCommunicator>(uri, 0, 1, "DashCommunicator");
31+}
tests/mocks/Unity/DashCommunicator/plugin.hnew file+34
@@ -0,0 +1,34 @@
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+ * Authors: Michael Zanetti <michael.zanetti@canonical.com>
17+ */
18+
19+#ifndef DASHCOMMUNICATOR_PLUGIN_H
20+#define DASHCOMMUNICATOR_PLUGIN_H
21+
22+#include <QtQml/QQmlEngine>
23+#include <QtQml/QQmlExtensionPlugin>
24+
25+class DashCommunicatorPlugin : public QQmlExtensionPlugin
26+{
27+ Q_OBJECT
28+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
29+
30+public:
31+ void registerTypes(const char *uri);
32+};
33+
34+#endif
tests/mocks/Unity/DashCommunicator/qmldirnew file+3
@@ -0,0 +1,3 @@
1+module Unity.DashCommunicator
2+plugin MockDashCommunicator-qml
3+typeinfo DashCommunicator.qmltypes
tests/qmltests/Dash/tst_Dash.qml+19
@@ -57,6 +57,7 @@ Item {
5757 verify(dashContentList != undefined);
5858 tryCompare(dashContentList, "count", 0);
5959 scopes.load();
60+ tryCompare(dashContentList, "currentIndex", 0);
6061 }
6162
6263 function get_scope_data() {
@@ -299,5 +300,23 @@ Item {
299300 // Original list went to the favorite
300301 compare(dashContentList.currentIndex, 0);
301302 }
303+
304+ function test_setCurrentScope() {
305+ var dashContentList = findChild(dash, "dashContentList");
306+ var startX = dash.width - units.gu(1);
307+ var startY = dash.height / 2;
308+ var stopX = units.gu(1)
309+ var stopY = startY;
310+ var retry = 0;
311+ while (dashContentList.currentIndex != 2 && retry <= 5) {
312+ mouseFlick(dash, startX, startY, stopX, stopY)
313+ waitForRendering(dashContentList)
314+ retry++;
315+ }
316+ compare(dashContentList.currentIndex, 2);
317+ var dashCommunicatorService = findInvisibleChild(dash, "dashCommunicatorService");
318+ dashCommunicatorService.mockSetCurrentScope("clickscope", true, true);
319+ tryCompare(dashContentList, "currentIndex", 1)
320+ }
302321 }
303322}
tests/qmltests/Stages/tst_PhoneStage.qml+3−2
@@ -231,9 +231,10 @@ Item {
231231 }
232232
233233 function cleanup() {
234− while (ApplicationManager.count > 0) {
234+ while (ApplicationManager.count > 1) {
235235 var oldCount = ApplicationManager.count;
236− ApplicationManager.stopApplication(ApplicationManager.get(0).appId)
236+ var closingIndex = ApplicationManager.focusedApplicationId == "unity8-dash" ? 1 : 0
237+ ApplicationManager.stopApplication(ApplicationManager.get(closingIndex).appId)
237238 tryCompare(ApplicationManager, "count", oldCount - 1)
238239 }
239240 }
tests/qmltests/tst_Shell.qml+62−275
@@ -56,49 +56,20 @@ Item {
5656 signalName: "sessionStarted"
5757 }
5858
59+ SignalSpy {
60+ id: dashCommunicatorSpy
61+ signalName: "setCurrentScopeCalled"
62+ }
63+
5964 UT.UnityTestCase {
6065 name: "Shell"
6166 when: windowShown
6267
6368 function initTestCase() {
64− var ok = false;
65− var attempts = 0;
66− var maxAttempts = 1000;
67−
68− // Qt loads a qml scene asynchronously. So early on, some findChild() calls made in
69− // tests may fail because the desired child item wasn't loaded yet.
70− // Thus here we try to ensure the scene has been fully loaded before proceeding with the tests.
71− // As I couldn't find an API in QQuickView & friends to tell me that the scene is 100% loaded
72− // (all items instantiated, etc), I resort to checking the existence of some key items until
73− // repeatedly until they're all there.
74− do {
75− var dashContentList = findChild(shell, "dashContentList");
76− waitForRendering(dashContentList);
77− var homeLoader = findChild(dashContentList, "clickscope loader");
78− ok = homeLoader !== null
79− && homeLoader.item !== undefined;
80−
81− var greeter = findChild(shell, "greeter");
82− ok &= greeter !== null;
83−
84− var launcherPanel = findChild(shell, "launcherPanel");
85− ok &= launcherPanel !== null;
86−
87− attempts++;
88− if (!ok) {
89− console.log("Attempt " + attempts + " failed. Waiting a bit before trying again.");
90− // wait a bit before retrying
91− wait(100);
92− } else {
93− console.log("All seem fine after " + attempts + " attempts.");
94− }
95− } while (!ok && attempts <= maxAttempts);
96−
97− verify(ok);
98−
9969 swipeAwayGreeter();
10070
10171 sessionSpy.target = findChild(shell, "greeter")
72+ dashCommunicatorSpy.target = findInvisibleChild(shell, "dashCommunicator");
10273 }
10374
10475 function cleanup() {
@@ -111,56 +82,16 @@ Item {
11182 // kill all (fake) running apps
11283 killApps(ApplicationManager);
11384
114− var dashContent = findChild(shell, "dashContent");
115− dashContent.closePreview();
116−
117− var dashHome = findChild(shell, "clickscope loader");
118− swipeUntilScopeViewIsReached(dashHome);
119−
85+ waitForUIToSettle();
12086 hideIndicators();
12187 }
12288
123− function killApps(apps) {
124− if (!apps) return;
125− while (apps.count > 0) {
126− ApplicationManager.stopApplication(apps.get(0).appId);
89+ function killApps() {
90+ while (ApplicationManager.count > 1) {
91+ var appIndex = ApplicationManager.get(0).appId == "unity8-dash" ? 1 : 0
92+ ApplicationManager.stopApplication(ApplicationManager.get(appIndex).appId);
12793 }
128− compare(ApplicationManager.count, 0)
129− }
130−
131− /*
132− Test the effect of a right-edge drag on the dash in 3 situations:
133− 1 - when no application has been launched yet
134− 2 - when there's a minimized application
135− 3 - after the last running application has been closed/stopped
136−
137− The behavior of Dash on 3 should be the same as on 1.
138− */
139− function test_rightEdgeDrag() {
140− checkRightEdgeDragWithNoRunningApps();
141−
142− dragLauncherIntoView();
143−
144− // Launch an app from the launcher
145− tapOnAppIconInLauncher();
146− waitUntilApplicationWindowIsFullyVisible();
147−
148− // Minimize the application we just launched
149− swipeFromLeftEdge(units.gu(27));
150−
151− waitForUIToSettle();
152−
153− checkRightEdgeDragWithMinimizedApp();
154−
155− // Minimize that application once again
156− swipeFromLeftEdge(units.gu(27));
157−
158− // Right edge behavior should now be the same as before that app,
159− // was launched. Manually cleanup beforehand to get to initial
160− // state.
161− cleanup();
162− waitForUIToSettle();
163− checkRightEdgeDragWithNoRunningApps();
94+ compare(ApplicationManager.count, 1)
16495 }
16596
16697 function test_leftEdgeDrag_data() {
@@ -183,7 +114,7 @@ Item {
183114
184115 swipeFromLeftEdge(data.swipeLength);
185116 if (data.appHides)
186− waitUntilApplicationWindowIsFullyHidden();
117+ waitUntilDashIsFocused();
187118 else
188119 waitUntilApplicationWindowIsFullyVisible();
189120 }
@@ -239,100 +170,18 @@ Item {
239170 waitForRendering(greeter);
240171 }
241172
242− /*
243− Perform a right-edge drag when the Dash is being show and there are
244− no running/minimized apps to be restored.
245−
246− The expected behavior is that an animation should be played to hint the
247− user that his right-edge drag gesture has been successfully recognized
248− but there is no application to be brought to foreground.
249− */
250− function checkRightEdgeDragWithNoRunningApps() {
251− var touchX = shell.width - (shell.edgeSize / 2);
252− var touchY = shell.height / 2;
253−
254− var dash = findChild(shell, "dash");
255− // check that dash has normal scale and opacity
256− tryCompare(dash, "contentScale", 1.0);
257− tryCompare(dash, "opacity", 1.0);
258−
259− touchFlick(shell, touchX, touchY, shell.width * 0.1, touchY,
260− true /* beginTouch */, false /* endTouch */, units.gu(10), 50);
261−
262− // check that Dash has been scaled down and had its opacity reduced
263− tryCompareFunction(function() { return dash.contentScale <= 0.9; }, true);
264− tryCompareFunction(function() { return dash.opacity <= 0.5; }, true);
265−
266− touchRelease(shell, shell.width * 0.1, touchY);
267−
268− // and now everything should have gone back to normal
269− tryCompare(dash, "contentScale", 1.0);
270− tryCompare(dash, "opacity", 1.0);
271− }
272−
273− /*
274− Perform a right-edge drag when the Dash is being show and there is
275− a running/minimized app to be restored.
276−
277− The expected behavior is that the dash should fade away and ultimately be
278− made invisible once the gesture is finished as the restored app will now
279− be on foreground.
280− */
281− function checkRightEdgeDragWithMinimizedApp() {
282− var touchX = shell.width - (shell.edgeSize / 2);
283− var touchY = shell.height / 2;
284−
285− var dash = findChild(shell, "dash");
286− // check that dash has normal scale and opacity
287− tryCompare(dash, "contentScale", 1.0);
288− tryCompare(dash, "opacity", 1.0);
289−
290− touchFlick(shell, touchX, touchY, shell.width * 0.1, touchY,
291− true /* beginTouch */, false /* endTouch */, units.gu(10), 50);
292−
293− // check that Dash has been scaled down and had its opacity reduced
294− tryCompareFunction(function() { return dash.contentScale <= 0.9; }, true);
295− tryCompareFunction(function() { return dash.opacity <= 0.5; }, true);
296−
297− touchRelease(shell, shell.width * 0.1, touchY);
298−
299− // dash should have gone away, now that the app is on foreground
300− tryCompare(dash, "visible", false);
301− }
302−
303173 /*
304174 Regression test for bug https://bugs.launchpad.net/touch-preview-images/+bug/1193419
305175
306− When the user minimizes an application (left-edge swipe) he should always end up in the "Running Apps"
307− category of the "Applications" scope view.
176+ When the user minimizes an application (left-edge swipe) he should always end up in the
177+ "Applications" scope view.
308178
309179 Steps:
310− - go to apps lens
311− - scroll to the bottom
312− - reveal launcher and launch an app
180+ - reveal launcher and launch an app that covers the dash
313181 - perform long left edge swipe to go minimize the app and go back to the dash.
314−
315− Expected Results
316− - apps lens shown
182+ - verify the setCurrentScope() D-Bus call to the dash has been called for the correct scope id.
317183 */
318184 function test_minimizingAppTakesToDashApps() {
319− var dashApps = findChild(shell, "clickscope");
320− swipeUntilScopeViewIsReached(dashApps);
321−
322− // swipe finger up until the running/recent apps section (which we assume
323− // it's the first one) is as far from view as possible.
324− // We also assume that DashApps is tall enough that it's scrollable
325− var appsCategoryListView = findChild(dashApps, "categoryListView");
326− while (!appsCategoryListView.atYEnd) {
327− swipeUpFromCenter();
328− tryCompare(appsCategoryListView, "moving", false);
329− }
330−
331− // Switch away from the Applications scope.
332− swipeRightFromCenter();
333− waitUntilItemStopsMoving(dashApps);
334− verify(!itemIsOnScreen(dashApps));
335−
336185 dragLauncherIntoView();
337186
338187 // Launch an app from the launcher
@@ -340,19 +189,16 @@ Item {
340189
341190 waitUntilApplicationWindowIsFullyVisible();
342191
343− // Dragging launcher into view with a little bit of gap (units.gu(1)) should switch to Apps scope
344− dragLauncherIntoView();
345− verify(itemIsOnScreen(dashApps));
192+ verify(ApplicationManager.focusedApplicationId !== "unity8-dash")
346193
194+ dashCommunicatorSpy.clear();
347195 // Minimize the application we just launched
348196 swipeFromLeftEdge(units.gu(27));
349197
350− // Wait for the whole UI to settle down
351− waitUntilApplicationWindowIsFullyHidden();
352− waitUntilItemStopsMoving(dashApps);
353− tryCompare(appsCategoryListView, "moving", false);
198+ tryCompare(ApplicationManager, "focusedApplicationId", "unity8-dash");
354199
355− verify(itemIsOnScreen(dashApps));
200+ compare(dashCommunicatorSpy.count, 1);
201+ compare(dashCommunicatorSpy.signalArguments[0][0], "clickscope");
356202 }
357203
358204 function test_showInputMethod() {
@@ -409,9 +255,14 @@ Item {
409255
410256 // Wait for the whole UI to settle down
411257 function waitForUIToSettle() {
412− waitUntilApplicationWindowIsFullyHidden();
413− var dashContentList = findChild(shell, "dashContentList");
414− tryCompare(dashContentList, "moving", false);
258+ var launcher = findChild(shell, "launcherPanel")
259+ tryCompareFunction(function() {return launcher.x === 0 || launcher.x === -launcher.width;}, true);
260+ if (launcher.x === 0) {
261+ mouseClick(shell, shell.width / 2, shell.height / 2)
262+ }
263+ tryCompare(launcher, "x", -launcher.width)
264+
265+ waitForRendering(shell)
415266 }
416267
417268 function dragToCloseIndicatorsPanel() {
@@ -468,24 +319,13 @@ Item {
468319 }
469320
470321 function waitUntilApplicationWindowIsFullyVisible() {
471− var underlay = findChild(shell, "underlay");
472− tryCompare(underlay, "visible", false);
322+ var appDelegate = findChild(shell, "appDelegate0")
323+ var surfaceContainer = findChild(appDelegate, "surfaceContainer");
324+ tryCompareFunction(function() { return surfaceContainer.surface !== null; }, true);
473325 }
474326
475− function waitUntilApplicationWindowIsFullyHidden() {
476− var stages = findChild(shell, "stages");
477− tryCompare(stages, "fullyHidden", true);
478− }
479−
480− function swipeUntilScopeViewIsReached(scopeView) {
481− while (!itemIsOnScreen(scopeView)) {
482− if (itemIsToLeftOfScreen(scopeView)) {
483− swipeRightFromCenter();
484− } else {
485− swipeLeftFromCenter();
486− }
487− waitUntilItemStopsMoving(scopeView);
488− }
327+ function waitUntilDashIsFocused() {
328+ tryCompare(ApplicationManager, "focusedApplicationId", "unity8-dash");
489329 }
490330
491331 function swipeFromLeftEdge(swipeLength) {
@@ -494,24 +334,6 @@ Item {
494334 touchFlick(shell, touchStartX, touchStartY, swipeLength, touchStartY);
495335 }
496336
497− function swipeLeftFromCenter() {
498− var touchStartX = shell.width * 3 / 4;
499− var touchStartY = shell.height / 2;
500− touchFlick(shell, touchStartX, touchStartY, 0, touchStartY);
501− }
502−
503− function swipeRightFromCenter() {
504− var touchStartX = shell.width * 3 / 4;
505− var touchStartY = shell.height / 2;
506− touchFlick(shell, touchStartX, touchStartY, shell.width, touchStartY);
507− }
508−
509− function swipeUpFromCenter() {
510− var touchStartX = shell.width / 2;
511− var touchStartY = shell.height / 2;
512− touchFlick(shell, touchStartX, touchStartY, touchStartX, 0);
513− }
514−
515337 function itemIsOnScreen(item) {
516338 var itemRectInShell = item.mapToItem(shell, 0, 0, item.width, item.height);
517339
@@ -521,64 +343,6 @@ Item {
521343 && itemRectInShell.y + itemRectInShell.height <= shell.height;
522344 }
523345
524− function itemIsToLeftOfScreen(item) {
525− var itemRectInShell = item.mapToItem(shell, 0, 0, item.width, item.height);
526− return itemRectInShell.x < 0;
527− }
528−
529− function waitUntilItemStopsMoving(item) {
530− var itemRectInShell = item.mapToItem(shell, 0, 0, item.width, item.height);
531− var previousX = itemRectInShell.x;
532− var previousY = itemRectInShell.y;
533− var isStill = false;
534−
535− do {
536− wait(100);
537− itemRectInShell = item.mapToItem(shell, 0, 0, item.width, item.height);
538− if (itemRectInShell.x == previousX && itemRectInShell.y == previousY) {
539− isStill = true;
540− } else {
541− previousX = itemRectInShell.x;
542− previousY = itemRectInShell.y;
543− }
544− } while (!isStill);
545− }
546−
547− function test_DashShown_data() {
548− return [
549− {tag: "in focus", greeter: false, app: false, launcher: false, indicators: false, expectedShown: true},
550− {tag: "under greeter", greeter: true, app: false, launcher: false, indicators: false, expectedShown: false},
551− {tag: "under app", greeter: false, app: true, launcher: false, indicators: false, expectedShown: false},
552− {tag: "under launcher", greeter: false, app: false, launcher: true, indicators: false, expectedShown: true},
553− {tag: "under indicators", greeter: false, app: false, launcher: false, indicators: true, expectedShown: false},
554− ]
555− }
556−
557− function test_DashShown(data) {
558− if (data.greeter) {
559− // Swipe the greeter in
560− var greeter = findChild(shell, "greeter");
561− Powerd.displayPowerStateChange(Powerd.Off, 0);
562− tryCompare(greeter, "showProgress", 1);
563− }
564−
565− if (data.app) {
566− dragLauncherIntoView();
567− tapOnAppIconInLauncher();
568− }
569−
570− if (data.launcher) {
571− dragLauncherIntoView();
572− }
573−
574− if (data.indicators) {
575− showIndicators();
576− }
577−
578− var dash = findChild(shell, "dash");
579− tryCompare(dash, "shown", data.expectedShown);
580− }
581−
582346 function test_focusRequestedHidesGreeter() {
583347 var greeter = findChild(shell, "greeter");
584348
@@ -587,10 +351,9 @@ Item {
587351 tryCompareFunction(function() { return app.surface != null }, true);
588352
589353 // Minimize the application we just launched
590− swipeFromLeftEdge(units.gu(27));
354+ swipeFromLeftEdge(units.gu(26) + 1);
591355
592− // Wait for the whole UI to settle down
593− waitUntilApplicationWindowIsFullyHidden();
356+ waitUntilDashIsFocused();
594357
595358 greeter.show();
596359 tryCompare(greeter, "showProgress", 1);
@@ -606,8 +369,9 @@ Item {
606369
607370 showIndicators();
608371
372+ var oldCount = ApplicationManager.count;
609373 ApplicationManager.startApplication("camera-app");
610− tryCompare(ApplicationManager, "count", 1);
374+ tryCompare(ApplicationManager, "count", oldCount + 1);
611375
612376 tryCompare(indicators, "fullyClosed", true);
613377 }
@@ -616,6 +380,7 @@ Item {
616380 function test_showGreeterDBusCall() {
617381 var greeter = findChild(shell, "greeter")
618382 tryCompare(greeter, "showProgress", 0)
383+ waitForRendering(greeter);
619384 LightDM.Greeter.showGreeter()
620385 tryCompare(greeter, "showProgress", 1)
621386 }
@@ -624,6 +389,7 @@ Item {
624389 sessionSpy.clear()
625390
626391 var greeter = findChild(shell, "greeter")
392+ waitForRendering(greeter)
627393 greeter.show()
628394 tryCompare(greeter, "showProgress", 1)
629395
@@ -644,5 +410,26 @@ Item {
644410 ApplicationManager.requestFocusApplication("gallery-app");
645411 tryCompare(panel, "fullscreenMode", false);
646412 }
413+
414+ function test_leftEdgeDragFullscreen() {
415+ var panel = findChild(shell, "panel");
416+ tryCompare(panel, "fullscreenMode", false)
417+
418+ ApplicationManager.startApplication("camera-app");
419+ tryCompare(panel, "fullscreenMode", true)
420+
421+ var touchStartX = 2;
422+ var touchStartY = shell.height / 2;
423+
424+ touchFlick(shell, touchStartX, touchStartY, units.gu(2), touchStartY, true, false);
425+
426+ compare(panel.fullscreenMode, true);
427+
428+ touchFlick(shell, units.gu(2), touchStartY, units.gu(10), touchStartY, false, false);
429+
430+ tryCompare(panel, "fullscreenMode", false);
431+
432+ touchRelease(shell);
433+ }
647434 }
648435}
tests/qmltests/tst_ShellWithPin.qml+4−37
@@ -58,40 +58,6 @@ Item {
5858 when: windowShown
5959
6060 function initTestCase() {
61− var ok = false;
62− var attempts = 0;
63− var maxAttempts = 1000;
64−
65− // Qt loads a qml scene asynchronously. So early on, some findChild() calls made in
66− // tests may fail because the desired child item wasn't loaded yet.
67− // Thus here we try to ensure the scene has been fully loaded before proceeding with the tests.
68− // As I couldn't find an API in QQuickView & friends to tell me that the scene is 100% loaded
69− // (all items instantiated, etc), I resort to checking the existence of some key items until
70− // repeatedly until they're all there.
71− do {
72− var dashContentList = findChild(shell, "dashContentList");
73− waitForRendering(dashContentList);
74− var homeLoader = findChild(dashContentList, "clickscope loader");
75− ok = homeLoader !== null
76− && homeLoader.item !== undefined;
77−
78− var greeter = findChild(shell, "greeter");
79− ok &= greeter !== null;
80−
81− var launcherPanel = findChild(shell, "launcherPanel");
82− ok &= launcherPanel !== null;
83−
84− attempts++;
85− if (!ok) {
86− console.log("Attempt " + attempts + " failed. Waiting a bit before trying again.");
87− // wait a bit before retrying
88− wait(100);
89− } else {
90− console.log("All seem fine after " + attempts + " attempts.");
91− }
92− } while (!ok && attempts <= maxAttempts);
93−
94− verify(ok);
9561
9662 sessionSpy.target = findChild(shell, "greeter")
9763 }
@@ -110,10 +76,11 @@ Item {
11076 }
11177
11278 function killApps() {
113− while (ApplicationManager.count > 0) {
114− ApplicationManager.stopApplication(ApplicationManager.get(0).appId)
79+ while (ApplicationManager.count > 1) {
80+ var appIndex = ApplicationManager.get(0).appId == "unity8-dash" ? 1 : 0
81+ ApplicationManager.stopApplication(ApplicationManager.get(appIndex).appId);
11582 }
116− compare(ApplicationManager.count, 0)
83+ compare(ApplicationManager.count, 1)
11784 }
11885
11986 function swipeAwayGreeter() {