~boiko/dialer-app/uri_handler

« back to all changes in this revision

Viewing changes to src/dialerapplication.cpp

  • Committer: Tiago Salem Herrmann
  • Date: 2013-07-16 14:05:40 UTC
  • Revision ID: tiago.herrmann@canonical.com-20130716140540-bys6d4c1ri252vhk
initial commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2012 Canonical, Ltd.
 
3
 *
 
4
 * This file is part of dialer-app.
 
5
 *
 
6
 * dialer-app is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License as published by
 
8
 * the Free Software Foundation; version 3.
 
9
 *
 
10
 * dialer-app is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 * GNU General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU General Public License
 
16
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
17
 */
 
18
 
 
19
#include "dialerapplication.h"
 
20
 
 
21
#include <QDir>
 
22
#include <QUrl>
 
23
#include <QDebug>
 
24
#include <QStringList>
 
25
#include <QQuickItem>
 
26
#include <QQmlComponent>
 
27
#include <QQmlContext>
 
28
#include <QQuickView>
 
29
#include <QDBusInterface>
 
30
#include <QDBusReply>
 
31
#include <QDBusConnectionInterface>
 
32
#include <QLibrary>
 
33
#include "config.h"
 
34
#include "dialerappdbus.h"
 
35
#include <QQmlEngine>
 
36
 
 
37
static void printUsage(const QStringList& arguments)
 
38
{
 
39
    qDebug() << "usage:"
 
40
             << arguments.at(0).toUtf8().constData()
 
41
             << "[call://PHONE_NUMBER]"
 
42
             << "[voicemail://]"
 
43
             << "[--fullscreen]"
 
44
             << "[--test-contacts]"
 
45
             << "[--help]"
 
46
             << "[-testability]";
 
47
}
 
48
 
 
49
DialerApplication::DialerApplication(int &argc, char **argv)
 
50
    : QGuiApplication(argc, argv), m_view(0), m_applicationIsReady(false)
 
51
{
 
52
    setApplicationName("DialerApp");
 
53
    m_dbus = new DialerAppDBus(this);
 
54
}
 
55
 
 
56
bool DialerApplication::setup()
 
57
{
 
58
    static QList<QString> validSchemes;
 
59
    bool fullScreen = false;
 
60
    QString contactEngine = "folks";
 
61
 
 
62
    if (validSchemes.isEmpty()) {
 
63
        validSchemes << "call";
 
64
        validSchemes << "voicemail";
 
65
    }
 
66
 
 
67
    QString contactKey;
 
68
    QStringList arguments = this->arguments();
 
69
 
 
70
    if (arguments.contains("--help")) {
 
71
        printUsage(arguments);
 
72
        return false;
 
73
    }
 
74
 
 
75
    if (arguments.contains("--fullscreen")) {
 
76
        arguments.removeAll("--fullscreen");
 
77
        fullScreen = true;
 
78
    }
 
79
 
 
80
    if (arguments.contains("--test-contacts")) {
 
81
        arguments.removeAll("--test-contacts");
 
82
        contactEngine = "memory";
 
83
    }
 
84
 
 
85
    // The testability driver is only loaded by QApplication but not by QGuiApplication.
 
86
    // However, QApplication depends on QWidget which would add some unneeded overhead => Let's load the testability driver on our own.
 
87
    if (arguments.contains("-testability")) {
 
88
        arguments.removeAll("-testability");
 
89
        QLibrary testLib(QLatin1String("qttestability"));
 
90
        if (testLib.load()) {
 
91
            typedef void (*TasInitialize)(void);
 
92
            TasInitialize initFunction = (TasInitialize)testLib.resolve("qt_testability_init");
 
93
            if (initFunction) {
 
94
                initFunction();
 
95
            } else {
 
96
                qCritical("Library qttestability resolve failed!");
 
97
            }
 
98
        } else {
 
99
            qCritical("Library qttestability load failed!");
 
100
        }
 
101
    }
 
102
 
 
103
    /* Ubuntu APP Manager gathers info on the list of running applications from the .desktop
 
104
       file specified on the command line with the desktop_file_hint switch, and will also pass a stage hint
 
105
       So app will be launched like this:
 
106
 
 
107
       /usr/bin/dialer-app --desktop_file_hint=/usr/share/applications/dialer-app.desktop
 
108
                          --stage_hint=main_stage
 
109
 
 
110
       So remove whatever --arg still there before continue parsing
 
111
    */
 
112
    for (int i = arguments.count() - 1; i >=0; --i) {
 
113
        if (arguments[i].startsWith("--")) {
 
114
            arguments.removeAt(i);
 
115
        }
 
116
    }
 
117
 
 
118
    if (arguments.size() == 2) {
 
119
        QUrl uri(arguments.at(1));
 
120
        if (validSchemes.contains(uri.scheme())) {
 
121
            m_arg = arguments.at(1);
 
122
        }
 
123
    }
 
124
 
 
125
    // check if the app is already running, if it is, send the message to the running instance
 
126
    QDBusReply<bool> reply = QDBusConnection::sessionBus().interface()->isServiceRegistered("com.canonical.DialerApp");
 
127
    if (reply.isValid() && reply.value()) {
 
128
        QDBusInterface appInterface("com.canonical.DialerApp",
 
129
                                    "/com/canonical/DialerApp",
 
130
                                    "com.canonical.DialerApp");
 
131
        appInterface.call("SendAppMessage", m_arg);
 
132
        return false;
 
133
    }
 
134
 
 
135
    if (!m_dbus->connectToBus()) {
 
136
        qWarning() << "Failed to expose com.canonical.DialerApp on DBUS.";
 
137
    }
 
138
 
 
139
    m_view = new QQuickView();
 
140
    QObject::connect(m_view, SIGNAL(statusChanged(QQuickView::Status)), this, SLOT(onViewStatusChanged(QQuickView::Status)));
 
141
    QObject::connect(m_view->engine(), SIGNAL(quit()), SLOT(quit()));
 
142
    m_view->setResizeMode(QQuickView::SizeRootObjectToView);
 
143
    m_view->setTitle("Dialer");
 
144
    m_view->rootContext()->setContextProperty("application", this);
 
145
    m_view->rootContext()->setContextProperty("contactKey", contactKey);
 
146
    m_view->rootContext()->setContextProperty("dbus", m_dbus);
 
147
    m_view->rootContext()->setContextProperty("contactEngine", contactEngine);
 
148
    m_view->engine()->setBaseUrl(QUrl::fromLocalFile(dialerAppDirectory()));
 
149
 
 
150
    QString pluginPath = ubuntuPhonePluginPath();
 
151
    if (!pluginPath.isNull()) {
 
152
        m_view->engine()->addImportPath(pluginPath);
 
153
    }
 
154
 
 
155
    m_view->setSource(QUrl::fromLocalFile("dialer-app.qml"));
 
156
    if (fullScreen) {
 
157
        m_view->showFullScreen();
 
158
    } else {
 
159
        m_view->show();
 
160
    }
 
161
 
 
162
    connect(m_dbus,
 
163
            SIGNAL(request(QString)),
 
164
            SLOT(onMessageReceived(QString)));
 
165
 
 
166
    return true;
 
167
}
 
