~ubuntu-branches/ubuntu/precise/kde-workspace/precise-updates

« back to all changes in this revision

Viewing changes to .pc/fix_plasma_init_order.diff/libs/plasmagenericshell/scripting/scriptengine.cpp

  • Committer: Package Import Robot
  • Author(s): Rohan Garg
  • Date: 2013-02-13 10:18:02 UTC
  • mfrom: (46.1.3 precise-proposed)
  • Revision ID: package-import@ubuntu.com-20130213101802-rxi1x4m3snddd7ay
Tags: 4:4.8.5-0ubuntu0.3
Add fix_plasma_init_order.diff from upstream to fix plasma init 
order LP: #1123126

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 Library 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 "scriptengine.h"
 
21
 
 
22
#include <QApplication>
 
23
#include <QDesktopWidget>
 
24
#include <QDir>
 
25
#include <QFile>
 
26
#include <QFileInfo>
 
27
#include <QScriptValueIterator>
 
28
 
 
29
#include <KDebug>
 
30
#include <kdeversion.h>
 
31
#include <KGlobalSettings>
 
32
#include <KMimeTypeTrader>
 
33
#include <KServiceTypeTrader>
 
34
#include <KShell>
 
35
#include <KStandardDirs>
 
36
 
 
37
// KIO
 
38
#include <kemailsettings.h> // no camelcase include
 
39
 
 
40
#include <Plasma/Applet>
 
41
#include <Plasma/Containment>
 
42
#include <Plasma/Corona>
 
43
#include <Plasma/Package>
 
44
#include <Plasma/Wallpaper>
 
45
 
 
46
#include "appinterface.h"
 
47
#include "containment.h"
 
48
#include "i18n.h"
 
49
#include "layouttemplatepackagestructure.h"
 
50
#include "widget.h"
 
51
 
 
52
QScriptValue constructQRectFClass(QScriptEngine *engine);
 
53
 
 
54
namespace WorkspaceScripting
 
