Port declarative scripting to QtQuick

Getting all functionality from old solution into new one is not really
possible. Main problems are that QtScript provided more functionality
than the QJSEngine. For example it's no longer possible to just export
functions to the engine. We need to have a Qt wrapper object. At the
moment this wrapper object doesn't export all functions as the callbacks
are tricky. A solution might be to create specific QML types
encapsulating functionality which used to be exported on the functions.

Nevertheless a basic QML script loads and works and the ported readConfig
function works, too.
This commit is contained in:
Martin Gräßlin 2013-08-12 13:09:46 +02:00
parent 416b881a00
commit abbe84bab4
3 changed files with 72 additions and 33 deletions

View file

@ -221,7 +221,6 @@ set(kwin_OWN_LIBS
)
set(kwin_QT_LIBS
${Qt5Declarative_LIBRARIES}
${Qt5Quick_LIBRARIES}
${Qt5X11Extras_LIBRARIES}
)
@ -229,6 +228,7 @@ set(kwin_QT_LIBS
set(kwin_KDE_LIBS
${KDE4Support_LIBRARIES}
${KDE4_KDEUI_LIBRARY}
${KDECLARATIVE_LIBRARIES}
KF5::KCrash
KF5::plasma
KF5::KWindowSystem

View file

@ -26,9 +26,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "workspace_wrapper.h"
#include "scripting_model.h"
#include "../client.h"
#if KWIN_QT5_PORTING
#include "../thumbnailitem.h"
#endif
#include "../options.h"
#include "../workspace.h"
// KDE
@ -46,13 +44,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <QFutureWatcher>
#include <QSettings>
#include <QtConcurrentRun>
#include <QtDeclarative/QDeclarativeComponent>
#include <QtDeclarative/QDeclarativeContext>
#include <QtDeclarative/QDeclarativeEngine>
#include <QtDeclarative/QDeclarativeItem>
#include <QtDeclarative/QDeclarativeView>
#include <QtDeclarative/qdeclarative.h>
#include <QMenu>
#include <QQmlContext>
#include <QQmlEngine>
#include <QtScript/QScriptEngine>
#include <QtScript/QScriptValue>
@ -266,7 +260,7 @@ bool KWin::AbstractScript::borderActivated(KWin::ElectricBorder edge)
return true;
}
void KWin::AbstractScript::installScriptFunctions(QScriptEngine* engine)
void KWin::Script::installScriptFunctions(QScriptEngine* engine)
{
// add our print
QScriptValue printFunc = engine->newFunction(kwinScriptPrint);
@ -533,9 +527,8 @@ void KWin::ScriptUnloaderAgent::scriptUnload(qint64 id)
KWin::DeclarativeScript::DeclarativeScript(int id, QString scriptName, QString pluginName, QObject* parent)
: AbstractScript(id, scriptName, pluginName, parent)
, m_engine(new QDeclarativeEngine(this))
, m_component(new QDeclarativeComponent(m_engine, this))
, m_scene(new QGraphicsScene(this))
, m_engine(new QQmlEngine(this))
, m_component(new QQmlComponent(m_engine, this))
{
}
@ -548,29 +541,26 @@ void KWin::DeclarativeScript::run()
if (running()) {
return;
}
// add read config
#warning DeclarativeScripts needs porting of KDeclarative
#if KWIN_QT5_PORTING
KDeclarative kdeclarative;
kdeclarative.setDeclarativeEngine(m_engine);
kdeclarative.initialize();
kdeclarative.setupBindings();
installScriptFunctions(kdeclarative.scriptEngine());
qmlRegisterType<DesktopThumbnailItem>("org.kde.kwin", 0, 1, "DesktopThumbnailItem");
qmlRegisterType<WindowThumbnailItem>("org.kde.kwin", 0, 1, "ThumbnailItem");
#endif
qmlRegisterType<DesktopThumbnailItem>("org.kde.kwin", 2, 0, "DesktopThumbnailItem");
qmlRegisterType<WindowThumbnailItem>("org.kde.kwin", 2, 0, "ThumbnailItem");
qmlRegisterType<KWin::ScriptingClientModel::ClientModel>();
qmlRegisterType<KWin::ScriptingClientModel::SimpleClientModel>("org.kde.kwin", 0, 1, "ClientModel");
qmlRegisterType<KWin::ScriptingClientModel::ClientModelByScreen>("org.kde.kwin", 0, 1, "ClientModelByScreen");
qmlRegisterType<KWin::ScriptingClientModel::ClientModelByScreenAndDesktop>("org.kde.kwin", 0, 1, "ClientModelByScreenAndDesktop");
qmlRegisterType<KWin::ScriptingClientModel::ClientFilterModel>("org.kde.kwin", 0, 1, "ClientFilterModel");
qmlRegisterType<KWin::ScriptingClientModel::SimpleClientModel>("org.kde.kwin", 2, 0, "ClientModel");
qmlRegisterType<KWin::ScriptingClientModel::ClientModelByScreen>("org.kde.kwin", 2, 0, "ClientModelByScreen");
qmlRegisterType<KWin::ScriptingClientModel::ClientModelByScreenAndDesktop>("org.kde.kwin", 2, 0, "ClientModelByScreenAndDesktop");
qmlRegisterType<KWin::ScriptingClientModel::ClientFilterModel>("org.kde.kwin", 2, 0, "ClientFilterModel");
qmlRegisterType<KWin::Client>();
m_engine->rootContext()->setContextProperty(QStringLiteral("workspace"), AbstractScript::workspace());
m_engine->rootContext()->setContextProperty(QStringLiteral("options"), options);
m_engine->rootContext()->setContextProperty(QStringLiteral("KWin"), new JSEngineGlobalMethodsWrapper(this));
m_component->loadUrl(QUrl::fromLocalFile(scriptFile().fileName()));
if (m_component->isLoading()) {
connect(m_component, SIGNAL(statusChanged(QDeclarativeComponent::Status)), SLOT(createComponent()));
connect(m_component, &QQmlComponent::statusChanged, this, &DeclarativeScript::createComponent);
} else {
createComponent();
}
@ -581,11 +571,26 @@ void KWin::DeclarativeScript::createComponent()
if (m_component->isError()) {
kDebug(1212) << "Component failed to load: " << m_component->errors();
} else {
m_scene->addItem(qobject_cast<QDeclarativeItem*>(m_component->create()));
m_component->create();
}
setRunning(true);
}
KWin::JSEngineGlobalMethodsWrapper::JSEngineGlobalMethodsWrapper(KWin::DeclarativeScript *parent)
: QObject(parent)
, m_script(parent)
{
}
KWin::JSEngineGlobalMethodsWrapper::~JSEngineGlobalMethodsWrapper()
{
}
QVariant KWin::JSEngineGlobalMethodsWrapper::readConfig(const QString &key, QVariant defaultValue)
{
return m_script->config().readEntry(key, defaultValue);
}
KWin::Scripting *KWin::Scripting::s_self = NULL;
KWin::Scripting *KWin::Scripting::create(QObject *parent)

View file

@ -30,8 +30,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <QStringList>
#include <QtScript/QScriptEngineAgent>
class QDeclarativeComponent;
class QDeclarativeEngine;
class QQmlComponent;
class QQmlEngine;
class QAction;
class QDBusPendingCallWatcher;
class QGraphicsScene;
@ -166,8 +166,6 @@ protected:
return m_workspace;
}
void installScriptFunctions(QScriptEngine *engine);
private:
/**
* @brief Parses the @p value to either a QMenu or QAction.
@ -246,6 +244,7 @@ private Q_SLOTS:
void slotScriptLoadedFromFile();
private:
void installScriptFunctions(QScriptEngine *engine);
/**
* Read the script from file into a byte array.
* If file cannot be read an empty byte array is returned.
@ -281,9 +280,44 @@ private Q_SLOTS:
void createComponent();
private:
QDeclarativeEngine *m_engine;
QDeclarativeComponent *m_component;
QGraphicsScene *m_scene;
QQmlEngine *m_engine;
QQmlComponent *m_component;
};
class JSEngineGlobalMethodsWrapper : public QObject
{
Q_OBJECT
Q_ENUMS(ClientAreaOption)
public:
//------------------------------------------------------------------
//enums copy&pasted from kwinglobals.h for exporting
enum ClientAreaOption {
///< geometry where a window will be initially placed after being mapped
PlacementArea,
///< window movement snapping area? ignore struts
MovementArea,
///< geometry to which a window will be maximized
MaximizeArea,
///< like MaximizeArea, but ignore struts - used e.g. for topmenu
MaximizeFullArea,
///< area for fullscreen windows
FullScreenArea,
///< whole workarea (all screens together)
WorkArea,
///< whole area (all screens together), ignore struts
FullArea,
///< one whole screen, ignore struts
ScreenArea
};
explicit JSEngineGlobalMethodsWrapper(DeclarativeScript *parent);
virtual ~JSEngineGlobalMethodsWrapper();
public Q_SLOTS:
QVariant readConfig(const QString &key, QVariant defaultValue = QVariant());
private:
DeclarativeScript *m_script;
};
/**