Changeset View
Changeset View
Standalone View
Standalone View
src/plugins/scripting/kexiscripting/kexiscriptdesignview.cpp
Show All 16 Lines | 1 | /* This file is part of the KDE project | |||
---|---|---|---|---|---|
17 | You should have received a copy of the GNU Library General Public License | 17 | You should have received a copy of the GNU Library General Public License | ||
18 | along with this program; see the file COPYING. If not, write to | 18 | along with this program; see the file COPYING. If not, write to | ||
19 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 19 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
20 | * Boston, MA 02110-1301, USA. | 20 | * Boston, MA 02110-1301, USA. | ||
21 | */ | 21 | */ | ||
22 | 22 | | |||
23 | #include "kexiscriptdesignview.h" | 23 | #include "kexiscriptdesignview.h" | ||
24 | #include "kexiscripteditor.h" | 24 | #include "kexiscripteditor.h" | ||
25 | #include "kexiscriptadaptor.h" | ||||
26 | #include "../kexidb/kexidbmodule.h" | ||||
27 | #include "kexiscriptingdebug.h" | ||||
28 | | ||||
25 | #include <KexiIcon.h> | 29 | #include <KexiIcon.h> | ||
26 | #include <KexiMainWindowIface.h> | 30 | #include <KexiMainWindowIface.h> | ||
27 | 31 | #include <kexipart.h> | |||
28 | #include <Kross/Manager> | | |||
29 | #include <Kross/Action> | | |||
30 | #include <Kross/Interpreter> | | |||
31 | 32 | | |||
32 | #include <KDbConnection> | 33 | #include <KDbConnection> | ||
33 | 34 | | |||
34 | #include <KActionMenu> | 35 | #include <KActionMenu> | ||
35 | #include <KMessageBox> | 36 | #include <KMessageBox> | ||
36 | 37 | | |||
37 | #include <QSplitter> | 38 | #include <QSplitter> | ||
38 | #include <QTimer> | 39 | #include <QTimer> | ||
39 | #include <QDomDocument> | 40 | #include <QDomDocument> | ||
40 | #include <QTextBrowser> | 41 | #include <QTextBrowser> | ||
41 | #include <QDebug> | | |||
42 | #include <QFileDialog> | 42 | #include <QFileDialog> | ||
43 | #include <QMenu> | ||||
44 | #include <QJSEngine> | ||||
45 | #include <QJSValue> | ||||
46 | #include <QJSValueIterator> | ||||
43 | 47 | | |||
44 | /// @internal | 48 | /// @internal | ||
45 | class KexiScriptDesignViewPrivate | 49 | class KexiScriptDesignViewPrivate | ||
46 | { | 50 | { | ||
47 | public: | 51 | public: | ||
48 | 52 | | |||
49 | QSplitter* splitter; | 53 | QSplitter* splitter; | ||
50 | 54 | | |||
51 | /** | 55 | /** | ||
52 | * The \a Kross::Action instance which provides | 56 | * The \a QJSEngine which allows | ||
53 | * us access to the scripting framework Kross. | 57 | * the script program to be executed | ||
54 | */ | 58 | */ | ||
55 | Kross::Action* scriptaction; | 59 | QJSEngine scriptEngine; | ||
60 | | ||||
61 | Scripting::KexiDBModule kexidbmodule; | ||||
56 | 62 | | |||
57 | /// The \a KexiScriptEditor to edit the scripting code. | 63 | /// The \a KexiScriptEditor to edit the scripting code. | ||
58 | KexiScriptEditor* editor; | 64 | KexiScriptEditor* editor; | ||
59 | 65 | | |||
60 | /// The \a KPropertySet used in the propertyeditor. | 66 | /// The \a KPropertySet used in the propertyeditor. | ||
61 | KPropertySet* properties; | 67 | KPropertySet* properties; | ||
62 | 68 | | |||
63 | /// Boolean flag to avoid infinite recursion. | 69 | /// Boolean flag to avoid infinite recursion. | ||
64 | bool updatesProperties; | 70 | bool updatesProperties; | ||
65 | 71 | | |||
66 | /// Used to display statusmessages. | 72 | /// Used to display statusmessages. | ||
67 | QTextBrowser* statusbrowser; | 73 | QTextBrowser* statusbrowser; | ||
68 | 74 | | |||
69 | /** The type of script | 75 | /** The type of script | ||
70 | * executable = regular script that can be executed by the user | 76 | * executable = regular script that can be executed by the user | ||
71 | * module = a script which doesn't contain a 'main', only | 77 | * module = a script which doesn't contain a 'main', only | ||
72 | * functions that can be used by other scripts | 78 | * functions that can be used by other scripts | ||
73 | * object = a script which contains code to be loaded into another | 79 | * object = a script which contains code to be loaded into another | ||
74 | object such as a report or form | 80 | object such as a report or form | ||
75 | */ | 81 | */ | ||
76 | QString scriptType; | 82 | QString scriptType; | ||
83 | | ||||
84 | QString factoryConstructors; | ||||
77 | }; | 85 | }; | ||
78 | 86 | | |||
79 | KexiScriptDesignView::KexiScriptDesignView( | 87 | KexiScriptDesignView::KexiScriptDesignView( | ||
80 | QWidget *parent, Kross::Action* scriptaction) | 88 | QWidget *parent) | ||
81 | : KexiView(parent) | 89 | : KexiView(parent) | ||
82 | , d(new KexiScriptDesignViewPrivate()) | 90 | , d(new KexiScriptDesignViewPrivate()) | ||
83 | { | 91 | { | ||
84 | setObjectName("KexiScriptDesignView"); | 92 | setObjectName("KexiScriptDesignView"); | ||
85 | d->scriptaction = scriptaction; | 93 | | ||
94 | // QJSValue val = d->scriptEngine.newQObject(&d->adaptor); | ||||
95 | // d->scriptEngine.globalObject().setProperty("Project", val); | ||||
96 | registerMetaObjects(); | ||||
97 | | ||||
98 | QJSValue val = d->scriptEngine.newQObject(&d->kexidbmodule); | ||||
99 | d->scriptEngine.globalObject().setProperty("KDb", val); | ||||
100 | | ||||
101 | d->scriptEngine.installExtensions(QJSEngine::ConsoleExtension); | ||||
102 | | ||||
103 | QJSValueIterator it(d->scriptEngine.globalObject()); | ||||
104 | while (it.hasNext()) { | ||||
105 | it.next(); | ||||
106 | KexiScriptingDebug() << it.name() << ": " << it.value().toString(); | ||||
107 | } | ||||
108 | | ||||
86 | d->updatesProperties = false; | 109 | d->updatesProperties = false; | ||
87 | 110 | | |||
88 | d->splitter = new QSplitter(this); | 111 | d->splitter = new QSplitter(this); | ||
89 | d->splitter->setOrientation(Qt::Vertical); | 112 | d->splitter->setOrientation(Qt::Vertical); | ||
90 | 113 | | |||
91 | d->editor = new KexiScriptEditor(d->splitter); | 114 | d->editor = new KexiScriptEditor(d->splitter); | ||
92 | d->splitter->addWidget(d->editor); | 115 | d->splitter->addWidget(d->editor); | ||
93 | d->editor->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); | 116 | d->editor->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); | ||
▲ Show 20 Lines • Show All 74 Lines • ▼ Show 20 Line(s) | |||||
168 | a->setObjectName("script_export"); | 191 | a->setObjectName("script_export"); | ||
169 | a->setToolTip(xi18n("Export script")); | 192 | a->setToolTip(xi18n("Export script")); | ||
170 | a->setWhatsThis(xi18n("Exports script to a file.")); | 193 | a->setWhatsThis(xi18n("Exports script to a file.")); | ||
171 | connect(a, SIGNAL(triggered(bool)), this, SLOT(slotExport())); | 194 | connect(a, SIGNAL(triggered(bool)), this, SLOT(slotExport())); | ||
172 | mainMenuActions << a; | 195 | mainMenuActions << a; | ||
173 | 196 | | |||
174 | setMainMenuActions(mainMenuActions); | 197 | setMainMenuActions(mainMenuActions); | ||
175 | 198 | | |||
176 | loadData(); | | |||
177 | | ||||
178 | d->properties = new KPropertySet(this); | 199 | d->properties = new KPropertySet(this); | ||
179 | connect(d->properties, SIGNAL(propertyChanged(KPropertySet&,KProperty&)), | 200 | connect(d->properties, SIGNAL(propertyChanged(KPropertySet&,KProperty&)), | ||
180 | this, SLOT(slotPropertyChanged(KPropertySet&,KProperty&))); | 201 | this, SLOT(slotPropertyChanged(KPropertySet&,KProperty&))); | ||
181 | 202 | | |||
182 | // To schedule the initialize fixes a crasher in Kate. | 203 | initialize(""); | ||
183 | QTimer::singleShot(50, this, SLOT(initialize())); | 204 | loadData(); | ||
184 | } | 205 | } | ||
185 | 206 | | |||
186 | KexiScriptDesignView::~KexiScriptDesignView() | 207 | KexiScriptDesignView::~KexiScriptDesignView() | ||
187 | { | 208 | { | ||
188 | delete d->properties; | 209 | delete d->properties; | ||
189 | delete d; | 210 | delete d; | ||
190 | } | 211 | } | ||
191 | 212 | | |||
192 | Kross::Action* KexiScriptDesignView::scriptAction() const | 213 | #if 0 | ||
214 | QString KexiScriptDesignView::scriptAction() const | ||||
193 | { | 215 | { | ||
194 | return d->scriptaction; | 216 | return d->scriptaction; | ||
195 | } | 217 | } | ||
218 | #endif | ||||
196 | 219 | | |||
197 | void KexiScriptDesignView::initialize() | 220 | void KexiScriptDesignView::initialize(const QString &program) | ||
198 | { | 221 | { | ||
199 | setDirty(false); | 222 | setDirty(false); | ||
200 | updateProperties(); | 223 | updateProperties(); | ||
201 | d->editor->initialize(d->scriptaction); | 224 | d->editor->initialize(program); | ||
202 | connect(d->editor, SIGNAL(textChanged()), this, SLOT(setDirty())); | 225 | connect(d->editor, SIGNAL(textChanged()), this, SLOT(setDirty())); | ||
203 | d->splitter->setSizes( QList<int>() << height() * 2 / 3 << height() * 1 / 3 ); | 226 | d->splitter->setSizes( QList<int>() << height() * 2 / 3 << height() * 1 / 3 ); | ||
204 | } | 227 | } | ||
205 | 228 | | |||
206 | void KexiScriptDesignView::slotImport() | 229 | void KexiScriptDesignView::slotImport() | ||
207 | { | 230 | { | ||
208 | QStringList filters; | | |||
209 | foreach(const QString &interpreter, Kross::Manager::self().interpreters()) { | | |||
210 | filters << Kross::Manager::self().interpreterInfo(interpreter)->mimeTypes(); | | |||
211 | } | | |||
212 | //! @todo KEXI3 add equivalent of kfiledialog:/// | | |||
213 | //! @todo KEXI3 multiple filters | | |||
214 | // for now support jsut one filter | | |||
215 | QString filterString; | | |||
216 | if (filters.count() == 1) { | | |||
217 | const QMimeDatabase db; | | |||
218 | const QString filterString = db.mimeTypeForName(filters.first()).filterString(); | | |||
219 | } | | |||
220 | //QUrl("kfiledialog:///kexiscriptingdesigner"), | 231 | //QUrl("kfiledialog:///kexiscriptingdesigner"), | ||
221 | const QUrl result = QFileDialog::getOpenFileUrl(this, xi18nc("@title:window", "Import Script"), | 232 | const QUrl result = QFileDialog::getOpenFileUrl(this, xi18nc("@title:window", "Import Script"), | ||
222 | QUrl(), filterString); | 233 | QUrl(), "Javascript (*.js)"); | ||
223 | if (!result.isValid()) { | 234 | if (!result.isValid()) { | ||
224 | return; | 235 | return; | ||
225 | } | 236 | } | ||
226 | //! @todo support remote files? | 237 | //! @todo support remote files? | ||
227 | QFile f(result.toLocalFile()); | 238 | QFile f(result.toLocalFile()); | ||
228 | if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) { | 239 | if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) { | ||
229 | KMessageBox::sorry(this, | 240 | KMessageBox::sorry(this, | ||
230 | xi18nc("@info", "Could not read <filename>%1</filename>.", file)); | 241 | xi18nc("@info", "Could not read <filename>%1</filename>.", result.toLocalFile())); | ||
231 | return; | 242 | return; | ||
232 | } | 243 | } | ||
233 | d->editor->setText(f.readAll()); | 244 | d->editor->setText(f.readAll()); | ||
234 | f.close(); | 245 | f.close(); | ||
235 | } | 246 | } | ||
236 | 247 | | |||
237 | void KexiScriptDesignView::slotExport() | 248 | void KexiScriptDesignView::slotExport() | ||
238 | { | 249 | { | ||
239 | QStringList filters; | 250 | const QUrl result = QFileDialog::getSaveFileUrl(this, xi18nc("@title:window", "Export Script"), | ||
240 | foreach(const QString &interpreter, Kross::Manager::self().interpreters()) { | 251 | QUrl("kfiledialog:///kexiscriptingdesigner"), "Javascript (*.js)" ); | ||
241 | filters << Kross::Manager::self().interpreterInfo(interpreter)->mimeTypes(); | 252 | if (!result.isValid()) | ||
242 | } | | |||
243 | const QString file = KFileDialog::getSaveFileName( | | |||
244 | QUrl("kfiledialog:///kexiscriptingdesigner"), | | |||
245 | filters.join(" "), this, xi18nc("@title:window", "Export Script")); | | |||
246 | if (file.isEmpty()) | | |||
247 | return; | 253 | return; | ||
248 | QFile f(file); | 254 | QFile f(result.toLocalFile()); | ||
249 | if (! f.open(QIODevice::WriteOnly | QIODevice::Text)) { | 255 | if (! f.open(QIODevice::WriteOnly | QIODevice::Text)) { | ||
250 | KMessageBox::sorry(this, | 256 | KMessageBox::sorry(this, | ||
251 | xi18nc("@info", "Could not write <filename>%1</filename>.", file)); | 257 | xi18nc("@info", "Could not write <filename>%1</filename>.", result.toLocalFile())); | ||
252 | return; | 258 | return; | ||
253 | } | 259 | } | ||
254 | f.write(d->editor->text().toUtf8()); | 260 | f.write(d->editor->text().toUtf8()); | ||
255 | f.close(); | 261 | f.close(); | ||
256 | } | 262 | } | ||
257 | 263 | | |||
258 | void KexiScriptDesignView::updateProperties() | 264 | void KexiScriptDesignView::updateProperties() | ||
259 | { | 265 | { | ||
260 | if (d->updatesProperties) | 266 | if (d->updatesProperties) | ||
261 | return; | 267 | return; | ||
262 | d->updatesProperties = true; | 268 | d->updatesProperties = true; | ||
263 | 269 | | |||
264 | Kross::Manager* manager = &Kross::Manager::self(); | | |||
265 | | ||||
266 | QString interpretername = d->scriptaction->interpreter(); | | |||
267 | Kross::InterpreterInfo* info = interpretername.isEmpty() ? 0 : manager->interpreterInfo(interpretername); | | |||
268 | | ||||
269 | if (!info) { | | |||
270 | // if interpreter isn't defined or invalid, try to fallback. | | |||
271 | foreach (const QString& interpretername, | | |||
272 | QStringList() << "python" << "ruby" << "qtscript" << "javascript" << "java") | | |||
273 | { | | |||
274 | info = manager->interpreterInfo(interpretername); | | |||
275 | if (info) { | | |||
276 | d->scriptaction->setInterpreter(interpretername); | | |||
277 | break; | | |||
278 | } | | |||
279 | } | | |||
280 | } | | |||
281 | | ||||
282 | if (!info) { | | |||
283 | d->updatesProperties = false; | | |||
284 | return; | | |||
285 | } | | |||
286 | | ||||
287 | d->properties->clear(); | 270 | d->properties->clear(); | ||
288 | 271 | | |||
289 | QStringList types; | 272 | QStringList types; | ||
290 | types << "executable" << "module" << "object"; | 273 | types << "executable" << "module" << "object"; | ||
291 | KPropertyListData* typelist = new KPropertyListData(types, types); | 274 | KPropertyListData* typelist = new KPropertyListData(types, types); | ||
292 | KProperty* t = new KProperty( | 275 | KProperty* t = new KProperty( | ||
293 | "type", // name | 276 | "type", // name | ||
294 | typelist, // ListData | 277 | typelist, // ListData | ||
295 | (d->scriptType.isEmpty() ? "executable" : d->scriptType), // value | 278 | (d->scriptType.isEmpty() ? "executable" : d->scriptType), // value | ||
296 | xi18n("Script Type"), // caption | 279 | xi18n("Script Type"), // caption | ||
297 | xi18n("The type of script"), // description | 280 | xi18n("The type of script"), // description | ||
298 | KProperty::List // type | 281 | KProperty::List // type | ||
299 | ); | 282 | ); | ||
300 | d->properties->addProperty(t); | 283 | d->properties->addProperty(t); | ||
301 | 284 | | |||
302 | QStringList interpreters = manager->interpreters(); | | |||
303 | | ||||
304 | qDebug() << interpreters; | | |||
305 | | ||||
306 | KPropertyListData* proplist = new KPropertyListData(interpreters, interpreters); | | |||
307 | KProperty* prop = new KProperty( | | |||
308 | "language", // name | | |||
309 | proplist, // ListData | | |||
310 | d->scriptaction->interpreter(), // value | | |||
311 | xi18n("Interpreter"), // caption | | |||
312 | xi18n("The used scripting interpreter."), // description | | |||
313 | KProperty::List // type | | |||
314 | ); | | |||
315 | d->properties->addProperty(prop); | | |||
316 | | ||||
317 | Kross::InterpreterInfo::Option::Map options = info->options(); | | |||
318 | Kross::InterpreterInfo::Option::Map::ConstIterator it, end(options.constEnd()); | | |||
319 | for (it = options.constBegin(); it != end; ++it) { | | |||
320 | Kross::InterpreterInfo::Option* option = it.value(); | | |||
321 | KProperty* prop = new KProperty( | | |||
322 | it.key().toLatin1(), // name | | |||
323 | d->scriptaction->option(it.key(), option->value), // value | | |||
324 | it.key(), // caption | | |||
325 | option->comment, // description | | |||
326 | KProperty::Auto // type | | |||
327 | ); | | |||
328 | d->properties->addProperty(prop); | | |||
329 | } | | |||
330 | | ||||
331 | //propertySetSwitched(); | 285 | //propertySetSwitched(); | ||
332 | propertySetReloaded(true); | 286 | propertySetReloaded(true); | ||
333 | d->updatesProperties = false; | 287 | d->updatesProperties = false; | ||
334 | } | 288 | } | ||
335 | 289 | | |||
336 | KPropertySet* KexiScriptDesignView::propertySet() | 290 | KPropertySet* KexiScriptDesignView::propertySet() | ||
337 | { | 291 | { | ||
338 | return d->properties; | 292 | return d->properties; | ||
339 | } | 293 | } | ||
340 | 294 | | |||
341 | void KexiScriptDesignView::slotPropertyChanged(KPropertySet& /*set*/, KProperty& property) | 295 | void KexiScriptDesignView::slotPropertyChanged(KPropertySet& /*set*/, KProperty& property) | ||
342 | { | 296 | { | ||
343 | if (property.isNull()) | 297 | if (property.isNull()) | ||
344 | return; | 298 | return; | ||
345 | 299 | | |||
346 | if (property.name() == "language") { | 300 | if (property.name() == "type") { | ||
347 | QString language = property.value().toString(); | | |||
348 | qDebug() << "language:" << language; | | |||
349 | d->scriptaction->setInterpreter(language); | | |||
350 | // We assume Kross and the HighlightingInterface are using same | | |||
351 | // names for the support languages... | | |||
352 | d->editor->setHighlightMode(language); | | |||
353 | updateProperties(); | | |||
354 | } | | |||
355 | else if (property.name() == "type") { | | |||
356 | d->scriptType = property.value().toString(); | 301 | d->scriptType = property.value().toString(); | ||
357 | } | 302 | } | ||
358 | else { | 303 | else { | ||
359 | bool ok = d->scriptaction->setOption(property.name(), property.value()); | | |||
360 | if (! ok) { | | |||
361 | qWarning() << "unknown property:" << property.name(); | 304 | qWarning() << "unknown property:" << property.name(); | ||
362 | return; | 305 | return; | ||
363 | } | 306 | } | ||
364 | } | | |||
365 | 307 | | |||
366 | setDirty(true); | 308 | setDirty(true); | ||
367 | } | 309 | } | ||
368 | 310 | | |||
369 | void KexiScriptDesignView::execute() | 311 | void KexiScriptDesignView::execute() | ||
370 | { | 312 | { | ||
371 | d->statusbrowser->clear(); | 313 | d->statusbrowser->clear(); | ||
372 | QTime time; | 314 | QTime time; | ||
373 | time.start(); | 315 | time.start(); | ||
374 | d->statusbrowser->append(xi18nc("@info", | 316 | d->statusbrowser->append(xi18nc("@info", | ||
375 | "Execution of the script <resource>%1</resource> started.", | 317 | "Execution of the script <resource>%1</resource> started.", | ||
376 | d->scriptaction->name())); | 318 | part()->instanceName())); | ||
377 | 319 | | |||
378 | d->scriptaction->trigger(); | 320 | QString program = d->factoryConstructors + "\n" + d->editor->text().toUtf8(); | ||
379 | if (d->scriptaction->hadError()) { | | |||
380 | QString errormessage = d->scriptaction->errorMessage(); | | |||
381 | d->statusbrowser->append(QString("<b>%2</b><br>").arg(errormessage.toHtmlEscaped())); | | |||
382 | 321 | | |||
383 | QString tracedetails = d->scriptaction->errorTrace(); | 322 | KexiScriptingDebug() << "Program:\n" << program; | ||
384 | d->statusbrowser->append(tracedetails.toHtmlEscaped()); | 323 | QJSValue result = d->scriptEngine.evaluate(d->editor->text().toUtf8()); | ||
385 | 324 | | |||
386 | long lineno = d->scriptaction->errorLineNo(); | 325 | if (result.isError()) { | ||
326 | QString errormessage = result.toString(); | ||||
327 | d->statusbrowser->append(QString("<b>%2</b><br>").arg(errormessage.toHtmlEscaped())); | ||||
328 | | ||||
329 | long lineno = result.property("lineNumber").toInt(); | ||||
387 | if (lineno >= 0) | 330 | if (lineno >= 0) | ||
388 | d->editor->setLineNo(lineno); | 331 | d->editor->setLineNo(lineno); | ||
389 | } | 332 | } | ||
390 | else { | 333 | else { | ||
391 | // xgettext: no-c-format | 334 | // xgettext: no-c-format | ||
392 | d->statusbrowser->append(xi18n("Successfully executed. Time elapsed: %1ms", time.elapsed())); | 335 | d->statusbrowser->append(xi18n("Successfully executed. Time elapsed: %1ms", time.elapsed())); | ||
393 | } | 336 | } | ||
394 | } | 337 | } | ||
395 | 338 | | |||
396 | bool KexiScriptDesignView::loadData() | 339 | bool KexiScriptDesignView::loadData() | ||
397 | { | 340 | { | ||
398 | QString data; | 341 | QString data; | ||
399 | if (!loadDataBlock(&data)) { | 342 | if (!loadDataBlock(&data)) { | ||
400 | qDebug() << "no DataBlock"; | 343 | KexiScriptingDebug() << "no DataBlock"; | ||
401 | return false; | 344 | return false; | ||
402 | } | 345 | } | ||
403 | 346 | | |||
404 | QString errMsg; | 347 | QString errMsg; | ||
405 | int errLine; | 348 | int errLine; | ||
406 | int errCol; | 349 | int errCol; | ||
407 | 350 | | |||
408 | QDomDocument domdoc; | 351 | QDomDocument domdoc; | ||
409 | bool parsed = domdoc.setContent(data, false, &errMsg, &errLine, &errCol); | 352 | bool parsed = domdoc.setContent(data, false, &errMsg, &errLine, &errCol); | ||
410 | 353 | | |||
411 | if (! parsed) { | 354 | if (! parsed) { | ||
412 | qDebug() << "XML parsing error line: " << errLine << " col: " << errCol << " message: " << errMsg; | 355 | KexiScriptingDebug() << "XML parsing error line: " << errLine << " col: " << errCol << " message: " << errMsg; | ||
staniek: -> KexiScriptingWarning | |||||
413 | return false; | 356 | return false; | ||
414 | } | 357 | } | ||
415 | 358 | | |||
416 | QDomElement scriptelem = domdoc.namedItem("script").toElement(); | 359 | QDomElement scriptelem = domdoc.namedItem("script").toElement(); | ||
417 | if (scriptelem.isNull()) { | 360 | if (scriptelem.isNull()) { | ||
418 | qDebug() << "script domelement is null"; | 361 | KexiScriptingDebug() << "script domelement is null"; | ||
staniek: -> KexiScriptingWarning | |||||
419 | return false; | 362 | return false; | ||
420 | } | 363 | } | ||
421 | 364 | | |||
422 | d->scriptType = scriptelem.attribute("scripttype"); | 365 | d->scriptType = scriptelem.attribute("scripttype"); | ||
423 | if (d->scriptType.isEmpty()) { | 366 | if (d->scriptType.isEmpty()) { | ||
424 | d->scriptType = "executable"; | 367 | d->scriptType = "executable"; | ||
425 | } | 368 | } | ||
426 | 369 | | |||
427 | QString interpretername = scriptelem.attribute("language"); | 370 | initialize(scriptelem.text().toUtf8()); | ||
428 | Kross::Manager* manager = &Kross::Manager::self(); | | |||
429 | Kross::InterpreterInfo* info = interpretername.isEmpty() ? 0 : manager->interpreterInfo(interpretername); | | |||
430 | if (info) { | | |||
431 | d->scriptaction->setInterpreter(interpretername); | | |||
432 | | ||||
433 | Kross::InterpreterInfo::Option::Map options = info->options(); | | |||
434 | Kross::InterpreterInfo::Option::Map::ConstIterator it, end = options.constEnd(); | | |||
435 | for (it = options.constBegin(); it != end; ++it) { | | |||
436 | QString value = scriptelem.attribute(it.key()); | | |||
437 | if (! value.isNull()) { | | |||
438 | QVariant v(value); | | |||
439 | if (v.convert(it.value()->value.type())) // preserve the QVariant's type | | |||
440 | d->scriptaction->setOption(it.key(), v); | | |||
441 | } | | |||
442 | } | | |||
443 | } | | |||
444 | | ||||
445 | d->scriptaction->setCode(scriptelem.text().toUtf8()); | | |||
446 | 371 | | |||
447 | return true; | 372 | return true; | ||
448 | } | 373 | } | ||
449 | 374 | | |||
450 | KDbObject* KexiScriptDesignView::storeNewData(const KDbObject& object, | 375 | KDbObject* KexiScriptDesignView::storeNewData(const KDbObject& object, | ||
451 | KexiView::StoreNewDataOptions options, | 376 | KexiView::StoreNewDataOptions options, | ||
452 | bool *cancel) | 377 | bool *cancel) | ||
453 | { | 378 | { | ||
454 | KDbObject *s = KexiView::storeNewData(object, options, cancel); | 379 | KDbObject *s = KexiView::storeNewData(object, options, cancel); | ||
455 | 380 | | |||
456 | if (!s || *cancel) { | 381 | if (!s || *cancel) { | ||
457 | delete s; | 382 | delete s; | ||
458 | return 0; | 383 | return 0; | ||
459 | } | 384 | } | ||
460 | qDebug() << "new id:" << s->id(); | 385 | KexiScriptingDebug() << "new id:" << s->id(); | ||
461 | 386 | | |||
462 | if (! storeData()) { | 387 | if (! storeData()) { | ||
463 | qWarning() << "Failed to store the data."; | 388 | qWarning() << "Failed to store the data."; | ||
464 | //failure: remove object's object data to avoid garbage | 389 | //failure: remove object's object data to avoid garbage | ||
465 | KDbConnection *conn = KexiMainWindowIface::global()->project()->dbConnection(); | 390 | KDbConnection *conn = KexiMainWindowIface::global()->project()->dbConnection(); | ||
466 | conn->removeObject(s->id()); | 391 | conn->removeObject(s->id()); | ||
467 | delete s; | 392 | delete s; | ||
468 | return 0; | 393 | return 0; | ||
469 | } | 394 | } | ||
470 | 395 | | |||
471 | return s; | 396 | return s; | ||
472 | } | 397 | } | ||
473 | 398 | | |||
474 | tristate KexiScriptDesignView::storeData(bool /*dontAsk*/) | 399 | tristate KexiScriptDesignView::storeData(bool /*dontAsk*/) | ||
475 | { | 400 | { | ||
401 | KexiScriptingDebug() << "Saving script" << d->editor->text().toUtf8(); | ||||
476 | QDomDocument domdoc("script"); | 402 | QDomDocument domdoc("script"); | ||
477 | QDomElement scriptelem = domdoc.createElement("script"); | 403 | QDomElement scriptelem = domdoc.createElement("script"); | ||
478 | domdoc.appendChild(scriptelem); | 404 | domdoc.appendChild(scriptelem); | ||
479 | 405 | | |||
480 | QString language = d->scriptaction->interpreter(); | 406 | scriptelem.setAttribute("language", "javascript"); | ||
481 | scriptelem.setAttribute("language", language); | | |||
482 | //! @todo move different types to their own part?? | 407 | //! @todo move different types to their own part?? | ||
483 | scriptelem.setAttribute("scripttype", d->scriptType); | 408 | scriptelem.setAttribute("scripttype", d->scriptType); | ||
484 | 409 | | |||
485 | Kross::InterpreterInfo* info = Kross::Manager::self().interpreterInfo(language); | 410 | QDomText scriptcode = domdoc.createTextNode(d->editor->text().toUtf8()); | ||
486 | if (info) { | | |||
487 | Kross::InterpreterInfo::Option::Map defoptions = info->options(); | | |||
488 | QMap<QString, QVariant> options = d->scriptaction->options(); | | |||
489 | QMap<QString, QVariant>::ConstIterator it, end(options.constEnd()); | | |||
490 | for (it = options.constBegin(); it != end; ++it) | | |||
491 | if (defoptions.contains(it.key())) // only remember options which the InterpreterInfo knows about... | | |||
492 | scriptelem.setAttribute(it.key(), it.value().toString()); | | |||
493 | } | | |||
494 | | ||||
495 | QDomText scriptcode = domdoc.createTextNode(d->scriptaction->code()); | | |||
496 | scriptelem.appendChild(scriptcode); | 411 | scriptelem.appendChild(scriptcode); | ||
497 | 412 | | |||
498 | return storeDataBlock(domdoc.toString()); | 413 | return storeDataBlock(domdoc.toString()); | ||
499 | } | 414 | } | ||
500 | 415 | | |||
501 | 416 | void KexiScriptDesignView::registerMetaObjects() | |||
417 | { | ||||
418 | QJSValue meta = d->scriptEngine.newQMetaObject(&KexiScriptAdaptor::staticMetaObject); | ||||
BTW staniek: BTW
Can we have have check for Qt version in CMake and if < 5.8 then disable scritping. I am OK… | |||||
staniek: Sorry for confusion wrt disabling scripting. | |||||
419 | d->scriptEngine.globalObject().setProperty("KexiScriptAdaptor", meta); | ||||
420 | } |
-> KexiScriptingWarning