@@ -16,7 +16,6 @@
1616
1717#include "ApplicationManager.h"
1818#include "ApplicationInfo.h"
19−#include "ApplicationListModel.h"
2019#include "paths.h"
2120
2221#include <QDir>
@@ -26,11 +25,7 @@
2625#include <QQmlComponent>
2726
2827ApplicationManager::ApplicationManager(QObject *parent)
29− : QObject(parent)
30− , m_mainStageApplications(new ApplicationListModel())
31− , m_sideStageApplications(new ApplicationListModel())
32− , m_mainStageFocusedApplication(0)
33− , m_sideStageFocusedApplication(0)
28+ : ApplicationManagerInterface(parent)
3429 , m_mainStageComponent(0)
3530 , m_mainStage(0)
3631 , m_sideStageComponent(0)
@@ -41,8 +36,65 @@ ApplicationManager::ApplicationManager(QObject *parent)
4136
4237ApplicationManager::~ApplicationManager()
4338{
44− delete m_mainStageApplications;
45− delete m_sideStageApplications;
39+}
40+
41+int ApplicationManager::rowCount(const QModelIndex& parent) const {
42+ return !parent.isValid() ? m_runningApplications.size() : 0;
43+}
44+
45+QVariant ApplicationManager::data(const QModelIndex& index, int role) const {
46+ if (index.row() < 0 || index.row() >= m_runningApplications.size())
47+ return QVariant();
48+
49+ auto app = m_runningApplications.at(index.row());
50+ switch(role) {
51+ case RoleAppId:
52+ return app->appId();
53+ case RoleName:
54+ return app->name();
55+ case RoleComment:
56+ return app->comment();
57+ case RoleIcon:
58+ return app->icon();
59+ case RoleStage:
60+ return app->stage();
61+ case RoleState:
62+ return app->state();
63+ case RoleFocused:
64+ return app->focused();
65+ default:
66+ return QVariant();
67+ }
68+}
69+
70+ApplicationInfo *ApplicationManager::get(int row) const {
71+ if (row < 0 || row >= m_runningApplications.size())
72+ return nullptr;
73+
74+ return m_runningApplications.at(row);
75+}
76+
77+ApplicationInfo *ApplicationManager::findApplication(const QString &appId) const {
78+ for (ApplicationInfo *app : m_runningApplications) {
79+ if (app->appId() == appId) {
80+ return app;
81+ }
82+ }
83+ return nullptr;
84+}
85+
86+void ApplicationManager::move(int from, int to) {
87+ if (from == to) return;
88+
89+ if (from >= 0 && from < m_runningApplications.size() && to >= 0 && to < m_runningApplications.size()) {
90+ QModelIndex parent;
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);
96+ endMoveRows();
97+ }
4698}
4799
48100int ApplicationManager::keyboardHeight() const
@@ -70,36 +122,22 @@ ApplicationManager::FormFactorHint ApplicationManager::formFactorHint() const
70122 return PhoneFormFactor;
71123}
72124
73−ApplicationListModel* ApplicationManager::mainStageApplications() const
74−{
75− return m_mainStageApplications;
76−}
77−
78−ApplicationListModel* ApplicationManager::sideStageApplications() const
125+ApplicationInfo* ApplicationManager::startApplication(const QString &appId,
126+ const QStringList &arguments)
79127{
80− return m_sideStageApplications;
128+ return this->startApplication(appId, NoFlag, arguments);
81129}
82130
83−ApplicationInfo* ApplicationManager::mainStageFocusedApplication() const
84−{
85− return m_mainStageFocusedApplication;
86−}
87−
88−ApplicationInfo* ApplicationManager::sideStageFocusedApplication() const
89−{
90− return m_sideStageFocusedApplication;
91−}
92−
93−ApplicationInfo* ApplicationManager::startProcess(QString desktopFile,
131+ApplicationInfo* ApplicationManager::startApplication(const QString &appId,
94132 ExecFlags flags,
95− QStringList arguments)
133+ const QStringList &arguments)
96134{
97135 Q_UNUSED(arguments)
98136 ApplicationInfo *application = 0;
99137
100138 for (int i = 0; i < m_availableApplications.count(); ++i) {
101139 ApplicationInfo *availableApp = m_availableApplications[i];
102− if (availableApp->desktopFile() == desktopFile) {
140+ if (availableApp->appId() == appId) {
103141 application = availableApp;
104142 break;
105143 }
@@ -108,87 +146,88 @@ ApplicationInfo* ApplicationManager::startProcess(QString desktopFile,
108146 if (!application)
109147 return 0;
110148
149+ m_runningApplications.append(application);
111150 if (flags.testFlag(ApplicationManager::ForceMainStage)
112− || application->stage() == ApplicationInfo::MainStage) {
113− m_mainStageApplications->add(application);
114− } else {
115− m_sideStageApplications->add(application);
151+ && application->stage() == ApplicationInfo::SideStage) {
152+ application->setStage(ApplicationInfo::MainStage);
116153 }
117154
155+ application->setFocused(true);
156+ Q_EMIT focusedApplicationIdChanged();
118157 return application;
119158}
120159
121−void ApplicationManager::stopProcess(ApplicationInfo* application)
160+bool ApplicationManager::stopApplication(const QString &appId)
122161{
123− if (m_mainStageApplications->contains(application)) {
124− m_mainStageApplications->remove(application);
125−
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);
162+ ApplicationInfo *application = this->findApplication(appId);
163+ if (application == nullptr)
164+ return false;
165+
166+ application->setFocused(false);
167+ m_runningApplications.removeAll(application);
168+ Q_EMIT focusedApplicationIdChanged();
169+ return true;
170+}
132171
133− if (m_sideStageFocusedApplication == application) {
134− m_sideStageFocusedApplication = 0;
135− Q_EMIT sideStageFocusedApplicationChanged();
136− }
172+QString ApplicationManager::focusedApplicationId() const {
173+ for (ApplicationInfo *app : m_runningApplications) {
174+ if (app->focused())
175+ return app->appId();
137176 }
177+ return QString();
138178}
139179
140−void ApplicationManager::focusApplication(int handle)
180+bool ApplicationManager::focusApplication(const QString &appId)
141181{
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;
182+ ApplicationInfo *application = this->findApplication(appId);
183+ if (application == nullptr)
184+ return false;
185+
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);
156191 }
157− }
158192
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;
193+ // focus this app
194+ application->setFocused(true);
195+ if (!m_mainStage)
196+ createMainStage();
197+ application->showWindow(m_mainStage);
198+ m_mainStage->setZ(-1000);
199+ if (m_sideStage)
200+ m_sideStage->setZ(-2000);
201+ } else if (application->stage() == ApplicationInfo::SideStage) {
202+ // unfocus currently focused sidestage app
203+ for (ApplicationInfo *app : m_runningApplications) {
204+ if (app->focused() && app->stage() == ApplicationInfo::SideStage)
205+ app->setFocused(false);
173206 }
207+
208+ // focus this app
209+ application->setFocused(true);
210+ if (!m_sideStage)
211+ createSideStage();
212+ application->showWindow(m_sideStage);
213+ m_sideStage->setZ(-1000);
214+ if (m_mainStage)
215+ m_mainStage->setZ(-2000);
174216 }
217+
218+ // move app to top of stack
219+ this->move(m_runningApplications.indexOf(application), 0);
220+ Q_EMIT focusedApplicationIdChanged();
221+ return true;
175222}
176223
177−void ApplicationManager::unfocusCurrentApplication(StageHint stageHint)
224+void ApplicationManager::unfocusCurrentApplication()
178225{
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− }
226+ for (ApplicationInfo *app : m_runningApplications) {
227+ if (app->focused())
228+ app->setFocused(false);
191229 }
230+ Q_EMIT focusedApplicationIdChanged();
192231}
193232
194233void ApplicationManager::generateQmlStrings(ApplicationInfo *application)
@@ -213,7 +252,7 @@ void ApplicationManager::generateQmlStrings(ApplicationInfo *application)
213252 " fillMode: Image.PreserveAspectCrop\n"
214253 "}").arg(topMargin)
215254 .arg(shellAppDirectory())
216− .arg(application->icon());
255+ .arg(application->icon().toString());
217256 application->setWindowQml(windowQml);
218257
219258 QString imageQml = QString(
@@ -224,159 +263,130 @@ void ApplicationManager::generateQmlStrings(ApplicationInfo *application)
224263 " smooth: true\n"
225264 " fillMode: Image.PreserveAspectCrop\n"
226265 "}").arg(shellAppDirectory())
227− .arg(application->icon());
266+ .arg(application->icon().toString());
228267 application->setImageQml(imageQml);
229268}
230269
231270void ApplicationManager::buildListOfAvailableApplications()
232271{
233272 ApplicationInfo *application;
234− qint64 nextHandle = 1;
235273
236274 application = new ApplicationInfo(this);
237− application->setDesktopFile("/usr/share/applications/phone-app.desktop");
275+ application->setAppId("phone-app");
238276 application->setName("Phone");
239− application->setIcon("phone");
240− application->setExec("/usr/bin/phone-app");
277+ application->setIcon(QUrl("phone"));
241278 application->setStage(ApplicationInfo::SideStage);
242− application->setHandle(nextHandle++);
243279 generateQmlStrings(application);
244280 m_availableApplications.append(application);
245281
246282 application = new ApplicationInfo(this);
247− application->setDesktopFile("/usr/share/applications/camera-app.desktop");
283+ application->setAppId("camera-app");
248284 application->setName("Camera");
249− application->setIcon("camera");
285+ application->setIcon(QUrl("camera"));
250286 application->setFullscreen(true);
251− application->setExec("/usr/bin/camera-app --fullscreen");
252− application->setHandle(nextHandle++);
253287 generateQmlStrings(application);
254288 m_availableApplications.append(application);
255289
256290 application = new ApplicationInfo(this);
257− application->setDesktopFile("/usr/share/applications/gallery-app.desktop");
291+ application->setAppId("gallery-app");
258292 application->setName("Gallery");
259− application->setIcon("gallery");
260− application->setExec("/usr/bin/gallery-app");
261− application->setHandle(nextHandle++);
293+ application->setIcon(QUrl("gallery"));
262294 generateQmlStrings(application);
263295 m_availableApplications.append(application);
264296
265297 application = new ApplicationInfo(this);
266− application->setDesktopFile("/usr/share/applications/facebook-webapp.desktop");
298+ application->setAppId("facebook-webapp");
267299 application->setName("Facebook");
268− application->setIcon("facebook");
269− application->setExec("/usr/bin/webbrowser-app --chromeless http://m.facebook.com");
300+ application->setIcon(QUrl("facebook"));
270301 application->setStage(ApplicationInfo::SideStage);
271− application->setHandle(nextHandle++);
272302 generateQmlStrings(application);
273303 m_availableApplications.append(application);
274304
275305 application = new ApplicationInfo(this);
276− application->setDesktopFile("/usr/share/applications/webbrowser-app.desktop");
306+ application->setAppId("webbrowser-app");
277307 application->setName("Browser");
278− application->setIcon("browser");
279− application->setExec("/usr/bin/webbrowser-app");
280− application->setHandle(nextHandle++);
308+ application->setIcon(QUrl("browser"));
281309 generateQmlStrings(application);
282310 m_availableApplications.append(application);
283311
284312 application = new ApplicationInfo(this);
285− application->setDesktopFile("/usr/share/applications/twitter-webapp.desktop");
313+ application->setAppId("twitter-webapp");
286314 application->setName("Twitter");
287− application->setIcon("twitter");
288− application->setExec("/usr/bin/webbrowser-app --chromeless http://www.twitter.com");
315+ application->setIcon(QUrl("twitter"));
289316 application->setStage(ApplicationInfo::SideStage);
290− application->setHandle(nextHandle++);
291317 generateQmlStrings(application);
292318 m_availableApplications.append(application);
293319
294320 application = new ApplicationInfo(this);
295− application->setDesktopFile("/usr/share/applications/gmail-webapp.desktop");
321+ application->setAppId("gmail-webapp");
296322 application->setName("GMail");
297− application->setIcon("gmail");
298− application->setExec("/usr/bin/webbrowser-app --chromeless http://m.gmail.com");
299− application->setHandle(nextHandle++);
323+ application->setIcon(QUrl("gmail"));
300324 m_availableApplications.append(application);
301325
302326 application = new ApplicationInfo(this);
303− application->setDesktopFile("/usr/share/applications/ubuntu-weather-app.desktop");
327+ application->setAppId("ubuntu-weather-app");
304328 application->setName("Weather");
305− application->setIcon("weather");
306− application->setExec("/usr/bin/qmlscene /usr/share/ubuntu-weather-app/ubuntu-weather-app.qml");
329+ application->setIcon(QUrl("weather"));
307330 application->setStage(ApplicationInfo::SideStage);
308− application->setHandle(nextHandle++);
309331 generateQmlStrings(application);
310332 m_availableApplications.append(application);
311333
312334 application = new ApplicationInfo(this);
313− application->setDesktopFile("/usr/share/applications/notes-app.desktop");
335+ application->setAppId("notes-app");
314336 application->setName("Notepad");
315− application->setIcon("notepad");
316− application->setExec("/usr/bin/qmlscene /usr/share/notes-app/NotesApp.qml");
337+ application->setIcon(QUrl("notepad"));
317338 application->setStage(ApplicationInfo::SideStage);
318− application->setHandle(nextHandle++);
319339 m_availableApplications.append(application);
320340
321341 application = new ApplicationInfo(this);
322− application->setDesktopFile("/usr/share/applications/calendar-app.desktop");
342+ application->setAppId("calendar-app");
323343 application->setName("Calendar");
324− application->setIcon("calendar");
325− application->setExec("/usr/bin/qmlscene /usr/share/calendar-app/calendar.qml");
344+ application->setIcon(QUrl("calendar"));
326345 application->setStage(ApplicationInfo::SideStage);
327− application->setHandle(nextHandle++);
328346 m_availableApplications.append(application);
329347
330348 application = new ApplicationInfo(this);
331− application->setDesktopFile("/usr/share/applications/mediaplayer-app.desktop");
349+ application->setAppId("mediaplayer-app");
332350 application->setName("Media Player");
333− application->setIcon("mediaplayer-app");
351+ application->setIcon(QUrl("mediaplayer-app"));
334352 application->setFullscreen(true);
335− application->setExec("/usr/bin/mediaplayer-app");
336− application->setHandle(nextHandle++);
337353 m_availableApplications.append(application);
338354
339355 application = new ApplicationInfo(this);
340− application->setDesktopFile("/usr/share/applications/evernote.desktop");
356+ application->setAppId("evernote");
341357 application->setName("Evernote");
342− application->setIcon("evernote");
343− application->setHandle(nextHandle++);
358+ application->setIcon(QUrl("evernote"));
344359 m_availableApplications.append(application);
345360
346361 application = new ApplicationInfo(this);
347− application->setDesktopFile("/usr/share/applications/map.desktop");
362+ application->setAppId("map");
348363 application->setName("Map");
349− application->setIcon("map");
350− application->setHandle(nextHandle++);
364+ application->setIcon(QUrl("map"));
351365 generateQmlStrings(application);
352366 m_availableApplications.append(application);
353367
354368 application = new ApplicationInfo(this);
355− application->setDesktopFile("/usr/share/applications/pinterest.desktop");
369+ application->setAppId("pinterest");
356370 application->setName("Pinterest");
357− application->setIcon("pinterest");
358− application->setHandle(nextHandle++);
371+ application->setIcon(QUrl("pinterest"));
359372 m_availableApplications.append(application);
360373
361374 application = new ApplicationInfo(this);
362− application->setDesktopFile("/usr/share/applications/soundcloud.desktop");
375+ application->setAppId("soundcloud");
363376 application->setName("SoundCloud");
364− application->setIcon("soundcloud");
365− application->setHandle(nextHandle++);
377+ application->setIcon(QUrl("soundcloud"));
366378 m_availableApplications.append(application);
367379
368380 application = new ApplicationInfo(this);
369− application->setDesktopFile("/usr/share/applications/wikipedia.desktop");
381+ application->setAppId("wikipedia");
370382 application->setName("Wikipedia");
371− application->setIcon("wikipedia");
372− application->setHandle(nextHandle++);
383+ application->setIcon(QUrl("wikipedia"));
373384 m_availableApplications.append(application);
374385
375386 application = new ApplicationInfo(this);
376− application->setDesktopFile("/usr/share/applications/youtube.desktop");
387+ application->setAppId("youtube");
377388 application->setName("YouTube");
378− application->setIcon("youtube");
379− application->setHandle(nextHandle++);
389+ application->setIcon(QUrl("youtube"));
380390 m_availableApplications.append(application);
381391}
382392