~ubuntu-branches/ubuntu/natty/kdebase-runtime/natty-proposed

« back to all changes in this revision

Viewing changes to plasma/scriptengines/javascript/dataengine/javascriptdataengine.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jonathan Riddell
  • Date: 2010-11-24 11:07:10 UTC
  • mto: (0.8.7 upstream)
  • mto: This revision was merged to the branch mainline in revision 129.
  • Revision ID: james.westby@ubuntu.com-20101124110710-6dbsyw0yh21qvn82
Tags: upstream-4.5.80
ImportĀ upstreamĀ versionĀ 4.5.80

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *   Copyright 2009 Aaron Seigo <aseigo@kde.org>
 
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
 
6
 *   published by the Free Software Foundation; either version 2, or
 
7
 *   (at your option) any later version.
 
8
 *
 
9
 *   This program is distributed in the hope that it will be useful,
 
10
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
 *   GNU General Public License for more details
 
13
 *
 
14
 *   You should have received a copy of the GNU Library General Public
 
15
 *   License along with this program; if not, write to the
 
16
 *   Free Software Foundation, Inc.,
 
17
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
18
 */
 
19
 
 
20
#include "javascriptdataengine.h"
 
21
 
 
22
#include <QScriptEngine>
 
23
 
 
24
#include <Plasma/Package>
 
25
 
 
26
#include "javascriptservice.h"
 
27
#include "common/authorization.h"
 
28
#include "common/scriptenv.h"
 
29
#include "simplebindings/i18n.h"
 
30
#include "simplebindings/dataengine.h"
 
31
 
 
32
void registerNonGuiMetaTypes(QScriptEngine *engine);
 
33
 
 
34
JavaScriptDataEngine::JavaScriptDataEngine(QObject *parent, const QVariantList &args)
 
35
    : DataEngineScript(parent)
 
36
{
 
37
    Q_UNUSED(args);
 
38
 
 
39
    m_qscriptEngine = new QScriptEngine(this);
 
40
    m_env = new ScriptEnv(this, m_qscriptEngine);
 
41
 
 
42
    connect(m_env, SIGNAL(reportError(ScriptEnv*,bool)), this, SLOT(reportError(ScriptEnv*,bool)));
 
43
}
 
44
 
 
45
bool JavaScriptDataEngine::init()
 
46
{
 
47
    QScriptValue global = m_qscriptEngine->globalObject();
 
48
 
 
49
    bindI18N(m_qscriptEngine);
 
50
 
 
51
    m_iface = m_qscriptEngine->newQObject(this);
 
52
    m_iface.setScope(global);
 
53
    m_env->addMainObjectProperties(m_iface);
 
54
 
 
55
    global.setProperty("engine", m_iface);
 
56
 
 
57
    global.setProperty("setData", m_qscriptEngine->newFunction(JavaScriptDataEngine::jsSetData));
 
58
    global.setProperty("removeAllData", m_qscriptEngine->newFunction(JavaScriptDataEngine::jsRemoveAllData));
 
59
    global.setProperty("removeData", m_qscriptEngine->newFunction(JavaScriptDataEngine::jsRemoveData));
 
60
    global.setProperty("removeAllSources", m_qscriptEngine->newFunction(JavaScriptDataEngine::jsRemoveAllSources));
 
61
    global.setProperty("Service", m_qscriptEngine->newFunction(JavaScriptDataEngine::serviceCtor));
 
62
 
 
63
    registerNonGuiMetaTypes(m_qscriptEngine);
 
64
 
 
65
    Authorization auth;
 
66
    if (!m_env->importExtensions(description(), m_iface, auth)) {
 
67
        return false;
 
68
    }
 
69
 
 
70
    return m_env->include(mainScript());
 
71
}
 
72
 
 
73
QScriptEngine *JavaScriptDataEngine::engine() const
 
74
{
 
75
    return m_qscriptEngine;
 
76
}
 
77
 
 
78
void JavaScriptDataEngine::jsSetMaxSourceCount(int count)
 
79
{
 
80
    setMaxSourceCount(count);
 
81
}
 
82
 
 
83
int JavaScriptDataEngine::maxSourceCount() const
 
84
{
 
85
    return dataEngine()->maxSourceCount();
 
86
}
 
87
 
 
88
void JavaScriptDataEngine::jsSetMinimumPollingInterval(int interval)
 
89
{
 
90
    setMinimumPollingInterval(interval);
 
91
}
 
92
 
 
93
int JavaScriptDataEngine::jsMinimumPollingInterval() const
 
94
{
 
95
    return minimumPollingInterval();
 
96
}
 
97
 
 
98
void JavaScriptDataEngine::jsSetPollingInterval(int interval)
 
99
{
 
100
    m_pollingInterval = interval;
 
101
    setPollingInterval(interval);
 
102
}
 
103
 
 
104
int JavaScriptDataEngine::pollingInterval() const
 
105
{
 
106
    return m_pollingInterval;
 
107
}
 
