complete context init & build

This commit is contained in:
王劲鹏 2021-02-02 20:42:37 +08:00 committed by osborn
parent 3b72ab56aa
commit fb4df95d0a
27 changed files with 274 additions and 28 deletions

View File

@ -1,9 +1,12 @@
#include "context.h"
#include "native_driver.h"
#include "context_manager.h"
#include "utils/constant.h"
Context::Context(QString contextId, QString source, QString extra)
{
this->mRootNode = new RootNode();
this->mContextId = contextId;
this->source = source;
this->extra = extra;
@ -13,9 +16,41 @@ Context* Context::create(QString script, QString source, QString extra)
{
Context *context = ContextManager::getInstance()->createContext(script, source, extra);
context->script = script;
context->init(extra);
QVariantList args;
context->callEntity(Constant::DORIC_ENTITY_CREATE, args);
return context;
}
void Context::init(QString initData)
{
this->extra = initData;
if (!initData.isEmpty()) {
QVariantList args;
args.push_back(initData);
callEntity(Constant::DORIC_ENTITY_INIT, args);
}
}
void Context::build(int width, int height)
{
QMap<QString, QVariant> map;
map.insert("width", QVariant(width));
map.insert("height", QVariant(height));
QVariant jsValue(map);
this->initParams = jsValue;
QVariantList args;
args.push_back(this->initParams);
callEntity(Constant::DORIC_ENTITY_BUILD, args);
}
void Context::callEntity(QString methodName, QVariantList args)
{
return getDriver()->invokeContextEntityMethod(this->mContextId, methodName, args);
}
InterfaceDriver* Context::getDriver()
{
if (driver == NULL)

View File

@ -1,17 +1,20 @@
#ifndef CONTEXT_H
#define CONTEXT_H
#include <QString>
#include <QVariant>
#include "interface_driver.h"
#include "shader/root_node.h"
class Context
{
private:
QString mContextId;
RootNode *mRootNode;
QString source;
QString script;
QString extra;
QVariant initParams;
InterfaceDriver *driver = NULL;
public:
@ -19,6 +22,12 @@ public:
static Context* create(QString script, QString source, QString extra);
void init(QString initData);
void build(int width, int height);
void callEntity(QString methodName, QVariantList args);
InterfaceDriver* getDriver();
};

View File

@ -0,0 +1,23 @@
#include <QDebug>
#include "demo_bridge.h"
#include "utils/utils.h"
#include "panel.h"
DemoBridge::DemoBridge(QObject *parent) : QObject(parent)
{
}
void DemoBridge::navigate(QVariant route)
{
switch (route.toInt()) {
case 0:
QString name = "Snake.js";
QString script = Utils::readAssetFile("/doric/bundles", name);
Panel panel;
panel.config(script, name, NULL);
break;
}
}

View File

@ -0,0 +1,19 @@
#ifndef DEMOBRIDGE_H
#define DEMOBRIDGE_H
#include <QObject>
#include <QVariant>
class DemoBridge : public QObject
{
Q_OBJECT
public:
explicit DemoBridge(QObject *parent = nullptr);
Q_INVOKABLE
void navigate(QVariant route);
signals:
};
#endif // DEMOBRIDGE_H

View File

@ -18,14 +18,18 @@ SOURCES += \
async/settable_future.cpp \
context.cpp \
context_manager.cpp \
demo/demo_bridge.cpp \
engine/bridge_extension.cpp \
engine/js_engine.cpp \
engine/native_empty.cpp \
engine/native_jse.cpp \
engine/native_log.cpp \
engine/native_require.cpp \
engine/timer_extension.cpp \
main.cpp \
native_driver.cpp \
panel.cpp \
shader/root_node.cpp \
utils/constant.cpp
RESOURCES += qml.qrc
@ -48,15 +52,19 @@ HEADERS += \
async/settable_future.h \
context.h \
context_manager.h \
demo/demo_bridge.h \
engine/bridge_extension.h \
engine/interface_jse.h \
engine/js_engine.h \
engine/native_empty.h \
engine/native_jse.h \
engine/native_log.h \
engine/native_require.h \
engine/timer_extension.h \
interface_driver.h \
native_driver.h \
panel.h \
shader/root_node.h \
template/singleton.h \
utils/constant.h \
utils/count_down_latch.h \

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 4.11.1, 2021-01-28T17:40:51. -->
<!-- Written by QtCreator 4.11.1, 2021-02-01T17:32:31. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>

View File

@ -13,7 +13,7 @@ public:
virtual void injectGlobalJSFunction(QString name, QObject *function, QString property) = 0;
virtual QJSValue invokeObject(QString objectName, QString functionName, QJSValueList arguments) = 0;
virtual QJSValue invokeObject(QString objectName, QString functionName, QVariantList arguments) = 0;
};
#endif // INTERFACE_JSE_H

View File

@ -10,6 +10,7 @@
#include "../utils/constant.h"
#include "native_log.h"
#include "native_empty.h"
#include "native_require.h"
#include "timer_extension.h"
#include "bridge_extension.h"
#include "../utils/utils.h"
@ -51,11 +52,14 @@ JSEngine::JSEngine(QObject *parent) : QObject(parent)
NativeEmpty *nativeEmpty = new NativeEmpty();
mJSE->injectGlobalJSFunction(Constant::INJECT_EMPTY, nativeEmpty, "function");
// inject require
NativeRequire *nativeRequire = new NativeRequire();
mJSE->injectGlobalJSFunction(Constant::INJECT_REQUIRE, nativeRequire, "function");
// inject timer set & clear
std::function<void(void)> func = [](){};
TimerExtension *timerExtension = new TimerExtension([this](long timerId){
QJSValueList arguments;
arguments.append(QJSValue((int)timerId));
QVariantList arguments;
arguments.push_back(QVariant((int)timerId));
this->invokeDoricMethod(Constant::DORIC_TIMER_CALLBACK, arguments);
});
mJSE->injectGlobalJSFunction(Constant::INJECT_TIMER_SET, timerExtension, "setTimer");
@ -75,7 +79,7 @@ JSEngine::JSEngine(QObject *parent) : QObject(parent)
});
}
QJSValue JSEngine::invokeDoricMethod(QString method, QJSValueList arguments)
QJSValue JSEngine::invokeDoricMethod(QString method, QVariantList arguments)
{
return mJSE->invokeObject(Constant::GLOBAL_DORIC, method, arguments);
}

