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