108
 
 
109
QScriptValue JavaScriptDataEngine::jsSetData(QScriptContext *context, QScriptEngine *engine)
 
110
{
 
111
    if (context->argumentCount() < 1) {
 
112
        return context->throwError(i18n("setData() takes at least one argument"));
 
113
    }
 
114
 
 
115
    QString error;
 
116
    JavaScriptDataEngine *iFace = extractIFace(engine, error);
 
117
 
 
118
    if (!iFace) {
 
119
        return context->throwError(error);
 
120
    }
 
121
 
 
122
    const QString source = context->argument(0).toString();
 
123
    if (context->argumentCount() == 1) {
 
124
        iFace->setData(source, DataEngine::Data());
 
125
    } else if (context->argument(1).isArray()  || context->argument(1).isObject()) {
 
126
        kDebug( )<< "array or object";
 
127
        QScriptValueIterator it(context->argument(1));
 
128
        DataEngine::Data data;
 
129
 
 
130
        while (it.hasNext()) {
 
131
            it.next();
 
132
            data.insert(it.name(), it.value().toVariant());
 
133
        }
 
134
 
 
135
        iFace->setData(source, data);
 
136
    } else {
 
137
        const QString value = context->argument(1).toString();
 
138
        if (context->argumentCount() > 2) {
 
139
            if (context->argument(2).isArray() || context->argument(2).isObject()) {
 
140
                QScriptValueIterator it(context->argument(2));
 
141
                DataEngine::Data data;
 
142
 
 
143
                while (it.hasNext()) {
 
144
                    it.next();
 
145
                    data.insert(it.name(), it.value().toVariant());
 
146
                }
 
147
 
 
148
                iFace->setData(source, value, data);
 
149
            } else {
 
150
                iFace->setData(source, value, context->argument(2).toString());
 
151
            }
 
152
        } else {
 
153
            iFace->setData(source, value);
 
154
        }
 
155
    }
 
156
 
 
157
    return engine->newVariant(true);
 
158
}
 
159
 
 
160
JavaScriptDataEngine *JavaScriptDataEngine::extractIFace(QScriptEngine *engine, QString &error)
 
161
{
 
162
    JavaScriptDataEngine *interface = 0;
 
163
    QScriptValue engineValue = engine->globalObject().property("engine");
 
164
    QObject *engineObject = engineValue.toQObject();
 
165
 
 
166
    if (!engineObject) {
 
167
        error = i18n("Could not extract the DataEngineObject");
 
168
    } else {
 
169
        interface = qobject_cast<JavaScriptDataEngine *>(engineObject);
 
170
        if (!interface) {
 
171
            error = i18n("Could not extract the DataEngine");
 
172
        }
 
173
    }
 
174
 
 
175
    return interface;
 
176
}
 
177
 
 
178
QScriptValue JavaScriptDataEngine::jsRemoveAllData(QScriptContext *context, QScriptEngine *engine)
 
179
{
 
180
    if (context->argumentCount() < 1) {
 
181
        return context->throwError(i18n("removeAllData() takes at least one argument (the source name)"));
 
182
    }
 
183
 
 
184
    QString source = context->argument(0).toString();
 
185
    QString error;
 
186
    JavaScriptDataEngine *iFace = extractIFace(engine, error);
 
187
 
 
188
    if (iFace) {
 
189
        iFace->removeAllData(source);
 
190
        return engine->newVariant(true);
 
191
    }
 
192
 
 
193
    return context->throwError(error);
 
194
}
 
195
 
 
196
QScriptValue JavaScriptDataEngine::jsRemoveData(QScriptContext *context, QScriptEngine *engine)
 
197
{
 
198
    if (context->argumentCount() < 2) {
 
199
        return context->throwError(i18n("removeData() takes at least two arguments (the source and key names)"));
 
200
    }
 
201
 
 
202
    QString source = context->argument(0).toString();
 
203
    QString key = context->argument(1).toString();
 
204
    QString error;
 
205
    JavaScriptDataEngine *iFace = extractIFace(engine, error);
 
206
 
 
207
    if (iFace) {
 
208
        iFace->removeData(source, key);
 
209
        return engine->newVariant(true);
 
210
    }
 
211
 
 
212
    return context->throwError(error);
 
213
}
 
214
 
 
215
QScriptValue JavaScriptDataEngine::jsRemoveAllSources(QScriptContext *context, QScriptEngine *engine)
 
216
{
 
217
    QString error;
 
218
    JavaScriptDataEngine *iFace = extractIFace(engine, error);
 
219
 
 
220
    if (iFace) {
 
221
        iFace->removeAllSources();
 
222
        return engine->newVariant(true);
 
223
    }
 
224
 
 
225
    return context->throwError(error);
 
226
}
 
227
 
 
228
QScriptValue JavaScriptDataEngine::serviceCtor(QScriptContext *context, QScriptEngine *engine)
 
