1 | /* |
2 | * Copyright 2011 Marco Martin <mart@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 "kdeclarative.h" |
21 | #include "bindings/i18n_p.h" |
22 | #include "private/kdeclarative_p.h" |
23 | #include "private/engineaccess_p.h" |
24 | #include "private/kiconprovider_p.h" |
25 | |
26 | #include <QtDeclarative/QDeclarativeComponent> |
27 | #include <QtDeclarative/QDeclarativeContext> |
28 | #include <QtDeclarative/QDeclarativeEngine> |
29 | #include <QtDeclarative/QDeclarativeExpression> |
30 | #include <QtDeclarative/qdeclarativedebug.h> |
31 | #include <QtScript/QScriptEngine> |
32 | #include <QtScript/QScriptValueIterator> |
33 | #include <QtCore/QWeakPointer> |
34 | |
35 | #include <kcmdlineargs.h> |
36 | #include <kdebug.h> |
37 | #include <kglobal.h> |
38 | #include <kstandarddirs.h> |
39 | #include <kurl.h> |
40 | #include <kconfiggroup.h> |
41 | #include <ksharedconfig.h> |
42 | |
43 | void registerNonGuiMetaTypes(QScriptEngine *engine); |
44 | QScriptValue constructIconClass(QScriptEngine *engine); |
45 | QScriptValue constructKUrlClass(QScriptEngine *engine); |
46 | |
47 | KDeclarativePrivate::KDeclarativePrivate() |
48 | : initialized(false) |
49 | { |
50 | } |
51 | |
52 | KDeclarative::KDeclarative() |
53 | : d(new KDeclarativePrivate) |
54 | { |
55 | } |
56 | |
57 | KDeclarative::~KDeclarative() |
58 | { |
59 | delete d; |
60 | } |
61 | |
62 | |
63 | void KDeclarative::setDeclarativeEngine(QDeclarativeEngine *engine) |
64 | { |
65 | if (d->declarativeEngine.data() == engine) { |
66 | return; |
67 | } |
68 | d->initialized = false; |
69 | d->declarativeEngine = engine; |
70 | } |
71 | |
72 | QDeclarativeEngine *KDeclarative::declarativeEngine() const |
73 | { |
74 | return d->declarativeEngine.data(); |
75 | } |
76 | |
77 | void KDeclarative::initialize() |
78 | { |
79 | //Glorious hack:steal the engine |
80 | //create the access object |
81 | EngineAccess *engineAccess = new EngineAccess(this); |
82 | d->declarativeEngine.data()->rootContext()->setContextProperty("__engineAccess" , engineAccess); |
83 | |
84 | //make engineaccess set our d->scriptengine |
85 | QDeclarativeExpression *expr = new QDeclarativeExpression(d->declarativeEngine.data()->rootContext(), d->declarativeEngine.data()->rootContext()->contextObject(), "__engineAccess.setEngine(this)" ); |
86 | expr->evaluate(); |
87 | delete expr; |
88 | |
89 | //we don't need engineaccess anymore |
90 | d->declarativeEngine.data()->rootContext()->setContextProperty("__engineAccess" , 0); |
91 | engineAccess->deleteLater(); |
92 | |
93 | //fail? |
94 | if (!d->scriptEngine) { |
95 | kWarning() << "Failed to get the script engine" ; |
96 | return; |
97 | } |
98 | |
99 | //change the old globalobject with a new read/write copy |
100 | QScriptValue originalGlobalObject = d->scriptEngine.data()->globalObject(); |
101 | |
102 | QScriptValue newGlobalObject = d->scriptEngine.data()->newObject(); |
103 | |
104 | QString eval = QLatin1String("eval" ); |
105 | QString version = QLatin1String("version" ); |
106 | |
107 | { |
108 | QScriptValueIterator iter(originalGlobalObject); |
109 | QVector<QString> names; |
110 | QVector<QScriptValue> values; |
111 | QVector<QScriptValue::PropertyFlags> flags; |
112 | while (iter.hasNext()) { |
113 | iter.next(); |
114 | |
115 | QString name = iter.name(); |
116 | |
117 | if (name == version) { |
118 | continue; |
119 | } |
120 | |
121 | if (name != eval) { |
122 | names.append(name); |
123 | values.append(iter.value()); |
124 | flags.append(iter.flags() | QScriptValue::Undeletable); |
125 | } |
126 | newGlobalObject.setProperty(iter.scriptName(), iter.value()); |
127 | |
128 | // m_illegalNames.insert(name); |
129 | } |
130 | |
131 | } |
132 | |
133 | d->scriptEngine.data()->setGlobalObject(newGlobalObject); |
134 | |
135 | d->initialized = true; |
136 | } |
137 | |
138 | void KDeclarative::setupBindings() |
139 | { |
140 | QScriptEngine *engine = d->scriptEngine.data(); |
141 | if (!engine) { |
142 | return; |
143 | } |
144 | |
145 | /*tell the engine to search for import in the kde4 plugin dirs. |
146 | addImportPath adds the path at the beginning, so to honour user's |
147 | paths we need to traverse the list in reverse order*/ |
148 | |
149 | const QStringList importPathList = KGlobal::dirs()->findDirs("module" , "imports" ); |
150 | QStringListIterator importPathIterator(importPathList); |
151 | importPathIterator.toBack(); |
152 | while (importPathIterator.hasPrevious()) { |
153 | d->declarativeEngine.data()->addImportPath(importPathIterator.previous()); |
154 | } |
155 | |
156 | const QString target = componentsTarget(); |
157 | if (target != defaultComponentsTarget()) { |
158 | const QStringList paths = KGlobal::dirs()->findDirs("module" , "platformimports/" % target); |
159 | QStringListIterator it(paths); |
160 | it.toBack(); |
161 | while (it.hasPrevious()) { |
162 | d->declarativeEngine.data()->addImportPath(it.previous()); |
163 | } |
164 | } |
165 | |
166 | QScriptValue global = engine->globalObject(); |
167 | |
168 | //KConfig and KJob |
169 | registerNonGuiMetaTypes(d->scriptEngine.data()); |
170 | |
171 | // Stuff from Qt |
172 | global.setProperty("QIcon" , constructIconClass(engine)); |
173 | |
174 | // Add stuff from KDE libs |
175 | bindI18N(engine); |
176 | qScriptRegisterSequenceMetaType<KUrl::List>(engine); |
177 | global.setProperty("Url" , constructKUrlClass(engine)); |
178 | |
179 | // setup ImageProvider for KDE icons |
180 | d->declarativeEngine.data()->addImageProvider(QString("icon" ), new KIconProvider); |
181 | } |
182 | |
183 | QScriptEngine *KDeclarative::scriptEngine() const |
184 | { |
185 | return d->scriptEngine.data(); |
186 | } |
187 | |
188 | void KDeclarative::setupQmlJsDebugger() |
189 | { |
190 | if (KCmdLineArgs::parsedArgs("qt" )->isSet("qmljsdebugger" )) { |
191 | QDeclarativeDebuggingEnabler enabler; |
192 | } |
193 | } |
194 | |
195 | QString KDeclarative::defaultComponentsTarget() |
196 | { |
197 | return QLatin1String("desktop" ); |
198 | } |
199 | |
200 | QString KDeclarative::componentsTarget() |
201 | { |
202 | const QStringList platform = runtimePlatform(); |
203 | if (platform.isEmpty()) { |
204 | return defaultComponentsTarget(); |
205 | } |
206 | |
207 | return platform.last(); |
208 | } |
209 | |
210 | QStringList KDeclarative::runtimePlatform() |
211 | { |
212 | static QStringList *runtimePlatform = 0; |
213 | if (!runtimePlatform) { |
214 | const QString env = getenv("PLASMA_PLATFORM" ); |
215 | runtimePlatform = new QStringList(env.split(":" , QString::SkipEmptyParts)); |
216 | if (runtimePlatform->isEmpty()) { |
217 | KConfigGroup cg(KGlobal::config(), "General" ); |
218 | *runtimePlatform = cg.readEntry("runtimePlatform" , *runtimePlatform); |
219 | } |
220 | } |
221 | |
222 | return *runtimePlatform; |
223 | } |
224 | |
225 | |