on 7acf415 help sign in
unity8/tests/mocks/Ubuntu/Application/ApplicationManager.cpp
449 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();
40 createMainStageComponent();
41 createSideStageComponent();
44ApplicationManager::~ApplicationManager()
46 delete m_mainStageApplications;
47 delete m_sideStageApplications;
50int ApplicationManager::keyboardHeight() const
52 return 0;
55bool ApplicationManager::keyboardVisible() const
57 return false;
60int ApplicationManager::sideStageWidth() const
62 return 0;
65ApplicationManager::StageHint ApplicationManager::stageHint() const
67 return MainStage;
70ApplicationManager::FormFactorHint ApplicationManager::formFactorHint() const
72 return PhoneFormFactor;
75ApplicationListModel* ApplicationManager::mainStageApplications() const
77 return m_mainStageApplications;
80ApplicationListModel* ApplicationManager::sideStageApplications() const
82 return m_sideStageApplications;
85ApplicationInfo* ApplicationManager::mainStageFocusedApplication() const
87 return m_mainStageFocusedApplication;
90ApplicationInfo* ApplicationManager::sideStageFocusedApplication() const
92 return m_sideStageFocusedApplication;
95ApplicationInfo* ApplicationManager::startProcess(QString desktopFile,
96 ExecFlags flags,
97 QStringList arguments)
99 Q_UNUSED(arguments)
100 ApplicationInfo *application = 0;
102 for (int i = 0; i < m_availableApplications.count(); ++i) {
103 ApplicationInfo *availableApp = m_availableApplications[i];
104 if (availableApp->desktopFile() == desktopFile) {
105 application = availableApp;
106 break;
107 }
108 }
110 if (!application)
111 return 0;
113 if (flags.testFlag(ApplicationManager::ForceMainStage)
114 || application->stage() == ApplicationInfo::MainStage) {
115 m_mainStageApplications->add(application);
116 } else {
117 m_sideStageApplications->add(application);
118 }
120 return application;
123void ApplicationManager::stopProcess(ApplicationInfo* application)
125 if (m_mainStageApplications->contains(application)) {
126 m_mainStageApplications->remove(application);
128 if (m_mainStageFocusedApplication == application) {
129 m_mainStageFocusedApplication = 0;
130 Q_EMIT mainStageFocusedApplicationChanged();
131 }
132 } else if (m_sideStageApplications->contains(application)){
133 m_sideStageApplications->remove(application);
135 if (m_sideStageFocusedApplication == application) {
136 m_sideStageFocusedApplication = 0;
137 Q_EMIT sideStageFocusedApplicationChanged();
138 }
139 }
142void ApplicationManager::focusApplication(int handle)
144 for (int i = 0; i < m_mainStageApplications->m_applications.count(); ++i) {
145 ApplicationInfo *application = m_mainStageApplications->m_applications[i];
146 if (application->handle() == handle) {
147 if (m_mainStageFocusedApplication)
148 m_mainStageFocusedApplication->hideWindow();
149 m_mainStageFocusedApplication = application;
150 if (!m_mainStage)
151 createMainStage();
152 application->showWindow(m_mainStage);
153 m_mainStage->setZ(-1000);
154 if (m_sideStage)
155 m_sideStage->setZ(-2000);
156 Q_EMIT mainStageFocusedApplicationChanged();
157 return;
158 }
159 }
161 for (int i = 0; i < m_sideStageApplications->m_applications.count(); ++i) {
162 ApplicationInfo *application = m_sideStageApplications->m_applications[i];
163 if (application->handle() == handle) {
164 if (m_sideStageFocusedApplication)
165 m_sideStageFocusedApplication->hideWindow();
166 m_sideStageFocusedApplication = application;
167 if (!m_sideStage)
168 createSideStage();
169 application->showWindow(m_sideStage);
170 m_sideStage->setZ(-1000);
171 if (m_mainStage)
172 m_mainStage->setZ(-2000);
173 Q_EMIT sideStageFocusedApplicationChanged();
174 return;
175 }
176 }
179void ApplicationManager::unfocusCurrentApplication(StageHint stageHint)
181 if (stageHint == SideStage) {
182 if (m_sideStageFocusedApplication) {
183 m_sideStageFocusedApplication->hideWindow();
184 m_sideStageFocusedApplication = 0;
185 Q_EMIT sideStageFocusedApplicationChanged();
186 }
187 } else {
188 if (m_mainStageFocusedApplication) {
189 m_mainStageFocusedApplication->hideWindow();
190 m_mainStageFocusedApplication = 0;
191 Q_EMIT mainStageFocusedApplicationChanged();
192 }
193 }
196void ApplicationManager::generateQmlStrings(ApplicationInfo *application)
198 // TODO: Is there a better way of solving this fullscreen vs. regular
199 // application height?
200 QString topMargin;
201 if (application->fullscreen()) {
202 topMargin.append("0");
203 } else {
204 // Taken from Panel.panelHeight
205 topMargin.append("units.gu(3) + units.dp(2)");
206 }
208 QString windowQml = QString(
209 "import QtQuick 2.0\n"
210 "Image {\n"
211 " anchors.fill: parent\n"
212 " anchors.topMargin: %1\n"
213 " source: \"file://%2/Dash/graphics/phone/screenshots/%3.png\"\n"
214 " smooth: true\n"
215 " fillMode: Image.PreserveAspectCrop\n"
216 "}").arg(topMargin)
217 .arg(shellAppDirectory())
218 .arg(application->icon());
219 application->setWindowQml(windowQml);
221 QString imageQml = QString(
222 "import QtQuick 2.0\n"
223 "Image {\n"
224 " anchors.fill: parent\n"
225 " source: \"file://%1/Dash/graphics/phone/screenshots/%2.png\"\n"
226 " smooth: true\n"
227 " fillMode: Image.PreserveAspectCrop\n"
228 "}").arg(shellAppDirectory())
229 .arg(application->icon());
230 application->setImageQml(imageQml);
233void ApplicationManager::buildListOfAvailableApplications()
235 ApplicationInfo *application;
236 qint64 nextHandle = 1;
238 application = new ApplicationInfo(this);
239 application->setDesktopFile("/usr/share/applications/phone-app.desktop");
240 application->setName("Phone");
241 application->setIcon("phone");
242 application->setExec("/usr/bin/phone-app");
243 application->setStage(ApplicationInfo::SideStage);
244 application->setHandle(nextHandle++);
245 generateQmlStrings(application);
246 m_availableApplications.append(application);
248 application = new ApplicationInfo(this);
249 application->setDesktopFile("/usr/share/applications/camera-app.desktop");
250 application->setName("Camera");
251 application->setIcon("camera");
252 application->setFullscreen(true);
253 application->setExec("/usr/bin/camera-app --fullscreen");
254 application->setHandle(nextHandle++);
255 generateQmlStrings(application);
256 m_availableApplications.append(application);
258 application = new ApplicationInfo(this);
259 application->setDesktopFile("/usr/share/applications/gallery-app.desktop");
260 application->setName("Gallery");
261 application->setIcon("gallery");
262 application->setExec("/usr/bin/gallery-app");
263 application->setHandle(nextHandle++);
264 generateQmlStrings(application);
265 m_availableApplications.append(application);
267 application = new ApplicationInfo(this);
268 application->setDesktopFile("/usr/share/applications/facebook-webapp.desktop");
269 application->setName("Facebook");
270 application->setIcon("facebook");
271 application->setExec("/usr/bin/webbrowser-app --chromeless http://m.facebook.com");
272 application->setStage(ApplicationInfo::SideStage);
273 application->setHandle(nextHandle++);
274 generateQmlStrings(application);
275 m_availableApplications.append(application);
277 application = new ApplicationInfo(this);
278 application->setDesktopFile("/usr/share/applications/webbrowser-app.desktop");
279 application->setName("Browser");
280 application->setIcon("browser");
281 application->setExec("/usr/bin/webbrowser-app");
282 application->setHandle(nextHandle++);
283 generateQmlStrings(application);
284 m_availableApplications.append(application);
286 application = new ApplicationInfo(this);
287 application->setDesktopFile("/usr/share/applications/twitter-webapp.desktop");
288 application->setName("Twitter");
289 application->setIcon("twitter");
290 application->setExec("/usr/bin/webbrowser-app --chromeless http://www.twitter.com");
291 application->setStage(ApplicationInfo::SideStage);
292 application->setHandle(nextHandle++);
293 generateQmlStrings(application);
294 m_availableApplications.append(application);
296 application = new ApplicationInfo(this);
297 application->setDesktopFile("/usr/share/applications/gmail-webapp.desktop");
298 application->setName("GMail");
299 application->setIcon("gmail");
300 application->setExec("/usr/bin/webbrowser-app --chromeless http://m.gmail.com");
301 application->setHandle(nextHandle++);
302 m_availableApplications.append(application);
304 application = new ApplicationInfo(this);
305 application->setDesktopFile("/usr/share/applications/ubuntu-weather-app.desktop");
306 application->setName("Weather");
307 application->setIcon("weather");
308 application->setExec("/usr/bin/qmlscene /usr/share/ubuntu-weather-app/ubuntu-weather-app.qml");
309 application->setStage(ApplicationInfo::SideStage);
310 application->setHandle(nextHandle++);
311 generateQmlStrings(application);
312 m_availableApplications.append(application);
314 application = new ApplicationInfo(this);
315 application->setDesktopFile("/usr/share/applications/notes-app.desktop");
316 application->setName("Notepad");
317 application->setIcon("notepad");
318 application->setExec("/usr/bin/qmlscene /usr/share/notes-app/NotesApp.qml");
319 application->setStage(ApplicationInfo::SideStage);
320 application->setHandle(nextHandle++);
321 m_availableApplications.append(application);
323 application = new ApplicationInfo(this);
324 application->setDesktopFile("/usr/share/applications/ubuntu-calendar-app.desktop");
325 application->setName("Calendar");
326 application->setIcon("calendar");
327 application->setExec("/usr/bin/qmlscene /usr/share/ubuntu-calendar-app/calendar.qml");
328 application->setStage(ApplicationInfo::SideStage);
329 application->setHandle(nextHandle++);
330 m_availableApplications.append(application);
332 application = new ApplicationInfo(this);
333 application->setDesktopFile("/usr/share/applications/mediaplayer-app.desktop");
334 application->setName("Media Player");
335 application->setIcon("mediaplayer-app");
336 application->setFullscreen(true);
337 application->setExec("/usr/bin/mediaplayer-app");
338 application->setHandle(nextHandle++);
339 m_availableApplications.append(application);
341 application = new ApplicationInfo(this);
342 application->setDesktopFile("/usr/share/applications/evernote.desktop");
343 application->setName("Evernote");
344 application->setIcon("evernote");
345 application->setHandle(nextHandle++);
346 m_availableApplications.append(application);
348 application = new ApplicationInfo(this);
349 application->setDesktopFile("/usr/share/applications/map.desktop");
350 application->setName("Map");
351 application->setIcon("map");
352 application->setHandle(nextHandle++);
353 generateQmlStrings(application);
354 m_availableApplications.append(application);
356 application = new ApplicationInfo(this);
357 application->setDesktopFile("/usr/share/applications/pinterest.desktop");
358 application->setName("Pinterest");
359 application->setIcon("pinterest");
360 application->setHandle(nextHandle++);
361 m_availableApplications.append(application);
363 application = new ApplicationInfo(this);
364 application->setDesktopFile("/usr/share/applications/soundcloud.desktop");
365 application->setName("SoundCloud");
366 application->setIcon("soundcloud");
367 application->setHandle(nextHandle++);
368 m_availableApplications.append(application);
370 application = new ApplicationInfo(this);
371 application->setDesktopFile("/usr/share/applications/wikipedia.desktop");
372 application->setName("Wikipedia");
373 application->setIcon("wikipedia");
374 application->setHandle(nextHandle++);
375 m_availableApplications.append(application);
377 application = new ApplicationInfo(this);
378 application->setDesktopFile("/usr/share/applications/youtube.desktop");
379 application->setName("YouTube");
380 application->setIcon("youtube");
381 application->setHandle(nextHandle++);
382 m_availableApplications.append(application);
385void ApplicationManager::createMainStageComponent()
387 // The assumptions I make here really should hold.
388 QQuickView *quickView =
389 qobject_cast<QQuickView*>(QGuiApplication::topLevelWindows()[0]);
391 QQmlEngine *engine = quickView->engine();
393 m_mainStageComponent = new QQmlComponent(engine, this);
394 QString mainStageQml =
395 "import QtQuick 2.0\n"
396 "Rectangle {\n"
397 " anchors.fill: parent\n"
398 " color: 'black'\n"
399 " z: -2000\n"
400 "}\n";
401 m_mainStageComponent->setData(mainStageQml.toLatin1(), QUrl());
404void ApplicationManager::createMainStage()
406 // The assumptions I make here really should hold.
407 QQuickView *quickView =
408 qobject_cast<QQuickView*>(QGuiApplication::topLevelWindows()[0]);
410 QQuickItem *shell = quickView->rootObject();
412 m_mainStage = qobject_cast<QQuickItem *>(m_mainStageComponent->create());
413 m_mainStage->setParentItem(shell);
416void ApplicationManager::createSideStageComponent()
418 // The assumptions I make here really should hold.
419 QQuickView *quickView =
420 qobject_cast<QQuickView*>(QGuiApplication::topLevelWindows()[0]);
422 QQmlEngine *engine = quickView->engine();
424 m_sideStageComponent = new QQmlComponent(engine, this);
425 QString sideStageQml =
426 "import QtQuick 2.0\n"
427 "import Ubuntu.Components 0.1\n"
428 "Item {\n"
429 " width: units.gu(40)\n" // from SideStage in Shell.qml
430 " anchors.top: parent.top\n"
431 " anchors.bottom: parent.bottom\n"
432 " anchors.right: parent.right\n"
433 " z: -1000\n"
434 "}\n";
435 m_sideStageComponent->setData(sideStageQml.toLatin1(), QUrl());
438void ApplicationManager::createSideStage()
440 // The assumptions I make here really should hold.
441 QQuickView *quickView =
442 qobject_cast<QQuickView*>(QGuiApplication::topLevelWindows()[0]);
444 QQuickItem *shell = quickView->rootObject();
446 m_sideStage = qobject_cast<QQuickItem *>(m_sideStageComponent->create());
447 m_sideStage->setParentItem(shell);
448 m_sideStage->setFlag(QQuickItem::ItemHasContents, false);