on xenial help sign in
Sessions-in-sessions
commit8183eb12dfb1c8ed92e840d0c944e3a5957cd5d2 authorNick Dedekind <nicholas.dedekind@gmail.com> dateThu 21 Aug 2014, 17:57 (12 years ago) parentf60c804
25 files changed+735−400
qml/Stages/Animations/BaseSurfaceAnimation.qml+2−2 qml/Stages/Animations/SwipeFromBottomAnimation.qml+4−4 qml/Stages/Animations/SwipeUpAnimation.qml+4−4 qml/Stages/AppSurfaceContainer.qml → qml/Stages/ApplicationSessionContainer.qml+1−47 qml/Stages/SessionContainer.qml+113 qml/Stages/SpreadDelegate.qml+6−6 qml/Stages/SurfaceContainer.qml+9−45 tests/mocks/Unity/Application/ApplicationInfo.cpp+24−73 tests/mocks/Unity/Application/ApplicationInfo.h+8−20 tests/mocks/Unity/Application/ApplicationManager.cpp+7−11 tests/mocks/Unity/Application/ApplicationManager.h+1−2 tests/mocks/Unity/Application/ApplicationTestInterface.cpp+47−22 tests/mocks/Unity/Application/ApplicationTestInterface.h+7−5 tests/mocks/Unity/Application/CMakeLists.txt+2−1 tests/mocks/Unity/Application/MirItemModel.h+108 tests/mocks/Unity/Application/MirSessionItem.cpp+172 tests/mocks/Unity/Application/MirSessionItem.h+77 tests/mocks/Unity/Application/MirSessionItemModel.h+28 tests/mocks/Unity/Application/MirSurfaceItem.cpp+17−13 tests/mocks/Unity/Application/MirSurfaceItem.h+8−6 tests/mocks/Unity/Application/MirSurfaceItemModel.cpp−102 tests/mocks/Unity/Application/MirSurfaceItemModel.h+3−37 tests/mocks/Unity/Application/SessionManager.cpp+45 tests/mocks/Unity/Application/SessionManager.h+38 tests/mocks/Unity/Application/plugin.cpp+4
qml/Stages/Animations/BaseSurfaceAnimation.qml+2−2
@@ -37,7 +37,7 @@ import QtQuick 2.0
3737 */
3838Item {
3939 id: base
40− property Item surface: null
40+ property Item session: null
4141
4242 // changes applied when state changes to "in"
4343 property list<QtObject> outChanges
@@ -61,7 +61,7 @@ Item {
6161 states: [
6262 State {
6363 name: "baseAnimation"
64− PropertyChanges { target: base.surface; anchors.fill: undefined }
64+ PropertyChanges { target: base.session; anchors.fill: undefined }
6565 },
6666
6767 State {
qml/Stages/Animations/SwipeFromBottomAnimation.qml+4−4
@@ -19,20 +19,20 @@ import QtQuick 2.0
1919BaseSurfaceAnimation {
2020 id: animation
2121
22− outChanges: [ AnchorChanges { target: animation.surface; anchors.top: animation.parent.bottom } ]
22+ outChanges: [ AnchorChanges { target: animation.session; anchors.top: animation.parent.bottom } ]
2323 outAnimations: [
2424 SequentialAnimation {
2525 PropertyAction { target: animation.parent; property: "clip"; value: true }
2626 AnchorAnimation { easing.type: Easing.InOutQuad; duration: 400 }
27− PropertyAction { target: animation.surface; property: "visible"; value: !animation.parent.removing }
27+ PropertyAction { target: animation.session; property: "visible"; value: !animation.parent.removing }
2828 PropertyAction { target: animation.parent; property: "clip"; value: false }
29− ScriptAction { script: { if (animation.parent.removing) animation.surface.release(); } }
29+ ScriptAction { script: { if (animation.parent.removing) animation.session.release(); } }
3030 }
3131 ]
3232
3333 inChanges: [
3434 AnchorChanges {
35− target: animation.surface;
35+ target: animation.session;
3636 anchors.top: animation.parent.top
3737 anchors.right: undefined
3838 anchors.bottom: undefined
qml/Stages/Animations/SwipeUpAnimation.qml+4−4
@@ -22,16 +22,16 @@ BaseSurfaceAnimation {
2222 outAnimations: [
2323 SequentialAnimation {
2424 PropertyAction { target: animation.parent; property: "clip"; value: true }
25− PropertyAction { target: animation.surface; property: "visible"; value: true }
25+ PropertyAction { target: animation.session; property: "visible"; value: true }
2626 AnchorAnimation { easing.type: Easing.InOutQuad; duration: 400 }
2727 PropertyAction { target: animation.parent; property: "clip"; value: false }
28− ScriptAction { script: { if (animation.parent.removing) animation.surface.release(); } }
28+ ScriptAction { script: { if (animation.parent.removing) animation.session.release(); } }
2929 }
3030 ]
3131
3232 inChanges: [
3333 AnchorChanges {
34− target: animation.surface;
34+ target: animation.session;
3535 anchors.top: undefined
3636 anchors.right: undefined
3737 anchors.bottom: animation.parent.top
@@ -42,7 +42,7 @@ BaseSurfaceAnimation {
4242 SequentialAnimation {
4343 PropertyAction { target: animation.parent; property: "clip"; value: true }
4444 AnchorAnimation { easing.type: Easing.InOutQuad; duration: 400 }
45− PropertyAction { target: animation.surface; property: "visible"; value: false}
45+ PropertyAction { target: animation.session; property: "visible"; value: false}
4646 PropertyAction { target: animation.parent; property: "clip"; value: false }
4747 }
4848 ]
qml/Stages/AppSurfaceContainer.qml → qml/Stages/ApplicationSessionContainer.qmlrenamed+1−47
@@ -17,10 +17,8 @@
1717import QtQuick 2.0
1818import "Animations"
1919
20−SurfaceContainer {
20+SessionContainer {
2121 id: root
22− property var promptSurfaces
23−
2422 property bool appHasCreatedASurface: false
2523
2624 onSurfaceChanged: {
@@ -49,50 +47,6 @@ SurfaceContainer {
4947 z: 3
5048 }
5149
52− Repeater {
53− id: promptRepeater
54− model: root.promptSurfaces
55−
56− delegate: SurfaceContainer {
57− objectName: "promptDelegate" + index
58− id: prompt
59−
60− anchors {
61− fill: root
62− topMargin: root.surface.anchors.topMargin
63− rightMargin: root.surface.anchors.rightMargin
64− bottomMargin: root.surface.anchors.bottomMargin
65− leftMargin: root.surface.anchors.leftMargin
66− }
67− z: 4 + index
68−
69− surface: modelData
70−
71− Component.onCompleted: {
72− prompt.animateIn(swipeFromBottom);
73− }
74−
75− Connections {
76− target: prompt.surface
77− onRemoved: {
78− // remove all prompts after this one.
79− if (index !== promptRepeater.count-1) {
80− var nextSurface = promptRepeater.itemAt(index+1).surface;
81− nextSurface.removed();
82− }
83−
84− prompt.removing = true;
85− prompt.animateOut();
86− }
87− }
88−
89− Component {
90− id: swipeFromBottom
91− SwipeFromBottomAnimation {}
92− }
93− }
94− }
95−
9650 StateGroup {
9751 id: appSurfaceState
9852 states: [
qml/Stages/SessionContainer.qmlnew file+113
@@ -0,0 +1,113 @@
1+/*
2+ * Copyright 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 Lesser General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU Lesser General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+*/
16+
17+import QtQuick 2.0
18+import "Animations"
19+
20+Item {
21+ id: root
22+ objectName: "sessionContainer"
23+ property Item session
24+ property var children: session ? session.childSessions : 0
25+ property bool removing: false
26+ property alias surface: surfaceContainer.surface
27+
28+ onSessionChanged: {
29+ if (session) {
30+ session.parent = root;
31+ session.z = 1;
32+ state = "initial"
33+ }
34+ }
35+
36+ SurfaceContainer {
37+ id: surfaceContainer
38+ anchors.fill: session
39+ z: 2;
40+
41+ surface: session ? session.surface : null
42+ onSurfaceChanged: {
43+ root.animateIn(swipeFromBottom);
44+ }
45+ }
46+
47+ Repeater {
48+ model: root.children
49+
50+ delegate: Loader {
51+ objectName: "childDelegate" + index
52+ anchors {
53+ fill: root
54+ topMargin: root.surface.anchors.topMargin
55+ rightMargin: root.surface.anchors.rightMargin
56+ bottomMargin: root.surface.anchors.bottomMargin
57+ leftMargin: root.surface.anchors.leftMargin
58+ }
59+ z: 4
60+
61+ // Only way to do recursive qml items.
62+ source: Qt.resolvedUrl("SessionContainer.qml")
63+ onLoaded: {
64+ item.session = modelData;
65+ }
66+
67+ Connections {
68+ target: modelData
69+ onRemoved: {
70+ item.animateOut();
71+ }
72+ }
73+ }
74+ }
75+
76+ function animateIn(animationComponent) {
77+ var animation = animationComponent.createObject(root, { "session": root.session });
78+ animation.start();
79+
80+ var tmp = d.animations;
81+ tmp.push(animation);
82+ d.animations = tmp;
83+ }
84+
85+ function animateOut() {
86+ if (d.animations.length > 0) {
87+ var tmp = d.animations;
88+ var popped = tmp.pop();
89+ popped.end();
90+ d.animations = tmp;
91+ } else {
92+ root.state = "initial";
93+ }
94+ }
95+
96+ QtObject {
97+ id: d
98+ property var animations: []
99+ property var currentAnimation: animations.length > 0 ? animations[animations.length-1] : undefined
100+ }
101+
102+ Component {
103+ id: swipeFromBottom
104+ SwipeFromBottomAnimation {}
105+ }
106+
107+ states: [
108+ State {
109+ name: "initial"
110+ PropertyChanges { target: session; anchors.fill: root }
111+ }
112+ ]
113+}
qml/Stages/SpreadDelegate.qml+6−6
@@ -29,24 +29,24 @@ Item {
2929 property bool dropShadow: true
3030 property real maximizedAppTopMargin
3131 property alias swipeToCloseEnabled: dragArea.enabled
32+ property alias surface: surfaceContainer.surface
3233
33− readonly property bool isFullscreen: surface !== null && surfaceContainer.surface.anchors.topMargin == 0
34+ readonly property bool isFullscreen: surface !== null && session.anchors.topMargin == 0
3435
3536 signal clicked()
3637 signal closed()
3738
38− AppSurfaceContainer {
39+ ApplicationSessionContainer {
3940 id: surfaceContainer
4041 objectName: "surfaceContainer"
4142 anchors.fill: parent
42− surface: model.surface
43− promptSurfaces: model.promptSurfaces
43+ session: model.session
4444
4545 Binding {
46− target: surfaceContainer.surface
46+ target: surface
4747 property: "anchors.topMargin"
4848 value: {
49− return surfaceContainer.surface == null ||
49+ return surface == null ||
5050 surfaceContainer.surface.state === MirSurfaceItem.Fullscreen ? 0 : maximizedAppTopMargin;
5151 }
5252 }
qml/Stages/SurfaceContainer.qml+9−45
@@ -25,6 +25,7 @@ Item {
2525 property bool removing: false
2626
2727 onSurfaceChanged: {
28+ console.log("SURFACE " + surface)
2829 if (surface) {
2930 surface.parent = root;
3031 surface.z = 1;
@@ -32,18 +33,19 @@ Item {
3233 }
3334 }
3435
36+ Connections {
37+ target: surface
38+ onRemoved: {
39+ surface.release();
40+ }
41+ }
42+
3543 Repeater {
3644 model: root.childSurfaces
3745
3846 delegate: Loader {
3947 objectName: "childDelegate" + index
40− anchors {
41− fill: root
42− topMargin: root.surface.anchors.topMargin
43− rightMargin: root.surface.anchors.rightMargin
44− bottomMargin: root.surface.anchors.bottomMargin
45− leftMargin: root.surface.anchors.leftMargin
46− }
48+ anchors.fill: root
4749 z: 2
4850
4951 // Only way to do recursive qml items.
@@ -51,47 +53,9 @@ Item {
5153 onLoaded: {
5254 item.surface = modelData;
5355 }
54−
55− Connections {
56− target: modelData
57− onRemoved: {
58− modelData.release()
59− }
60− }
61− }
62− }
63−
64− function animateIn(animationComponent) {
65− var animation = animationComponent.createObject(root, { "surface": root.surface });
66− animation.start();
67−
68− var tmp = d.animations;
69− tmp.push(animation);
70− d.animations = tmp;
71− }
72−
73− function animateOut() {
74− if (d.animations.length > 0) {
75− var tmp = d.animations;
76− var popped = tmp.pop();
77− popped.end();
78− d.animations = tmp;
79− } else {
80− root.state = "initial";
8156 }
8257 }
8358
84− QtObject {
85− id: d
86− property var animations: []
87− property var currentAnimation: animations.length > 0 ? animations[animations.length-1] : undefined
88− }
89−
90− Component {
91− id: swipeFromBottom
92− SwipeFromBottomAnimation {}
93− }
94−
9559 states: [
9660 State {
9761 name: "initial"
tests/mocks/Unity/Application/ApplicationInfo.cpp+24−73
@@ -15,14 +15,13 @@
1515 */
1616
1717#include "ApplicationInfo.h"
18−#include "MirSurfaceItem.h"
19−#include "MirSurfaceItemModel.h"
18+#include "MirSessionItem.h"
19+#include "SessionManager.h"
2020
2121#include <QGuiApplication>
2222#include <QQuickItem>
2323#include <QQuickView>
2424#include <QQmlComponent>
25−#include <QTimer>
2625
2726ApplicationInfo::ApplicationInfo(const QString &appId, QObject *parent)
2827 : ApplicationInfoInterface(appId, parent)
@@ -32,10 +31,9 @@ ApplicationInfo::ApplicationInfo(const QString &appId, QObject *parent)
3231 , m_focused(false)
3332 , m_fullscreen(false)
3433 , m_parentItem(0)
35− , m_surface(0)
36− , m_promptSurfaces(new MirSurfaceItemModel(this))
34+ , m_session(0)
3735{
38− connect(this, &ApplicationInfo::stateChanged, this, &ApplicationInfo::onStateChanged);
36+ createSession();
3937}
4038
4139ApplicationInfo::ApplicationInfo(QObject *parent)
@@ -45,89 +43,42 @@ ApplicationInfo::ApplicationInfo(QObject *parent)
4543 , m_focused(false)
4644 , m_fullscreen(false)
4745 , m_parentItem(0)
48− , m_surface(0)
49− , m_promptSurfaces(new MirSurfaceItemModel(this))
46+ , m_session(0)
5047{
51− connect(this, &ApplicationInfo::stateChanged, this, &ApplicationInfo::onStateChanged);
48+ createSession();
5249}
5350
5451ApplicationInfo::~ApplicationInfo()
5552{
56− QList<MirSurfaceItem*> promptSurfaces(m_promptSurfaces->list());
57− for (MirSurfaceItem* promptSurface : promptSurfaces) {
58− delete promptSurface;
59− }
60−
61− delete m_surface;
62− delete m_promptSurfaces;
53+ delete m_session;
6354}
6455
65−void ApplicationInfo::onStateChanged(State state)
56+void ApplicationInfo::createSession()
6657{
67− if (state == ApplicationInfo::Running) {
68− QTimer::singleShot(1000, this, SLOT(createSurface()));
69− } else if (state == ApplicationInfo::Stopped) {
70− setSurface(nullptr);
71− }
58+ setSession(SessionManager::singleton()->createSession(name(), screenshot()));
7259}
7360
74−void ApplicationInfo::createSurface()
61+void ApplicationInfo::setSession(MirSessionItem* session)
7562{
76− if (m_surface || state() == ApplicationInfo::Stopped) return;
77−
78− setSurface(SurfaceManager::singleton()->createSurface(name(),
79− MirSurfaceItem::Normal,
80− fullscreen() ? MirSurfaceItem::Fullscreen : MirSurfaceItem::Maximized,
81− screenshot()));
82−}
83−
84−void ApplicationInfo::setSurface(MirSurfaceItem* surface)
85−{
86− qDebug() << "Application::setSurface - appId=" << appId() << "surface=" << surface;
87− if (m_surface == surface)
63+ qDebug() << "Application::setSession - appId=" << appId() << "session=" << session;
64+ if (m_session == session)
8865 return;
8966
90− if (m_surface) {
91− m_surface->setApplication(nullptr);
92− m_surface->setParent(nullptr);
67+ if (m_session) {
68+ disconnect(this, 0, m_session, 0);
69+ m_session->setApplication(nullptr);
70+ m_session->setParent(nullptr);
9371 }
9472
95− m_surface = surface;
96−
97− if (m_surface) {
98− m_surface->setApplication(this);
99− m_surface->setParent(this);
100− }
101−
102− Q_EMIT surfaceChanged(m_surface);
103−}
104−
105−void ApplicationInfo::addPromptSurface(MirSurfaceItem* surface)
106−{
107− insertPromptSurface(m_promptSurfaces->count(), surface);
108−}
109−
110−void ApplicationInfo::insertPromptSurface(uint index, MirSurfaceItem* surface)
111−{
112− qDebug() << "ApplicationInfo::insertPromptSurface - " << surface->name() << " to " << name() << " @ " << index;
73+ m_session = session;
11374
114− surface->setApplication(this);
115− m_promptSurfaces->insertSurface(index, surface);
116−}
117−
118−void ApplicationInfo::removeSurface(MirSurfaceItem* surface)
119−{
120− qDebug() << "Application::removeSurface - " << surface->name() << " from " << name();
121−
122− if (m_surface == surface) {
123− setSurface(nullptr);
124− } else {
125− m_promptSurfaces->removeSurface(surface);
126− surface->setApplication(nullptr);
75+ if (m_session) {
76+ m_session->setApplication(this);
77+ m_session->setParent(this);
78+ connect(this, &ApplicationInfo::screenshotChanged, m_session, [this](const QUrl& screenshot) {
79+ m_session->setScreenshot(screenshot);
80+ });
12781 }
128−}
12982
130−MirSurfaceItemModel* ApplicationInfo::promptSurfaces() const
131−{
132− return m_promptSurfaces;
83+ Q_EMIT sessionChanged(m_session);
13384}
tests/mocks/Unity/Application/ApplicationInfo.h+8−20
@@ -18,13 +18,13 @@
1818#define APPLICATION_H
1919
2020#include "SurfaceManager.h"
21+#include "MirSurfaceItemModel.h"
2122
2223#include <QObject>
2324#include <QQmlComponent>
2425
2526class QQuickItem;
2627class MirSurfaceItem;
27−class MirSurfaceItemModel;
2828
2929// unity-api
3030#include <unity/shell/application/ApplicationInfoInterface.h>
@@ -40,8 +40,7 @@ class ApplicationInfo : public ApplicationInfoInterface {
4040
4141 Q_PROPERTY(bool fullscreen READ fullscreen WRITE setFullscreen NOTIFY fullscreenChanged)
4242 Q_PROPERTY(Stage stage READ stage WRITE setStage NOTIFY stageChanged)
43− Q_PROPERTY(MirSurfaceItem* surface READ surface NOTIFY surfaceChanged)
44− Q_PROPERTY(MirSurfaceItemModel* promptSurfaces READ promptSurfaces DESIGNABLE false CONSTANT)
43+ Q_PROPERTY(MirSessionItem* session READ session NOTIFY sessionChanged)
4544
4645 // Only exists in this fake implementation
4746
@@ -86,30 +85,19 @@ public:
8685 #undef IMPLEMENT_PROPERTY
8786
8887public:
89− void setSurface(MirSurfaceItem* surface);
90− MirSurfaceItem* surface() const { return m_surface; }
91−
92− void removeSurface(MirSurfaceItem* surface);
93−
94− void addPromptSurface(MirSurfaceItem* surface);
95− void insertPromptSurface(uint index, MirSurfaceItem* surface);
96− MirSurfaceItemModel* promptSurfaces() const;
88+ void setSession(MirSessionItem* session);
89+ MirSessionItem* session() const { return m_session; }
9790
9891Q_SIGNALS:
99− void surfaceChanged(MirSurfaceItem*);
100−
101−private Q_SLOTS:
102− void onStateChanged(State state);
103−
104− void createSurface();
92+ void sessionChanged(MirSessionItem*);
10593
10694private:
95+ void createSession();
96+
10797 QQuickItem *m_parentItem;
108− MirSurfaceItem* m_surface;
109− MirSurfaceItemModel* m_promptSurfaces;
98+ MirSessionItem* m_session;
11099};
111100
112101Q_DECLARE_METATYPE(ApplicationInfo*)
113−Q_DECLARE_METATYPE(QQmlListProperty<MirSurfaceItem>)
114102
115103#endif // APPLICATION_H
tests/mocks/Unity/Application/ApplicationManager.cpp+7−11
@@ -16,8 +16,7 @@
1616
1717#include "ApplicationManager.h"
1818#include "ApplicationInfo.h"
19−#include "MirSurfaceItem.h"
20−#include "MirSurfaceItemModel.h"
19+#include "MirSessionItem.h"
2120#include "ApplicationTestInterface.h"
2221
2322#include <paths.h>
@@ -45,9 +44,8 @@ ApplicationManager::ApplicationManager(QObject *parent)
4544 : ApplicationManagerInterface(parent)
4645 , m_suspended(false)
4746{
48− m_roleNames.insert(RoleSurface, "surface");
47+ m_roleNames.insert(RoleSession, "session");
4948 m_roleNames.insert(RoleFullscreen, "fullscreen");
50− m_roleNames.insert(RolePromptSurfaces, "promptSurfaces");
5149
5250 buildListOfAvailableApplications();
5351
@@ -85,12 +83,10 @@ QVariant ApplicationManager::data(const QModelIndex& index, int role) const {
8583 return app->focused();
8684 case RoleScreenshot:
8785 return app->screenshot();
88− case RoleSurface:
89− return QVariant::fromValue(app->surface());
86+ case RoleSession:
87+ return QVariant::fromValue(app->session());
9088 case RoleFullscreen:
9189 return app->fullscreen();
92− case RolePromptSurfaces:
93− return QVariant::fromValue(app->promptSurfaces());
9490 default:
9591 return QVariant();
9692 }
@@ -134,10 +130,10 @@ void ApplicationManager::add(ApplicationInfo *application) {
134130 Q_EMIT countChanged();
135131 if (count() == 1) Q_EMIT emptyChanged(isEmpty()); // was empty but not anymore
136132
137− connect(application, &ApplicationInfo::surfaceChanged, this, [application, this]() {
133+ connect(application, &ApplicationInfo::sessionChanged, this, [application, this]() {
138134 QModelIndex appIndex = findIndex(application);
139135 if (!appIndex.isValid()) return;
140− Q_EMIT dataChanged(appIndex, appIndex, QVector<int>() << ApplicationManager::RoleSurface);
136+ Q_EMIT dataChanged(appIndex, appIndex, QVector<int>() << ApplicationManager::RoleSession);
141137 });
142138}
143139
@@ -151,7 +147,7 @@ void ApplicationManager::remove(ApplicationInfo *application) {
151147 Q_EMIT countChanged();
152148 if (isEmpty()) Q_EMIT emptyChanged(isEmpty());
153149 }
154− disconnect(application, &ApplicationInfo::surfaceChanged, this, 0);
150+ disconnect(application, &ApplicationInfo::sessionChanged, this, 0);
155151}
156152
157153void ApplicationManager::move(int from, int to) {
tests/mocks/Unity/Application/ApplicationManager.h+1−2
@@ -51,9 +51,8 @@ class ApplicationManager : public ApplicationManagerInterface {
5151 static ApplicationManager *singleton();
5252
5353 enum MoreRoles {
54− RoleSurface = RoleScreenshot+1,
54+ RoleSession = RoleScreenshot+1,
5555 RoleFullscreen,
56− RolePromptSurfaces,
5756 };
5857 enum Role {
5958 Dash, Default, Indicators, Notifications, Greeter, Launcher, OnScreenKeyboard,
tests/mocks/Unity/Application/ApplicationTestInterface.cpp+47−22
@@ -17,9 +17,10 @@
1717#include "ApplicationInfo.h"
1818#include "ApplicationTestInterface.h"
1919#include "ApplicationManager.h"
20+#include "SessionManager.h"
2021#include "SurfaceManager.h"
22+#include "MirSessionItem.h"
2123#include "MirSurfaceItem.h"
22−#include "MirSurfaceItemModel.h"
2324
2425quint32 nextId = 0;
2526
@@ -31,29 +32,51 @@ ApplicationTestInterface::ApplicationTestInterface(QObject* parent)
3132 connection.registerObject("/com/canonical/Unity8/Mocks", parent);
3233}
3334
34−quint32 ApplicationTestInterface::addPromptSurface(const QString &appId, const QString &surfaceImage)
35+quint32 ApplicationTestInterface::addChildSession(const QString& appId, quint32 existingSessionId, const QString& surfaceImage)
3536{
36− qDebug() << "ApplicationTestInterface::addPromptSurface to " << appId;
37+ qDebug() << "ApplicationTestInterface::addChildSession to " << appId;
3738
3839 ApplicationInfo* application = ApplicationManager::singleton()->findApplication(appId);
3940 if (!application) {
40− qDebug() << "ApplicationTestInterface::addPromptSurface - No application found for " << appId;
41+ qDebug() << "ApplicationTestInterface::addChildSession - No application found for " << appId;
4142 return 0;
4243 }
43− quint32 surfaceId = ++nextId;
44− MirSurfaceItem* surface = SurfaceManager::singleton()->createSurface(
45− QString("%1-Prompt%2").arg(appId)
46− .arg(surfaceId),
47− MirSurfaceItem::Normal,
48− MirSurfaceItem::Maximized,
44+
45+ MirSessionItem* parentSession = nullptr;
46+ if (m_childSessions.contains(existingSessionId)) {
47+ parentSession = m_childSessions[existingSessionId];
48+ } else if (application->session()) {
49+ parentSession = application->session();
50+ } else {
51+ qDebug() << "ApplicationTestInterface::addChildSession - No session for " << appId << ":" << existingSessionId;
52+ return 0;
53+ }
54+
55+ quint32 sessionId = ++nextId;
56+ MirSessionItem* session = SessionManager::singleton()->createSession(
57+ QString("%1-Child%2").arg(parentSession->name())
58+ .arg(sessionId),
4959 QUrl(surfaceImage));
50− m_childItems[surfaceId] = surface;
51− application->addPromptSurface(surface);
60+ parentSession->addChildSession(session);
61+ session->createSurface();
62+ m_childSessions[sessionId] = session;
5263
53− return surfaceId;
64+ return sessionId;
65+}
66+
67+void ApplicationTestInterface::removeSession(quint32 sessionId)
68+{
69+ qDebug() << "ApplicationTestInterface::removeSession - " << sessionId;
70+
71+ if (!m_childSessions.contains(sessionId)) {
72+ qDebug() << "ApplicationTestInterface::removeSession - No added session for " << sessionId;
73+ return;
74+ }
75+ MirSessionItem* session = m_childSessions.take(sessionId);
76+ Q_EMIT session->removed();
5477}
5578
56−quint32 ApplicationTestInterface::addChildSurface(const QString& appId, const quint32 existingSurfaceId, const QString& surfaceImage)
79+quint32 ApplicationTestInterface::addChildSurface(const QString& appId, quint32 existingSessionId, quint32 existingSurfaceId, const QString& surfaceImage)
5780{
5881 qDebug() << "ApplicationTestInterface::addChildSurface to " << appId;
5982
@@ -64,10 +87,12 @@ quint32 ApplicationTestInterface::addChildSurface(const QString& appId, const qu
6487 }
6588
6689 MirSurfaceItem* parentSurface = nullptr;
67− if (m_childItems.contains(existingSurfaceId)) {
68− parentSurface = m_childItems[existingSurfaceId];
69− } else if (application->surface()) {
70− parentSurface = application->surface();
90+ if (m_childSessions.contains(existingSessionId) && m_childSessions[existingSessionId]->surface()) {
91+ parentSurface = m_childSessions[existingSessionId]->surface();
92+ } else if (m_childSurfaces.contains(existingSurfaceId)) {
93+ parentSurface = m_childSurfaces[existingSurfaceId];
94+ } else if (application->session() && application->session()->surface()) {
95+ parentSurface = application->session()->surface();
7196 } else {
7297 qDebug() << "ApplicationTestInterface::addChildSurface - No surface for " << appId << ":" << existingSurfaceId;
7398 return 0;
@@ -81,19 +106,19 @@ quint32 ApplicationTestInterface::addChildSurface(const QString& appId, const qu
81106 MirSurfaceItem::Maximized,
82107 QUrl(surfaceImage));
83108 parentSurface->addChildSurface(surface);
84− m_childItems[surfaceId] = surface;
109+ m_childSurfaces[surfaceId] = surface;
85110
86111 return surfaceId;
87112}
88113
89−void ApplicationTestInterface::removeSurface(int surfaceId)
114+void ApplicationTestInterface::removeSurface(quint32 surfaceId)
90115{
91116 qDebug() << "ApplicationTestInterface::removeSurface - " << surfaceId;
92117
93− if (!m_childItems.contains(surfaceId)) {
118+ if (!m_childSurfaces.contains(surfaceId)) {
94119 qDebug() << "ApplicationTestInterface::removeSurface - No added surface for " << surfaceId;
95120 return;
96121 }
97− MirSurfaceItem* surface = m_childItems.take(surfaceId);
122+ MirSurfaceItem* surface = m_childSurfaces.take(surfaceId);
98123 Q_EMIT surface->removed();
99124}
tests/mocks/Unity/Application/ApplicationTestInterface.h+7−5
@@ -20,7 +20,7 @@
2020#include <QtDBus/QtDBus>
2121
2222class ApplicationManager;
23−class SurfaceManager;
23+class MirSessionItem;
2424class MirSurfaceItem;
2525
2626class ApplicationTestInterface : public QDBusAbstractAdaptor
@@ -31,12 +31,14 @@ public:
3131 ApplicationTestInterface(QObject* parent = 0);
3232
3333public Q_SLOTS:
34− Q_INVOKABLE quint32 addPromptSurface(const QString& appId, const QString& surfaceImage);
35− Q_INVOKABLE quint32 addChildSurface(const QString& appId, const quint32 existingSurfaceId, const QString& surfaceImage);
36− Q_INVOKABLE void removeSurface(int surfaceId);
34+ Q_INVOKABLE quint32 addChildSession(const QString& appId, quint32 existingSessionId, const QString& surfaceImage);
35+ Q_INVOKABLE quint32 addChildSurface(const QString& appId, quint32 existingSessionId, quint32 existingSurfaceId, const QString& surfaceImage);
36+ Q_INVOKABLE void removeSession(quint32 sessionId);
37+ Q_INVOKABLE void removeSurface(quint32 surfaceId);
3738
3839private:
39− QHash<quint32, MirSurfaceItem*> m_childItems;
40+ QHash<quint32, MirSessionItem*> m_childSessions;
41+ QHash<quint32, MirSurfaceItem*> m_childSurfaces;
4042};
4143
4244#endif // APPLICATIONTESTINTERFACE_H
tests/mocks/Unity/Application/CMakeLists.txt+2−1
@@ -7,8 +7,9 @@ set(FakeUnityApplicationQml_SOURCES
77 ApplicationManager.cpp
88 ApplicationScreenshotProvider.cpp
99 ApplicationTestInterface.cpp
10+ MirSessionItem.cpp
1011 MirSurfaceItem.cpp
11− MirSurfaceItemModel.cpp
12+ SessionManager.cpp
1213 SurfaceManager.cpp
1314 VirtualKeyboard.cpp
1415 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationInfoInterface.h
tests/mocks/Unity/Application/MirItemModel.hnew file+108
@@ -0,0 +1,108 @@
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 MIRITEMMODEL_H
18+#define MIRITEMMODEL_H
19+
20+// Qt
21+#include <QAbstractListModel>
22+
23+class MirSurfaceItem;
24+
25+template<class TYPE>
26+class MirItemModel : public QAbstractListModel
27+{
28+public:
29+ MirItemModel(QObject *parent = 0)
30+ : QAbstractListModel(parent)
31+ {}
32+
33+ enum Roles {
34+ RoleModelData = Qt::UserRole,
35+ };
36+
37+ const QList<TYPE*>& list() const { return m_items; }
38+ bool contains(TYPE* item) const { return m_items.contains(item); }
39+
40+ void insert(uint index, TYPE* item)
41+ {
42+ index = qMin(index, (uint)m_items.count());
43+
44+ int existingIndex = m_items.indexOf(item);
45+ if (existingIndex != -1) {
46+ move(existingIndex, index);
47+ } else {
48+ beginInsertRows(QModelIndex(), index, index);
49+ m_items.insert(index, item);
50+ endInsertRows();
51+ }
52+ }
53+
54+ void remove(TYPE* item)
55+ {
56+ int existingIndex = m_items.indexOf(item);
57+ if (existingIndex != -1) {
58+ beginRemoveRows(QModelIndex(), existingIndex, existingIndex);
59+ m_items.removeAt(existingIndex);
60+ endRemoveRows();
61+ }
62+ }
63+
64+ // from QAbstractItemModel
65+ int rowCount(const QModelIndex& = QModelIndex()) const override
66+ {
67+ return m_items.count();
68+ }
69+
70+ QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const override
71+ {
72+ if (index.row() >= 0 && index.row() < m_items.count()) {
73+ if (role == RoleModelData) {
74+ TYPE *item = m_items.at(index.row());
75+ return QVariant::fromValue(item);
76+ }
77+ }
78+ return QVariant();
79+ }
80+
81+ QHash<int, QByteArray> roleNames() const
82+ {
83+ QHash<int, QByteArray> roleNames;
84+ roleNames.insert(RoleModelData, "modelData");
85+ return roleNames;
86+ }
87+
88+private:
89+ void move(int from, int to)
90+ {
91+ if (from == to) return;
92+
93+ if (from >= 0 && from < m_items.size() && to >= 0 && to < m_items.size()) {
94+ QModelIndex parent;
95+ /* When moving an item down, the destination index needs to be incremented
96+ by one, as explained in the documentation:
97+ http://qt-project.org/doc/qt-5.0/qtcore/qabstractitemmodel.html#beginMoveRows */
98+
99+ beginMoveRows(parent, from, from, parent, to + (to > from ? 1 : 0));
100+ m_items.move(from, to);
101+ endMoveRows();
102+ }
103+ }
104+
105+ QList<TYPE*> m_items;
106+};
107+
108+#endif // MIRITEMMODEL_H
tests/mocks/Unity/Application/MirSessionItem.cppnew file+172
@@ -0,0 +1,172 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include "MirSessionItem.h"
18+#include "ApplicationInfo.h"
19+#include "SurfaceManager.h"
20+
21+#include <QPainter>
22+#include <QQmlEngine>
23+#include <QTimer>
24+
25+MirSessionItem::MirSessionItem(const QString &name,
26+ const QUrl& screenshot,
27+ QQuickItem *parent)
28+ : QQuickItem(parent)
29+ , m_name(name)
30+ , m_screenshot(screenshot)
31+ , m_application(nullptr)
32+ , m_surface(nullptr)
33+ , m_parentSession(nullptr)
34+ , m_children(new MirSessionItemModel(this))
35+{
36+ qDebug() << "MirSessionItem::MirSessionItem() " << this->name();
37+
38+ QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);
39+}
40+
41+MirSessionItem::~MirSessionItem()
42+{
43+ qDebug() << "MirSessionItem::~MirSessionItem() " << name();
44+
45+ QList<MirSessionItem*> children(m_children->list());
46+ for (MirSessionItem* child : children) {
47+ delete child;
48+ }
49+ if (m_parentSession) {
50+ m_parentSession->removeChildSession(this);
51+ }
52+ if (m_application) {
53+ m_application->setSession(nullptr);
54+ }
55+ delete m_surface;
56+ delete m_children;
57+}
58+
59+void MirSessionItem::release()
60+{
61+ qDebug() << "MirSessionItem::release " << name();
62+
63+ if (m_parentSession) {
64+ m_parentSession->removeChildSession(this);
65+ }
66+ if (m_application) {
67+ m_application->setSession(nullptr);
68+ }
69+ if (!parent()) {
70+ deleteLater();
71+ }
72+}
73+
74+void MirSessionItem::setApplication(ApplicationInfo* application)
75+{
76+ if (m_application == application)
77+ return;
78+
79+ if (m_application) {
80+ disconnect(m_application, 0, this, 0);
81+ }
82+
83+ m_application = application;
84+
85+ if (m_application) {
86+ connect(m_application, &ApplicationInfo::stateChanged, this, [this](ApplicationInfo::State state) {
87+ if (state == ApplicationInfo::Running) {
88+ QTimer::singleShot(500, this, SLOT(createSurface()));
89+ } else if (state == ApplicationInfo::Stopped) {
90+ setSurface(nullptr);
91+ }
92+ });
93+ }
94+}
95+
96+void MirSessionItem::setSurface(MirSurfaceItem* surface)
97+{
98+ qDebug() << "MirSessionItem::setSurface - session=" << name() << "surface=" << surface;
99+ if (m_surface == surface)
100+ return;
101+
102+ if (m_surface) {
103+ m_surface->setSession(nullptr);
104+ m_surface->setParent(nullptr);
105+ }
106+
107+ m_surface = surface;
108+
109+ if (m_surface) {
110+ m_surface->setSession(this);
111+ m_surface->setParent(this);
112+ }
113+
114+ Q_EMIT surfaceChanged(m_surface);
115+}
116+
117+void MirSessionItem::setScreenshot(const QUrl& screenshot)
118+{
119+ if (screenshot != m_screenshot) {
120+ m_screenshot = screenshot;
121+ if (m_surface) {
122+ m_surface->setScreenshot(m_screenshot);
123+ }
124+ }
125+}
126+
127+void MirSessionItem::setParentSession(MirSessionItem* session)
128+{
129+ if (m_parentSession == session || session == this)
130+ return;
131+
132+ m_parentSession = session;
133+ Q_EMIT parentSessionChanged(session);
134+}
135+
136+void MirSessionItem::createSurface()
137+{
138+ if (m_surface) return;
139+
140+ setSurface(SurfaceManager::singleton()->createSurface(name(),
141+ MirSurfaceItem::Normal,
142+ m_application && m_application->fullscreen() ? MirSurfaceItem::Fullscreen : MirSurfaceItem::Maximized,
143+ m_screenshot));
144+}
145+
146+void MirSessionItem::addChildSession(MirSessionItem* session)
147+{
148+ insertChildSession(m_children->rowCount(), session);
149+}
150+
151+void MirSessionItem::insertChildSession(uint index, MirSessionItem* session)
152+{
153+ qDebug() << "MirSessionItem::insertChildSession - " << session->name() << " to " << name() << " @ " << index;
154+
155+ session->setParentSession(this);
156+ m_children->insert(index, session);
157+}
158+
159+void MirSessionItem::removeChildSession(MirSessionItem* session)
160+{
161+ qDebug() << "MirSessionItem::removeChildSession - " << session->name() << " from " << name();
162+
163+ if (m_children->contains(session)) {
164+ m_children->remove(session);
165+ session->setParentSession(nullptr);
166+ }
167+}
168+
169+MirSessionItemModel* MirSessionItem::childSessions() const
170+{
171+ return m_children;
172+}
tests/mocks/Unity/Application/MirSessionItem.hnew file+77
@@ -0,0 +1,77 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#ifndef MIRSESSIONITEM_H
18+#define MIRSESSIONITEM_H
19+
20+#include "MirSessionItemModel.h"
21+
22+#include <QQuickItem>
23+
24+class ApplicationInfo;
25+
26+class MirSessionItem : public QQuickItem
27+{
28+ Q_OBJECT
29+ Q_PROPERTY(MirSurfaceItem* surface READ surface NOTIFY surfaceChanged)
30+ Q_PROPERTY(MirSessionItem* parentSession READ parentSession NOTIFY parentSessionChanged DESIGNABLE false)
31+ Q_PROPERTY(MirSessionItemModel* childSessions READ childSessions DESIGNABLE false CONSTANT)
32+
33+public:
34+ explicit MirSessionItem(const QString &name,
35+ const QUrl& screenshot,
36+ QQuickItem *parent = 0);
37+ ~MirSessionItem();
38+
39+ Q_INVOKABLE void release();
40+
41+ //getters
42+ QString name() const { return m_name; }
43+ ApplicationInfo* application() const { return m_application; }
44+ MirSurfaceItem* surface() const { return m_surface; }
45+ MirSessionItem* parentSession() const { return m_parentSession; }
46+
47+ void setApplication(ApplicationInfo* item);
48+ void setSurface(MirSurfaceItem* surface);
49+ void setScreenshot(const QUrl& m_screenshot);
50+
51+ void addChildSession(MirSessionItem* session);
52+ void insertChildSession(uint index, MirSessionItem* session);
53+ void removeChildSession(MirSessionItem* session);
54+
55+Q_SIGNALS:
56+ void surfaceChanged(MirSurfaceItem*);
57+ void parentSessionChanged(MirSessionItem*);
58+ void removed();
59+
60+public Q_SLOTS:
61+ void createSurface();
62+
63+private:
64+ MirSessionItemModel* childSessions() const;
65+ void setParentSession(MirSessionItem* session);
66+
67+ QString m_name;
68+ QUrl m_screenshot;
69+ ApplicationInfo* m_application;
70+ MirSurfaceItem* m_surface;
71+ MirSessionItem* m_parentSession;
72+ MirSessionItemModel* m_children;
73+};
74+
75+Q_DECLARE_METATYPE(MirSessionItem*)
76+
77+#endif // MIRSESSIONITEM_H
tests/mocks/Unity/Application/MirSessionItemModel.hnew file+28
@@ -0,0 +1,28 @@
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 MIRSESSIONITEMMODEL_H
18+#define MIRSESSIONITEMMODEL_H
19+
20+// Local
21+#include "MirItemModel.h"
22+
23+class MirSessionItem;
24+typedef MirItemModel<MirSessionItem> MirSessionItemModel;
25+
26+Q_DECLARE_METATYPE(MirSessionItemModel*)
27+
28+#endif // MIRSESSIONITEMMODEL_H
tests/mocks/Unity/Application/MirSurfaceItem.cpp+17−13
@@ -15,8 +15,7 @@
1515 */
1616
1717#include "MirSurfaceItem.h"
18−#include "MirSurfaceItemModel.h"
19−#include "ApplicationInfo.h"
18+#include "MirSessionItem.h"
2019
2120#include <QPainter>
2221#include <QQmlEngine>
@@ -27,7 +26,7 @@ MirSurfaceItem::MirSurfaceItem(const QString& name,
2726 const QUrl& screenshot,
2827 QQuickItem *parent)
2928 : QQuickPaintedItem(parent)
30− , m_application(nullptr)
29+ , m_session(nullptr)
3130 , m_name(name)
3231 , m_type(type)
3332 , m_state(state)
@@ -60,8 +59,8 @@ MirSurfaceItem::~MirSurfaceItem()
6059 if (m_parentSurface) {
6160 m_parentSurface->removeChildSurface(this);
6261 }
63− if (m_application) {
64− m_application->removeSurface(this);
62+ if (m_session) {
63+ m_session->setSurface(nullptr);
6564 }
6665 delete m_children;
6766}
@@ -80,18 +79,23 @@ void MirSurfaceItem::release()
8079 if (m_parentSurface) {
8180 m_parentSurface->removeChildSurface(this);
8281 }
83−
84− if (m_application) {
85− m_application->removeSurface(this);
82+ if (m_session) {
83+ m_session->setSurface(nullptr);
8684 }
8785 if (!parent()) {
8886 deleteLater();
8987 }
9088}
9189
92−void MirSurfaceItem::setApplication(ApplicationInfo* application)
90+void MirSurfaceItem::setSession(MirSessionItem* session)
91+{
92+ m_session = session;
93+}
94+
95+void MirSurfaceItem::setScreenshot(const QUrl& screenshot)
9396{
94− m_application = application;
97+ m_img.load(screenshot.isLocalFile() ? screenshot.toLocalFile() : screenshot.toString());
98+ update();
9599}
96100
97101void MirSurfaceItem::setParentSurface(MirSurfaceItem* surface)
@@ -105,7 +109,7 @@ void MirSurfaceItem::setParentSurface(MirSurfaceItem* surface)
105109
106110void MirSurfaceItem::addChildSurface(MirSurfaceItem* surface)
107111{
108− insertChildSurface(m_children->count(), surface);
112+ insertChildSurface(m_children->rowCount(), surface);
109113}
110114
111115void MirSurfaceItem::insertChildSurface(uint index, MirSurfaceItem* surface)
@@ -113,7 +117,7 @@ void MirSurfaceItem::insertChildSurface(uint index, MirSurfaceItem* surface)
113117 qDebug() << "MirSurfaceItem::insertChildSurface - " << surface->name() << " to " << name() << " @ " << index;
114118
115119 surface->setParentSurface(this);
116− m_children->insertSurface(index, surface);
120+ m_children->insert(index, surface);
117121}
118122
119123void MirSurfaceItem::removeChildSurface(MirSurfaceItem* surface)
@@ -121,7 +125,7 @@ void MirSurfaceItem::removeChildSurface(MirSurfaceItem* surface)
121125 qDebug() << "MirSurfaceItem::removeChildSurface - " << surface->name() << " from " << name();
122126
123127 if (m_children->contains(surface)) {
124− m_children->removeSurface(surface);
128+ m_children->remove(surface);
125129 surface->setParentSurface(nullptr);
126130 }
127131}
tests/mocks/Unity/Application/MirSurfaceItem.h+8−6
@@ -17,11 +17,12 @@
1717#ifndef MIRSURFACEITEM_H
1818#define MIRSURFACEITEM_H
1919
20+#include "MirSurfaceItemModel.h"
21+
2022#include <QQuickPaintedItem>
2123#include <QImage>
2224
23−class ApplicationInfo;
24−class MirSurfaceItemModel;
25+class MirSessionItem;
2526
2627class MirSurfaceItem : public QQuickPaintedItem
2728{
@@ -59,13 +60,14 @@ public:
5960 ~MirSurfaceItem();
6061
6162 //getters
62− ApplicationInfo* application() const { return m_application; }
63+ MirSessionItem* session() const { return m_session; }
6364 Type type() const { return m_type; }
6465 State state() const { return m_state; }
6566 QString name() const { return m_name; }
6667 MirSurfaceItem* parentSurface() const { return m_parentSurface; }
6768
68− void setApplication(ApplicationInfo* item);
69+ void setSession(MirSessionItem* item);
70+ void setScreenshot(const QUrl& screenshot);
6971
7072 Q_INVOKABLE void setState(State newState);
7173 Q_INVOKABLE void release();
@@ -106,11 +108,11 @@ protected:
106108 void setParentSurface(MirSurfaceItem* surface);
107109
108110private:
109− ApplicationInfo* m_application;
111+ MirSessionItem* m_session;
110112 const QString m_name;
111113 const Type m_type;
112114 State m_state;
113− const QImage m_img;
115+ QImage m_img;
114116
115117 MirSurfaceItem* m_parentSurface;
116118 MirSurfaceItemModel* m_children;
tests/mocks/Unity/Application/MirSurfaceItemModel.cppdeleted−102
@@ -1,102 +0,0 @@
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 <QQmlEngine>
18−
19−// local
20−#include "MirSurfaceItemModel.h"
21−#include "MirSurfaceItem.h"
22−
23−MirSurfaceItemModel::MirSurfaceItemModel(
24− QObject *parent)
25− : QAbstractListModel(parent)
26−{
27− QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);
28−}
29−
30−void MirSurfaceItemModel::insertSurface(uint index, MirSurfaceItem* surface)
31−{
32− index = qMin(index, (uint)count());
33−
34− int existingSurfaceIndex = m_surfaceItems.indexOf(surface);
35− if (existingSurfaceIndex != -1) {
36− move(existingSurfaceIndex, index);
37− } else {
38− beginInsertRows(QModelIndex(), index, index);
39− m_surfaceItems.insert(index, surface);
40− endInsertRows();
41− Q_EMIT countChanged();
42− }
43−}
44−
45−void MirSurfaceItemModel::removeSurface(MirSurfaceItem* surface)
46−{
47− int existingSurfaceIndex = m_surfaceItems.indexOf(surface);
48− if (existingSurfaceIndex != -1) {
49− beginRemoveRows(QModelIndex(), existingSurfaceIndex, existingSurfaceIndex);
50− m_surfaceItems.removeAt(existingSurfaceIndex);
51− endRemoveRows();
52− Q_EMIT countChanged();
53− }
54−}
55−
56−void MirSurfaceItemModel::move(int from, int to)
57−{
58− if (from == to) return;
59−
60− if (from >= 0 && from < m_surfaceItems.size() && to >= 0 && to < m_surfaceItems.size()) {
61− QModelIndex parent;
62− /* When moving an item down, the destination index needs to be incremented
63− by one, as explained in the documentation:
64− http://qt-project.org/doc/qt-5.0/qtcore/qabstractitemmodel.html#beginMoveRows */
65−
66− beginMoveRows(parent, from, from, parent, to + (to > from ? 1 : 0));
67− m_surfaceItems.move(from, to);
68− endMoveRows();
69− }
70−}
71−
72−QHash<int, QByteArray> MirSurfaceItemModel::roleNames() const
73−{
74− QHash<int, QByteArray> roleNames;
75− roleNames.insert(RoleSurface, "surface");
76− return roleNames;
77−}
78−
79−int MirSurfaceItemModel::rowCount(const QModelIndex & /*parent*/) const
80−{
81− return m_surfaceItems.count();
82−}
83−
84−QVariant MirSurfaceItemModel::data(const QModelIndex & index, int role) const
85−{
86− if (index.row() >= 0 && index.row() < m_surfaceItems.count()) {
87− MirSurfaceItem *surfaceItem = m_surfaceItems.at(index.row());
88− switch (role) {
89− case RoleSurface:
90− return QVariant::fromValue(surfaceItem);
91− default:
92− return QVariant();
93− }
94− } else {
95− return QVariant();
96− }
97−}
98−
99−MirSurfaceItem* MirSurfaceItemModel::getSurface(int index)
100−{
101− return m_surfaceItems[index];
102−}
tests/mocks/Unity/Application/MirSurfaceItemModel.h+3−37
@@ -17,45 +17,11 @@
1717#ifndef MIRSURFACEITEMMODEL_H
1818#define MIRSURFACEITEMMODEL_H
1919
20−// Qt
21−#include <QAbstractListModel>
20+// Llocal
21+#include "MirItemModel.h"
2222
2323class MirSurfaceItem;
24−
25−class MirSurfaceItemModel : public QAbstractListModel
26−{
27− Q_OBJECT
28− Q_ENUMS(Roles)
29− Q_PROPERTY(int count READ count NOTIFY countChanged)
30−
31−public:
32− enum Roles {
33− RoleSurface = Qt::UserRole,
34− };
35−
36− explicit MirSurfaceItemModel(QObject *parent = 0);
37−
38− const QList<MirSurfaceItem*>& list() const { return m_surfaceItems; }
39− bool contains(MirSurfaceItem* surface) const { return m_surfaceItems.contains(surface); }
40− int count() const { return rowCount(); }
41−
42− void insertSurface(uint index, MirSurfaceItem* surface);
43− void removeSurface(MirSurfaceItem* surface);
44−
45− // from QAbstractItemModel
46− int rowCount(const QModelIndex & parent = QModelIndex()) const override;
47− QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const override;
48− QHash<int, QByteArray> roleNames() const override;
49−
50− Q_INVOKABLE MirSurfaceItem* getSurface(int index);
51−
52−Q_SIGNALS:
53− void countChanged();
54−
55−private:
56− void move(int from, int to);
57− QList<MirSurfaceItem*> m_surfaceItems;
58−};
24+typedef MirItemModel<MirSurfaceItem> MirSurfaceItemModel;
5925
6026Q_DECLARE_METATYPE(MirSurfaceItemModel*)
6127
tests/mocks/Unity/Application/SessionManager.cppnew file+45
@@ -0,0 +1,45 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include "SessionManager.h"
18+
19+#include "MirSurfaceItem.h"
20+#include "VirtualKeyboard.h"
21+
22+SessionManager *SessionManager::the_session_manager = nullptr;
23+
24+SessionManager *SessionManager::singleton()
25+{
26+ if (!the_session_manager) {
27+ the_session_manager = new SessionManager();
28+ }
29+ return the_session_manager;
30+}
31+
32+SessionManager::SessionManager(QObject *parent) :
33+ QObject(parent)
34+{
35+}
36+
37+
38+MirSessionItem *SessionManager::createSession(const QString& name,
39+ const QUrl& screenshot)
40+{
41+ MirSessionItem* session = new MirSessionItem(name, screenshot);
42+ connect(session, &MirSessionItem::destroyed, this, [&](QObject*) {
43+ });
44+ return session;
45+}
tests/mocks/Unity/Application/SessionManager.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
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#ifndef SESSIONMANAGER_
18+#define SESSIONMANAGER_
19+
20+#include <QObject>
21+
22+#include "MirSessionItem.h"
23+
24+class SessionManager : public QObject
25+{
26+ Q_OBJECT
27+public:
28+ explicit SessionManager(QObject *parent = 0);
29+
30+ static SessionManager *singleton();
31+
32+ MirSessionItem* createSession(const QString& name, const QUrl& screenshot);
33+
34+private:
35+ static SessionManager *the_session_manager;
36+};
37+
38+#endif // SESSIONMANAGER_
tests/mocks/Unity/Application/plugin.cpp+4
@@ -19,6 +19,7 @@
1919#include "ApplicationImage.h"
2020#include "ApplicationManager.h"
2121#include "ApplicationScreenshotProvider.h"
22+#include "MirSessionItem.h"
2223#include "MirSurfaceItem.h"
2324#include "MirSurfaceItemModel.h"
2425#include "SurfaceManager.h"
@@ -52,11 +53,14 @@ static QObject* applicationTestInterface(QQmlEngine* engine, QJSEngine* scriptEn
5253
5354void FakeUnityApplicationQmlPlugin::registerTypes(const char *uri)
5455{
56+ qRegisterMetaType<MirSessionItem*>("MirSessionItem*");
5557 qRegisterMetaType<MirSurfaceItem*>("MirSurfaceItem*");
58+ qRegisterMetaType<MirSurfaceItemModel*>("MirSessionItemModel*");
5659 qRegisterMetaType<MirSurfaceItemModel*>("MirSurfaceItemModel*");
5760
5861 qmlRegisterUncreatableType<unity::shell::application::ApplicationManagerInterface>(uri, 0, 1, "ApplicationManagerInterface", "Abstract interface. Cannot be created in QML");
5962 qmlRegisterUncreatableType<unity::shell::application::ApplicationInfoInterface>(uri, 0, 1, "ApplicationInfoInterface", "Abstract interface. Cannot be created in QML");
63+ qmlRegisterUncreatableType<MirSessionItem>(uri, 0, 1, "MirSessionItem", "MirSessionItem can't be instantiated from QML");
6064 qmlRegisterUncreatableType<MirSurfaceItem>(uri, 0, 1, "MirSurfaceItem", "MirSurfaceItem can't be instantiated from QML");
6165
6266 qmlRegisterType<ApplicationInfo>(uri, 0, 1, "ApplicationInfo");