View File

@ -22,7 +22,7 @@ public:
~JSEngine();
QJSValue invokeDoricMethod(QString method, QJSValueList arguments);
QJSValue invokeDoricMethod(QString method, QVariantList arguments);
void prepareContext(QString contextId, QString script, QString source);
};

View File

@ -35,9 +35,35 @@ void NativeJSE::injectGlobalJSFunction(QString name, QObject *function, QString
mJSEngine.globalObject().setProperty(name, functionObject.property(property));
}
QJSValue NativeJSE::invokeObject(QString objectName, QString functionName, QJSValueList arguments)
QJSValue NativeJSE::invokeObject(QString objectName, QString functionName, QVariantList arguments)
{
QJSValue object = mJSEngine.evaluate(objectName);
QJSValue function = object.property(functionName);
return function.call(arguments);
QJSValueList args;
foreach(QVariant variant, arguments) {
if (variant.type() == QVariant::String) {
args.push_back(QJSValue(variant.toString()));
} else if (variant.type() == QVariant::Map) {
QJSValue arg = mJSEngine.newObject();
QMap<QString, QVariant> map = variant.toMap();
foreach (QString key, map.keys()) {
QVariant value = map.value(key);
if (value.type() == QVariant::String) {
arg.setProperty(key, value.toString());
} else if (value.type() == QVariant::Int) {
arg.setProperty(key, value.toInt());
}
}
args.push_back(arg);
}
}
QJSValue result = function.call(args);
if (result.isError())
qDebug()
<< "Uncaught exception at line"
<< result.property("lineNumber").toInt()
<< ":" << result.toString();
return result;
}

View File

@ -17,7 +17,7 @@ public:
void injectGlobalJSFunction(QString name, QObject *function, QString property) override;
QJSValue invokeObject(QString objectName, QString functionName, QJSValueList arguments) override;
QJSValue invokeObject(QString objectName, QString functionName, QVariantList arguments) override;
};
#endif // NATIVE_JSE_H

View File

@ -0,0 +1,8 @@
#include "native_require.h"
#include <QDebug>
Q_INVOKABLE QJSValue NativeRequire::function(QString name) {
qDebug() << "nativeRequire";
return QJSValue::NullValue;
}

View File

@ -0,0 +1,18 @@
#ifndef NATIVE_REQUIRE_H
#define NATIVE_REQUIRE_H
#include <QObject>
#include <QJSValue>
class NativeRequire : public QObject {
Q_OBJECT
public:
NativeRequire(QObject *parent = nullptr) : QObject(parent) {}
Q_INVOKABLE QJSValue function(QString name);
};
#endif // NATIVE_REQUIRE_H

View File