55
{
 
56
 
 
57
ScriptEngine::ScriptEngine(Plasma::Corona *corona, QObject *parent)
 
58
    : QScriptEngine(parent),
 
59
      m_corona(corona)
 
60
{
 
61
    Q_ASSERT(m_corona);
 
62
    AppInterface *interface = new AppInterface(this);
 
63
    connect(interface, SIGNAL(print(QString)), this, SIGNAL(print(QString)));
 
64
    m_scriptSelf = newQObject(interface, QScriptEngine::QtOwnership,
 
65
                              QScriptEngine::ExcludeSuperClassProperties |
 
66
                              QScriptEngine::ExcludeSuperClassMethods);
 
67
    setupEngine();
 
68
    connect(this, SIGNAL(signalHandlerException(QScriptValue)), this, SLOT(exception(QScriptValue)));
 
69
    bindI18N(this);
 
70
}
 
71
 
 
72
ScriptEngine::~ScriptEngine()
 
73
{
 
74
}
 
75
 
 
76
QScriptValue ScriptEngine::activityById(QScriptContext *context, QScriptEngine *engine)
 
77
{
 
78
    if (context->argumentCount() == 0) {
 
79
        return context->throwError(i18n("activityById requires an id"));
 
80
    }
 
81
 
 
82
    const uint id = context->argument(0).toInt32();
 
83
    ScriptEngine *env = envFor(engine);
 
84
    foreach (Plasma::Containment *c, env->m_corona->containments()) {
 
85
        if (c->id() == id && !isPanel(c)) {
 
86
            return env->wrap(c);
 
87
        }
 
88
    }
 
89
 
 
90
    return engine->undefinedValue();
 
91
}
 
92
 
 
93
QScriptValue ScriptEngine::activityForScreen(QScriptContext *context, QScriptEngine *engine)
 
94
{
 
95
    if (context->argumentCount() == 0) {
 
96
        return context->throwError(i18n("activityForScreen requires a screen id"));
 
97
    }
 
98
 
 
99
    const uint screen = context->argument(0).toInt32();
 
100
    const uint desktop = context->argumentCount() > 1 ? context->argument(1).toInt32() : -1;
 
101
    ScriptEngine *env = envFor(engine);
 
102
    return env->wrap(env->m_corona->containmentForScreen(screen, desktop));
 
103
}
 
104
 
 
105
QScriptValue ScriptEngine::newActivity(QScriptContext *context, QScriptEngine *engine)
 
106
{
 
107
    return createContainment("desktop", "desktop", context, engine);
 
108
}
 
109
 
 
110
QScriptValue ScriptEngine::newPanel(QScriptContext *context, QScriptEngine *engine)
 
111
{
 
112
    return createContainment("panel", "panel", context, engine);
 
113
}
 
114
 
 
115
QScriptValue ScriptEngine::createContainment(const QString &type, const QString &defaultPlugin,
 
116
                                             QScriptContext *context, QScriptEngine *engine)
 
117
{
 
118
    QString plugin = context->argumentCount() > 0 ? context->argument(0).toString() :
 
119
                                                    defaultPlugin;
 
120
 
 
121
    bool exists = false;
 
122
    const KPluginInfo::List list = Plasma::Containment::listContainmentsOfType(type);
 
123
    foreach (const KPluginInfo &info, list) {
 
124
        if (info.pluginName() == plugin) {
 
125
            exists = true;
 
126
            break;
 
127
        }
 
128
    }
 
129
 
 
130
    if (!exists) {
 
131
        return context->throwError(i18n("Could not find a plugin for %1 named %2.", type, plugin));
 
132
    }
 
133
 
 
134
 
 
135
    ScriptEngine *env = envFor(engine);
 
136
    Plasma::Containment *c = env->m_corona->addContainment(plugin);
 
137
    if (c) {
 
138
        if (type == "panel") {
 
139
            // some defaults
 
140
            c->setScreen(env->defaultPanelScreen());
 
141
            c->setLocation(Plasma::TopEdge);
 
142
        }
 
143
        c->updateConstraints(Plasma::AllConstraints | Plasma::StartupCompletedConstraint);
 
144
        c->flushPendingConstraintsEvents();
 
145
        emit env->createPendingPanelViews();
 
146
    }
 
147
 
 
148
    return env->wrap(c);
 
149
}
 
150
 
 
151
QScriptValue ScriptEngine::wrap(Plasma::Applet *w)
 
152
{
 
153
    Widget *wrapper = new Widget(w);
 
154
    QScriptValue v = newQObject(wrapper, QScriptEngine::ScriptOwnership,
 
155
                                QScriptEngine::ExcludeSuperClassProperties |
 
156
                                QScriptEngine::ExcludeSuperClassMethods);
 
157
    return v;
 
158
}
 
159
 
 
160
QScriptValue ScriptEngine::wrap(Plasma::Containment *c)
 
161
{
 
162
    Containment *wrapper = new Containment(c);
 
163
    return wrap(wrapper);
 
164
}
 
165
 
 
166
QScriptValue ScriptEngine::wrap(Containment *c)
 
167
{
 
168
    QScriptValue v = newQObject(c, QScriptEngine::ScriptOwnership,
 
169
                                QScriptEngine::ExcludeSuperClassProperties |
 
170
                                QScriptEngine::ExcludeSuperClassMethods);
 
171
    v.setProperty("widgetById", newFunction(Containment::widgetById));
 
172
    v.setProperty("addWidget", newFunction(Containment::addWidget));
 
173
    v.setProperty("widgets", newFunction(Containment::widgets));
 
174
 
 
175
    return v;
 
176
}
 
177
 
 
178
int ScriptEngine::defaultPanelScreen() const
 
179
{
 
180
    return qApp ? qApp->desktop()->primaryScreen() : 0;
 
181
}
 
182
 
 
183
ScriptEngine *ScriptEngine::envFor(QScriptEngine *engine)
 
184
{
 
185
    QObject *object = engine->globalObject().toQObject();
 
186
    Q_ASSERT(object);
 
187
 
 
188
    AppInterface *interface = qobject_cast<AppInterface *>(object);
 
189
    Q_ASSERT(interface);
 
190
 
 
191
    ScriptEngine *env = qobject_cast<ScriptEngine *>(interface->parent());
 
192
    Q_ASSERT(env);
 
193
 
 
194
    return env;
 
195
}
 
196
 
 
197
QScriptValue ScriptEngine::panelById(QScriptContext *context, QScriptEngine *engine)
 
198
{
 
199
    if (context->argumentCount() == 0) {
 
200
        return context->throwError(i18n("activityById requires an id"));
 
201
    }
 
202
 
 
203
    const uint id = context->argument(0).toInt32();
 
204
    ScriptEngine *env = envFor(engine);
 
205
    foreach (Plasma::Containment *c, env->m_corona->containments()) {
 
206
        if (c->id() == id && isPanel(c)) {
 
207
            return env->wrap(c);
 
208
        }
 
209
    }
 
210
 
 
211
    return engine->undefinedValue();
 
212
}
 
213
 
 
214
QScriptValue ScriptEngine::panels(QScriptContext *context, QScriptEngine *engine)
 
215
{
 
216
    Q_UNUSED(context)
 
217
 
 
218
    QScriptValue panels = engine->newArray();
 
219
    ScriptEngine *env = envFor(engine);
 
220
    int count = 0;
 
221
 
 
222
    foreach (Plasma::Containment *c, env->m_corona->containments()) {
 
223
        if (isPanel(c)) {
 
224
            panels.setProperty(count, env->wrap(c));
 
225
            ++count;
 
226
        }
 
227
    }
 
228
 
 
229
    panels.setProperty("length", count);
 
230
    return panels;
 
231
}
 
232
 
 
233
QScriptValue ScriptEngine::fileExists(QScriptContext *context, QScriptEngine *engine)
 
234
{
 
235
    Q_UNUSED(engine)
 
236
    if (context->argumentCount() == 0) {
 
237
        return false;
 
238
    }
 
239
 
 
240
    const QString path = context->argument(0).toString();
 
241
    if (path.isEmpty()) {
 
242
        return false;
 
243
    }
 
244
 
 
245
    QFile f(KShell::tildeExpand(path));
 
246
    return f.exists();
 
247
}
 
248
 
 
249
QScriptValue ScriptEngine::loadTemplate(QScriptContext *context, QScriptEngine *engine)
 
250
{
 
251
    Q_UNUSED(engine)
 
252
    if (context->argumentCount() == 0) {
 
253
        kDebug() << "no arguments";
 
254
        return false;
 
255
    }
 
256
 
 
257
    const QString layout = context->argument(0).toString();
 
258
    if (layout.isEmpty() || layout.contains("'")) {
 
259
        kDebug() << "layout is empty";
 
260
        return false;
 
261
    }
 
262
 
 
263
    const QString constraint = QString("[X-Plasma-Shell] == '%1' and [X-KDE-PluginInfo-Name] == '%2'")
 
264
                                      .arg(KGlobal::mainComponent().componentName(),layout);
 
265
    KService::List offers = KServiceTypeTrader::self()->query("Plasma/LayoutTemplate", constraint);
 
266
 
 
267
    if (offers.isEmpty()) {
 
268
        kDebug() << "offers fail" << constraint;
 
269
        return false;
 
270
    }
 
271
 
 
272
    Plasma::PackageStructure::Ptr structure(new LayoutTemplatePackageStructure);
 
273
    KPluginInfo info(offers.first());
 
274
    const QString path = KStandardDirs::locate("data", structure->defaultPackageRoot() + '/' + info.pluginName() + '/');
 
275
    if (path.isEmpty()) {
 
276
        kDebug() << "script path is empty";
 
277
        return false;
 
278
    }
 
279
 
 
280
    Plasma::Package package(path, structure);
 
281
    const QString scriptFile = package.filePath("mainscript");
 
282
    if (scriptFile.isEmpty()) {
 
283
        kDebug() << "scriptfile is empty";
 
284
        return false;
 
285
    }
 
286
 
 
287
    QFile file(scriptFile);
 
288
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
 
289
        kWarning() << i18n("Unable to load script file: %1", path);
 
290
        return false;
 
291
    }
 
292
 
 
293
    QString script = file.readAll();
 
294
    if (script.isEmpty()) {
 
295
        kDebug() << "script is empty";
 
296
        return false;
 
297
    }
 
298
 
 
299
    ScriptEngine *env = envFor(engine);
 
300
    env->globalObject().setProperty("templateName", env->newVariant(info.name()), QScriptValue::ReadOnly | QScriptValue::Undeletable);
 
301
    env->globalObject().setProperty("templateComment", env->newVariant(info.comment()), QScriptValue::ReadOnly | QScriptValue::Undeletable);
 
302
 
 
303
    QScriptValue rv = env->newObject();
 
304
    QScriptContext *ctx = env->pushContext();
 
305
    ctx->setThisObject(rv);
 
306
 
 
307
    env->evaluateScript(script, path);
 
308
 
 
309
    env->popContext();
 
310
    return rv;
 
311
}
 
