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 | #include "kexiscriptpart.h" | ||||
29 | | ||||
25 | #include <KexiIcon.h> | 30 | #include <KexiIcon.h> | ||
26 | #include <KexiMainWindowIface.h> | 31 | #include <KexiMainWindowIface.h> | ||
27 | 32 | #include <kexipart.h> | |||
28 | #include <Kross/Manager> | | |||
29 | #include <Kross/Action> | | |||
30 | #include <Kross/Interpreter> | | |||
31 | 33 | | |||
32 | #include <KDbConnection> | 34 | #include <KDbConnection> | ||
33 | 35 | | |||
34 | #include <KActionMenu> | 36 | #include <KActionMenu> | ||
35 | #include <KMessageBox> | 37 | #include <KMessageBox> | ||
36 | 38 | | |||
37 | #include <QSplitter> | 39 | #include <QSplitter> | ||
38 | #include <QTimer> | 40 | #include <QTimer> | ||
39 | #include <QDomDocument> | 41 | #include <QDomDocument> | ||
40 | #include <QTextBrowser> | 42 | #include <QTextBrowser> | ||
41 | #include <QDebug> | | |||
42 | #include <QFileDialog> | 43 | #include <QFileDialog> | ||
44 | #include <QMenu> | ||||
45 | #include <QJSEngine> | ||||
46 | #include <QJSValue> | ||||
47 | #include <QJSValueIterator> | ||||
43 | 48 | | |||
44 | /// @internal | 49 | /// @internal | ||
45 | class KexiScriptDesignViewPrivate | 50 | class KexiScriptDesignViewPrivate | ||
46 | { | 51 | { | ||
47 | public: | 52 | public: | ||
48 | 53 | | |||
49 | QSplitter* splitter; | 54 | QSplitter* splitter; | ||
50 | 55 | | |||
51 | /** | | |||
52 | * The \a Kross::Action instance which provides | | |||
53 | * us access to the scripting framework Kross. | | |||
54 | */ | | |||
55 | Kross::Action* scriptaction; | | |||
56 | | ||||
57 | /// The \a KexiScriptEditor to edit the scripting code. | 56 | /// The \a KexiScriptEditor to edit the scripting code. | ||
58 | KexiScriptEditor* editor; | 57 | KexiScriptEditor* editor; | ||
59 | 58 | | |||
60 | /// The \a KPropertySet used in the propertyeditor. | 59 | /// The \a KPropertySet used in the propertyeditor. | ||
61 | KPropertySet* properties; | 60 | KPropertySet* properties; | ||
62 | 61 | | |||
63 | /// Boolean flag to avoid infinite recursion. | 62 | /// Boolean flag to avoid infinite recursion. | ||
64 | bool updatesProperties; | 63 | bool updatesProperties; | ||
65 | 64 | | |||
66 | /// Used to display statusmessages. | 65 | /// Used to display statusmessages. | ||
67 | QTextBrowser* statusbrowser; | 66 | QTextBrowser* statusbrowser; | ||
68 | 67 | | |||
69 | /** The type of script | 68 | /** The type of script | ||
70 | * executable = regular script that can be executed by the user | 69 | * executable = regular script that can be executed by the user | ||
71 | * module = a script which doesn't contain a 'main', only | 70 | * module = a script which doesn't contain a 'main', only | ||
72 | * functions that can be used by other scripts | 71 | * functions that can be used by other scripts | ||
73 | * object = a script which contains code to be loaded into another | 72 | * object = a script which contains code to be loaded into another | ||
74 | object such as a report or form | 73 | object such as a report or form | ||
75 | */ | 74 | */ | ||
76 | QString scriptType; | 75 | QString scriptType; | ||
76 | | ||||
77 | QString factoryConstructors; | ||||
77 | }; | 78 | }; | ||
78 | 79 | | |||
79 | KexiScriptDesignView::KexiScriptDesignView( | 80 | KexiScriptDesignView::KexiScriptDesignView( | ||
80 | QWidget *parent, Kross::Action* scriptaction) | 81 | QWidget *parent) | ||
81 | : KexiView(parent) | 82 | : KexiView(parent) | ||
82 | , d(new KexiScriptDesignViewPrivate()) | 83 | , d(new KexiScriptDesignViewPrivate()) | ||
83 | { | 84 | { | ||
84 | setObjectName("KexiScriptDesignView"); | 85 | setObjectName("KexiScriptDesignView"); | ||
85 | d->scriptaction = scriptaction; | 86 | | ||
86 | d->updatesProperties = false; | 87 | d->updatesProperties = false; | ||
87 | 88 | | |||
88 | d->splitter = new QSplitter(this); | 89 | d->splitter = new QSplitter(this); | ||
89 | d->splitter->setOrientation(Qt::Vertical); | 90 | d->splitter->setOrientation(Qt::Vertical); | ||
90 | 91 | | |||
91 | d->editor = new KexiScriptEditor(d->splitter); | 92 | d->editor = new KexiScriptEditor(d->splitter); | ||
92 | d->splitter->addWidget(d->editor); | 93 | d->splitter->addWidget(d->editor); | ||
93 | d->editor->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); | 94 | d->editor->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); | ||
▲ Show 20 Lines • Show All 74 Lines • ▼ Show 20 Line(s) | |||||
168 | a->setObjectName("script_export"); | 169 | a->setObjectName("script_export"); | ||
169 | a->setToolTip(xi18n("Export script")); | 170 | a->setToolTip(xi18n("Export script")); | ||
170 | a->setWhatsThis(xi18n("Exports script to a file.")); | 171 | a->setWhatsThis(xi18n("Exports script to a file.")); | ||
171 | connect(a, SIGNAL(triggered(bool)), this, SLOT(slotExport())); | 172 | connect(a, SIGNAL(triggered(bool)), this, SLOT(slotExport())); | ||
172 | mainMenuActions << a; | 173 | mainMenuActions << a; | ||
173 | 174 | | |||
174 | setMainMenuActions(mainMenuActions); | 175 | setMainMenuActions(mainMenuActions); | ||
175 | 176 | | |||
176 | loadData(); | | |||
177 | | ||||
178 | d->properties = new KPropertySet(this); | 177 | d->properties = new KPropertySet(this); | ||
179 | connect(d->properties, SIGNAL(propertyChanged(KPropertySet&,KProperty&)), | 178 | connect(d->properties, SIGNAL(propertyChanged(KPropertySet&,KProperty&)), | ||
180 | this, SLOT(slotPropertyChanged(KPropertySet&,KProperty&))); | 179 | this, SLOT(slotPropertyChanged(KPropertySet&,KProperty&))); | ||
181 | 180 | | |||
182 | // To schedule the initialize fixes a crasher in Kate. | 181 | initialize(""); | ||
183 | QTimer::singleShot(50, this, SLOT(initialize())); | 182 | loadData(); | ||
184 | } | 183 | } | ||
185 | 184 | | |||
186 | KexiScriptDesignView::~KexiScriptDesignView() | 185 | KexiScriptDesignView::~KexiScriptDesignView() | ||
187 | { | 186 | { | ||
188 | delete d->properties; | 187 | delete d->properties; | ||
189 | delete d; | 188 | delete d; | ||
190 | } | 189 | } | ||
191 | 190 | | |||
192 | Kross::Action* KexiScriptDesignView::scriptAction() const | 191 | #if 0 | ||
192 | QString KexiScriptDesignView::scriptAction() const | ||||
193 | { | 193 | { | ||
194 | return d->scriptaction; | 194 | return d->scriptaction; | ||
195 | } | 195 | } | ||
196 | #endif | ||||
196 | 197 | | |||
197 | void KexiScriptDesignView::initialize() | 198 | void KexiScriptDesignView::initialize(const QString &program) | ||
198 | { | 199 | { | ||
199 | setDirty(false); | 200 | setDirty(false); | ||
200 | updateProperties(); | 201 | updateProperties(); | ||
201 | d->editor->initialize(d->scriptaction); | 202 | d->editor->initialize(program); | ||
202 | connect(d->editor, SIGNAL(textChanged()), this, SLOT(setDirty())); | 203 | connect(d->editor, SIGNAL(textChanged()), this, SLOT(setDirty())); | ||
203 | d->splitter->setSizes( QList<int>() << height() * 2 / 3 << height() * 1 / 3 ); | 204 | d->splitter->setSizes( QList<int>() << height() * 2 / 3 << height() * 1 / 3 ); | ||
204 | } | 205 | } | ||
205 | 206 | | |||
206 | void KexiScriptDesignView::slotImport() | 207 | void KexiScriptDesignView::slotImport() | ||
207 | { | 208 | { | ||
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"), | 209 | //QUrl("kfiledialog:///kexiscriptingdesigner"), | ||
221 | const QUrl result = QFileDialog::getOpenFileUrl(this, xi18nc("@title:window", "Import Script"), | 210 | const QUrl result = QFileDialog::getOpenFileUrl(this, xi18nc("@title:window", "Import Script"), | ||
222 | QUrl(), filterString); | 211 | QUrl(), "Javascript (*.js)"); | ||
223 | if (!result.isValid()) { | 212 | if (!result.isValid()) { | ||
224 | return; | 213 | return; | ||
225 | } | 214 | } | ||
226 | //! @todo support remote files? | 215 | //! @todo support remote files? | ||
227 | QFile f(result.toLocalFile()); | 216 | QFile f(result.toLocalFile()); | ||
228 | if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) { | 217 | if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) { | ||
229 | KMessageBox::sorry(this, | 218 | KMessageBox::sorry(this, | ||
230 | xi18nc("@info", "Could not read <filename>%1</filename>.", file)); | 219 | xi18nc("@info", "Could not read <filename>%1</filename>.", result.toLocalFile())); | ||
231 | return; | 220 | return; | ||
232 | } | 221 | } | ||
233 | d->editor->setText(f.readAll()); | 222 | d->editor->setText(f.readAll()); | ||
234 | f.close(); | 223 | f.close(); | ||
235 | } | 224 | } | ||
236 | 225 | | |||
237 | void KexiScriptDesignView::slotExport() | 226 | void KexiScriptDesignView::slotExport() | ||
238 | { | 227 | { | ||
239 | QStringList filters; | 228 | const QUrl result = QFileDialog::getSaveFileUrl(this, xi18nc("@title:window", "Export Script"), | ||
240 | foreach(const QString &interpreter, Kross::Manager::self().interpreters()) { | 229 | QUrl("kfiledialog:///kexiscriptingdesigner"), "Javascript (*.js)" ); | ||
241 | filters << Kross::Manager::self().interpreterInfo(interpreter)->mimeTypes(); | 230 | 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; | 231 | return; | ||
248 | QFile f(file); | 232 | QFile f(result.toLocalFile()); | ||
249 | if (! f.open(QIODevice::WriteOnly | QIODevice::Text)) { | 233 | if (! f.open(QIODevice::WriteOnly | QIODevice::Text)) { | ||
250 | KMessageBox::sorry(this, | 234 | KMessageBox::sorry(this, | ||
251 | xi18nc("@info", "Could not write <filename>%1</filename>.", file)); | 235 | xi18nc("@info", "Could not write <filename>%1</filename>.", result.toLocalFile())); | ||
252 | return; | 236 | return; | ||
253 | } | 237 | } | ||
254 | f.write(d->editor->text().toUtf8()); | 238 | f.write(d->editor->text().toUtf8()); | ||
255 | f.close(); | 239 | f.close(); | ||
256 | } | 240 | } | ||
257 | 241 | | |||
258 | void KexiScriptDesignView::updateProperties() | 242 | void KexiScriptDesignView::updateProperties() | ||
259 | { | 243 | { | ||
260 | if (d->updatesProperties) | 244 | if (d->updatesProperties) | ||
261 | return; | 245 | return; | ||
262 | d->updatesProperties = true; | 246 | d->updatesProperties = true; | ||
263 | 247 | | |||
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(); | 248 | d->properties->clear(); | ||
288 | 249 | | |||
289 | QStringList types; | 250 | QStringList types; | ||
290 | types << "executable" << "module" << "object"; | 251 | types << "executable" << "module" << "object"; | ||
291 | KPropertyListData* typelist = new KPropertyListData(types, types); | 252 | KPropertyListData* typelist = new KPropertyListData(types, types); | ||
292 | KProperty* t = new KProperty( | 253 | KProperty* t = new KProperty( | ||
293 | "type", // name | 254 | "type", // name | ||
294 | typelist, // ListData | 255 | typelist, // ListData | ||
295 | (d->scriptType.isEmpty() ? "executable" : d->scriptType), // value | 256 | (d->scriptType.isEmpty() ? "executable" : d->scriptType), // value | ||
296 | xi18n("Script Type"), // caption | 257 | xi18n("Script Type"), // caption | ||
297 | xi18n("The type of script"), // description | 258 | xi18n("The type of script"), // description | ||
298 | KProperty::List // type | 259 | KProperty::List // type | ||
299 | ); | 260 | ); | ||
300 | d->properties->addProperty(t); | 261 | d->properties->addProperty(t); | ||
301 | 262 | | |||
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(); | 263 | //propertySetSwitched(); | ||
332 | propertySetReloaded(true); | 264 | propertySetReloaded(true); | ||
333 | d->updatesProperties = false; | 265 | d->updatesProperties = false; | ||
334 | } | 266 | } | ||
335 | 267 | | |||
336 | KPropertySet* KexiScriptDesignView::propertySet() | 268 | KPropertySet* KexiScriptDesignView::propertySet() | ||
337 | { | 269 | { | ||
338 | return d->properties; | 270 | return d->properties; | ||
339 | } | 271 | } | ||
340 | 272 | | |||
341 | void KexiScriptDesignView::slotPropertyChanged(KPropertySet& /*set*/, KProperty& property) | 273 | void KexiScriptDesignView::slotPropertyChanged(KPropertySet& /*set*/, KProperty& property) | ||
342 | { | 274 | { | ||
343 | if (property.isNull()) | 275 | if (property.isNull()) | ||
344 | return; | 276 | return; | ||
345 | 277 | | |||
346 | if (property.name() == "language") { | 278 | 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(); | 279 | d->scriptType = property.value().toString(); | ||
357 | } | 280 | } | ||
358 | else { | 281 | else { | ||
359 | bool ok = d->scriptaction->setOption(property.name(), property.value()); | | |||
360 | if (! ok) { | | |||
361 | qWarning() << "unknown property:" << property.name(); | 282 | qWarning() << "unknown property:" << property.name(); | ||
362 | return; | 283 | return; | ||
363 | } | 284 | } | ||
364 | } | | |||
365 | 285 | | |||
366 | setDirty(true); | 286 | setDirty(true); | ||
367 | } | 287 | } | ||
368 | 288 | | |||
369 | void KexiScriptDesignView::execute() | 289 | void KexiScriptDesignView::execute() | ||
370 | { | 290 | { | ||
371 | d->statusbrowser->clear(); | 291 | d->statusbrowser->clear(); | ||
372 | QTime time; | 292 | QTime time; | ||
373 | time.start(); | 293 | time.start(); | ||
374 | d->statusbrowser->append(xi18nc("@info", | 294 | d->statusbrowser->append(xi18nc("@info", | ||
375 | "Execution of the script <resource>%1</resource> started.", | 295 | "Execution of the script <resource>%1</resource> started.", | ||
376 | d->scriptaction->name())); | 296 | part()->instanceName())); | ||
377 | 297 | | |||
378 | d->scriptaction->trigger(); | 298 | KexiScriptPart *pt = qobject_cast<KexiScriptPart*>(part()); | ||
379 | if (d->scriptaction->hadError()) { | | |||
380 | QString errormessage = d->scriptaction->errorMessage(); | | |||
381 | d->statusbrowser->append(QString("<b>%2</b><br>").arg(errormessage.toHtmlEscaped())); | | |||
382 | 299 | | |||
383 | QString tracedetails = d->scriptaction->errorTrace(); | 300 | if (pt) { | ||
384 | d->statusbrowser->append(tracedetails.toHtmlEscaped()); | 301 | QJSValue result = pt->execute(d->editor->text().toUtf8()); | ||
385 | 302 | | |||
386 | long lineno = d->scriptaction->errorLineNo(); | 303 | if (result.isError()) { | ||
304 | QString errormessage = result.toString(); | ||||
305 | d->statusbrowser->append(QString("<b>%2</b><br>").arg(errormessage.toHtmlEscaped())); | ||||
306 | | ||||
307 | long lineno = result.property("lineNumber").toInt(); | ||||
387 | if (lineno >= 0) | 308 | if (lineno >= 0) | ||
388 | d->editor->setLineNo(lineno); | 309 | d->editor->setLineNo(lineno); | ||
389 | } | 310 | } | ||
390 | else { | 311 | else { | ||
391 | // xgettext: no-c-format | 312 | // xgettext: no-c-format | ||
392 | d->statusbrowser->append(xi18n("Successfully executed. Time elapsed: %1ms", time.elapsed())); | 313 | d->statusbrowser->append(xi18n("Successfully executed. Time elapsed: %1ms", time.elapsed())); | ||
393 | } | 314 | } | ||
394 | } | 315 | } | ||
316 | } | ||||
395 | 317 | | |||
396 | bool KexiScriptDesignView::loadData() | 318 | bool KexiScriptDesignView::loadData() | ||
397 | { | 319 | { | ||
398 | QString data; | 320 | QString data; | ||
399 | if (!loadDataBlock(&data)) { | 321 | if (!loadDataBlock(&data)) { | ||
400 | qDebug() << "no DataBlock"; | 322 | KexiScriptingDebug() << "no DataBlock"; | ||
401 | return false; | 323 | return false; | ||
402 | } | 324 | } | ||
403 | 325 | | |||
404 | QString errMsg; | 326 | QString errMsg; | ||
405 | int errLine; | 327 | int errLine; | ||
406 | int errCol; | 328 | int errCol; | ||
407 | 329 | | |||
408 | QDomDocument domdoc; | 330 | QDomDocument domdoc; | ||
409 | bool parsed = domdoc.setContent(data, false, &errMsg, &errLine, &errCol); | 331 | bool parsed = domdoc.setContent(data, false, &errMsg, &errLine, &errCol); | ||
410 | 332 | | |||
411 | if (! parsed) { | 333 | if (! parsed) { | ||
412 | qDebug() << "XML parsing error line: " << errLine << " col: " << errCol << " message: " << errMsg; | 334 | KexiScriptingDebug() << "XML parsing error line: " << errLine << " col: " << errCol << " message: " << errMsg; | ||
staniek: -> KexiScriptingWarning | |||||
413 | return false; | 335 | return false; | ||
414 | } | 336 | } | ||
415 | 337 | | |||
416 | QDomElement scriptelem = domdoc.namedItem("script").toElement(); | 338 | QDomElement scriptelem = domdoc.namedItem("script").toElement(); | ||
417 | if (scriptelem.isNull()) { | 339 | if (scriptelem.isNull()) { | ||
418 | qDebug() << "script domelement is null"; | 340 | KexiScriptingDebug() << "script domelement is null"; | ||
staniek: -> KexiScriptingWarning | |||||
419 | return false; | 341 | return false; | ||
420 | } | 342 | } | ||
421 | 343 | | |||
422 | d->scriptType = scriptelem.attribute("scripttype"); | 344 | d->scriptType = scriptelem.attribute("scripttype"); | ||
423 | if (d->scriptType.isEmpty()) { | 345 | if (d->scriptType.isEmpty()) { | ||
424 | d->scriptType = "executable"; | 346 | d->scriptType = "executable"; | ||
425 | } | 347 | } | ||
426 | 348 | | |||
427 | QString interpretername = scriptelem.attribute("language"); | 349 | 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 | 350 | | |||
447 | return true; | 351 | return true; | ||
448 | } | 352 | } | ||
449 | 353 | | |||
450 | KDbObject* KexiScriptDesignView::storeNewData(const KDbObject& object, | 354 | KDbObject* KexiScriptDesignView::storeNewData(const KDbObject& object, | ||
451 | KexiView::StoreNewDataOptions options, | 355 | KexiView::StoreNewDataOptions options, | ||
452 | bool *cancel) | 356 | bool *cancel) | ||
453 | { | 357 | { | ||
454 | KDbObject *s = KexiView::storeNewData(object, options, cancel); | 358 | KDbObject *s = KexiView::storeNewData(object, options, cancel); | ||
455 | 359 | | |||
456 | if (!s || *cancel) { | 360 | if (!s || *cancel) { | ||
457 | delete s; | 361 | delete s; | ||
458 | return 0; | 362 | return 0; | ||
459 | } | 363 | } | ||
460 | qDebug() << "new id:" << s->id(); | 364 | KexiScriptingDebug() << "new id:" << s->id(); | ||
461 | 365 | | |||
462 | if (! storeData()) { | 366 | if (! storeData()) { | ||
463 | qWarning() << "Failed to store the data."; | 367 | qWarning() << "Failed to store the data."; | ||
464 | //failure: remove object's object data to avoid garbage | 368 | //failure: remove object's object data to avoid garbage | ||
465 | KDbConnection *conn = KexiMainWindowIface::global()->project()->dbConnection(); | 369 | KDbConnection *conn = KexiMainWindowIface::global()->project()->dbConnection(); | ||
466 | conn->removeObject(s->id()); | 370 | conn->removeObject(s->id()); | ||
467 | delete s; | 371 | delete s; | ||
468 | return 0; | 372 | return 0; | ||
469 | } | 373 | } | ||
470 | 374 | | |||
471 | return s; | 375 | return s; | ||
472 | } | 376 | } | ||
473 | 377 | | |||
474 | tristate KexiScriptDesignView::storeData(bool /*dontAsk*/) | 378 | tristate KexiScriptDesignView::storeData(bool /*dontAsk*/) | ||
475 | { | 379 | { | ||
380 | KexiScriptingDebug() << "Saving script" << d->editor->text().toUtf8(); | ||||
476 | QDomDocument domdoc("script"); | 381 | QDomDocument domdoc("script"); | ||
477 | QDomElement scriptelem = domdoc.createElement("script"); | 382 | QDomElement scriptelem = domdoc.createElement("script"); | ||
478 | domdoc.appendChild(scriptelem); | 383 | domdoc.appendChild(scriptelem); | ||
479 | 384 | | |||
480 | QString language = d->scriptaction->interpreter(); | 385 | scriptelem.setAttribute("language", "javascript"); | ||
481 | scriptelem.setAttribute("language", language); | | |||
482 | //! @todo move different types to their own part?? | 386 | //! @todo move different types to their own part?? | ||
483 | scriptelem.setAttribute("scripttype", d->scriptType); | 387 | scriptelem.setAttribute("scripttype", d->scriptType); | ||
484 | 388 | | |||
485 | Kross::InterpreterInfo* info = Kross::Manager::self().interpreterInfo(language); | 389 | 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); | 390 | scriptelem.appendChild(scriptcode); | ||
497 | 391 | | |||
498 | return storeDataBlock(domdoc.toString()); | 392 | return storeDataBlock(domdoc.toString()); | ||
499 | } | 393 | } | ||
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. | |||||
500 | | ||||
501 | |
-> KexiScriptingWarning