on d07a47e help sign in
unity8/tests/mocks/Ubuntu/Application/ApplicationManager.cpp
453 lines 16 kB history raw
1/*
2 * Copyright (C) 2013 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
17#include "ApplicationManager.h"
18#include "ApplicationInfo.h"
19#include "ApplicationListModel.h"
20#include "paths.h"
22#include <QDir>
23#include <QGuiApplication>
24#include <QQuickItem>
25#include <QQuickView>
26#include <QQmlComponent>
28ApplicationManager::ApplicationManager(QObject *parent)
29 : QObject(parent)
30 , m_mainStageApplications(new ApplicationListModel())
31 , m_sideStageApplications(new ApplicationListModel())
32 , m_mainStageFocusedApplication(0)
33 , m_sideStageFocusedApplication(0)
34 , m_mainStageComponent(0)
35 , m_mainStage(0)
36 , m_sideStageComponent(0)
37 , m_sideStage(0)
39 buildListOfAvailableApplications();
42ApplicationManager::~ApplicationManager()
44 delete m_mainStageApplications;
45 delete m_sideStageApplications;
48int ApplicationManager::keyboardHeight() const
50 return 0;
53bool ApplicationManager::keyboardVisible() const
55 return false;
58int ApplicationManager::sideStageWidth() const
60 return 0;
63ApplicationManager::StageHint ApplicationManager::stageHint() const
65 return MainStage;
68ApplicationManager::FormFactorHint ApplicationManager::formFactorHint() const
70 return PhoneFormFactor;
73ApplicationListModel* ApplicationManager::mainStageApplications() const
75 return m_mainStageApplications;
78ApplicationListModel* ApplicationManager::sideStageApplications() const
80 return m_sideStageApplications;
83ApplicationInfo* ApplicationManager::mainStageFocusedApplication() const
85 return m_mainStageFocusedApplication;
88ApplicationInfo* ApplicationManager::sideStageFocusedApplication() const
90 return m_sideStageFocusedApplication;
93ApplicationInfo* ApplicationManager::startProcess(QString desktopFile,
94 ExecFlags flags,
95 QStringList arguments)
97 Q_UNUSED(arguments)
98 ApplicationInfo *application = 0;
100 for (int i = 0; i < m_availableApplications.count(); ++i) {
101 ApplicationInfo *availableApp = m_availableApplications[i];
102 if (availableApp->desktopFile() == desktopFile) {
103 application = availableApp;
104 break;
105 }
106 }
108 if (!application)
109 return 0;
111 if (flags.testFlag(ApplicationManager::ForceMainStage)
112 || application->stage() == ApplicationInfo::MainStage) {
113 m_mainStageApplications->add(application);
114 } else {
115 m_sideStageApplications->add(application);
116 }
118 return application;
121void ApplicationManager::stopProcess(ApplicationInfo* application)
123 if (m_mainStageApplications->contains(application)) {
124 m_mainStageApplications->remove(application);
126 if (m_mainStageFocusedApplication == application) {
127 m_mainStageFocusedApplication = 0;
128 Q_EMIT mainStageFocusedApplicationChanged();
129 }
130 } else if (m_sideStageApplications->contains(application)){
131 m_sideStageApplications->remove(application);
133 if (m_sideStageFocusedApplication == application) {
134 m_sideStageFocusedApplication = 0;
135 Q_EMIT sideStageFocusedApplicationChanged();
136 }
137 }
140void ApplicationManager::focusApplication(int handle)
142 for (int i = 0; i < m_mainStageApplications->m_applications.count(); ++i) {
143 ApplicationInfo *application = m_mainStageApplications->m_applications[i];
144 if (application->handle() == handle) {
145 if (m_mainStageFocusedApplication)
146 m_mainStageFocusedApplication->hideWindow();
147 m_mainStageFocusedApplication = application;
148 if (!m_mainStage)
149 createMainStage();
150 application->showWindow(m_mainStage);
151 m_mainStage->setZ(-1000);
152 if (m_sideStage)
153 m_sideStage->setZ(-2000);
154 Q_EMIT mainStageFocusedApplicationChanged();
155 return;
156 }
157 }
159 for (int i = 0; i < m_sideStageApplications->m_applications.count(); ++i) {
160 ApplicationInfo *application = m_sideStageApplications->m_applications[i];
161 if (application->handle() == handle) {
162 if (m_sideStageFocusedApplication)
163 m_sideStageFocusedApplication->hideWindow();
164 m_sideStageFocusedApplication = application;
165 if (!m_sideStage)
166 createSideStage();
167 application->showWindow(m_sideStage);
168 m_sideStage->setZ(-1000);
169 if (m_mainStage)
170 m_mainStage->setZ(-2000);
171 Q_EMIT sideStageFocusedApplicationChanged();
172 return;
173 }
174 }
177void ApplicationManager::unfocusCurrentApplication(StageHint stageHint)
179 if (stageHint == SideStage) {
180 if (m_sideStageFocusedApplication) {
181 m_sideStageFocusedApplication->hideWindow();
182 m_sideStageFocusedApplication = 0;
183 Q_EMIT sideStageFocusedApplicationChanged();
184 }
185 } else {
186 if (m_mainStageFocusedApplication) {
187 m_mainStageFocusedApplication->hideWindow();
188 m_mainStageFocusedApplication = 0;
189 Q_EMIT mainStageFocusedApplicationChanged();
190 }
191 }
194void ApplicationManager::generateQmlStrings(ApplicationInfo *application)
196 // TODO: Is there a better way of solving this fullscreen vs. regular
197 // application height?
198 QString topMargin;
199 if (application->fullscreen()) {
200 topMargin.append("0");
201 } else {
202 // Taken from Panel.panelHeight
203 topMargin.append("units.gu(3) + units.dp(2)");
204 }
206 QString windowQml = QString(
207 "import QtQuick 2.0\n"
208 "Image {\n"
209 " anchors.fill: parent\n"
210 " anchors.topMargin: %1\n"
211 " source: \"file://%2/Dash/graphics/phone/screenshots/%3.png\"\n"
212 " smooth: true\n"
213 " fillMode: Image.PreserveAspectCrop\n"
214 "}").arg(topMargin)
215 .arg(shellAppDirectory())
216 .arg(application->icon());
217 application->setWindowQml(windowQml);
219 QString imageQml = QString(
220 "import QtQuick 2.0\n"
221 "Image {\n"
222 " anchors.fill: parent\n"
223 " source: \"file://%1/Dash/graphics/phone/screenshots/%2.png\"\n"
224 " smooth: true\n"
225 " fillMode: Image.PreserveAspectCrop\n"
226 "}").arg(shellAppDirectory())
227 .arg(application->icon());
228 application->setImageQml(imageQml);
231void ApplicationManager::buildListOfAvailableApplications()
233 ApplicationInfo *application;
234 qint64 nextHandle = 1;
236 application = new ApplicationInfo(this);
237 application->setDesktopFile("/usr/share/applications/phone-app.desktop");
238 application->setName("Phone");
239 application->setIcon("phone");
240 application->setExec("/usr/bin/phone-app");
241 application->setStage(ApplicationInfo::SideStage);
242 application->setHandle(nextHandle++);
243 generateQmlStrings(application);
244 m_availableApplications.append(application);
246 application = new ApplicationInfo(this);
247 application->setDesktopFile("/usr/share/applications/camera-app.desktop");
248 application->setName("Camera");
249 application->setIcon("camera");
250 application->setFullscreen(true);
251 application->setExec("/usr/bin/camera-app --fullscreen");
252 application->setHandle(nextHandle++);
253 generateQmlStrings(application);
254 m_availableApplications.append(application);
256 application = new ApplicationInfo(this);
257 application->setDesktopFile("/usr/share/applications/gallery-app.desktop");
258 application->setName("Gallery");
259 application->setIcon("gallery");
260 application->setExec("/usr/bin/gallery-app");
261 application->setHandle(nextHandle++);
262 generateQmlStrings(application);
263 m_availableApplications.append(application);
265 application = new ApplicationInfo(this);
266 application->setDesktopFile("/usr/share/applications/facebook-webapp.desktop");
267 application->setName("Facebook");
268 application->setIcon("facebook");
269 application->setExec("/usr/bin/webbrowser-app --chromeless http://m.facebook.com");
270 application->setStage(ApplicationInfo::SideStage);
271 application->setHandle(nextHandle++);
272 generateQmlStrings(application);
273 m_availableApplications.append(application);
275 application = new ApplicationInfo(this);
276 application->setDesktopFile("/usr/share/applications/webbrowser-app.desktop");
277 application->setName("Browser");
278 application->setIcon("browser");
279 application->setExec("/usr/bin/webbrowser-app");
280 application->setHandle(nextHandle++);
281 generateQmlStrings(application);
282 m_availableApplications.append(application);
284 application = new ApplicationInfo(this);
285 application->setDesktopFile("/usr/share/applications/twitter-webapp.desktop");
286 application->setName("Twitter");
287 application->setIcon("twitter");
288 application->setExec("/usr/bin/webbrowser-app --chromeless http://www.twitter.com");
289 application->setStage(ApplicationInfo::SideStage);
290 application->setHandle(nextHandle++);
291 generateQmlStrings(application);
292 m_availableApplications.append(application);
294 application = new ApplicationInfo(this);
295 application->setDesktopFile("/usr/share/applications/gmail-webapp.desktop");
296 application->setName("GMail");
297 application->setIcon("gmail");
298 application->setExec("/usr/bin/webbrowser-app --chromeless http://m.gmail.com");
299 application->setHandle(nextHandle++);
300 m_availableApplications.append(application);
302 application = new ApplicationInfo(this);
303 application->setDesktopFile("/usr/share/applications/ubuntu-weather-app.desktop");
304 application->setName("Weather");
305 application->setIcon("weather");
306 application->setExec("/usr/bin/qmlscene /usr/share/ubuntu-weather-app/ubuntu-weather-app.qml");
307 application->setStage(ApplicationInfo::SideStage);
308 application->setHandle(nextHandle++);
309 generateQmlStrings(application);
310 m_availableApplications.append(application);
312 application = new ApplicationInfo(this);
313 application->setDesktopFile("/usr/share/applications/notes-app.desktop");
314 application->setName("Notepad");
315 application->setIcon("notepad");
316 application->setExec("/usr/bin/qmlscene /usr/share/notes-app/NotesApp.qml");
317 application->setStage(ApplicationInfo::SideStage);
318 application->setHandle(nextHandle++);
319 m_availableApplications.append(application);
321 application = new ApplicationInfo(this);
322 application->setDesktopFile("/usr/share/applications/calendar-app.desktop");
323 application->setName("Calendar");
324 application->setIcon("calendar");
325 application->setExec("/usr/bin/qmlscene /usr/share/calendar-app/calendar.qml");
326 application->setStage(ApplicationInfo::SideStage);
327 application->setHandle(nextHandle++);
328 m_availableApplications.append(application);
330 application = new ApplicationInfo(this);
331 application->setDesktopFile("/usr/share/applications/mediaplayer-app.desktop");
332 application->setName("Media Player");
333 application->setIcon("mediaplayer-app");
334 application->setFullscreen(true);
335 application->setExec("/usr/bin/mediaplayer-app");
336 application->setHandle(nextHandle++);
337 m_availableApplications.append(application);
339 application = new ApplicationInfo(this);
340 application->setDesktopFile("/usr/share/applications/evernote.desktop");
341 application->setName("Evernote");
342 application->setIcon("evernote");
343 application->setHandle(nextHandle++);
344 m_availableApplications.append(application);
346 application = new ApplicationInfo(this);
347 application->setDesktopFile("/usr/share/applications/map.desktop");
348 application->setName("Map");
349 application->setIcon("map");
350 application->setHandle(nextHandle++);
351 generateQmlStrings(application);
352 m_availableApplications.append(application);
354 application = new ApplicationInfo(this);
355 application->setDesktopFile("/usr/share/applications/pinterest.desktop");
356 application->setName("Pinterest");
357 application->setIcon("pinterest");
358 application->setHandle(nextHandle++);
359 m_availableApplications.append(application);
361 application = new ApplicationInfo(this);
362 application->setDesktopFile("/usr/share/applications/soundcloud.desktop");
363 application->setName("SoundCloud");
364 application->setIcon("soundcloud");
365 application->setHandle(nextHandle++);
366 m_availableApplications.append(application);
368 application = new ApplicationInfo(this);
369 application->setDesktopFile("/usr/share/applications/wikipedia.desktop");
370 application->setName("Wikipedia");
371 application->setIcon("wikipedia");
372 application->setHandle(nextHandle++);
373 m_availableApplications.append(application);
375 application = new ApplicationInfo(this);
376 application->setDesktopFile("/usr/share/applications/youtube.desktop");
377 application->setName("YouTube");
378 application->setIcon("youtube");
379 application->setHandle(nextHandle++);
380 m_availableApplications.append(application);
383void ApplicationManager::createMainStageComponent()
385 // The assumptions I make here really should hold.
386 QQuickView *quickView =
387 qobject_cast<QQuickView*>(QGuiApplication::topLevelWindows()[0]);
389 QQmlEngine *engine = quickView->engine();
391 m_mainStageComponent = new QQmlComponent(engine, this);
392 QString mainStageQml =
393 "import QtQuick 2.0\n"
394 "Rectangle {\n"
395 " anchors.fill: parent\n"
396 " color: 'black'\n"
397 " z: -2000\n"
398 "}\n";
399 m_mainStageComponent->setData(mainStageQml.toLatin1(), QUrl());
402void ApplicationManager::createMainStage()
404 if (!m_mainStageComponent)
405 createMainStageComponent();
407 // The assumptions I make here really should hold.
408 QQuickView *quickView =
409 qobject_cast<QQuickView*>(QGuiApplication::topLevelWindows()[0]);
411 QQuickItem *shell = quickView->rootObject();
413 m_mainStage = qobject_cast<QQuickItem *>(m_mainStageComponent->create());
414 m_mainStage->setParentItem(shell);
417void ApplicationManager::createSideStageComponent()
419 // The assumptions I make here really should hold.
420 QQuickView *quickView =
421 qobject_cast<QQuickView*>(QGuiApplication::topLevelWindows()[0]);
423 QQmlEngine *engine = quickView->engine();
425 m_sideStageComponent = new QQmlComponent(engine, this);
426 QString sideStageQml =
427 "import QtQuick 2.0\n"
428 "import Ubuntu.Components 0.1\n"
429 "Item {\n"
430 " width: units.gu(40)\n" // from SideStage in Shell.qml
431 " anchors.top: parent.top\n"
432 " anchors.bottom: parent.bottom\n"
433 " anchors.right: parent.right\n"
434 " z: -1000\n"
435 "}\n";
436 m_sideStageComponent->setData(sideStageQml.toLatin1(), QUrl());
439void ApplicationManager::createSideStage()
441 if (!m_sideStageComponent)
442 createSideStageComponent();
444 // The assumptions I make here really should hold.
445 QQuickView *quickView =
446 qobject_cast<QQuickView*>(QGuiApplication::topLevelWindows()[0]);
448 QQuickItem *shell = quickView->rootObject();
450 m_sideStage = qobject_cast<QQuickItem *>(m_sideStageComponent->create());
451 m_sideStage->setParentItem(shell);
452 m_sideStage->setFlag(QQuickItem::ItemHasContents, false);