312
 
 
313
QScriptValue ScriptEngine::applicationExists(QScriptContext *context, QScriptEngine *engine)
 
314
{
 
315
    Q_UNUSED(engine)
 
316
    if (context->argumentCount() == 0) {
 
317
        return false;
 
318
    }
 
319
 
 
320
    const QString application = context->argument(0).toString();
 
321
    if (application.isEmpty()) {
 
322
        return false;
 
323
    }
 
324
 
 
325
    // first, check for it in $PATH
 
326
    if (!KStandardDirs::findExe(application).isEmpty()) {
 
327
        return true;
 
328
    }
 
329
 
 
330
    if (KService::serviceByStorageId(application)) {
 
331
        return true;
 
332
    }
 
333
 
 
334
    if (application.contains("'")) {
 
335
        // apostrophes just screw up the trader lookups below, so check for it
 
336
        return false;
 
337
    }
 
338
 
 
339
    // next, consult ksycoca for an app by that name
 
340
    if (!KServiceTypeTrader::self()->query("Application", QString("Name =~ '%1'").arg(application)).isEmpty()) {
 
341
        return true;
 
342
    }
 
343
 
 
344
    // next, consult ksycoca for an app by that generic name
 
345
    if (!KServiceTypeTrader::self()->query("Application", QString("GenericName =~ '%1'").arg(application)).isEmpty()) {
 
346
        return true;
 
347
    }
 
348
 
 
349
    return false;
 
350
}
 
