diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -114,7 +114,7 @@ set(REQUIRED_QT_VERSION 5.4.0) find_package(Qt5 ${REQUIRED_QT_VERSION} REQUIRED COMPONENTS Core Gui Widgets Xml Network PrintSupport Test) -find_package(Qt5 ${REQUIRED_QT_VERSION} COMPONENTS UiTools WebKit WebKitWidgets) +find_package(Qt5 ${REQUIRED_QT_VERSION} COMPONENTS UiTools WebKit WebKitWidgets Qml) # use sane compile flags add_definitions( diff --git a/KexiProducts.cmake b/KexiProducts.cmake --- a/KexiProducts.cmake +++ b/KexiProducts.cmake @@ -60,7 +60,7 @@ # See APP_CONVERTER, FILEMANAGER_* # features -calligra_define_feature(FEATURE_SCRIPTING "Scripting feature" UNPORTED) # TODO +calligra_define_feature(FEATURE_SCRIPTING "Scripting feature") # products calligra_define_product(KEXI_CORE_APP "Kexi core app" REQUIRES) diff --git a/src/plugins/CMakeLists.txt b/src/plugins/CMakeLists.txt --- a/src/plugins/CMakeLists.txt +++ b/src/plugins/CMakeLists.txt @@ -9,6 +9,6 @@ add_subdirectory( importexport ) if(SHOULD_BUILD_FEATURE_SCRIPTING AND KEXI_SCRIPTS_SUPPORT) - # KEXI3 TODO add_subdirectory(scripting) + add_subdirectory(scripting) endif() endif () diff --git a/src/plugins/reports/KexiDBReportDataSource.h b/src/plugins/reports/KexiDBReportDataSource.h --- a/src/plugins/reports/KexiDBReportDataSource.h +++ b/src/plugins/reports/KexiDBReportDataSource.h @@ -66,8 +66,6 @@ virtual qint64 recordCount() const; //Utility Functions - virtual QStringList scriptList() const; - virtual QString scriptCode(const QString& script) const; virtual QStringList dataSourceNames() const; virtual KReportDataSource* create(const QString& source) const Q_REQUIRED_RESULT; diff --git a/src/plugins/reports/KexiDBReportDataSource.cpp b/src/plugins/reports/KexiDBReportDataSource.cpp --- a/src/plugins/reports/KexiDBReportDataSource.cpp +++ b/src/plugins/reports/KexiDBReportDataSource.cpp @@ -302,102 +302,6 @@ return 1; } -static bool isInterpreterSupported(const QString &interpreterName) -{ - return 0 == interpreterName.compare(QLatin1String("javascript"), Qt::CaseInsensitive) - || 0 == interpreterName.compare(QLatin1String("qtscript"), Qt::CaseInsensitive); -} - -QStringList KexiDBReportDataSource::scriptList() const -{ - QStringList scripts; - - if( d->connection) { - QList scriptids = d->connection->objectIds(KexiPart::ScriptObjectType); - QStringList scriptnames = d->connection->objectNames(KexiPart::ScriptObjectType); - - qDebug() << scriptids << scriptnames; - - //A blank entry - scripts << ""; - int i = 0; - foreach(int id, scriptids) { - qDebug() << "ID:" << id; - tristate res; - QString script; - res = d->connection->loadDataBlock(id, &script, QString()); - if (res == true) { - QDomDocument domdoc; - bool parsed = domdoc.setContent(script, false); - - QDomElement scriptelem = domdoc.namedItem("script").toElement(); - if (parsed && !scriptelem.isNull()) { - if (scriptelem.attribute("scripttype") == "object" - && isInterpreterSupported(scriptelem.attribute("language"))) - { - scripts << scriptnames[i]; - } - } else { - qDebug() << "Unable to parse script"; - } - } else { - qDebug() << "Unable to loadDataBlock"; - } - ++i; - } - - qDebug() << scripts; - } - return scripts; -} - -QString KexiDBReportDataSource::scriptCode(const QString& scriptname) const -{ - QString scripts; - - if (d->connection) { - QList scriptids = d->connection->objectIds(KexiPart::ScriptObjectType); - QStringList scriptnames = d->connection->objectNames(KexiPart::ScriptObjectType); - - int i = 0; - foreach(int id, scriptids) { - qDebug() << "ID:" << id; - tristate res; - QString script; - res = d->connection->loadDataBlock(id, &script, QString()); - if (res == true) { - QDomDocument domdoc; - bool parsed = domdoc.setContent(script, false); - - if (! parsed) { - qDebug() << "XML parsing error"; - return QString(); - } - - QDomElement scriptelem = domdoc.namedItem("script").toElement(); - if (scriptelem.isNull()) { - qDebug() << "script domelement is null"; - return QString(); - } - - QString interpretername = scriptelem.attribute("language"); - qDebug() << scriptelem.attribute("scripttype"); - qDebug() << scriptname << scriptnames[i]; - - if ((isInterpreterSupported(interpretername) && scriptelem.attribute("scripttype") == "module") - || scriptname == scriptnames[i]) - { - scripts += '\n' + scriptelem.text().toUtf8(); - } - ++i; - } else { - qDebug() << "Unable to loadDataBlock"; - } - } - } - return scripts; -} - QStringList KexiDBReportDataSource::dataSourceNames() const { //Get the list of queries in the database diff --git a/src/plugins/reports/kexireportdesignview.cpp b/src/plugins/reports/kexireportdesignview.cpp --- a/src/plugins/reports/kexireportdesignview.cpp +++ b/src/plugins/reports/kexireportdesignview.cpp @@ -163,6 +163,7 @@ m_reportDesigner = new KReportDesigner(this, tempData()->reportDefinition); m_sourceSelector->setConnectionData(tempData()->connectionDefinition); + m_reportDesigner->setScriptSource(qobject_cast(part())); } connect(m_reportDesigner, SIGNAL(itemInserted(QString)), this, SIGNAL(itemInserted(QString))); @@ -203,6 +204,7 @@ void KexiReportDesignView::slotSourceDataChanged() { + qDebug() << "Source data changed"; m_reportDesigner->setDataSource(m_sourceSelector->createSourceData()); tempData()->connectionDefinition = m_sourceSelector->connectionData(); setDirty(true); diff --git a/src/plugins/reports/kexireportpart.h b/src/plugins/reports/kexireportpart.h --- a/src/plugins/reports/kexireportpart.h +++ b/src/plugins/reports/kexireportpart.h @@ -24,6 +24,7 @@ #include #include +#include #include class KexiReportPartTempData : public KexiWindowData @@ -42,7 +43,7 @@ /** * @short Application Main Window */ -class KexiReportPart : public KexiPart::Part +class KexiReportPart : public KexiPart::Part, public KReportScriptSource { Q_OBJECT public: @@ -61,6 +62,9 @@ virtual KLocalizedString i18nMessage(const QString& englishMessage, KexiWindow* window) const; + QStringList scriptList() const override; + QString scriptCode(const QString& script) const override; + protected: virtual KexiView* createView(QWidget *parent, KexiWindow* win, KexiPart::Item *item, Kexi::ViewMode = Kexi::DataViewMode, diff --git a/src/plugins/reports/kexireportpart.cpp b/src/plugins/reports/kexireportpart.cpp --- a/src/plugins/reports/kexireportpart.cpp +++ b/src/plugins/reports/kexireportpart.cpp @@ -23,6 +23,8 @@ #include #include +#include + #include #include @@ -48,6 +50,12 @@ QMap toolboxActionsByName; }; +static bool isInterpreterSupported(const QString &interpreterName) +{ + return 0 == interpreterName.compare(QLatin1String("javascript"), Qt::CaseInsensitive) + || 0 == interpreterName.compare(QLatin1String("qtscript"), Qt::CaseInsensitive); +} + KexiReportPart::KexiReportPart(QObject *parent, const QVariantList &l) : KexiPart::Part(parent, xi18nc("Translate this word using only lowercase alphanumeric characters (a..z, 0..9). " @@ -201,3 +209,95 @@ } } +QStringList KexiReportPart::scriptList() const +{ + QStringList scripts; + + KexiMainWindowIface *win = KexiMainWindowIface::global(); + + if( win->project() && win->project()->dbConnection()) { + QList scriptids = win->project()->dbConnection()->objectIds(KexiPart::ScriptObjectType); + QStringList scriptnames = win->project()->dbConnection()->objectNames(KexiPart::ScriptObjectType); + + qDebug() << scriptids << scriptnames; + + //A blank entry + scripts << ""; + int i = 0; + foreach(int id, scriptids) { + qDebug() << "ID:" << id; + tristate res; + QString script; + res = win->project()->dbConnection()->loadDataBlock(id, &script, QString()); + if (res == true) { + QDomDocument domdoc; + bool parsed = domdoc.setContent(script, false); + + QDomElement scriptelem = domdoc.namedItem("script").toElement(); + if (parsed && !scriptelem.isNull()) { + if (scriptelem.attribute("scripttype") == "object" + && isInterpreterSupported(scriptelem.attribute("language"))) + { + scripts << scriptnames[i]; + } + } else { + qDebug() << "Unable to parse script"; + } + } else { + qDebug() << "Unable to loadDataBlock"; + } + ++i; + } + + qDebug() << scripts; + } + return scripts; +} + +QString KexiReportPart::scriptCode(const QString& scriptname) const +{ + QString scripts; + + KexiMainWindowIface *win = KexiMainWindowIface::global(); + + if( win->project() && win->project()->dbConnection()) { + QList scriptids = win->project()->dbConnection()->objectIds(KexiPart::ScriptObjectType); + QStringList scriptnames = win->project()->dbConnection()->objectNames(KexiPart::ScriptObjectType); + + int i = 0; + foreach(int id, scriptids) { + qDebug() << "ID:" << id; + tristate res; + QString script; + res = win->project()->dbConnection()->loadDataBlock(id, &script, QString()); + if (res == true) { + QDomDocument domdoc; + bool parsed = domdoc.setContent(script, false); + + if (! parsed) { + qDebug() << "XML parsing error"; + return QString(); + } + + QDomElement scriptelem = domdoc.namedItem("script").toElement(); + if (scriptelem.isNull()) { + qDebug() << "script domelement is null"; + return QString(); + } + + QString interpretername = scriptelem.attribute("language"); + qDebug() << scriptelem.attribute("scripttype"); + qDebug() << scriptname << scriptnames[i]; + + if ((isInterpreterSupported(interpretername) && scriptelem.attribute("scripttype") == "module") || scriptname == scriptnames[i]) + { + scripts += '\n' + scriptelem.text().toUtf8(); + } + ++i; + } else { + qDebug() << "Unable to loadDataBlock"; + } + } + } + return scripts; +} diff --git a/src/plugins/reports/kexireportview.cpp b/src/plugins/reports/kexireportview.cpp --- a/src/plugins/reports/kexireportview.cpp +++ b/src/plugins/reports/kexireportview.cpp @@ -367,6 +367,7 @@ reportData = createSourceData(tempData()->connectionDefinition); } m_preRenderer->setSourceData(reportData); + m_preRenderer->setScriptSource(qobject_cast(part())); m_preRenderer->setName(window()->partItem()->name()); diff --git a/src/plugins/scripting/CMakeLists.txt b/src/plugins/scripting/CMakeLists.txt --- a/src/plugins/scripting/CMakeLists.txt +++ b/src/plugins/scripting/CMakeLists.txt @@ -1,3 +1,3 @@ -add_subdirectory( kexidb ) +#add_subdirectory( kexidb ) add_subdirectory( kexiscripting ) #add_subdirectory( scripts ) diff --git a/src/plugins/scripting/kexiscripting/CMakeLists.txt b/src/plugins/scripting/kexiscripting/CMakeLists.txt --- a/src/plugins/scripting/kexiscripting/CMakeLists.txt +++ b/src/plugins/scripting/kexiscripting/CMakeLists.txt @@ -20,9 +20,8 @@ target_link_libraries(kexi_scriptplugin PRIVATE kexiextendedwidgets - kokross kexicore - + Qt5::Qml KF5::KIOWidgets ) install(TARGETS kexi_scriptplugin DESTINATION ${KEXI_PLUGIN_INSTALL_DIR}) diff --git a/src/plugins/scripting/kexiscripting/kexiscripthandler.desktop b/src/plugins/scripting/kexiscripting/kexi_scriptplugin.desktop rename from src/plugins/scripting/kexiscripting/kexiscripthandler.desktop rename to src/plugins/scripting/kexiscripting/kexi_scriptplugin.desktop --- a/src/plugins/scripting/kexiscripting/kexiscripthandler.desktop +++ b/src/plugins/scripting/kexiscripting/kexi_scriptplugin.desktop @@ -1,7 +1,4 @@ [Desktop Entry] -Type=Service -X-KDE-ServiceTypes=Kexi/Handler - GenericName=Scripts GenericName[ca]=Scripts GenericName[ca@valencia]=Scripts @@ -17,7 +14,8 @@ GenericName[ja]=スクリプト GenericName[nb]=Skripter GenericName[nl]=Scripts -GenericName[pl]=Skrypty +GenericName[pl]=SkryptyType=Service + GenericName[pt]=Programas GenericName[pt_BR]=Scripts GenericName[se]=Skriptat @@ -49,15 +47,28 @@ Name[uk]=Скрипт Name[x-test]=xxScriptxx Name[zh_CN]=脚本 -X-KDE-Library=kexihandler_script -X-KDE-ParentApp=kexi -X-Kexi-PartVersion=2 + +Type=Service +Icon=script +Encoding=UTF-8 + +X-KDE-Library=kexi_scriptplugin +X-KDE-ServiceTypes=Kexi/Viewer,Kexi/Designer +X-KDE-PluginInfo-Author=Kexi Team +X-KDE-PluginInfo-Email=kexi@kde.org +X-KDE-PluginInfo-Name=org.kexi-project.script +X-KDE-PluginInfo-Version=3.1 +X-KDE-PluginInfo-Website=http://kexi-project.org +X-KDE-PluginInfo-Category= +X-KDE-PluginInfo-Depends= +X-KDE-PluginInfo-License=LGPL +X-KDE-PluginInfo-EnabledByDefault=true + +X-Kexi-GroupName=Scripts X-Kexi-TypeName=script -X-Kexi-Class=org.kexi-project.script -X-Kexi-ItemIcon=script -X-Kexi-SupportsDataView=false -X-Kexi-SupportsDesignView=true -X-Kexi-SupportsDataViewInUserMode=false -X-Kexi-SupportsExecution=true +X-Kexi-ServiceTypesInUserMode=Kexi/Viewer +X-Kexi-VisibleInProjectNavigator=true X-Kexi-SupportsDataExport=false X-Kexi-SupportsPrinting=false +X-Kexi-SupportsExecution=true + diff --git a/src/plugins/scripting/kexiscripting/kexiscriptadaptor.h b/src/plugins/scripting/kexiscripting/kexiscriptadaptor.h --- a/src/plugins/scripting/kexiscripting/kexiscriptadaptor.h +++ b/src/plugins/scripting/kexiscripting/kexiscriptadaptor.h @@ -24,8 +24,6 @@ #include #include -#include - #include #include @@ -105,12 +103,14 @@ return project() ? project()->isConnected() : false; } +#if 0 /** * Returns the KexiDBConnection object that belongs to the opened * project or return NULL if there was no project opened (no * connection established). */ QObject* getConnection() { + if (! m_kexidbmodule) m_kexidbmodule = Kross::Manager::self().module("kexidb"); KDbConnection *connection = project() ? project()->dbConnection() : 0; @@ -121,6 +121,7 @@ } return 0; } +#endif /** * Returns a list of names of all items the part class provides. Possible @@ -133,11 +134,11 @@ * print Kexi.items("table") * \endcode */ - QStringList items(const QString& pluginId) { + QStringList items(const QString& plugin) { QStringList list; if (project()) { KexiPart::ItemList l; - project()->getSortedItemsForPluginId(&l, pluginId(pluginId).toUtf8()); + project()->getSortedItemsForPluginId(&l, pluginId(plugin).toUtf8()); l.sort(); foreach(KexiPart::Item* i, l) { list << i->name(); @@ -149,32 +150,32 @@ /** * Returns the caption for the item defined with \p pluginId and \p name . */ - QString itemCaption(const QString& pluginId, const QString& name) const { - KexiPart::Item *item = partItem(pluginId(pluginId), name); + QString itemCaption(const QString& plugin, const QString& name) const { + KexiPart::Item *item = partItem(pluginId(plugin), name); return item ? item->caption() : QString(); } /** * Set the caption for the item defined with \p pluginId and \p name . */ - void setItemCaption(const QString& pluginId, const QString& name, const QString& caption) { - if (KexiPart::Item *item = partItem(pluginId(pluginId), name)) + void setItemCaption(const QString& plugin, const QString& name, const QString& caption) { + if (KexiPart::Item *item = partItem(pluginId(plugin), name)) item->setCaption(caption); } /** * Returns the description for the item defined with \p className and \p name . */ - QString itemDescription(const QString& pluginId, const QString& name) const { - KexiPart::Item *item = partItem(pluginId(pluginId), name); + QString itemDescription(const QString& plugin, const QString& name) const { + KexiPart::Item *item = partItem(pluginId(plugin), name); return item ? item->description() : QString(); } /** * Set the description for the item defined with \p className and \p name . */ - void setItemDescription(const QString& pluginId, const QString& name, const QString& description) { - if (KexiPart::Item *item = partItem(pluginId(pluginId), name)) + void setItemDescription(const QString& plugin, const QString& name, const QString& description) { + if (KexiPart::Item *item = partItem(pluginId(plugin), name)) item->setDescription(description); } @@ -192,11 +193,11 @@ * Kexi.windowWidget().setDirty(True) * \endcode */ - bool openItem(const QString& pluginId, const QString& name, const QString& viewmode = QString(), + bool openItem(const QString& plugin, const QString& name, const QString& viewmode = QString(), QVariantMap args = QVariantMap()) { bool openingCancelled; - KexiPart::Item *item = partItem(pluginId(pluginId), name); + KexiPart::Item *item = partItem(pluginId(plugin), name); KexiWindow* window = item ? mainWindow()->openObject( item, @@ -220,26 +221,26 @@ * Kexi.closeItem("table","table1") * \endcode */ - bool closeItem(const QString& pluginId, const QString& name) { - if (KexiPart::Item *item = partItem(pluginId(pluginId), name)) + bool closeItem(const QString& plugin, const QString& name) { + if (KexiPart::Item *item = partItem(pluginId(plugin), name)) return mainWindow()->closeObject(item) == true; return false; } /** - * Print the item defined with \p pluginId and \p name . + * Print the item defined with \p plugin and \p name . */ - bool printItem(const QString& pluginId, const QString& name, bool preview = false) { - if (KexiPart::Item *item = partItem(pluginId(pluginId), name)) + bool printItem(const QString& plugin, const QString& name, bool preview = false) { + if (KexiPart::Item *item = partItem(pluginId(plugin), name)) return (preview ? mainWindow()->printPreviewForItem(item) : mainWindow()->printItem(item)) == true; return false; } /** * Executes custom action for the item defined with \p pluginId and \p name . */ - bool executeItem(const QString& pluginId, const QString& name, const QString& actionName) { - if (KexiPart::Item *item = partItem(pluginId(pluginId), name)) + bool executeItem(const QString& plugin, const QString& name, const QString& actionName) { + if (KexiPart::Item *item = partItem(pluginId(plugin), name)) return mainWindow()->executeCustomActionForObject(item, actionName) == true; return false; } @@ -293,8 +294,8 @@ KexiView* currentView() const { return currentWindow() ? currentWindow()->selectedView() : 0; } - KexiPart::Item* partItem(const QString& pluginId, const QString& name) const { - return project() ? project()->itemForPluginId(pluginId(pluginId), name) : 0; + KexiPart::Item* partItem(const QString& plugin, const QString& name) const { + return project() ? project()->itemForPluginId(pluginId(plugin), name) : 0; } QString pluginId(const QString& pluginId) const { return pluginId.contains('.') ? pluginId : (QString::fromLatin1("org.kexi-project.")+pluginId); diff --git a/src/plugins/scripting/kexiscripting/kexiscriptdesignview.h b/src/plugins/scripting/kexiscripting/kexiscriptdesignview.h --- a/src/plugins/scripting/kexiscripting/kexiscriptdesignview.h +++ b/src/plugins/scripting/kexiscripting/kexiscriptdesignview.h @@ -32,10 +32,7 @@ class KexiScriptEditor; class KexiScriptDesignViewPrivate; -namespace Kross -{ -class Action; -} + /** * The KexiScriptDesignView class provides the KexiView to @@ -52,18 +49,18 @@ /** * Constructor. */ - KexiScriptDesignView(QWidget *parent, Kross::Action* scriptaction); + KexiScriptDesignView(QWidget *parent); /** * Destructor. */ virtual ~KexiScriptDesignView(); /** - * \return the \a Kross::Action this \a KexiScriptDesignView + * \return the program string this \a KexiScriptDesignView * is responsible for. */ - Kross::Action* scriptAction() const; +// QString scriptAction() const; /** * \return a property set for this view. @@ -95,7 +92,7 @@ /** * Deferred initialization. */ - void initialize(); + void initialize(const QString &program); void slotImport(); void slotExport(); diff --git a/src/plugins/scripting/kexiscripting/kexiscriptdesignview.cpp b/src/plugins/scripting/kexiscripting/kexiscriptdesignview.cpp --- a/src/plugins/scripting/kexiscripting/kexiscriptdesignview.cpp +++ b/src/plugins/scripting/kexiscripting/kexiscriptdesignview.cpp @@ -22,12 +22,11 @@ #include "kexiscriptdesignview.h" #include "kexiscripteditor.h" +#include "kexiscriptadaptor.h" + #include #include - -#include -#include -#include +#include #include @@ -40,6 +39,9 @@ #include #include #include +#include +#include +#include /// @internal class KexiScriptDesignViewPrivate @@ -49,11 +51,13 @@ QSplitter* splitter; /** - * The \a Kross::Action instance which provides - * us access to the scripting framework Kross. + * The \a QJSEngine which allows + * the script program to be executed */ - Kross::Action* scriptaction; + QJSEngine scriptEngine; + KexiScriptAdaptor adaptor; + /// The \a KexiScriptEditor to edit the scripting code. KexiScriptEditor* editor; @@ -77,12 +81,15 @@ }; KexiScriptDesignView::KexiScriptDesignView( - QWidget *parent, Kross::Action* scriptaction) + QWidget *parent) : KexiView(parent) , d(new KexiScriptDesignViewPrivate()) { setObjectName("KexiScriptDesignView"); - d->scriptaction = scriptaction; + + QJSValue val = d->scriptEngine.newQObject(&d->adaptor); + d->scriptEngine.globalObject().setProperty("Kexi", val); + d->updatesProperties = false; d->splitter = new QSplitter(this); @@ -173,82 +180,64 @@ setMainMenuActions(mainMenuActions); - loadData(); - d->properties = new KPropertySet(this); connect(d->properties, SIGNAL(propertyChanged(KPropertySet&,KProperty&)), this, SLOT(slotPropertyChanged(KPropertySet&,KProperty&))); - // To schedule the initialize fixes a crasher in Kate. - QTimer::singleShot(50, this, SLOT(initialize())); + loadData(); } KexiScriptDesignView::~KexiScriptDesignView() { delete d->properties; delete d; } -Kross::Action* KexiScriptDesignView::scriptAction() const +#if 0 +QString KexiScriptDesignView::scriptAction() const { return d->scriptaction; } +#endif -void KexiScriptDesignView::initialize() +void KexiScriptDesignView::initialize(const QString &program) { setDirty(false); updateProperties(); - d->editor->initialize(d->scriptaction); + d->editor->initialize(program); connect(d->editor, SIGNAL(textChanged()), this, SLOT(setDirty())); d->splitter->setSizes( QList() << height() * 2 / 3 << height() * 1 / 3 ); } void KexiScriptDesignView::slotImport() { - QStringList filters; - foreach(const QString &interpreter, Kross::Manager::self().interpreters()) { - filters << Kross::Manager::self().interpreterInfo(interpreter)->mimeTypes(); - } - //! @todo KEXI3 add equivalent of kfiledialog:/// - //! @todo KEXI3 multiple filters - // for now support jsut one filter - QString filterString; - if (filters.count() == 1) { - const QMimeDatabase db; - const QString filterString = db.mimeTypeForName(filters.first()).filterString(); - } //QUrl("kfiledialog:///kexiscriptingdesigner"), const QUrl result = QFileDialog::getOpenFileUrl(this, xi18nc("@title:window", "Import Script"), - QUrl(), filterString); + QUrl(), "Javascript (*.js)"); if (!result.isValid()) { return; } //! @todo support remote files? QFile f(result.toLocalFile()); if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) { KMessageBox::sorry(this, - xi18nc("@info", "Could not read %1.", file)); + xi18nc("@info", "Could not read %1.", result.toLocalFile())); return; } d->editor->setText(f.readAll()); f.close(); } void KexiScriptDesignView::slotExport() { - QStringList filters; - foreach(const QString &interpreter, Kross::Manager::self().interpreters()) { - filters << Kross::Manager::self().interpreterInfo(interpreter)->mimeTypes(); - } - const QString file = KFileDialog::getSaveFileName( - QUrl("kfiledialog:///kexiscriptingdesigner"), - filters.join(" "), this, xi18nc("@title:window", "Export Script")); - if (file.isEmpty()) + const QUrl result = QFileDialog::getSaveFileUrl(this, xi18nc("@title:window", "Export Script"), + QUrl("kfiledialog:///kexiscriptingdesigner"), "Javascript (*.js)" ); + if (!result.isValid()) return; - QFile f(file); + QFile f(result.toLocalFile()); if (! f.open(QIODevice::WriteOnly | QIODevice::Text)) { KMessageBox::sorry(this, - xi18nc("@info", "Could not write %1.", file)); + xi18nc("@info", "Could not write %1.", result.toLocalFile())); return; } f.write(d->editor->text().toUtf8()); @@ -261,29 +250,6 @@ return; d->updatesProperties = true; - Kross::Manager* manager = &Kross::Manager::self(); - - QString interpretername = d->scriptaction->interpreter(); - Kross::InterpreterInfo* info = interpretername.isEmpty() ? 0 : manager->interpreterInfo(interpretername); - - if (!info) { - // if interpreter isn't defined or invalid, try to fallback. - foreach (const QString& interpretername, - QStringList() << "python" << "ruby" << "qtscript" << "javascript" << "java") - { - info = manager->interpreterInfo(interpretername); - if (info) { - d->scriptaction->setInterpreter(interpretername); - break; - } - } - } - - if (!info) { - d->updatesProperties = false; - return; - } - d->properties->clear(); QStringList types; @@ -299,35 +265,6 @@ ); d->properties->addProperty(t); - QStringList interpreters = manager->interpreters(); - - qDebug() << interpreters; - - KPropertyListData* proplist = new KPropertyListData(interpreters, interpreters); - KProperty* prop = new KProperty( - "language", // name - proplist, // ListData - d->scriptaction->interpreter(), // value - xi18n("Interpreter"), // caption - xi18n("The used scripting interpreter."), // description - KProperty::List // type - ); - d->properties->addProperty(prop); - - Kross::InterpreterInfo::Option::Map options = info->options(); - Kross::InterpreterInfo::Option::Map::ConstIterator it, end(options.constEnd()); - for (it = options.constBegin(); it != end; ++it) { - Kross::InterpreterInfo::Option* option = it.value(); - KProperty* prop = new KProperty( - it.key().toLatin1(), // name - d->scriptaction->option(it.key(), option->value), // value - it.key(), // caption - option->comment, // description - KProperty::Auto // type - ); - d->properties->addProperty(prop); - } - //propertySetSwitched(); propertySetReloaded(true); d->updatesProperties = false; @@ -343,24 +280,12 @@ if (property.isNull()) return; - if (property.name() == "language") { - QString language = property.value().toString(); - qDebug() << "language:" << language; - d->scriptaction->setInterpreter(language); - // We assume Kross and the HighlightingInterface are using same - // names for the support languages... - d->editor->setHighlightMode(language); - updateProperties(); - } - else if (property.name() == "type") { + if (property.name() == "type") { d->scriptType = property.value().toString(); } else { - bool ok = d->scriptaction->setOption(property.name(), property.value()); - if (! ok) { - qWarning() << "unknown property:" << property.name(); - return; - } + qWarning() << "unknown property:" << property.name(); + return; } setDirty(true); @@ -373,17 +298,15 @@ time.start(); d->statusbrowser->append(xi18nc("@info", "Execution of the script %1 started.", - d->scriptaction->name())); + part()->instanceName())); - d->scriptaction->trigger(); - if (d->scriptaction->hadError()) { - QString errormessage = d->scriptaction->errorMessage(); - d->statusbrowser->append(QString("%2
").arg(errormessage.toHtmlEscaped())); + QJSValue result = d->scriptEngine.evaluate(d->editor->text().toUtf8()); - QString tracedetails = d->scriptaction->errorTrace(); - d->statusbrowser->append(tracedetails.toHtmlEscaped()); + if (result.isError()) { + QString errormessage = result.toString(); + d->statusbrowser->append(QString("%2
").arg(errormessage.toHtmlEscaped())); - long lineno = d->scriptaction->errorLineNo(); + long lineno = result.property("lineNumber").toInt(); if (lineno >= 0) d->editor->setLineNo(lineno); } @@ -424,25 +347,7 @@ d->scriptType = "executable"; } - QString interpretername = scriptelem.attribute("language"); - Kross::Manager* manager = &Kross::Manager::self(); - Kross::InterpreterInfo* info = interpretername.isEmpty() ? 0 : manager->interpreterInfo(interpretername); - if (info) { - d->scriptaction->setInterpreter(interpretername); - - Kross::InterpreterInfo::Option::Map options = info->options(); - Kross::InterpreterInfo::Option::Map::ConstIterator it, end = options.constEnd(); - for (it = options.constBegin(); it != end; ++it) { - QString value = scriptelem.attribute(it.key()); - if (! value.isNull()) { - QVariant v(value); - if (v.convert(it.value()->value.type())) // preserve the QVariant's type - d->scriptaction->setOption(it.key(), v); - } - } - } - - d->scriptaction->setCode(scriptelem.text().toUtf8()); + initialize(scriptelem.text().toUtf8()); return true; } @@ -473,26 +378,16 @@ tristate KexiScriptDesignView::storeData(bool /*dontAsk*/) { + qDebug() << "Saving script" << d->editor->text().toUtf8(); QDomDocument domdoc("script"); QDomElement scriptelem = domdoc.createElement("script"); domdoc.appendChild(scriptelem); - QString language = d->scriptaction->interpreter(); - scriptelem.setAttribute("language", language); + scriptelem.setAttribute("language", "javascript"); //! @todo move different types to their own part?? scriptelem.setAttribute("scripttype", d->scriptType); - Kross::InterpreterInfo* info = Kross::Manager::self().interpreterInfo(language); - if (info) { - Kross::InterpreterInfo::Option::Map defoptions = info->options(); - QMap options = d->scriptaction->options(); - QMap::ConstIterator it, end(options.constEnd()); - for (it = options.constBegin(); it != end; ++it) - if (defoptions.contains(it.key())) // only remember options which the InterpreterInfo knows about... - scriptelem.setAttribute(it.key(), it.value().toString()); - } - - QDomText scriptcode = domdoc.createTextNode(d->scriptaction->code()); + QDomText scriptcode = domdoc.createTextNode(d->editor->text().toUtf8()); scriptelem.appendChild(scriptcode); return storeDataBlock(domdoc.toString()); diff --git a/src/plugins/scripting/kexiscripting/kexiscripteditor.h b/src/plugins/scripting/kexiscripting/kexiscripteditor.h --- a/src/plugins/scripting/kexiscripting/kexiscripteditor.h +++ b/src/plugins/scripting/kexiscripting/kexiscripteditor.h @@ -62,7 +62,7 @@ * highlighter will be reset, undo/redo are cleared and * setDirty(false) is set. */ - void initialize(Kross::Action* scriptaction); + void initialize(const QString &scriptProgram); public Q_SLOTS: void slotTextChanged(); diff --git a/src/plugins/scripting/kexiscripting/kexiscripteditor.cpp b/src/plugins/scripting/kexiscripting/kexiscripteditor.cpp --- a/src/plugins/scripting/kexiscripting/kexiscripteditor.cpp +++ b/src/plugins/scripting/kexiscripting/kexiscripteditor.cpp @@ -22,14 +22,12 @@ #include "kexiscripteditor.h" -#include - /// \internal d-pointer class class Q_DECL_HIDDEN KexiScriptEditor::Private { public: - Kross::Action* scriptaction; - Private() : scriptaction(0) {} + QString scriptaction; + Private() {}; }; KexiScriptEditor::KexiScriptEditor(QWidget *parent) @@ -45,18 +43,16 @@ bool KexiScriptEditor::isInitialized() const { - return d->scriptaction != 0; + return !d->scriptaction.isNull(); } -void KexiScriptEditor::initialize(Kross::Action* scriptaction) +void KexiScriptEditor::initialize(const QString &scriptaction) { d->scriptaction = scriptaction; - Q_ASSERT(d->scriptaction); disconnect(this, SIGNAL(textChanged()), this, SLOT(slotTextChanged())); - QString code = d->scriptaction->code(); - if (code.isEmpty()) { + if (d->scriptaction.isEmpty()) { // If there is no code we just add some information. ///@todo remove after release #if 0 @@ -71,10 +67,10 @@ "http://www.kexi-project.org/scripting/"), true).join("\n# ") + "\n"; #endif } - KexiEditor::setText(code); + KexiEditor::setText(d->scriptaction); // We assume Kross and the HighlightingInterface are using same // names for the support languages... - setHighlightMode(d->scriptaction->interpreter()); + setHighlightMode("javascript"); clearUndoRedo(); KexiEditor::setDirty(false); @@ -84,9 +80,7 @@ void KexiScriptEditor::slotTextChanged() { KexiEditor::setDirty(true); - if (d->scriptaction) { - d->scriptaction->setCode(KexiEditor::text().toUtf8()); - } + d->scriptaction = KexiEditor::text().toUtf8(); } void KexiScriptEditor::setLineNo(long lineno) diff --git a/src/plugins/scripting/kexiscripting/kexiscriptpart.h b/src/plugins/scripting/kexiscripting/kexiscriptpart.h --- a/src/plugins/scripting/kexiscripting/kexiscriptpart.h +++ b/src/plugins/scripting/kexiscripting/kexiscriptpart.h @@ -96,6 +96,8 @@ class Private; /// \internal d-pointer instance. Private* const d; + + QString loadData(KexiPart::Item* item); }; #endif diff --git a/src/plugins/scripting/kexiscripting/kexiscriptpart.cpp b/src/plugins/scripting/kexiscripting/kexiscriptpart.cpp --- a/src/plugins/scripting/kexiscripting/kexiscriptpart.cpp +++ b/src/plugins/scripting/kexiscripting/kexiscriptpart.cpp @@ -29,46 +29,34 @@ #include #include #include - -#include -#include +#include #include #include #include #include #include +#include +#include +#include +#include KEXI_PLUGIN_FACTORY(KexiScriptPart, "kexi_scriptplugin.json") /// \internal class Q_DECL_HIDDEN KexiScriptPart::Private { public: explicit Private(KexiScriptPart* p) - : p(p) - , actioncollection(new Kross::ActionCollection("projectscripts")) - , adaptor(0) {} + : p(p) {} ~Private() { - delete actioncollection; delete adaptor; } + QJSEngine engine; KexiScriptPart* p; - Kross::ActionCollection* actioncollection; - KexiScriptAdaptor* adaptor; - - Kross::Action* action(const QString &partname) { - Kross::Action *action = actioncollection->action(partname); - if (! action) { - if (! adaptor) - adaptor = new KexiScriptAdaptor(); - action = new Kross::Action(p, partname); - actioncollection->addAction(action); - action->addObject(adaptor); - } - return action; - } + KexiScriptAdaptor adaptor; + }; KexiScriptPart::KexiScriptPart(QObject *parent, const QVariantList& l) @@ -82,6 +70,8 @@ l) , d(new Private(this)) { + QJSValue val = d->engine.newQObject(&d->adaptor); + d->engine.globalObject().setProperty("Kexi", val); } KexiScriptPart::~KexiScriptPart() @@ -97,91 +87,18 @@ return false; } -#if 0 - KexiDialogBase* dialog = new KexiDialogBase(m_mainWin); - dialog->setId(item->identifier()); - KexiScriptDesignView* view = dynamic_cast( - createView(dialog, dialog, *item, Kexi::DesignViewMode)); - if (! view) { - qWarning() << "Failed to create a view."; - return false; - } - - Kross::Action* scriptaction = view->scriptAction(); - if (scriptaction) { - - const QString dontAskAgainName = "askExecuteScript"; - KSharedConfig::Ptr config = KSharedConfig::openConfig(); - QString dontask = config->readEntry(dontAskAgainName).toLower(); - - bool exec = (dontask == "yes"); - if (!exec && dontask != "no") { - exec = KMessageBox::Yes == KMessageBox::questionYesNo(view, - futureI18n("Do you want to execute the script \"%1\"?\n\n" - "Scripts obtained from unknown sources can contain dangerous code.", scriptaction->text()), - futureI18n("Execute Script?"), KGuiItem(futureI18nc("@action:button", "Execute"), koIconName("system-run")), - dontAskAgainName, KMessageBox::Notify | KMessageBox::Dangerous - ); - } + QString p = loadData(item); - if (exec) { - //QTimer::singleShot(10, scriptaction, SLOT(activate())); - d->scriptguiclient->executeScriptAction(scriptaction); - } + qDebug() << "Executing:\n" << p; + if (!p.isNull()) { + d->engine.evaluate(p); } - view->deleteLater(); // not needed any longer. -#else - - Kross::Action *action = d->action(item->name()); - Q_ASSERT(action); - action->trigger(); -#endif return true; } void KexiScriptPart::initPartActions() { - qDebug() << "............."; -#if 0 - if (m_mainWin) { - // At this stage the KexiPart::Part::m_mainWin should be defined, so - // that we are able to use it's KXMLGUIClient. - - // Initialize the ScriptGUIClient. - d->scriptguiclient = new Kross::Api::ScriptGUIClient(m_mainWin); - - // Publish the KexiMainWindow singelton instance. At least the KexiApp - // scripting-plugin depends on this instance and loading the plugin will - // fail if it's not avaiable. - if (! Kross::Api::Manager::scriptManager()->hasChild("KexiMainWindow")) { - Kross::Api::Manager::scriptManager()->addQObject(m_mainWin, "KexiMainWindow"); - - // Add the QAction's provided by the ScriptGUIClient to the - // KexiMainWindow. - //FIXME: fix+use createSharedPartAction() whyever it doesn't work as expected right now... - Q3PopupMenu* popup = m_mainWin->findPopupMenu("tools"); - if (popup) { - QAction* execscriptaction = d->scriptguiclient->action("executescriptfile"); - if (execscriptaction) - execscriptaction->plug(popup); - QAction* configscriptaction = d->scriptguiclient->action("configurescripts"); - if (configscriptaction) - configscriptaction->plug(popup); - QAction* scriptmenuaction = d->scriptguiclient->action("installedscripts"); - if (scriptmenuaction) - scriptmenuaction->plug(popup); - /* - QAction * execscriptmenuaction = d->scriptguiclient->action("executedscripts"); - if(execscriptmenuaction) - execscriptmenuaction->plug( popup ); - QAction * loadedscriptmenuaction = d->scriptguiclient->action("loadedscripts"); - if(loadedscriptmenuaction) - loadedscriptmenuaction->plug( popup ); - */ - } - } - } -#endif + } void KexiScriptPart::initInstanceActions() @@ -202,25 +119,8 @@ qDebug() << "............. createView"; QString partname = item->name(); if (! partname.isNull()) { - Kross::Action *action = d->action(partname); -#if 0 - KexiMainWindow *win = dialog->mainWin(); - if (!win || !win->project() || !win->project()->dbConnection()) - return 0; - Kross::Api::ScriptActionCollection* collection = d->scriptguiclient->getActionCollection("projectscripts"); - if (! collection) { - collection = new Kross::Api::ScriptActionCollection(xi18n("Scripts"), d->scriptguiclient->actionCollection(), "projectscripts"); - d->scriptguiclient->addActionCollection("projectscripts", collection); - } - const char* name = partname.toLatin1(); - Kross::Api::ScriptAction::Ptr scriptaction = collection->action(name); - if (! scriptaction) { - scriptaction = new Kross::Api::ScriptAction(partname); - collection->attach(scriptaction); //!< @todo remove again on unload! - } -#endif if (viewMode == Kexi::DesignViewMode) { - return new KexiScriptDesignView(parent, action); + return new KexiScriptDesignView(parent); } } return 0; @@ -236,4 +136,49 @@ return Part::i18nMessage(englishMessage, window); } +QString KexiScriptPart::loadData(KexiPart::Item* item) +{ + QString data; + if (!item) { + return QString(); + } + + if (true != KexiMainWindowIface::global()->project()->dbConnection()->loadDataBlock( + item->identifier(), &data)) + { + return QString(); + } + + QString errMsg; + int errLine; + int errCol; + + QString scriptType; + + QDomDocument domdoc; + bool parsed = domdoc.setContent(data, false, &errMsg, &errLine, &errCol); + + if (! parsed) { + qDebug() << "XML parsing error line: " << errLine << " col: " << errCol << " message: " << errMsg; + return QString(); + } + + QDomElement scriptelem = domdoc.namedItem("script").toElement(); + if (scriptelem.isNull()) { + qDebug() << "script domelement is null"; + return QString(); + } + + scriptType = scriptelem.attribute("scripttype"); + if (scriptType.isEmpty()) { + scriptType = "executable"; + } + + if (scriptType == "executable") { + return scriptelem.text().toUtf8(); + } else { + return QString(); + } +} + #include "kexiscriptpart.moc"