168
 
 
169
DialerApplication::~DialerApplication()
 
170
{
 
171
    if (m_view) {
 
172
        delete m_view;
 
173
    }
 
174
}
 
175
 
 
176
void DialerApplication::onViewStatusChanged(QQuickView::Status status)
 
177
{
 
178
    if (status != QQuickView::Ready) {
 
179
        return;
 
180
    }
 
181
 
 
182
    QQuickItem *mainView = m_view->rootObject();
 
183
    if (mainView) {
 
184
        QObject::connect(mainView, SIGNAL(applicationReady()), this, SLOT(onApplicationReady()));
 
185
    }
 
186
}
 
187
 
 
188
void DialerApplication::onApplicationReady()
 
189
{
 
190
    QObject::disconnect(QObject::sender(), SIGNAL(applicationReady()), this, SLOT(onApplicationReady()));
 
191
    m_applicationIsReady = true;
 
192
    parseArgument(m_arg);
 
193
    m_arg.clear();
 
194
}
 
195
 
 
196
void DialerApplication::parseArgument(const QString &arg)
 
197
{
 
198
    if (arg.isEmpty()) {
 
199
        return;
 
200
    }
 
201
 
 
202
    QStringList args = arg.split("://");
 
203
    if (args.size() != 2) {
 
204
        return;
 
205
    }
 
206
 
 
207
    QString scheme = args[0];
 
208
    QString value = args[1];
 
209
 
 
210
    QQuickItem *mainView = m_view->rootObject();
 
211
    if (!mainView) {
 
212
        return;
 
213
    }
 
214
    const QMetaObject *mo = mainView->metaObject();
 
215
 
 
216
 
 
217
    if (scheme == "call") {
 
218
        int index = mo->indexOfMethod("callNumber(QVariant)");
 
219
        if (index != -1) {
 
220
            QMetaMethod method = mo->method(index);
 
221
            method.invoke(mainView, Q_ARG(QVariant, QVariant(value)));
 
222
        }
 
223
    } else if (scheme == "voicemail") {
 
224
        int index = mo->indexOfMethod("showVoicemail()");
 
225
        if (index != -1) {
 
226
            QMetaMethod method = mo->method(index);
 
227
            method.invoke(mainView);
 
228
        }
 
229
    }
 
230
}
 
231
 
 
232
void DialerApplication::onMessageReceived(const QString &message)
 
233
{
 
234
    if (m_applicationIsReady) {
 
235
        parseArgument(message);
 
236
        m_arg.clear();
 
237
        activateWindow();
 
238
    } else {
 
239
        m_arg = message;
 
240
    }
 
241
}
 
242
 
 
243
void DialerApplication::activateWindow()
 
244
{
 
245
    if (m_view) {
 
246
        m_view->raise();
 
247
        m_view->requestActivate();
 
248
    }
 
249
}