351
 
 
352
QScriptValue ScriptEngine::defaultApplication(QScriptContext *context, QScriptEngine *engine)
 
353
{
 
354
    Q_UNUSED(engine)
 
355
    if (context->argumentCount() == 0) {
 
356
        return false;
 
357
    }
 
358
 
 
359
    const QString application = context->argument(0).toString();
 
360
    if (application.isEmpty()) {
 
361
        return false;
 
362
    }
 
363
 
 
364
    const bool storageId = context->argumentCount() < 2 ? false : context->argument(1).toBool();
 
365
 
 
366
    // FIXME: there are some pretty horrible hacks below, in the sense that they assume a very
 
367
    // specific implementation system. there is much room for improvement here. see
 
368
    // kdebase-runtime/kcontrol/componentchooser/ for all the gory details ;)
 
369
    if (application.compare("mailer", Qt::CaseInsensitive) == 0) {
 
370
        KEMailSettings settings;
 
371
 
 
372
        // in KToolInvocation, the default is kmail; but let's be friendlier :)
 
373
        QString command = settings.getSetting(KEMailSettings::ClientProgram);
 
374
        if (command.isEmpty()) {
 
375
            if (KService::Ptr kontact = KService::serviceByStorageId("kontact")) {
 
376
                return storageId ? kontact->storageId() : kontact->exec();
 
377
            } else if (KService::Ptr kmail = KService::serviceByStorageId("kmail")) {
 
378
                return storageId ? kmail->storageId() : kmail->exec();
 
379
            }
 
380
        }
 
381
 
 
382
        if (!command.isEmpty()) {
 
383
            if (settings.getSetting(KEMailSettings::ClientTerminal) == "true") {
 
384
                KConfigGroup confGroup(KGlobal::config(), "General");
 
385
                const QString preferredTerminal = confGroup.readPathEntry("TerminalApplication",
 
386
                        QString::fromLatin1("konsole"));
 
387
                command = preferredTerminal + QString::fromLatin1(" -e ") + command;
 
388
            }
 
389
 
 
390
            return command;
 
391
        }
 
392
    } else if (application.compare("browser", Qt::CaseInsensitive) == 0) {
 
393
        KConfigGroup config(KGlobal::config(), "General");
 
394
        QString browserApp = config.readPathEntry("BrowserApplication", QString());
 
395
        if (browserApp.isEmpty()) {
 
396
            const KService::Ptr htmlApp = KMimeTypeTrader::self()->preferredService(QLatin1String("text/html"));
 
397
            if (htmlApp) {
 
398
                browserApp = storageId ? htmlApp->storageId() : htmlApp->exec();
 
399
            }
 
400
        } else if (browserApp.startsWith('!')) {
 
401
            browserApp = browserApp.mid(1);
 
402
        }
 
403
 
 
404
        return browserApp;
 
405
    } else if (application.compare("terminal", Qt::CaseInsensitive) == 0) {
 
406
        KConfigGroup confGroup(KGlobal::config(), "General");
 
407
        return confGroup.readPathEntry("TerminalApplication", QString::fromLatin1("konsole"));
 
408
    } else if (application.compare("filemanager", Qt::CaseInsensitive) == 0) {
 
409
        KService::Ptr service = KMimeTypeTrader::self()->preferredService("inode/directory");
 
410
        if (service) {
 
411
            return storageId ? service->storageId() : service->exec();
 
412
        }
 
413
    } else if (application.compare("windowmanager", Qt::CaseInsensitive) == 0) {
 
414
        KConfig cfg("ksmserverrc", KConfig::NoGlobals);
 
415
        KConfigGroup confGroup(&cfg, "General");
 
416
        return confGroup.readEntry("windowManager", QString::fromLatin1("konsole"));
 
417
    } else if (KService::Ptr service = KMimeTypeTrader::self()->preferredService(application)) {
 
418
        return storageId ? service->storageId() : service->exec();
 
419
    } else {
 
420
        // try the files in share/apps/kcm_componentchooser/
 
421
        const QStringList services = KGlobal::dirs()->findAllResources("data","kcm_componentchooser/*.desktop", KStandardDirs::NoDuplicates);
 
422
        //kDebug() << "ok, trying in" << services.count();
 
423
        foreach (const QString &service, services) {
 
424
            KConfig config(service, KConfig::SimpleConfig);
 
425
            KConfigGroup cg = config.group(QByteArray());
 
426
            const QString type = cg.readEntry("valueName", QString());
 
427
            //kDebug() << "    checking" << service << type << application;
 
428
            if (type.compare(application, Qt::CaseInsensitive) == 0) {
 
429
                KConfig store(cg.readPathEntry("storeInFile", "null"));
 
430
                KConfigGroup storeCg(&store, cg.readEntry("valueSection", QString()));
 
431
                const QString exec = storeCg.readPathEntry(cg.readEntry("valueName", "kcm_componenchooser_null"),
 
432
                                                           cg.readEntry("defaultImplementation", QString()));
 
433
                if (!exec.isEmpty()) {
 
434
                    return exec;
 
435
                }
 
436
 
 
437
                break;
 
438
            }
 
439
        }
 
440
    }
 
441
 
 
442
    return false;
 
443
}
 
