@@ -16,7 +16,6 @@
17#include "ApplicationManager.h"
17#include "ApplicationManager.h"
18#include "ApplicationInfo.h"
18#include "ApplicationInfo.h"
19−#include "ApplicationListModel.h"
20#include "paths.h"
19#include "paths.h"
22#include <QDir>
21#include <QDir>
@@ -26,11 +25,7 @@
26#include <QQmlComponent>
25#include <QQmlComponent>
28ApplicationManager::ApplicationManager(QObject *parent)
27ApplicationManager::ApplicationManager(QObject *parent)
29− : QObject(parent)
28+ : ApplicationManagerInterface(parent)
30− , m_mainStageApplications(new ApplicationListModel())
31− , m_sideStageApplications(new ApplicationListModel())
32− , m_mainStageFocusedApplication(0)
33− , m_sideStageFocusedApplication(0)
34 , m_mainStageComponent(0)
29 , m_mainStageComponent(0)
35 , m_mainStage(0)
30 , m_mainStage(0)
36 , m_sideStageComponent(0)
31 , m_sideStageComponent(0)
@@ -41,8 +36,65 @@ ApplicationManager::ApplicationManager(QObject *parent)
42ApplicationManager::~ApplicationManager()
37ApplicationManager::~ApplicationManager()
44− delete m_mainStageApplications;
39+}
45− delete m_sideStageApplications;
40+
41+int ApplicationManager::rowCount(const QModelIndex& parent) const {
42+ return !parent.isValid() ? m_runningApplications.size() : 0;
45+QVariant ApplicationManager::data(const QModelIndex& index, int role) const {
46+ if (index.row() < 0 || index.row() >= m_runningApplications.size())
49+ auto app = m_runningApplications.at(index.row());
56+ return app->comment();
64+ return app->focused();
70+ApplicationInfo *ApplicationManager::get(int row) const {
71+ if (row < 0 || row >= m_runningApplications.size())
74+ return m_runningApplications.at(row);
77+ApplicationInfo *ApplicationManager::findApplication(const QString &appId) const {
78+ for (ApplicationInfo *app : m_runningApplications) {
79+ if (app->appId() == appId) {
86+void ApplicationManager::move(int from, int to) {
87+ if (from == to) return;
89+ if (from >= 0 && from < m_runningApplications.size() && to >= 0 && to < m_runningApplications.size()) {
91+ /* When moving an item down, the destination index needs to be incremented
92+ * by one, as explained in the documentation:
93+ * http://qt-project.org/doc/qt-5.0/qtcore/qabstractitemmodel.html#beginMoveRows */
94+ beginMoveRows(parent, from, from, parent, to + (to > from ? 1 : 0));
95+ m_runningApplications.move(from, to);
48int ApplicationManager::keyboardHeight() const
100int ApplicationManager::keyboardHeight() const
@@ -70,36 +122,22 @@ ApplicationManager::FormFactorHint ApplicationManager::formFactorHint() const
70 return PhoneFormFactor;
122 return PhoneFormFactor;
73−ApplicationListModel* ApplicationManager::mainStageApplications() const
125+ApplicationInfo* ApplicationManager::startApplication(const QString &appId,
74−{
126+ const QStringList &arguments)
75− return m_mainStageApplications;
78−ApplicationListModel* ApplicationManager::sideStageApplications() const
80− return m_sideStageApplications;
128+ return this->startApplication(appId, NoFlag, arguments);
83−ApplicationInfo* ApplicationManager::mainStageFocusedApplication() const
131+ApplicationInfo* ApplicationManager::startApplication(const QString &appId,
85− return m_mainStageFocusedApplication;
88−ApplicationInfo* ApplicationManager::sideStageFocusedApplication() const
90− return m_sideStageFocusedApplication;
93−ApplicationInfo* ApplicationManager::startProcess(QString desktopFile,
94 ExecFlags flags,
132 ExecFlags flags,
95− QStringList arguments)
133+ const QStringList &arguments)
97 Q_UNUSED(arguments)
135 Q_UNUSED(arguments)
98 ApplicationInfo *application = 0;
136 ApplicationInfo *application = 0;
100 for (int i = 0; i < m_availableApplications.count(); ++i) {
138 for (int i = 0; i < m_availableApplications.count(); ++i) {
101 ApplicationInfo *availableApp = m_availableApplications[i];
139 ApplicationInfo *availableApp = m_availableApplications[i];
102− if (availableApp->desktopFile() == desktopFile) {
140+ if (availableApp->appId() == appId) {
103 application = availableApp;
141 application = availableApp;
@@ -108,87 +146,88 @@ ApplicationInfo* ApplicationManager::startProcess(QString desktopFile,
108 if (!application)
146 if (!application)
109 return 0;
147 return 0;
149+ m_runningApplications.append(application);
111 if (flags.testFlag(ApplicationManager::ForceMainStage)
150 if (flags.testFlag(ApplicationManager::ForceMainStage)
112− || application->stage() == ApplicationInfo::MainStage) {
151+ && application->stage() == ApplicationInfo::SideStage) {
113− m_mainStageApplications->add(application);
152+ application->setStage(ApplicationInfo::MainStage);
115− m_sideStageApplications->add(application);
155+ application->setFocused(true);
156+ Q_EMIT focusedApplicationIdChanged();
118 return application;
157 return application;
121−void ApplicationManager::stopProcess(ApplicationInfo* application)
160+bool ApplicationManager::stopApplication(const QString &appId)
123− if (m_mainStageApplications->contains(application)) {
162+ ApplicationInfo *application = this->findApplication(appId);
124− m_mainStageApplications->remove(application);
163+ if (application == nullptr)
126− if (m_mainStageFocusedApplication == application) {
165+
127− m_mainStageFocusedApplication = 0;
166+ application->setFocused(false);
128− Q_EMIT mainStageFocusedApplicationChanged();
167+ m_runningApplications.removeAll(application);
129− }
168+ Q_EMIT focusedApplicationIdChanged();
130− } else if (m_sideStageApplications->contains(application)){
169+ return true;
131− m_sideStageApplications->remove(application);
170+}
133− if (m_sideStageFocusedApplication == application) {
172+QString ApplicationManager::focusedApplicationId() const {
134− m_sideStageFocusedApplication = 0;
173+ for (ApplicationInfo *app : m_runningApplications) {
135− Q_EMIT sideStageFocusedApplicationChanged();
174+ if (app->focused())
136− }
175+ return app->appId();
140−void ApplicationManager::focusApplication(int handle)
180+bool ApplicationManager::focusApplication(const QString &appId)
142− for (int i = 0; i < m_mainStageApplications->m_applications.count(); ++i) {
143− ApplicationInfo *application = m_mainStageApplications->m_applications[i];
182+ ApplicationInfo *application = this->findApplication(appId);
144− if (application->handle() == handle) {
145− if (m_mainStageFocusedApplication)
146− m_mainStageFocusedApplication->hideWindow();
147− m_mainStageFocusedApplication = application;
150− application->showWindow(m_mainStage);
183+ if (application == nullptr)
151− m_mainStage->setZ(-1000);
153− m_sideStage->setZ(-2000);
154− Q_EMIT mainStageFocusedApplicationChanged();
155− return;
184+ return false;
186+ if (application->stage() == ApplicationInfo::MainStage) {
187+ // unfocus currently focused mainstage app
188+ for (ApplicationInfo *app : m_runningApplications) {
189+ if (app->focused() && app->stage() == ApplicationInfo::MainStage)
190+ app->setFocused(false);
159− for (int i = 0; i < m_sideStageApplications->m_applications.count(); ++i) {
193+ // focus this app
160− ApplicationInfo *application = m_sideStageApplications->m_applications[i];
161− if (application->handle() == handle) {
194+ application->setFocused(true);
162− if (m_sideStageFocusedApplication)
195+ if (!m_mainStage)
163− m_sideStageFocusedApplication->hideWindow();
196+ createMainStage();
164− m_sideStageFocusedApplication = application;
167− application->showWindow(m_sideStage);
197+ application->showWindow(m_mainStage);
168− m_sideStage->setZ(-1000);
198+ m_mainStage->setZ(-1000);
169− if (m_mainStage)
199+ if (m_sideStage)
170− m_mainStage->setZ(-2000);
200+ m_sideStage->setZ(-2000);
171− Q_EMIT sideStageFocusedApplicationChanged();
201+ } else if (application->stage() == ApplicationInfo::SideStage) {
172− return;
202+ // unfocus currently focused sidestage app
203+ for (ApplicationInfo *app : m_runningApplications) {
204+ if (app->focused() && app->stage() == ApplicationInfo::SideStage)
205+ app->setFocused(false);
209+ application->setFocused(true);
212+ application->showWindow(m_sideStage);
213+ m_sideStage->setZ(-1000);
215+ m_mainStage->setZ(-2000);
218+ // move app to top of stack
219+ this->move(m_runningApplications.indexOf(application), 0);
220+ Q_EMIT focusedApplicationIdChanged();
177−void ApplicationManager::unfocusCurrentApplication(StageHint stageHint)
224+void ApplicationManager::unfocusCurrentApplication()
179− if (stageHint == SideStage) {
226+ for (ApplicationInfo *app : m_runningApplications) {
180− if (m_sideStageFocusedApplication) {
227+ if (app->focused())
181− m_sideStageFocusedApplication->hideWindow();
228+ app->setFocused(false);
182− m_sideStageFocusedApplication = 0;
183− Q_EMIT sideStageFocusedApplicationChanged();
186− if (m_mainStageFocusedApplication) {
187− m_mainStageFocusedApplication->hideWindow();
188− m_mainStageFocusedApplication = 0;
189− Q_EMIT mainStageFocusedApplicationChanged();
230+ Q_EMIT focusedApplicationIdChanged();
194void ApplicationManager::generateQmlStrings(ApplicationInfo *application)
233void ApplicationManager::generateQmlStrings(ApplicationInfo *application)
@@ -213,7 +252,7 @@ void ApplicationManager::generateQmlStrings(ApplicationInfo *application)
213 " fillMode: Image.PreserveAspectCrop\n"
252 " fillMode: Image.PreserveAspectCrop\n"
214 "}").arg(topMargin)
253 "}").arg(topMargin)
215 .arg(shellAppDirectory())
254 .arg(shellAppDirectory())
216− .arg(application->icon());
255+ .arg(application->icon().toString());
217 application->setWindowQml(windowQml);
256 application->setWindowQml(windowQml);
219 QString imageQml = QString(
258 QString imageQml = QString(
@@ -224,159 +263,130 @@ void ApplicationManager::generateQmlStrings(ApplicationInfo *application)
224 " smooth: true\n"
263 " smooth: true\n"
225 " fillMode: Image.PreserveAspectCrop\n"
264 " fillMode: Image.PreserveAspectCrop\n"
226 "}").arg(shellAppDirectory())
265 "}").arg(shellAppDirectory())
227− .arg(application->icon());
266+ .arg(application->icon().toString());
228 application->setImageQml(imageQml);
267 application->setImageQml(imageQml);
231void ApplicationManager::buildListOfAvailableApplications()
270void ApplicationManager::buildListOfAvailableApplications()
233 ApplicationInfo *application;
272 ApplicationInfo *application;
234− qint64 nextHandle = 1;
236 application = new ApplicationInfo(this);
274 application = new ApplicationInfo(this);
237− application->setDesktopFile("/usr/share/applications/phone-app.desktop");
275+ application->setAppId("phone-app");
238 application->setName("Phone");
276 application->setName("Phone");
239− application->setIcon("phone");
277+ application->setIcon(QUrl("phone"));
240− application->setExec("/usr/bin/phone-app");
241 application->setStage(ApplicationInfo::SideStage);
278 application->setStage(ApplicationInfo::SideStage);
242− application->setHandle(nextHandle++);
243 generateQmlStrings(application);
279 generateQmlStrings(application);
244 m_availableApplications.append(application);
280 m_availableApplications.append(application);
246 application = new ApplicationInfo(this);
282 application = new ApplicationInfo(this);
247− application->setDesktopFile("/usr/share/applications/camera-app.desktop");
283+ application->setAppId("camera-app");
248 application->setName("Camera");
284 application->setName("Camera");
249− application->setIcon("camera");
285+ application->setIcon(QUrl("camera"));
250 application->setFullscreen(true);
286 application->setFullscreen(true);
251− application->setExec("/usr/bin/camera-app --fullscreen");
252− application->setHandle(nextHandle++);
253 generateQmlStrings(application);
287 generateQmlStrings(application);
254 m_availableApplications.append(application);
288 m_availableApplications.append(application);
256 application = new ApplicationInfo(this);
290 application = new ApplicationInfo(this);
257− application->setDesktopFile("/usr/share/applications/gallery-app.desktop");
291+ application->setAppId("gallery-app");
258 application->setName("Gallery");
292 application->setName("Gallery");
259− application->setIcon("gallery");
293+ application->setIcon(QUrl("gallery"));
260− application->setExec("/usr/bin/gallery-app");
261− application->setHandle(nextHandle++);
262 generateQmlStrings(application);
294 generateQmlStrings(application);
263 m_availableApplications.append(application);
295 m_availableApplications.append(application);
265 application = new ApplicationInfo(this);
297 application = new ApplicationInfo(this);
266− application->setDesktopFile("/usr/share/applications/facebook-webapp.desktop");
298+ application->setAppId("facebook-webapp");
267 application->setName("Facebook");
299 application->setName("Facebook");
268− application->setIcon("facebook");
300+ application->setIcon(QUrl("facebook"));
269− application->setExec("/usr/bin/webbrowser-app --chromeless http://m.facebook.com");
270 application->setStage(ApplicationInfo::SideStage);
301 application->setStage(ApplicationInfo::SideStage);
271− application->setHandle(nextHandle++);
272 generateQmlStrings(application);
302 generateQmlStrings(application);
273 m_availableApplications.append(application);
303 m_availableApplications.append(application);
275 application = new ApplicationInfo(this);
305 application = new ApplicationInfo(this);
276− application->setDesktopFile("/usr/share/applications/webbrowser-app.desktop");
306+ application->setAppId("webbrowser-app");
277 application->setName("Browser");
307 application->setName("Browser");
278− application->setIcon("browser");
308+ application->setIcon(QUrl("browser"));
279− application->setExec("/usr/bin/webbrowser-app");
280− application->setHandle(nextHandle++);
281 generateQmlStrings(application);
309 generateQmlStrings(application);
282 m_availableApplications.append(application);
310 m_availableApplications.append(application);
284 application = new ApplicationInfo(this);
312 application = new ApplicationInfo(this);
285− application->setDesktopFile("/usr/share/applications/twitter-webapp.desktop");
313+ application->setAppId("twitter-webapp");
286 application->setName("Twitter");
314 application->setName("Twitter");
287− application->setIcon("twitter");
315+ application->setIcon(QUrl("twitter"));
288− application->setExec("/usr/bin/webbrowser-app --chromeless http://www.twitter.com");
289 application->setStage(ApplicationInfo::SideStage);
316 application->setStage(ApplicationInfo::SideStage);
290− application->setHandle(nextHandle++);
291 generateQmlStrings(application);
317 generateQmlStrings(application);
292 m_availableApplications.append(application);
318 m_availableApplications.append(application);
294 application = new ApplicationInfo(this);
320 application = new ApplicationInfo(this);
295− application->setDesktopFile("/usr/share/applications/gmail-webapp.desktop");
321+ application->setAppId("gmail-webapp");
296 application->setName("GMail");
322 application->setName("GMail");
297− application->setIcon("gmail");
323+ application->setIcon(QUrl("gmail"));
298− application->setExec("/usr/bin/webbrowser-app --chromeless http://m.gmail.com");
299− application->setHandle(nextHandle++);
300 m_availableApplications.append(application);
324 m_availableApplications.append(application);
302 application = new ApplicationInfo(this);
326 application = new ApplicationInfo(this);
303− application->setDesktopFile("/usr/share/applications/ubuntu-weather-app.desktop");
327+ application->setAppId("ubuntu-weather-app");
304 application->setName("Weather");
328 application->setName("Weather");
305− application->setIcon("weather");
329+ application->setIcon(QUrl("weather"));
306− application->setExec("/usr/bin/qmlscene /usr/share/ubuntu-weather-app/ubuntu-weather-app.qml");
307 application->setStage(ApplicationInfo::SideStage);
330 application->setStage(ApplicationInfo::SideStage);
308− application->setHandle(nextHandle++);
309 generateQmlStrings(application);
331 generateQmlStrings(application);
310 m_availableApplications.append(application);
332 m_availableApplications.append(application);
312 application = new ApplicationInfo(this);
334 application = new ApplicationInfo(this);
313− application->setDesktopFile("/usr/share/applications/notes-app.desktop");
335+ application->setAppId("notes-app");
314 application->setName("Notepad");
336 application->setName("Notepad");
315− application->setIcon("notepad");
337+ application->setIcon(QUrl("notepad"));
316− application->setExec("/usr/bin/qmlscene /usr/share/notes-app/NotesApp.qml");
317 application->setStage(ApplicationInfo::SideStage);
338 application->setStage(ApplicationInfo::SideStage);
318− application->setHandle(nextHandle++);
319 m_availableApplications.append(application);
339 m_availableApplications.append(application);
321 application = new ApplicationInfo(this);
341 application = new ApplicationInfo(this);
322− application->setDesktopFile("/usr/share/applications/calendar-app.desktop");
342+ application->setAppId("calendar-app");
323 application->setName("Calendar");
343 application->setName("Calendar");
324− application->setIcon("calendar");
344+ application->setIcon(QUrl("calendar"));
325− application->setExec("/usr/bin/qmlscene /usr/share/calendar-app/calendar.qml");
326 application->setStage(ApplicationInfo::SideStage);
345 application->setStage(ApplicationInfo::SideStage);
327− application->setHandle(nextHandle++);
328 m_availableApplications.append(application);
346 m_availableApplications.append(application);
330 application = new ApplicationInfo(this);
348 application = new ApplicationInfo(this);
331− application->setDesktopFile("/usr/share/applications/mediaplayer-app.desktop");
349+ application->setAppId("mediaplayer-app");
332 application->setName("Media Player");
350 application->setName("Media Player");
333− application->setIcon("mediaplayer-app");
351+ application->setIcon(QUrl("mediaplayer-app"));
334 application->setFullscreen(true);
352 application->setFullscreen(true);
335− application->setExec("/usr/bin/mediaplayer-app");
336− application->setHandle(nextHandle++);
337 m_availableApplications.append(application);
353 m_availableApplications.append(application);
339 application = new ApplicationInfo(this);
355 application = new ApplicationInfo(this);
340− application->setDesktopFile("/usr/share/applications/evernote.desktop");
356+ application->setAppId("evernote");
341 application->setName("Evernote");
357 application->setName("Evernote");
342− application->setIcon("evernote");
358+ application->setIcon(QUrl("evernote"));
343− application->setHandle(nextHandle++);
344 m_availableApplications.append(application);
359 m_availableApplications.append(application);
346 application = new ApplicationInfo(this);
361 application = new ApplicationInfo(this);
347− application->setDesktopFile("/usr/share/applications/map.desktop");
362+ application->setAppId("map");
348 application->setName("Map");
363 application->setName("Map");
349− application->setIcon("map");
364+ application->setIcon(QUrl("map"));
350− application->setHandle(nextHandle++);
351 generateQmlStrings(application);
365 generateQmlStrings(application);
352 m_availableApplications.append(application);
366 m_availableApplications.append(application);
354 application = new ApplicationInfo(this);
368 application = new ApplicationInfo(this);
355− application->setDesktopFile("/usr/share/applications/pinterest.desktop");
369+ application->setAppId("pinterest");
356 application->setName("Pinterest");
370 application->setName("Pinterest");
357− application->setIcon("pinterest");
371+ application->setIcon(QUrl("pinterest"));
358− application->setHandle(nextHandle++);
359 m_availableApplications.append(application);
372 m_availableApplications.append(application);
361 application = new ApplicationInfo(this);
374 application = new ApplicationInfo(this);
362− application->setDesktopFile("/usr/share/applications/soundcloud.desktop");
375+ application->setAppId("soundcloud");
363 application->setName("SoundCloud");
376 application->setName("SoundCloud");
364− application->setIcon("soundcloud");
377+ application->setIcon(QUrl("soundcloud"));
365− application->setHandle(nextHandle++);
366 m_availableApplications.append(application);
378 m_availableApplications.append(application);
368 application = new ApplicationInfo(this);
380 application = new ApplicationInfo(this);
369− application->setDesktopFile("/usr/share/applications/wikipedia.desktop");
381+ application->setAppId("wikipedia");
370 application->setName("Wikipedia");
382 application->setName("Wikipedia");
371− application->setIcon("wikipedia");
383+ application->setIcon(QUrl("wikipedia"));
372− application->setHandle(nextHandle++);
373 m_availableApplications.append(application);
384 m_availableApplications.append(application);
375 application = new ApplicationInfo(this);
386 application = new ApplicationInfo(this);
376− application->setDesktopFile("/usr/share/applications/youtube.desktop");
387+ application->setAppId("youtube");
377 application->setName("YouTube");
388 application->setName("YouTube");
378− application->setIcon("youtube");
389+ application->setIcon(QUrl("youtube"));
379− application->setHandle(nextHandle++);
380 m_availableApplications.append(application);
390 m_availableApplications.append(application);