qml 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +46 -0
- data/.rspec +2 -0
- data/.travis.yml +15 -0
- data/.yardopts +4 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +351 -0
- data/Rakefile +6 -0
- data/examples/assets/fonts/fontawesome-webfont.ttf +0 -0
- data/examples/fizzbuzz/fizzbuzz.rb +43 -0
- data/examples/fizzbuzz/main.qml +38 -0
- data/examples/imageprovider/imageprovider.rb +57 -0
- data/examples/imageprovider/main.qml +51 -0
- data/examples/todo/main.qml +70 -0
- data/examples/todo/todo.rb +36 -0
- data/examples/twitter/main.qml +36 -0
- data/examples/twitter/twitter.rb +55 -0
- data/ext/qml/accessclass.cpp +71 -0
- data/ext/qml/accessclass.h +19 -0
- data/ext/qml/accessobject.cpp +30 -0
- data/ext/qml/accessobject.h +22 -0
- data/ext/qml/application.cpp +54 -0
- data/ext/qml/application.h +17 -0
- data/ext/qml/common.h +18 -0
- data/ext/qml/ext_accesssupport.cpp +77 -0
- data/ext/qml/ext_accesssupport.h +42 -0
- data/ext/qml/ext_gcmarker.cpp +39 -0
- data/ext/qml/ext_gcmarker.h +27 -0
- data/ext/qml/ext_kernel.cpp +62 -0
- data/ext/qml/ext_kernel.h +11 -0
- data/ext/qml/ext_metaobject.cpp +410 -0
- data/ext/qml/ext_metaobject.h +62 -0
- data/ext/qml/ext_pluginloader.cpp +55 -0
- data/ext/qml/ext_pluginloader.h +32 -0
- data/ext/qml/ext_pointer.cpp +134 -0
- data/ext/qml/ext_pointer.h +43 -0
- data/ext/qml/ext_testutil.cpp +42 -0
- data/ext/qml/ext_testutil.h +11 -0
- data/ext/qml/extconf.rb +84 -0
- data/ext/qml/foreignclass.cpp +72 -0
- data/ext/qml/foreignclass.h +88 -0
- data/ext/qml/foreignmetaobject.cpp +345 -0
- data/ext/qml/foreignmetaobject.h +46 -0
- data/ext/qml/foreignobject.cpp +22 -0
- data/ext/qml/foreignobject.h +21 -0
- data/ext/qml/functioninfo.h +16 -0
- data/ext/qml/init.cpp +69 -0
- data/ext/qml/listmodel.cpp +112 -0
- data/ext/qml/listmodel.h +43 -0
- data/ext/qml/markable.h +12 -0
- data/ext/qml/objectdata.cpp +26 -0
- data/ext/qml/objectdata.h +20 -0
- data/ext/qml/objectgc.cpp +69 -0
- data/ext/qml/objectgc.h +28 -0
- data/ext/qml/plugins/core/applicationextension.cpp +34 -0
- data/ext/qml/plugins/core/applicationextension.h +28 -0
- data/ext/qml/plugins/core/componentextension.cpp +41 -0
- data/ext/qml/plugins/core/componentextension.h +28 -0
- data/ext/qml/plugins/core/contextextension.cpp +39 -0
- data/ext/qml/plugins/core/contextextension.h +29 -0
- data/ext/qml/plugins/core/core.pro +29 -0
- data/ext/qml/plugins/core/coreplugin.cpp +87 -0
- data/ext/qml/plugins/core/coreplugin.h +49 -0
- data/ext/qml/plugins/core/engineextension.cpp +27 -0
- data/ext/qml/plugins/core/engineextension.h +28 -0
- data/ext/qml/plugins/core/imageprovider.cpp +38 -0
- data/ext/qml/plugins/core/imageprovider.h +18 -0
- data/ext/qml/plugins/core/imagerequestpromise.cpp +19 -0
- data/ext/qml/plugins/core/imagerequestpromise.h +21 -0
- data/ext/qml/plugins/core/qmlexception.cpp +11 -0
- data/ext/qml/plugins/core/qmlexception.h +17 -0
- data/ext/qml/plugins/testutil/objectlifechecker.cpp +17 -0
- data/ext/qml/plugins/testutil/objectlifechecker.h +24 -0
- data/ext/qml/plugins/testutil/ownershiptest.cpp +26 -0
- data/ext/qml/plugins/testutil/ownershiptest.h +30 -0
- data/ext/qml/plugins/testutil/testobject.cpp +6 -0
- data/ext/qml/plugins/testutil/testobject.h +108 -0
- data/ext/qml/plugins/testutil/testobjectsubclass.cpp +10 -0
- data/ext/qml/plugins/testutil/testobjectsubclass.h +19 -0
- data/ext/qml/plugins/testutil/testutil.pro +20 -0
- data/ext/qml/plugins/testutil/testutilplugin.cpp +47 -0
- data/ext/qml/plugins/testutil/testutilplugin.h +32 -0
- data/ext/qml/qmltyperegisterer.cpp +74 -0
- data/ext/qml/qmltyperegisterer.h +30 -0
- data/ext/qml/rubyclass.cpp +94 -0
- data/ext/qml/rubyclass.h +234 -0
- data/ext/qml/rubyvalue.cpp +690 -0
- data/ext/qml/rubyvalue.h +256 -0
- data/ext/qml/signalforwarder.cpp +66 -0
- data/ext/qml/signalforwarder.h +29 -0
- data/ext/qml/util.cpp +120 -0
- data/ext/qml/util.h +101 -0
- data/ext/qml/valuereference.cpp +50 -0
- data/ext/qml/valuereference.h +22 -0
- data/ext/qml/weakvaluereference.cpp +27 -0
- data/ext/qml/weakvaluereference.h +19 -0
- data/lib/qml.rb +41 -0
- data/lib/qml/access.rb +137 -0
- data/lib/qml/application.rb +139 -0
- data/lib/qml/class_builder.rb +126 -0
- data/lib/qml/component.rb +53 -0
- data/lib/qml/context.rb +71 -0
- data/lib/qml/data.rb +2 -0
- data/lib/qml/data/array_model.rb +103 -0
- data/lib/qml/data/error.rb +5 -0
- data/lib/qml/data/list_model.rb +146 -0
- data/lib/qml/dispatchable.rb +34 -0
- data/lib/qml/dispatcher.rb +61 -0
- data/lib/qml/engine.rb +54 -0
- data/lib/qml/error_converter.rb +15 -0
- data/lib/qml/errors.rb +26 -0
- data/lib/qml/geometry.rb +3 -0
- data/lib/qml/geometry/point.rb +5 -0
- data/lib/qml/geometry/rectangle.rb +5 -0
- data/lib/qml/geometry/size.rb +5 -0
- data/lib/qml/image_provider.rb +87 -0
- data/lib/qml/meta_object.rb +20 -0
- data/lib/qml/models.rb +1 -0
- data/lib/qml/name_helper.rb +12 -0
- data/lib/qml/platform.rb +15 -0
- data/lib/qml/plugin_loader.rb +46 -0
- data/lib/qml/plugins.rb +26 -0
- data/lib/qml/qml.rb +1 -0
- data/lib/qml/qt.rb +6 -0
- data/lib/qml/qt_classes.rb +9 -0
- data/lib/qml/qt_object_base.rb +108 -0
- data/lib/qml/reactive.rb +8 -0
- data/lib/qml/reactive/bindable.rb +79 -0
- data/lib/qml/reactive/chained_signal.rb +25 -0
- data/lib/qml/reactive/error.rb +5 -0
- data/lib/qml/reactive/object.rb +278 -0
- data/lib/qml/reactive/property.rb +19 -0
- data/lib/qml/reactive/signal.rb +116 -0
- data/lib/qml/reactive/signal_spy.rb +27 -0
- data/lib/qml/reactive/signals/map_signal.rb +21 -0
- data/lib/qml/reactive/signals/merge_signal.rb +21 -0
- data/lib/qml/reactive/signals/select_signal.rb +21 -0
- data/lib/qml/reactive/simple_property.rb +17 -0
- data/lib/qml/reactive/unbound_property.rb +42 -0
- data/lib/qml/reactive/unbound_signal.rb +51 -0
- data/lib/qml/root_path.rb +3 -0
- data/lib/qml/test_util.rb +1 -0
- data/lib/qml/test_util/object_life_checker.rb +17 -0
- data/lib/qml/version.rb +3 -0
- data/lib/qml/wrappable.rb +9 -0
- data/qml.gemspec +28 -0
- data/spec/assets/testobj.qml +5 -0
- data/spec/qml/.access_spec.rb.swp +0 -0
- data/spec/qml/access_spec.rb +162 -0
- data/spec/qml/application_spec.rb +43 -0
- data/spec/qml/component_spec.rb +44 -0
- data/spec/qml/context_spec.rb +43 -0
- data/spec/qml/conversion_spec.rb +59 -0
- data/spec/qml/data/array_model_spec.rb +215 -0
- data/spec/qml/dispatchable_spec.rb +26 -0
- data/spec/qml/dispatcher_spec.rb +48 -0
- data/spec/qml/geometry/point_spec.rb +4 -0
- data/spec/qml/geometry/rectangle_spec.rb +4 -0
- data/spec/qml/geometry/size_spec.rb +4 -0
- data/spec/qml/plugin_loader_spec.rb +33 -0
- data/spec/qml/qt_object_base_spec.rb +119 -0
- data/spec/qml/reactive/object_spec.rb +273 -0
- data/spec/qml/reactive/property_spec.rb +70 -0
- data/spec/qml/reactive/signal_spec.rb +191 -0
- data/spec/qml/reactive/signal_spy_spec.rb +26 -0
- data/spec/qml/test_object_spec.rb +186 -0
- data/spec/qml_spec.rb +7 -0
- data/spec/spec_helper.rb +5 -0
- metadata +321 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
#include <QMetaObject>
|
|
3
|
+
#include <QVector>
|
|
4
|
+
#include <QHash>
|
|
5
|
+
#include <QVariant>
|
|
6
|
+
#include "common.h"
|
|
7
|
+
|
|
8
|
+
namespace RubyQml {
|
|
9
|
+
|
|
10
|
+
class ForeignClass;
|
|
11
|
+
class ForeignObject;
|
|
12
|
+
|
|
13
|
+
class ForeignMetaObject : public QMetaObject
|
|
14
|
+
{
|
|
15
|
+
public:
|
|
16
|
+
ForeignMetaObject(const SP<ForeignClass> &foreignClass, const SP<ForeignMetaObject> &superMetaObject = SP<ForeignMetaObject>());
|
|
17
|
+
|
|
18
|
+
int dynamicMetaCall(ForeignObject *obj, QMetaObject::Call call, int index, void **argv);
|
|
19
|
+
void emitSignal(ForeignObject *obj, std::size_t id, const QVariantList &args);
|
|
20
|
+
void dump();
|
|
21
|
+
|
|
22
|
+
private:
|
|
23
|
+
class StringPool;
|
|
24
|
+
|
|
25
|
+
void buildData();
|
|
26
|
+
QVector<uint> writeMetaData(StringPool &stringPool);
|
|
27
|
+
|
|
28
|
+
QVector<uint8_t> mStringData;
|
|
29
|
+
QVector<uint> mData;
|
|
30
|
+
|
|
31
|
+
SP<ForeignClass> mForeignClass;
|
|
32
|
+
SP<ForeignMetaObject> mSuperMetaObject;
|
|
33
|
+
|
|
34
|
+
QHash<std::size_t, int> mSignalIndexHash;
|
|
35
|
+
|
|
36
|
+
QList<std::size_t> mMethodIds;
|
|
37
|
+
QList<int> mMethodArities;
|
|
38
|
+
int mMethodCount;
|
|
39
|
+
int mSignalCount;
|
|
40
|
+
|
|
41
|
+
QList<std::size_t> mPropertySetterIds;
|
|
42
|
+
QList<std::size_t> mPropertyGetterIds;
|
|
43
|
+
int mPropertyCount;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
} // namespace RubyQml
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#include "foreignobject.h"
|
|
2
|
+
#include "foreignmetaobject.h"
|
|
3
|
+
|
|
4
|
+
namespace RubyQml {
|
|
5
|
+
|
|
6
|
+
ForeignObject::ForeignObject(const SP<ForeignMetaObject> &metaobj, QObject *parent) :
|
|
7
|
+
QObject(parent),
|
|
8
|
+
mMetaObject(metaobj)
|
|
9
|
+
{
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const QMetaObject *ForeignObject::metaObject() const
|
|
13
|
+
{
|
|
14
|
+
return mMetaObject.get();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
int ForeignObject::qt_metacall(QMetaObject::Call call, int index, void **argv)
|
|
18
|
+
{
|
|
19
|
+
return mMetaObject->dynamicMetaCall(this, call, index, argv);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
} // namespace RubyQml
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
#include <QObject>
|
|
3
|
+
#include "common.h"
|
|
4
|
+
|
|
5
|
+
namespace RubyQml {
|
|
6
|
+
|
|
7
|
+
class ForeignMetaObject;
|
|
8
|
+
|
|
9
|
+
class ForeignObject : public QObject
|
|
10
|
+
{
|
|
11
|
+
public:
|
|
12
|
+
explicit ForeignObject(const SP<ForeignMetaObject> &mMetaObject, QObject *parent = 0);
|
|
13
|
+
|
|
14
|
+
const QMetaObject *metaObject() const override;
|
|
15
|
+
int qt_metacall(QMetaObject::Call call, int index, void **argv) override;
|
|
16
|
+
|
|
17
|
+
private:
|
|
18
|
+
SP<ForeignMetaObject> mMetaObject;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
} // namespace RubyQml
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
namespace RubyQml {
|
|
4
|
+
|
|
5
|
+
template <typename TFunction, TFunction function>
|
|
6
|
+
struct FunctionInfo {};
|
|
7
|
+
|
|
8
|
+
#define RUBYQML_FUNCTION_INFO(func) FunctionInfo<decltype(func), func>()
|
|
9
|
+
|
|
10
|
+
template <typename TMemberFunction, TMemberFunction memberFunction>
|
|
11
|
+
struct MemberFunctionInfo {};
|
|
12
|
+
|
|
13
|
+
#define RUBYQML_MEMBER_FUNCTION_INFO(memfn) MemberFunctionInfo<decltype(memfn), memfn>()
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
} // namespace RubyQml
|
data/ext/qml/init.cpp
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
#include "ext_metaobject.h"
|
|
2
|
+
#include "ext_pointer.h"
|
|
3
|
+
#include "ext_pluginloader.h"
|
|
4
|
+
#include "ext_gcmarker.h"
|
|
5
|
+
#include "ext_accesssupport.h"
|
|
6
|
+
#include "ext_testutil.h"
|
|
7
|
+
#include "ext_kernel.h"
|
|
8
|
+
#include "application.h"
|
|
9
|
+
#include "signalforwarder.h"
|
|
10
|
+
#include "valuereference.h"
|
|
11
|
+
#include "objectgc.h"
|
|
12
|
+
#include "listmodel.h"
|
|
13
|
+
#include <QtCore/QSet>
|
|
14
|
+
|
|
15
|
+
using namespace RubyQml;
|
|
16
|
+
|
|
17
|
+
namespace {
|
|
18
|
+
|
|
19
|
+
void defineMetaTypes()
|
|
20
|
+
{
|
|
21
|
+
qRegisterMetaType<const QMetaObject *>();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
void defineClasses()
|
|
25
|
+
{
|
|
26
|
+
Ext::MetaObject::defineClass();
|
|
27
|
+
Ext::Pointer::defineClass();
|
|
28
|
+
Ext::PluginLoader::defineClass();
|
|
29
|
+
Ext::GCMarker::defineClass();
|
|
30
|
+
Ext::AccessWrapperFactory::defineClass();
|
|
31
|
+
Ext::TestUtil::defineModule();
|
|
32
|
+
Ext::Kernel::defineModule();
|
|
33
|
+
ListModel::defineUtilMethods();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
void setupGlobalGCMarking()
|
|
37
|
+
{
|
|
38
|
+
auto marker = Ext::GCMarker::fromMarkFunction([] {
|
|
39
|
+
ValueReference::markAllReferences();
|
|
40
|
+
ObjectGC::instance()->markNonOwnedObjects();
|
|
41
|
+
});
|
|
42
|
+
rb_gc_register_mark_object(marker);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
void cleanup()
|
|
46
|
+
{
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
void setupEndProc()
|
|
50
|
+
{
|
|
51
|
+
rb_set_end_proc([](VALUE) { unprotect(cleanup); }, Qnil);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
extern "C"
|
|
57
|
+
void Init_qml()
|
|
58
|
+
{
|
|
59
|
+
rb_require("date");
|
|
60
|
+
rb_require("qml/errors");
|
|
61
|
+
rb_require("qml/error_converter");
|
|
62
|
+
|
|
63
|
+
unprotect([&] {
|
|
64
|
+
defineMetaTypes();
|
|
65
|
+
defineClasses();
|
|
66
|
+
setupGlobalGCMarking();
|
|
67
|
+
setupEndProc();
|
|
68
|
+
});
|
|
69
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
#include "listmodel.h"
|
|
2
|
+
#include "rubyclass.h"
|
|
3
|
+
#include <QMetaObject>
|
|
4
|
+
#include <QMetaMethod>
|
|
5
|
+
|
|
6
|
+
namespace RubyQml {
|
|
7
|
+
|
|
8
|
+
ListModel::ListModel(RubyValue rubyModel, QObject *parent) :
|
|
9
|
+
QAbstractListModel(parent),
|
|
10
|
+
mRubyModel(rubyModel)
|
|
11
|
+
{
|
|
12
|
+
auto columns = rubyModel.send("class").send("columns").to<QList<QByteArray>>();
|
|
13
|
+
for (int i = 0; i < columns.size(); ++i) {
|
|
14
|
+
auto role = Qt::UserRole + i;
|
|
15
|
+
mColumnNames[role] = columns[i];
|
|
16
|
+
mColumnIDs[role] = rb_intern(columns[i]);
|
|
17
|
+
}
|
|
18
|
+
rubyModel.send("qt_models").send("push", RubyValue::fromQObject(this, false));
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
ListModel::~ListModel()
|
|
22
|
+
{
|
|
23
|
+
mRubyModel.send("qt_models").send("delete", RubyValue::fromQObject(this, false));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
QHash<int, QByteArray> ListModel::roleNames() const
|
|
27
|
+
{
|
|
28
|
+
return mColumnNames;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
QVariant ListModel::data(const QModelIndex &index, int role) const
|
|
32
|
+
{
|
|
33
|
+
if (!index.isValid()) {
|
|
34
|
+
return QVariant();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return mRubyModel.send("[]", RubyValue::from(index.row())).send("[]", RubyValue::fromID(mColumnIDs[role])).to<QVariant>();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
int ListModel::rowCount(const QModelIndex &parent) const
|
|
41
|
+
{
|
|
42
|
+
if (parent.isValid()) {
|
|
43
|
+
return 0;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return mRubyModel.send("count").to<int>();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
QModelIndex ListModel::index(int row, int column, const QModelIndex &parent) const
|
|
50
|
+
{
|
|
51
|
+
if (parent.isValid()) {
|
|
52
|
+
return QModelIndex();
|
|
53
|
+
}
|
|
54
|
+
return createIndex(row, column);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
void ListModel::beginMove(int first, int last, int destination)
|
|
58
|
+
{
|
|
59
|
+
beginMoveRows(QModelIndex(), first, last ,QModelIndex(), destination);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
void ListModel::endMove()
|
|
63
|
+
{
|
|
64
|
+
endMoveRows();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
void ListModel::beginInsert(int first, int last)
|
|
68
|
+
{
|
|
69
|
+
beginInsertRows(QModelIndex(), first, last);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
void ListModel::endInsert()
|
|
73
|
+
{
|
|
74
|
+
endInsertRows();
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
void ListModel::beginRemove(int first, int last)
|
|
78
|
+
{
|
|
79
|
+
beginRemoveRows(QModelIndex(), first, last);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
void ListModel::endRemove()
|
|
83
|
+
{
|
|
84
|
+
endRemoveRows();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
void ListModel::update(int first, int last)
|
|
88
|
+
{
|
|
89
|
+
emit dataChanged(index(first), index(last));
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
void ListModel::gc_mark()
|
|
93
|
+
{
|
|
94
|
+
rb_gc_mark(mRubyModel);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
namespace {
|
|
98
|
+
|
|
99
|
+
RubyValue createWrapper(RubyValue self)
|
|
100
|
+
{
|
|
101
|
+
return RubyValue::fromQObject(new ListModel(self), false);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
void ListModel::defineUtilMethods()
|
|
107
|
+
{
|
|
108
|
+
auto klass = RubyClass(RubyModule(RubyModule("QML"), "Data"), "ListModel");
|
|
109
|
+
klass.defineMethod("create_wrapper", RUBYQML_FUNCTION_INFO(&createWrapper));
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
} // namespace RubyQml
|
data/ext/qml/listmodel.h
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include "markable.h"
|
|
4
|
+
#include "rubyvalue.h"
|
|
5
|
+
#include <QAbstractListModel>
|
|
6
|
+
|
|
7
|
+
namespace RubyQml {
|
|
8
|
+
|
|
9
|
+
class ListModel : public QAbstractListModel, public Markable
|
|
10
|
+
{
|
|
11
|
+
Q_OBJECT
|
|
12
|
+
public:
|
|
13
|
+
explicit ListModel(RubyValue rubyModel, QObject *parent = 0);
|
|
14
|
+
~ListModel();
|
|
15
|
+
|
|
16
|
+
RubyValue rubyModel() { return mRubyModel; }
|
|
17
|
+
|
|
18
|
+
QHash<int, QByteArray> roleNames() const override;
|
|
19
|
+
|
|
20
|
+
QVariant data(const QModelIndex &index, int role) const override;
|
|
21
|
+
int rowCount(const QModelIndex &parent) const override;
|
|
22
|
+
QModelIndex index(int row, int column = 0, const QModelIndex &parent = QModelIndex()) const override;
|
|
23
|
+
|
|
24
|
+
void gc_mark() override;
|
|
25
|
+
|
|
26
|
+
static void defineUtilMethods();
|
|
27
|
+
|
|
28
|
+
public slots:
|
|
29
|
+
void beginMove(int first, int last, int destination);
|
|
30
|
+
void endMove();
|
|
31
|
+
void beginInsert(int first, int last);
|
|
32
|
+
void endInsert();
|
|
33
|
+
void beginRemove(int first, int last);
|
|
34
|
+
void endRemove();
|
|
35
|
+
void update(int first, int last);
|
|
36
|
+
|
|
37
|
+
private:
|
|
38
|
+
RubyValue mRubyModel;
|
|
39
|
+
QHash<int, QByteArray> mColumnNames;
|
|
40
|
+
QHash<int, ID> mColumnIDs;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
} // namespace RubyQml
|
data/ext/qml/markable.h
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#include "objectdata.h"
|
|
2
|
+
|
|
3
|
+
namespace RubyQml {
|
|
4
|
+
|
|
5
|
+
ObjectData::ObjectData(QObject *target) :
|
|
6
|
+
QObject(target)
|
|
7
|
+
{
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
ObjectData *ObjectData::getOrCreate(QObject *target)
|
|
11
|
+
{
|
|
12
|
+
for (auto child : target->children()) {
|
|
13
|
+
auto data = dynamic_cast<ObjectData *>(child);
|
|
14
|
+
if (data) {
|
|
15
|
+
return data;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return new ObjectData(target);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
void ObjectData::gc_mark()
|
|
22
|
+
{
|
|
23
|
+
rb_gc_mark(rubyObject);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
} // namespace RubyQml
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
#include <QObject>
|
|
3
|
+
#include "rubyvalue.h"
|
|
4
|
+
#include "markable.h"
|
|
5
|
+
|
|
6
|
+
namespace RubyQml {
|
|
7
|
+
|
|
8
|
+
class ObjectData : public QObject, public Markable
|
|
9
|
+
{
|
|
10
|
+
public:
|
|
11
|
+
ObjectData(QObject *target);
|
|
12
|
+
RubyValue rubyObject;
|
|
13
|
+
bool owned = false;
|
|
14
|
+
|
|
15
|
+
void gc_mark() override;
|
|
16
|
+
|
|
17
|
+
static ObjectData *getOrCreate(QObject *target);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
} // namespace RubyQml
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
#include "objectgc.h"
|
|
2
|
+
#include "markable.h"
|
|
3
|
+
#include "objectdata.h"
|
|
4
|
+
#include <QObject>
|
|
5
|
+
#include <QDebug>
|
|
6
|
+
#include <QBuffer>
|
|
7
|
+
|
|
8
|
+
namespace RubyQml {
|
|
9
|
+
|
|
10
|
+
void ObjectGC::addObject(QObject *obj)
|
|
11
|
+
{
|
|
12
|
+
mObjects << obj;
|
|
13
|
+
connect(obj, &QObject::destroyed, this, [this](QObject *obj) {
|
|
14
|
+
mObjects.remove(obj);
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
void ObjectGC::mark(QObject *obj, bool markOwned)
|
|
19
|
+
{
|
|
20
|
+
auto objData = dynamic_cast<ObjectData *>(obj);
|
|
21
|
+
if (!markOwned) {
|
|
22
|
+
if (objData && objData->owned) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
auto markable = dynamic_cast<Markable *>(obj);
|
|
28
|
+
if (markable) {
|
|
29
|
+
debug() << "\u270F\uFE0F marking object:" << obj << "parent:" << obj->parent();
|
|
30
|
+
markable->gc_mark();
|
|
31
|
+
}
|
|
32
|
+
for (auto child : obj->children()) {
|
|
33
|
+
mark(child, markOwned);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
void ObjectGC::markOwnedObject(QObject *obj)
|
|
38
|
+
{
|
|
39
|
+
mark(obj, true);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
void ObjectGC::markNonOwnedObjects()
|
|
43
|
+
{
|
|
44
|
+
for (auto obj : mObjects) {
|
|
45
|
+
mark(obj, false);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
QDebug ObjectGC::debug()
|
|
50
|
+
{
|
|
51
|
+
static auto emptyBuffer = [] {
|
|
52
|
+
auto buf = new QBuffer();
|
|
53
|
+
buf->open(QIODevice::WriteOnly);
|
|
54
|
+
return buf;
|
|
55
|
+
}();
|
|
56
|
+
if (mDebugMessageEnabled) {
|
|
57
|
+
return qDebug();
|
|
58
|
+
} else {
|
|
59
|
+
return QDebug(emptyBuffer);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
ObjectGC *ObjectGC::instance()
|
|
64
|
+
{
|
|
65
|
+
static auto gc = new ObjectGC();
|
|
66
|
+
return gc;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
} // namespace RubyQml
|