444
 
 
445
QScriptValue ScriptEngine::applicationPath(QScriptContext *context, QScriptEngine *engine)
 
446
{
 
447
    Q_UNUSED(engine)
 
448
    if (context->argumentCount() == 0) {
 
449
        return false;
 
450
    }
 
451
 
 
452
    const QString application = context->argument(0).toString();
 
453
    if (application.isEmpty()) {
 
454
        return false;
 
455
    }
 
456
 
 
457
    // first, check for it in $PATH
 
458
    const QString path = KStandardDirs::findExe(application);
 
459
    if (!path.isEmpty()) {
 
460
        return path;
 
461
    }
 
462
 
 
463
    if (KService::Ptr service = KService::serviceByStorageId(application)) {
 
464
        return KStandardDirs::locate("apps", service->entryPath());
 
465
    }
 
466
 
 
467
    if (application.contains("'")) {
 
468
        // apostrophes just screw up the trader lookups below, so check for it
 
469
        return QString();
 
470
    }
 
471
 
 
472
    // next, consult ksycoca for an app by that name
 
473
    KService::List offers = KServiceTypeTrader::self()->query("Application", QString("Name =~ '%1'").arg(application));
 
474
    if (offers.isEmpty()) {
 
475
        // next, consult ksycoca for an app by that generic name
 
476
        offers = KServiceTypeTrader::self()->query("Application", QString("GenericName =~ '%1'").arg(application));
 
477
    }
 
478
 
 
479
    if (!offers.isEmpty()) {
 
480
        KService::Ptr offer = offers.first();
 
481
        return KStandardDirs::locate("apps", offer->entryPath());
 
482
    }
 
483
 
 
484
    return QString();
 
485
}
 