@ -2,14 +2,14 @@
#define INTERFACEDRIVER_H
#include <QString>
#include <QObject>
#include <QVariant>
class InterfaceDriver
{
public:
virtual void invokeContextEntityMethod(QString contextId, QString method, QList<QObject> args) = 0;
virtual void invokeContextEntityMethod(QString contextId, QString method, QVariantList args) = 0;
virtual void invokeDoricMethod(QString method, QList<QObject> args) = 0;
virtual void invokeDoricMethod(QString method, QVariantList args) = 0;
virtual void createContext(QString contextId, QString script, QString source) = 0;

View File

@ -1,5 +1,8 @@
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "demo/demo_bridge.h"
int main(int argc, char *argv[])
{
@ -14,7 +17,11 @@ int main(int argc, char *argv[])
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
DemoBridge *demoBridge = new DemoBridge();
auto context = engine.rootContext();
context->setContextProperty("demoBridge", demoBridge);
engine.load(url);
return app.exec();
}

View File

@ -12,11 +12,20 @@ ApplicationWindow {
ListView {
width: parent.width
model: 20
delegate: ItemDelegate {
text: "Item " + (index + 1)
model: 1
delegate: Rectangle {
Column {
anchors.centerIn: parent
Text {
text: {return "Snake.js"}
}
}
width: parent.width
height: 100
height: 60
MouseArea {
anchors.fill: parent
onClicked: {demoBridge.navigate(index)}
}
}
}
}

View File

@ -1,16 +1,21 @@
#include "native_driver.h"
#include "async/async_call.h"
#include <functional>
void NativeDriver::invokeContextEntityMethod(QString contextId, QString method, QList<QObject> args)
{
#include "native_driver.h"
#include "async/async_call.h"
#include "utils/constant.h"
void NativeDriver::invokeContextEntityMethod(QString contextId, QString method, QVariantList args)
{
args.insert(0, QVariant(contextId));
args.insert(1, QVariant(method));
invokeDoricMethod(Constant::DORIC_CONTEXT_INVOKE, args);
}
void NativeDriver::invokeDoricMethod(QString method, QList<QObject> args)
void NativeDriver::invokeDoricMethod(QString method, QVariantList args)
{
return AsyncCall::ensureRunInThreadPool(&jsEngine.mJSThreadPool, [this, method, args]{
qDebug() << "invokeDoricMethod: " << this->jsEngine.invokeDoricMethod(method, args).toString();
});
}
void NativeDriver::createContext(QString contextId, QString script, QString source)

View File

@ -29,9 +29,9 @@ public:
return &instance;
}
void invokeContextEntityMethod(QString contextId, QString method, QList<QObject> args) override;
void invokeContextEntityMethod(QString contextId, QString method, QVariantList args) override;
void invokeDoricMethod(QString method, QList<QObject> args) override;
void invokeDoricMethod(QString method, QVariantList args) override;
void createContext(QString contextId, QString script, QString source) override;

18
doric-Qt/doric/panel.cpp Normal file
View File

@ -0,0 +1,18 @@
#include "panel.h"
Panel::Panel()
{
}
void Panel::config(QString script, QString alias, QString extra)
{
Context *context = Context::create(script, alias, extra);
config(context);
}
void Panel::config(Context *context)
{
this->mContext = context;
this->mContext->build(960, 720);
}

21
doric-Qt/doric/panel.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef PANEL_H
#define PANEL_H
#include "context.h"
class Panel
{
private:
Context *mContext;
int renderedWidth = -1;
int renderedHeight = -1;
public:
Panel();
void config(QString script, QString alias, QString extra);
void config(Context *context);
};
#endif // PANEL_H

View File

@ -2,10 +2,13 @@
<qresource prefix="/">
<file>main.qml</file>
<file>qtquickcontrols2.conf</file>
<file>view.qml</file>
</qresource>
<qresource prefix="/doric">
<file alias="doric-sandbox.js">../../doric-js/bundle/doric-sandbox.js</file>
<file alias="doric-lib.js">../../doric-js/bundle/doric-lib.js</file>
</qresource>
<qresource prefix="/doric/bundles">
<file alias="Snake.js">../../doric-demo/bundle/src/Snake.js</file>
</qresource>
</RCC>

View File

@ -0,0 +1,6 @@
#include "root_node.h"
RootNode::RootNode()
{
}

View File

@ -0,0 +1,10 @@
#ifndef ROOTNODE_H
#define ROOTNODE_H
class RootNode
{
public:
RootNode();
};
#endif // ROOTNODE_H

View File

@ -34,4 +34,9 @@ const QString Constant::TEMPLATE_MODULE = QString("Reflect.apply(doric.jsRegiste
const QString Constant::TEMPLATE_CONTEXT_DESTROY = QString("doric.jsReleaseContext(\"%s\")");
const QString Constant::GLOBAL_DORIC = "doric";
const QString Constant::DORIC_CONTEXT_INVOKE = "jsCallEntityMethod";
const QString Constant::DORIC_TIMER_CALLBACK = "jsCallbackTimer";
const QString Constant::DORIC_ENTITY_INIT = "__init__";
const QString Constant::DORIC_ENTITY_CREATE = "__onCreate__";
const QString Constant::DORIC_ENTITY_BUILD = "__build__";

View File

@ -23,7 +23,12 @@ public:
static const QString TEMPLATE_CONTEXT_DESTROY;
static const QString GLOBAL_DORIC;
static const QString DORIC_CONTEXT_INVOKE;
static const QString DORIC_TIMER_CALLBACK;
static const QString DORIC_ENTITY_CREATE;
static const QString DORIC_ENTITY_INIT;
static const QString DORIC_ENTITY_BUILD;
};

View File

@ -14,6 +14,7 @@ public:
QFile *file = new QFile(resource.fileName());
file->open(QFile::ReadOnly | QFile::Text);
QTextStream in(file);
in.setCodec("UTF-8");
QString content = in.readAll();
file->close();
delete file;

6
doric-Qt/doric/view.qml Normal file
View File

@ -0,0 +1,6 @@
import QtQuick 2.12
import QtQuick.Controls 2.5
Rectangle {
color: 'red'
}