229
{
 
230
    QString error;
 
231
    JavaScriptDataEngine *iFace = extractIFace(engine, error);
 
232
    if (!iFace) {
 
233
        return context->throwError(error);
 
234
    }
 
235
 
 
236
    if (context->argumentCount() < 1) {
 
237
        return context->throwError(i18n("Service requires at least one parameter: the name of the service"));
 
238
    }
 
239
 
 
240
    const QString &serviceName = context->argument(0).toString();
 
241
    if (serviceName.isEmpty()) {
 
242
        return context->throwError(i18n("Service requires at least one parameter: the name of the service"));
 
243
    }
 
244
 
 
245
    JavaScriptService *service = new JavaScriptService(serviceName, iFace);
 
246
    if (service->wasFound()) {
 
247
        QScriptValue v = engine->newQObject(service, QScriptEngine::QtOwnership, QScriptEngine::ExcludeSuperClassContents);
 
248
        return v;
 
249
    }
 
250
 
 
251
    delete service;
 
252
    return context->throwError(i18n("Requested service %1 was not found in the Package.", serviceName));
 
253
}
 
254
 
 
255
QScriptValue JavaScriptDataEngine::callFunction(const QString &functionName, const QScriptValueList &args)
 
256
{
 
257
    QScriptValue func = m_iface.property(functionName);
 
258
    return m_env->callFunction(func, args, m_iface);
 
259
}
 
260
 
 
261
void JavaScriptDataEngine::reportError(ScriptEnv *env, bool fatal) const
 
262
{
 
263
    Q_UNUSED(fatal)
 
264
 
 
265
    kDebug() << "Error: " << env->engine()->uncaughtException().toString()
 
266
             << " at line " << env->engine()->uncaughtExceptionLineNumber() << endl;
 
267
    kDebug() << env->engine()->uncaughtExceptionBacktrace();
 
268
}
 
269
 
 
270
QStringList JavaScriptDataEngine::sources() const
 
271
{
 
272
    JavaScriptDataEngine *unconst = const_cast<JavaScriptDataEngine *>(this);
 
273
    QScriptValueList args;
 
274
    QScriptValue rv = unconst->callFunction("sources", args);
 
275
    if (rv.isValid() && (rv.isVariant() || rv.isArray())) {
 
276
        return rv.toVariant().toStringList();
 
277
    }
 
278
 
 
279
    return DataEngineScript::sources();
 
280
}
 
281
 
 
282
bool JavaScriptDataEngine::sourceRequestEvent(const QString &name)
 
283
{
 
284
    QScriptValueList args;
 
285
    args << name;
 
286
    m_env->callEventListeners("sourceRequestEvent", args);
 
287
    QScriptValue rv = callFunction("sourceRequestEvent", args);
 
288
    if (rv.isValid() && rv.isBool()) {
 
289
        return rv.toBool();
 
290
    }
 
291
 
 
292
    return false;
 
293
}
 
294
 
 
295
bool JavaScriptDataEngine::updateSourceEvent(const QString &source)
 
296
{
 
297
    QScriptValueList args;
 
298
    args << source;
 
299
    m_env->callEventListeners("updateSourcEvent", args);
 
300
    QScriptValue rv = callFunction("updateSourceEvent", args);
 
301
    if (rv.isValid() && rv.isBool()) {
 
302
        return rv.toBool();
 
303
    }
 
304
 
 
305
    return false;
 
306
}
 
307
 
 
308
Plasma::Service *JavaScriptDataEngine::serviceForSource(const QString &source)
 
309
{
 
310
    QScriptValueList args;
 
311
    args << source;
 
312
    QScriptValue rv = callFunction("serviceForSource", args);
 
313
    if (rv.isValid() && rv.isQObject()) {
 
314
        Plasma::Service *service = qobject_cast<Plasma::Service *>(rv.toQObject());
 
315
        if (service) {
 
316
            if (service->destination().isEmpty()) {
 
317
                service->setDestination(source);
 
318
            }
 
319
 
 
320
            return service;
 
321
        } else {
 
322
            delete rv.toQObject();
 
323
        }
 
324
    }
 
325
 
 
326
    return 0;
 
327
}
 
328
 
 
329
QString JavaScriptDataEngine::filePath(const char *type, const QString &file) const
 
330
{
 
331
    const QString path = m_env->filePathFromScriptContext(type, file);
 
332
    if (!path.isEmpty()) {
 
333
        return path;
 
334
    }
 
335
 
 
336
    return package()->filePath(type, file);
 
337
}
 
338
 
 
339
bool JavaScriptDataEngine::include(const QString &script)
 
340
{
 
341
    const QString path = filePath("scripts", script);
 
342
    if (path.isEmpty()) {
 
343
        return false;
 
344
    }
 
345
 
 
346
    return m_env->include(path);
 
347
}
 
348
 
 
349
K_EXPORT_PLASMA_DATAENGINESCRIPTENGINE(javascriptdataengine, JavaScriptDataEngine)
 
350
 
 
351
#include <javascriptdataengine.moc>
 
352