486
 
 
487
QScriptValue ScriptEngine::userDataPath(QScriptContext *context, QScriptEngine *engine)
 
488
{
 
489
    Q_UNUSED(engine)
 
490
    if (context->argumentCount() == 0) {
 
491
        return QDir::homePath();
 
492
    }
 
493
 
 
494
    const QString type = context->argument(0).toString();
 
495
    if (type.isEmpty()) {
 
496
        return QDir::homePath();
 
497
    }
 
498
 
 
499
    if (context->argumentCount() > 1) {
 
500
        const QString filename = context->argument(1).toString();
 
501
        return KStandardDirs::locateLocal(type.toLatin1(), filename);
 
502
    }
 
503
 
 
504
    if (type.compare("desktop", Qt::CaseInsensitive) == 0) {
 
505
        return KGlobalSettings::desktopPath();
 
506
    } else if (type.compare("autostart", Qt::CaseInsensitive) == 0) {
 
507
        return KGlobalSettings::autostartPath();
 
508
    } else if (type.compare("documents", Qt::CaseInsensitive) == 0) {
 
509
        return KGlobalSettings::documentPath();
 
510
    } else if (type.compare("music", Qt::CaseInsensitive) == 0) {
 
511
        return KGlobalSettings::musicPath();
 
512
    } else if (type.compare("video", Qt::CaseInsensitive) == 0) {
 
513
        return KGlobalSettings::videosPath();
 
514
    } else if (type.compare("downloads", Qt::CaseInsensitive) == 0) {
 
515
        return KGlobalSettings::downloadPath();
 
516
    } else if (type.compare("pictures", Qt::CaseInsensitive) == 0) {
 
517
        return KGlobalSettings::picturesPath();
 
518
    }
 
519
 
 
520
    return QString();
 
521
}
 
522
 
 
523
QScriptValue ScriptEngine::knownWallpaperPlugins(QScriptContext *context, QScriptEngine *engine)
 
