/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 3. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "ApplicationManager.h" #include "ApplicationInfo.h" #include "ApplicationListModel.h" #include "paths.h" #include #include #include #include #include ApplicationManager::ApplicationManager(QObject *parent) : QObject(parent) , m_mainStageApplications(new ApplicationListModel()) , m_sideStageApplications(new ApplicationListModel()) , m_mainStageFocusedApplication(0) , m_sideStageFocusedApplication(0) , m_mainStageComponent(0) , m_mainStage(0) , m_sideStageComponent(0) , m_sideStage(0) { buildListOfAvailableApplications(); } ApplicationManager::~ApplicationManager() { delete m_mainStageApplications; delete m_sideStageApplications; } int ApplicationManager::keyboardHeight() const { return 0; } bool ApplicationManager::keyboardVisible() const { return false; } int ApplicationManager::sideStageWidth() const { return 0; } ApplicationManager::StageHint ApplicationManager::stageHint() const { return MainStage; } ApplicationManager::FormFactorHint ApplicationManager::formFactorHint() const { return PhoneFormFactor; } ApplicationListModel* ApplicationManager::mainStageApplications() const { return m_mainStageApplications; } ApplicationListModel* ApplicationManager::sideStageApplications() const { return m_sideStageApplications; } ApplicationInfo* ApplicationManager::mainStageFocusedApplication() const { return m_mainStageFocusedApplication; } ApplicationInfo* ApplicationManager::sideStageFocusedApplication() const { return m_sideStageFocusedApplication; } ApplicationInfo* ApplicationManager::startProcess(QString desktopFile, ExecFlags flags, QStringList arguments) { Q_UNUSED(arguments) ApplicationInfo *application = 0; for (int i = 0; i < m_availableApplications.count(); ++i) { ApplicationInfo *availableApp = m_availableApplications[i]; if (availableApp->desktopFile() == desktopFile) { application = availableApp; break; } } if (!application) return 0; if (flags.testFlag(ApplicationManager::ForceMainStage) || application->stage() == ApplicationInfo::MainStage) { m_mainStageApplications->add(application); } else { m_sideStageApplications->add(application); } return application; } void ApplicationManager::stopProcess(ApplicationInfo* application) { if (m_mainStageApplications->contains(application)) { m_mainStageApplications->remove(application); if (m_mainStageFocusedApplication == application) { m_mainStageFocusedApplication = 0; Q_EMIT mainStageFocusedApplicationChanged(); } } else if (m_sideStageApplications->contains(application)){ m_sideStageApplications->remove(application); if (m_sideStageFocusedApplication == application) { m_sideStageFocusedApplication = 0; Q_EMIT sideStageFocusedApplicationChanged(); } } } void ApplicationManager::focusApplication(int handle) { for (int i = 0; i < m_mainStageApplications->m_applications.count(); ++i) { ApplicationInfo *application = m_mainStageApplications->m_applications[i]; if (application->handle() == handle) { if (m_mainStageFocusedApplication) m_mainStageFocusedApplication->hideWindow(); m_mainStageFocusedApplication = application; if (!m_mainStage) createMainStage(); application->showWindow(m_mainStage); m_mainStage->setZ(-1000); if (m_sideStage) m_sideStage->setZ(-2000); Q_EMIT mainStageFocusedApplicationChanged(); return; } } for (int i = 0; i < m_sideStageApplications->m_applications.count(); ++i) { ApplicationInfo *application = m_sideStageApplications->m_applications[i]; if (application->handle() == handle) { if (m_sideStageFocusedApplication) m_sideStageFocusedApplication->hideWindow(); m_sideStageFocusedApplication = application; if (!m_sideStage) createSideStage(); application->showWindow(m_sideStage); m_sideStage->setZ(-1000); if (m_mainStage) m_mainStage->setZ(-2000); Q_EMIT sideStageFocusedApplicationChanged(); return; } } } void ApplicationManager::unfocusCurrentApplication(StageHint stageHint) { if (stageHint == SideStage) { if (m_sideStageFocusedApplication) { m_sideStageFocusedApplication->hideWindow(); m_sideStageFocusedApplication = 0; Q_EMIT sideStageFocusedApplicationChanged(); } } else { if (m_mainStageFocusedApplication) { m_mainStageFocusedApplication->hideWindow(); m_mainStageFocusedApplication = 0; Q_EMIT mainStageFocusedApplicationChanged(); } } } void ApplicationManager::generateQmlStrings(ApplicationInfo *application) { // TODO: Is there a better way of solving this fullscreen vs. regular // application height? QString topMargin; if (application->fullscreen()) { topMargin.append("0"); } else { // Taken from Panel.panelHeight topMargin.append("units.gu(3) + units.dp(2)"); } QString windowQml = QString( "import QtQuick 2.0\n" "Image {\n" " anchors.fill: parent\n" " anchors.topMargin: %1\n" " source: \"file://%2/Dash/graphics/phone/screenshots/%3.png\"\n" " smooth: true\n" " fillMode: Image.PreserveAspectCrop\n" "}").arg(topMargin) .arg(shellAppDirectory()) .arg(application->icon()); application->setWindowQml(windowQml); QString imageQml = QString( "import QtQuick 2.0\n" "Image {\n" " anchors.fill: parent\n" " source: \"file://%1/Dash/graphics/phone/screenshots/%2.png\"\n" " smooth: true\n" " fillMode: Image.PreserveAspectCrop\n" "}").arg(shellAppDirectory()) .arg(application->icon()); application->setImageQml(imageQml); } void ApplicationManager::buildListOfAvailableApplications() { ApplicationInfo *application; qint64 nextHandle = 1; application = new ApplicationInfo(this); application->setDesktopFile("/usr/share/applications/phone-app.desktop"); application->setName("Phone"); application->setIcon("phone"); application->setExec("/usr/bin/phone-app"); application->setStage(ApplicationInfo::SideStage); application->setHandle(nextHandle++); generateQmlStrings(application); m_availableApplications.append(application); application = new ApplicationInfo(this); application->setDesktopFile("/usr/share/applications/camera-app.desktop"); application->setName("Camera"); application->setIcon("camera"); application->setFullscreen(true); application->setExec("/usr/bin/camera-app --fullscreen"); application->setHandle(nextHandle++); generateQmlStrings(application); m_availableApplications.append(application); application = new ApplicationInfo(this); application->setDesktopFile("/usr/share/applications/gallery-app.desktop"); application->setName("Gallery"); application->setIcon("gallery"); application->setExec("/usr/bin/gallery-app"); application->setHandle(nextHandle++); generateQmlStrings(application); m_availableApplications.append(application); application = new ApplicationInfo(this); application->setDesktopFile("/usr/share/applications/facebook-webapp.desktop"); application->setName("Facebook"); application->setIcon("facebook"); application->setExec("/usr/bin/webbrowser-app --chromeless http://m.facebook.com"); application->setStage(ApplicationInfo::SideStage); application->setHandle(nextHandle++); generateQmlStrings(application); m_availableApplications.append(application); application = new ApplicationInfo(this); application->setDesktopFile("/usr/share/applications/webbrowser-app.desktop"); application->setName("Browser"); application->setIcon("browser"); application->setExec("/usr/bin/webbrowser-app"); application->setHandle(nextHandle++); generateQmlStrings(application); m_availableApplications.append(application); application = new ApplicationInfo(this); application->setDesktopFile("/usr/share/applications/twitter-webapp.desktop"); application->setName("Twitter"); application->setIcon("twitter"); application->setExec("/usr/bin/webbrowser-app --chromeless http://www.twitter.com"); application->setStage(ApplicationInfo::SideStage); application->setHandle(nextHandle++); generateQmlStrings(application); m_availableApplications.append(application); application = new ApplicationInfo(this); application->setDesktopFile("/usr/share/applications/gmail-webapp.desktop"); application->setName("GMail"); application->setIcon("gmail"); application->setExec("/usr/bin/webbrowser-app --chromeless http://m.gmail.com"); application->setHandle(nextHandle++); m_availableApplications.append(application); application = new ApplicationInfo(this); application->setDesktopFile("/usr/share/applications/ubuntu-weather-app.desktop"); application->setName("Weather"); application->setIcon("weather"); application->setExec("/usr/bin/qmlscene /usr/share/ubuntu-weather-app/ubuntu-weather-app.qml"); application->setStage(ApplicationInfo::SideStage); application->setHandle(nextHandle++); generateQmlStrings(application); m_availableApplications.append(application); application = new ApplicationInfo(this); application->setDesktopFile("/usr/share/applications/notes-app.desktop"); application->setName("Notepad"); application->setIcon("notepad"); application->setExec("/usr/bin/qmlscene /usr/share/notes-app/NotesApp.qml"); application->setStage(ApplicationInfo::SideStage); application->setHandle(nextHandle++); m_availableApplications.append(application); application = new ApplicationInfo(this); application->setDesktopFile("/usr/share/applications/calendar-app.desktop"); application->setName("Calendar"); application->setIcon("calendar"); application->setExec("/usr/bin/qmlscene /usr/share/calendar-app/calendar.qml"); application->setStage(ApplicationInfo::SideStage); application->setHandle(nextHandle++); m_availableApplications.append(application); application = new ApplicationInfo(this); application->setDesktopFile("/usr/share/applications/mediaplayer-app.desktop"); application->setName("Media Player"); application->setIcon("mediaplayer-app"); application->setFullscreen(true); application->setExec("/usr/bin/mediaplayer-app"); application->setHandle(nextHandle++); m_availableApplications.append(application); application = new ApplicationInfo(this); application->setDesktopFile("/usr/share/applications/evernote.desktop"); application->setName("Evernote"); application->setIcon("evernote"); application->setHandle(nextHandle++); m_availableApplications.append(application); application = new ApplicationInfo(this); application->setDesktopFile("/usr/share/applications/map.desktop"); application->setName("Map"); application->setIcon("map"); application->setHandle(nextHandle++); generateQmlStrings(application); m_availableApplications.append(application); application = new ApplicationInfo(this); application->setDesktopFile("/usr/share/applications/pinterest.desktop"); application->setName("Pinterest"); application->setIcon("pinterest"); application->setHandle(nextHandle++); m_availableApplications.append(application); application = new ApplicationInfo(this); application->setDesktopFile("/usr/share/applications/soundcloud.desktop"); application->setName("SoundCloud"); application->setIcon("soundcloud"); application->setHandle(nextHandle++); m_availableApplications.append(application); application = new ApplicationInfo(this); application->setDesktopFile("/usr/share/applications/wikipedia.desktop"); application->setName("Wikipedia"); application->setIcon("wikipedia"); application->setHandle(nextHandle++); m_availableApplications.append(application); application = new ApplicationInfo(this); application->setDesktopFile("/usr/share/applications/youtube.desktop"); application->setName("YouTube"); application->setIcon("youtube"); application->setHandle(nextHandle++); m_availableApplications.append(application); } void ApplicationManager::createMainStageComponent() { // The assumptions I make here really should hold. QQuickView *quickView = qobject_cast(QGuiApplication::topLevelWindows()[0]); QQmlEngine *engine = quickView->engine(); m_mainStageComponent = new QQmlComponent(engine, this); QString mainStageQml = "import QtQuick 2.0\n" "Rectangle {\n" " anchors.fill: parent\n" " color: 'black'\n" " z: -2000\n" "}\n"; m_mainStageComponent->setData(mainStageQml.toLatin1(), QUrl()); } void ApplicationManager::createMainStage() { if (!m_mainStageComponent) createMainStageComponent(); // The assumptions I make here really should hold. QQuickView *quickView = qobject_cast(QGuiApplication::topLevelWindows()[0]); QQuickItem *shell = quickView->rootObject(); m_mainStage = qobject_cast(m_mainStageComponent->create()); m_mainStage->setParentItem(shell); } void ApplicationManager::createSideStageComponent() { // The assumptions I make here really should hold. QQuickView *quickView = qobject_cast(QGuiApplication::topLevelWindows()[0]); QQmlEngine *engine = quickView->engine(); m_sideStageComponent = new QQmlComponent(engine, this); QString sideStageQml = "import QtQuick 2.0\n" "import Ubuntu.Components 0.1\n" "Item {\n" " width: units.gu(40)\n" // from SideStage in Shell.qml " anchors.top: parent.top\n" " anchors.bottom: parent.bottom\n" " anchors.right: parent.right\n" " z: -1000\n" "}\n"; m_sideStageComponent->setData(sideStageQml.toLatin1(), QUrl()); } void ApplicationManager::createSideStage() { if (!m_sideStageComponent) createSideStageComponent(); // The assumptions I make here really should hold. QQuickView *quickView = qobject_cast(QGuiApplication::topLevelWindows()[0]); QQuickItem *shell = quickView->rootObject(); m_sideStage = qobject_cast(m_sideStageComponent->create()); m_sideStage->setParentItem(shell); m_sideStage->setFlag(QQuickItem::ItemHasContents, false); }