524
{
 
525
    Q_UNUSED(engine)
 
526
 
 
527
    QString formFactor;
 
528
    if (context->argumentCount() > 0) {
 
529
        formFactor = context->argument(0).toString();
 
530
    }
 
531
 
 
532
    QString constraint;
 
533
    if (!formFactor.isEmpty()) {
 
534
        constraint.append("[X-Plasma-FormFactors] ~~ '").append(formFactor).append("'");
 
535
    }
 
536
 
 
537
    KService::List services = KServiceTypeTrader::self()->query("Plasma/Wallpaper", constraint);
 
538
    QScriptValue rv = engine->newArray(services.size());
 
539
    foreach (const KService::Ptr service, services) {
 
540
        QList<KServiceAction> modeActions = service->actions();
 
541
        QScriptValue modes = engine->newArray(modeActions.size());
 
542
        int i = 0;
 
543
        foreach (const KServiceAction &action, modeActions) {
 
544
            modes.setProperty(i++, action.name());
 
545
        }
 
546
 
 
547
        rv.setProperty(service->name(), modes);
 
548
    }
 
549
 
 
550
    return rv;
 
551
}
 
552
 
 
553
void ScriptEngine::setupEngine()
 
554
{
 
555
    QScriptValue v = globalObject();
 
556
    QScriptValueIterator it(v);
 
557
    while (it.hasNext()) {
 
558
        it.next();
 
559
        // we provide our own print implementation, but we want the rest
 
560
        if (it.name() != "print") {
 
561
            m_scriptSelf.setProperty(it.name(), it.value());
 
562
        }
 
563
    }
 
564
 
 
565
    m_scriptSelf.setProperty("QRectF", constructQRectFClass(this));
 
566
    m_scriptSelf.setProperty("Activity", newFunction(ScriptEngine::newActivity));
 
567
    m_scriptSelf.setProperty("Panel", newFunction(ScriptEngine::newPanel));
 
568
    m_scriptSelf.setProperty("activities", newFunction(ScriptEngine::activities));
 
569
    m_scriptSelf.setProperty("activityById", newFunction(ScriptEngine::activityById));
 
570
    m_scriptSelf.setProperty("activityForScreen", newFunction(ScriptEngine::activityForScreen));
 
571
    m_scriptSelf.setProperty("panelById", newFunction(ScriptEngine::panelById));
 
572
    m_scriptSelf.setProperty("panels", newFunction(ScriptEngine::panels));
 
573
    m_scriptSelf.setProperty("fileExists", newFunction(ScriptEngine::fileExists));
 
574
    m_scriptSelf.setProperty("loadTemplate", newFunction(ScriptEngine::loadTemplate));
 
575
    m_scriptSelf.setProperty("applicationExists", newFunction(ScriptEngine::applicationExists));
 
576
    m_scriptSelf.setProperty("defaultApplication", newFunction(ScriptEngine::defaultApplication));
 
577
    m_scriptSelf.setProperty("userDataPath", newFunction(ScriptEngine::userDataPath));
 
578
    m_scriptSelf.setProperty("applicationPath", newFunction(ScriptEngine::applicationPath));
 
579
    m_scriptSelf.setProperty("knownWallpaperPlugins", newFunction(ScriptEngine::knownWallpaperPlugins));
 
580
 
 
581
    setGlobalObject(m_scriptSelf);
 
582
}
 
583
 
 
584
bool ScriptEngine::isPanel(const Plasma::Containment *c)
 
585
{
 
586
    if (!c) {
 
587
        return false;
 
588
    }
 
589
 
 
590
    return c->containmentType() == Plasma::Containment::PanelContainment ||
 
591
           c->containmentType() == Plasma::Containment::CustomPanelContainment;
 
592
}
 
593
 
 
594
QScriptValue ScriptEngine::activities(QScriptContext *context, QScriptEngine *engine)
 
595
{
 
596
    Q_UNUSED(context)
 
597
 
 
598
    QScriptValue containments = engine->newArray();
 
599
    ScriptEngine *env = envFor(engine);
 
600
    int count = 0;
 
601
 
 
602
    foreach (Plasma::Containment *c, env->corona()->containments()) {
 
603
        if (!isPanel(c)) {
 
604
            containments.setProperty(count, env->wrap(c));
 
605
            ++count;
 
606
        }
 
607
    }
 
608
 
 
609
    containments.setProperty("length", count);
 
610
    return containments;
 
611
}
 
612
 
 
613
Plasma::Corona *ScriptEngine::corona() const
 
614
{
 
615
    return m_corona;
 
616
}
 
617
 
 
618
bool ScriptEngine::evaluateScript(const QString &script, const QString &path)
 
619
{
 
620
    //kDebug() << "evaluating" << m_editor->toPlainText();
 
621
    evaluate(script, path);
 
622
    if (hasUncaughtException()) {
 
623
        //kDebug() << "catch the exception!";
 
624
        QString error = i18n("Error: %1 at line %2\n\nBacktrace:\n%3",
 
625
                             uncaughtException().toString(),
 
626
                             QString::number(uncaughtExceptionLineNumber()),
 
627
                             uncaughtExceptionBacktrace().join("\n  "));
 
628
        emit printError(error);
 
629
        return false;
 
630
    }
 
631
 
 
632
    return true;
 
633
}
 
634
 
 
635
void ScriptEngine::exception(const QScriptValue &value)
 
636
{
 
637
    //kDebug() << "exception caught!" << value.toVariant();
 
638
    emit printError(value.toVariant().toString());
 
639
}
 
640
 
 
641
QStringList ScriptEngine::pendingUpdateScripts()
 
642
{
 
643
    const QString appName = KGlobal::activeComponent().aboutData()->appName();
 
644
    QStringList scripts = KGlobal::dirs()->findAllResources("data", appName + "/updates/*.js");
 
645
    QStringList scriptPaths;
 
646
 
 
647
    if (scripts.isEmpty()) {
 
648
        //kDebug() << "no update scripts";
 
649
        return scriptPaths;
 
650
    }
 
651
 
 
652
    KConfigGroup cg(KGlobal::config(), "Updates");
 
653
    QStringList performed = cg.readEntry("performed", QStringList());
 
654
    const QString localDir = KGlobal::dirs()->localkdedir();
 
655
    const QString localXdgDir = KGlobal::dirs()->localxdgdatadir();
 
656
 
 
657
    foreach (const QString &script, scripts) {
 
658
        if (performed.contains(script)) {
 
659
            continue;
 
660
        }
 
661
 
 
662
        if (script.startsWith(localDir) || script.startsWith(localXdgDir)) {
 
663
            kDebug() << "skipping user local script: " << script;
 
664
            continue;
 
665
        }
 
666
 
 
667
        scriptPaths.append(script);
 
668
        performed.append(script);
 
669
    }
 
670
 
 
671
    cg.writeEntry("performed", performed);
 
672
    KGlobal::config()->sync();
 
673
    return scriptPaths;
 
674
}
 
675
 
 
676
QStringList ScriptEngine::defaultLayoutScripts()
 
677
{
 
678
    const QString appName = KGlobal::activeComponent().aboutData()->appName();
 
679
    QStringList scripts = KGlobal::dirs()->findAllResources("data", appName + "/init/*.js");
 
680
    scripts.sort();
 
681
 
 
682
    QStringList scriptPaths;
 
683
 
 
684
    if (scripts.isEmpty()) {
 
685
        //kDebug() << "no javascript based layouts";
 
686
        return scriptPaths;
 
687
    }
 
688
 
 
689
    const QString localDir = KGlobal::dirs()->localkdedir();
 
690
    const QString localXdgDir = KGlobal::dirs()->localxdgdatadir();
 
691
 
 
692
    QSet<QString> scriptNames;
 
693
    foreach (const QString &script, scripts) {
 
694
        if (script.startsWith(localDir) || script.startsWith(localXdgDir)) {
 
695
            kDebug() << "skipping user local script: " << script;
 
696
            continue;
 
697
        }
 
698
 
 
699
        QFileInfo f(script);
 
700
        QString filename = f.fileName();
 
701
        if (!scriptNames.contains(filename)) {
 
702
            scriptNames.insert(filename);
 
703
            scriptPaths.append(script);
 
704
        }
 
705
    }
 
706
 
 
707
    return scriptPaths;
 
708
}
 
709
 
 
710
}
 
711
 
 
712
#include "scriptengine.moc"
 
713