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.
Files changed (170) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +46 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +15 -0
  5. data/.yardopts +4 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +351 -0
  9. data/Rakefile +6 -0
  10. data/examples/assets/fonts/fontawesome-webfont.ttf +0 -0
  11. data/examples/fizzbuzz/fizzbuzz.rb +43 -0
  12. data/examples/fizzbuzz/main.qml +38 -0
  13. data/examples/imageprovider/imageprovider.rb +57 -0
  14. data/examples/imageprovider/main.qml +51 -0
  15. data/examples/todo/main.qml +70 -0
  16. data/examples/todo/todo.rb +36 -0
  17. data/examples/twitter/main.qml +36 -0
  18. data/examples/twitter/twitter.rb +55 -0
  19. data/ext/qml/accessclass.cpp +71 -0
  20. data/ext/qml/accessclass.h +19 -0
  21. data/ext/qml/accessobject.cpp +30 -0
  22. data/ext/qml/accessobject.h +22 -0
  23. data/ext/qml/application.cpp +54 -0
  24. data/ext/qml/application.h +17 -0
  25. data/ext/qml/common.h +18 -0
  26. data/ext/qml/ext_accesssupport.cpp +77 -0
  27. data/ext/qml/ext_accesssupport.h +42 -0
  28. data/ext/qml/ext_gcmarker.cpp +39 -0
  29. data/ext/qml/ext_gcmarker.h +27 -0
  30. data/ext/qml/ext_kernel.cpp +62 -0
  31. data/ext/qml/ext_kernel.h +11 -0
  32. data/ext/qml/ext_metaobject.cpp +410 -0
  33. data/ext/qml/ext_metaobject.h +62 -0
  34. data/ext/qml/ext_pluginloader.cpp +55 -0
  35. data/ext/qml/ext_pluginloader.h +32 -0
  36. data/ext/qml/ext_pointer.cpp +134 -0
  37. data/ext/qml/ext_pointer.h +43 -0
  38. data/ext/qml/ext_testutil.cpp +42 -0
  39. data/ext/qml/ext_testutil.h +11 -0
  40. data/ext/qml/extconf.rb +84 -0
  41. data/ext/qml/foreignclass.cpp +72 -0
  42. data/ext/qml/foreignclass.h +88 -0
  43. data/ext/qml/foreignmetaobject.cpp +345 -0
  44. data/ext/qml/foreignmetaobject.h +46 -0
  45. data/ext/qml/foreignobject.cpp +22 -0
  46. data/ext/qml/foreignobject.h +21 -0
  47. data/ext/qml/functioninfo.h +16 -0
  48. data/ext/qml/init.cpp +69 -0
  49. data/ext/qml/listmodel.cpp +112 -0
  50. data/ext/qml/listmodel.h +43 -0
  51. data/ext/qml/markable.h +12 -0
  52. data/ext/qml/objectdata.cpp +26 -0
  53. data/ext/qml/objectdata.h +20 -0
  54. data/ext/qml/objectgc.cpp +69 -0
  55. data/ext/qml/objectgc.h +28 -0
  56. data/ext/qml/plugins/core/applicationextension.cpp +34 -0
  57. data/ext/qml/plugins/core/applicationextension.h +28 -0
  58. data/ext/qml/plugins/core/componentextension.cpp +41 -0
  59. data/ext/qml/plugins/core/componentextension.h +28 -0
  60. data/ext/qml/plugins/core/contextextension.cpp +39 -0
  61. data/ext/qml/plugins/core/contextextension.h +29 -0
  62. data/ext/qml/plugins/core/core.pro +29 -0
  63. data/ext/qml/plugins/core/coreplugin.cpp +87 -0
  64. data/ext/qml/plugins/core/coreplugin.h +49 -0
  65. data/ext/qml/plugins/core/engineextension.cpp +27 -0
  66. data/ext/qml/plugins/core/engineextension.h +28 -0
  67. data/ext/qml/plugins/core/imageprovider.cpp +38 -0
  68. data/ext/qml/plugins/core/imageprovider.h +18 -0
  69. data/ext/qml/plugins/core/imagerequestpromise.cpp +19 -0
  70. data/ext/qml/plugins/core/imagerequestpromise.h +21 -0
  71. data/ext/qml/plugins/core/qmlexception.cpp +11 -0
  72. data/ext/qml/plugins/core/qmlexception.h +17 -0
  73. data/ext/qml/plugins/testutil/objectlifechecker.cpp +17 -0
  74. data/ext/qml/plugins/testutil/objectlifechecker.h +24 -0
  75. data/ext/qml/plugins/testutil/ownershiptest.cpp +26 -0
  76. data/ext/qml/plugins/testutil/ownershiptest.h +30 -0
  77. data/ext/qml/plugins/testutil/testobject.cpp +6 -0
  78. data/ext/qml/plugins/testutil/testobject.h +108 -0
  79. data/ext/qml/plugins/testutil/testobjectsubclass.cpp +10 -0
  80. data/ext/qml/plugins/testutil/testobjectsubclass.h +19 -0
  81. data/ext/qml/plugins/testutil/testutil.pro +20 -0
  82. data/ext/qml/plugins/testutil/testutilplugin.cpp +47 -0
  83. data/ext/qml/plugins/testutil/testutilplugin.h +32 -0
  84. data/ext/qml/qmltyperegisterer.cpp +74 -0
  85. data/ext/qml/qmltyperegisterer.h +30 -0
  86. data/ext/qml/rubyclass.cpp +94 -0
  87. data/ext/qml/rubyclass.h +234 -0
  88. data/ext/qml/rubyvalue.cpp +690 -0
  89. data/ext/qml/rubyvalue.h +256 -0
  90. data/ext/qml/signalforwarder.cpp +66 -0
  91. data/ext/qml/signalforwarder.h +29 -0
  92. data/ext/qml/util.cpp +120 -0
  93. data/ext/qml/util.h +101 -0
  94. data/ext/qml/valuereference.cpp +50 -0
  95. data/ext/qml/valuereference.h +22 -0
  96. data/ext/qml/weakvaluereference.cpp +27 -0
  97. data/ext/qml/weakvaluereference.h +19 -0
  98. data/lib/qml.rb +41 -0
  99. data/lib/qml/access.rb +137 -0
  100. data/lib/qml/application.rb +139 -0
  101. data/lib/qml/class_builder.rb +126 -0
  102. data/lib/qml/component.rb +53 -0
  103. data/lib/qml/context.rb +71 -0
  104. data/lib/qml/data.rb +2 -0
  105. data/lib/qml/data/array_model.rb +103 -0
  106. data/lib/qml/data/error.rb +5 -0
  107. data/lib/qml/data/list_model.rb +146 -0
  108. data/lib/qml/dispatchable.rb +34 -0
  109. data/lib/qml/dispatcher.rb +61 -0
  110. data/lib/qml/engine.rb +54 -0
  111. data/lib/qml/error_converter.rb +15 -0
  112. data/lib/qml/errors.rb +26 -0
  113. data/lib/qml/geometry.rb +3 -0
  114. data/lib/qml/geometry/point.rb +5 -0
  115. data/lib/qml/geometry/rectangle.rb +5 -0
  116. data/lib/qml/geometry/size.rb +5 -0
  117. data/lib/qml/image_provider.rb +87 -0
  118. data/lib/qml/meta_object.rb +20 -0
  119. data/lib/qml/models.rb +1 -0
  120. data/lib/qml/name_helper.rb +12 -0
  121. data/lib/qml/platform.rb +15 -0
  122. data/lib/qml/plugin_loader.rb +46 -0
  123. data/lib/qml/plugins.rb +26 -0
  124. data/lib/qml/qml.rb +1 -0
  125. data/lib/qml/qt.rb +6 -0
  126. data/lib/qml/qt_classes.rb +9 -0
  127. data/lib/qml/qt_object_base.rb +108 -0
  128. data/lib/qml/reactive.rb +8 -0
  129. data/lib/qml/reactive/bindable.rb +79 -0
  130. data/lib/qml/reactive/chained_signal.rb +25 -0
  131. data/lib/qml/reactive/error.rb +5 -0
  132. data/lib/qml/reactive/object.rb +278 -0
  133. data/lib/qml/reactive/property.rb +19 -0
  134. data/lib/qml/reactive/signal.rb +116 -0
  135. data/lib/qml/reactive/signal_spy.rb +27 -0
  136. data/lib/qml/reactive/signals/map_signal.rb +21 -0
  137. data/lib/qml/reactive/signals/merge_signal.rb +21 -0
  138. data/lib/qml/reactive/signals/select_signal.rb +21 -0
  139. data/lib/qml/reactive/simple_property.rb +17 -0
  140. data/lib/qml/reactive/unbound_property.rb +42 -0
  141. data/lib/qml/reactive/unbound_signal.rb +51 -0
  142. data/lib/qml/root_path.rb +3 -0
  143. data/lib/qml/test_util.rb +1 -0
  144. data/lib/qml/test_util/object_life_checker.rb +17 -0
  145. data/lib/qml/version.rb +3 -0
  146. data/lib/qml/wrappable.rb +9 -0
  147. data/qml.gemspec +28 -0
  148. data/spec/assets/testobj.qml +5 -0
  149. data/spec/qml/.access_spec.rb.swp +0 -0
  150. data/spec/qml/access_spec.rb +162 -0
  151. data/spec/qml/application_spec.rb +43 -0
  152. data/spec/qml/component_spec.rb +44 -0
  153. data/spec/qml/context_spec.rb +43 -0
  154. data/spec/qml/conversion_spec.rb +59 -0
  155. data/spec/qml/data/array_model_spec.rb +215 -0
  156. data/spec/qml/dispatchable_spec.rb +26 -0
  157. data/spec/qml/dispatcher_spec.rb +48 -0
  158. data/spec/qml/geometry/point_spec.rb +4 -0
  159. data/spec/qml/geometry/rectangle_spec.rb +4 -0
  160. data/spec/qml/geometry/size_spec.rb +4 -0
  161. data/spec/qml/plugin_loader_spec.rb +33 -0
  162. data/spec/qml/qt_object_base_spec.rb +119 -0
  163. data/spec/qml/reactive/object_spec.rb +273 -0
  164. data/spec/qml/reactive/property_spec.rb +70 -0
  165. data/spec/qml/reactive/signal_spec.rb +191 -0
  166. data/spec/qml/reactive/signal_spy_spec.rb +26 -0
  167. data/spec/qml/test_object_spec.rb +186 -0
  168. data/spec/qml_spec.rb +7 -0
  169. data/spec/spec_helper.rb +5 -0
  170. metadata +321 -0
@@ -0,0 +1,62 @@
1
+ #pragma once
2
+
3
+ #include "rubyvalue.h"
4
+ #include <QtCore/QMetaObject>
5
+ #include <QtCore/QVector>
6
+ #include <QtCore/QHash>
7
+ #include <QtCore/QObject>
8
+
9
+ namespace RubyQml {
10
+ namespace Ext {
11
+
12
+ class MetaObject
13
+ {
14
+ public:
15
+ MetaObject(RubyValue self);
16
+
17
+ RubyValue className() const;
18
+
19
+ RubyValue methodNames() const;
20
+ RubyValue isPublic(RubyValue name) const;
21
+ RubyValue isProtected(RubyValue name) const;
22
+ RubyValue isPrivate(RubyValue name) const;
23
+ RubyValue isSignal(RubyValue name) const;
24
+
25
+ RubyValue invokeMethod(RubyValue object, RubyValue methodName, RubyValue args) const;
26
+ RubyValue connectSignal(RubyValue object, RubyValue signalName, RubyValue proc) const;
27
+
28
+ RubyValue propertyNames() const;
29
+ RubyValue getProperty(RubyValue object, RubyValue name) const;
30
+ RubyValue setProperty(RubyValue object, RubyValue name, RubyValue newValue) const;
31
+ RubyValue notifySignal(RubyValue name) const;
32
+
33
+ RubyValue enumerators() const;
34
+
35
+ RubyValue superClass() const;
36
+
37
+ RubyValue isEqual(RubyValue other) const;
38
+ RubyValue hash() const;
39
+
40
+ void setMetaObject(const QMetaObject *metaObject);
41
+ const QMetaObject *metaObject() const { return mMetaObject; }
42
+
43
+ void gc_mark() {}
44
+
45
+ static RubyValue fromMetaObject(const QMetaObject *metaObject);
46
+ static void defineClass();
47
+
48
+ private:
49
+ void checkThread() const;
50
+
51
+ QList<int> findMethods(RubyValue name) const;
52
+ int findProperty(RubyValue name) const;
53
+
54
+ const RubyValue self;
55
+
56
+ const QMetaObject *mMetaObject = nullptr;
57
+ QMultiHash<ID, int> mMethodHash;
58
+ QHash<ID, int> mPropertyHash;
59
+ };
60
+
61
+ } // namespace Ext
62
+ } // namespace RubyQml
@@ -0,0 +1,55 @@
1
+ #include "ext_pluginloader.h"
2
+ #include "ext_pointer.h"
3
+ #include "rubyclass.h"
4
+ #include <QtCore/QPluginLoader>
5
+ #include <QtCore/QSet>
6
+
7
+ namespace RubyQml {
8
+ namespace Ext {
9
+
10
+ PluginLoader::PluginLoader(RubyValue self) :
11
+ self(self),
12
+ mPluginLoader(new QPluginLoader())
13
+ {
14
+ }
15
+
16
+ PluginLoader::~PluginLoader()
17
+ {
18
+ }
19
+
20
+ RubyValue PluginLoader::initialize(RubyValue path)
21
+ {
22
+ mPluginLoader->setFileName(path.to<QString>());
23
+ return self;
24
+ }
25
+
26
+ RubyValue PluginLoader::load()
27
+ {
28
+ auto ok = mPluginLoader->load();
29
+ if (!ok) {
30
+ fail("QML::PluginError", mPluginLoader->errorString());
31
+ }
32
+ return self;
33
+ }
34
+
35
+ RubyValue PluginLoader::instance()
36
+ {
37
+ self.send("load");
38
+ auto instance = mPluginLoader->instance();
39
+ if (instance) {
40
+ return RubyValue::from(instance);
41
+ } else {
42
+ return Qnil;
43
+ }
44
+ }
45
+
46
+ void PluginLoader::defineClass()
47
+ {
48
+ WrapperRubyClass<PluginLoader> klass(RubyModule::fromPath("QML"), "PluginLoader");
49
+ klass.defineMethod(MethodAccess::Private, "initialize", RUBYQML_MEMBER_FUNCTION_INFO(&PluginLoader::initialize));
50
+ klass.defineMethod(MethodAccess::Public, "load", RUBYQML_MEMBER_FUNCTION_INFO(&PluginLoader::load));
51
+ klass.defineMethod(MethodAccess::Public, "instance", RUBYQML_MEMBER_FUNCTION_INFO(&PluginLoader::instance));
52
+ }
53
+
54
+ } // namespace Ext
55
+ } // namespace RubyQml
@@ -0,0 +1,32 @@
1
+ #pragma once
2
+
3
+ #include "rubyvalue.h"
4
+ #include <memory>
5
+
6
+ class QPluginLoader;
7
+
8
+ namespace RubyQml {
9
+ namespace Ext {
10
+
11
+ class PluginLoader
12
+ {
13
+ public:
14
+ PluginLoader(RubyValue self);
15
+ ~PluginLoader();
16
+
17
+ RubyValue initialize(RubyValue path);
18
+ RubyValue load();
19
+ RubyValue instance();
20
+
21
+ void gc_mark() {}
22
+
23
+ static void defineClass();
24
+
25
+ private:
26
+ const RubyValue self;
27
+ std::unique_ptr<QPluginLoader> mPluginLoader;
28
+ };
29
+
30
+ } // namespace Ext
31
+ } // namespace RubyQml
32
+
@@ -0,0 +1,134 @@
1
+ #include "ext_pointer.h"
2
+ #include "markable.h"
3
+ #include "objectdata.h"
4
+ #include "objectgc.h"
5
+ #include "application.h"
6
+ #include <QObject>
7
+ #include <QHash>
8
+ #include <QQmlEngine>
9
+ #include <QQmlContext>
10
+ #include <QDebug>
11
+ #include <QCoreApplication>
12
+
13
+ namespace RubyQml {
14
+ namespace Ext {
15
+
16
+ Pointer::Pointer(RubyValue self) :
17
+ self(self)
18
+ {
19
+ }
20
+
21
+ Pointer::~Pointer()
22
+ {
23
+ ObjectGC::instance()->debug() << "\u267B\uFE0F releasing object:" << mObject << "managed:" << mIsManaged;
24
+ }
25
+
26
+ RubyValue Pointer::fromQObject(QObject *obj, bool owned)
27
+ {
28
+ auto klass = wrapperRubyClass<Pointer>();
29
+ auto ptr = klass.newInstance();
30
+ klass.unwrap(ptr)->setQObject(obj, owned);
31
+ return ptr;
32
+ }
33
+
34
+ QObject *Pointer::fetchQObject()
35
+ {
36
+ if (!mObject) {
37
+ fail("QML::QtObjectError", "referencing already deleted Qt Object");
38
+ }
39
+ return mObject;
40
+ }
41
+
42
+ void Pointer::setQObject(QObject *obj, bool managed)
43
+ {
44
+ if (!obj) {
45
+ throw std::logic_error("null object");
46
+ }
47
+ mObject = obj;
48
+ ObjectGC::instance()->addObject(obj);
49
+
50
+ preferManaged(managed);
51
+ ObjectGC::instance()->debug() << "\u2728 acquiring object:" << mObject;
52
+ }
53
+
54
+ void Pointer::setManaged(bool managed)
55
+ {
56
+ if (mObject) {
57
+ if (managed) {
58
+ QQmlEngine::setObjectOwnership(mObject, QQmlEngine::JavaScriptOwnership);
59
+ mJSValue = Application::engine()->newQObject(mObject);
60
+ } else {
61
+ QQmlEngine::setObjectOwnership(mObject, QQmlEngine::CppOwnership);
62
+ mJSValue = QJSValue();
63
+ }
64
+
65
+ ObjectData::getOrCreate(mObject)->owned = managed;
66
+ mIsManaged = managed;
67
+ }
68
+ }
69
+
70
+ void Pointer::preferManaged(bool managed)
71
+ {
72
+ auto ownership = QQmlEngine::objectOwnership(mObject);
73
+
74
+ if (ownership == QQmlEngine::JavaScriptOwnership) {
75
+ managed = true;
76
+ } else {
77
+ // owned by parent
78
+ if (mObject->parent()) {
79
+ managed = false;
80
+ }
81
+ }
82
+
83
+ setManaged(managed);
84
+ }
85
+
86
+ RubyValue Pointer::ext_isManaged() const
87
+ {
88
+ return RubyValue::from(mIsManaged);
89
+ }
90
+
91
+ RubyValue Pointer::ext_setManaged(RubyValue managed)
92
+ {
93
+ setManaged(managed.to<bool>());
94
+ return ext_isManaged();
95
+ }
96
+
97
+ RubyValue Pointer::ext_preferManaged(RubyValue managed)
98
+ {
99
+ preferManaged(managed.to<bool>());
100
+ return ext_isManaged();
101
+ }
102
+
103
+ RubyValue Pointer::ext_isNull() const
104
+ {
105
+ return RubyValue::from(!mObject);
106
+ }
107
+
108
+ RubyValue Pointer::ext_toString() const
109
+ {
110
+ QString name;
111
+ QDebug(&name) << mObject.data();
112
+ return RubyValue::from(name);
113
+ }
114
+
115
+ void Pointer::gc_mark()
116
+ {
117
+ if (mIsManaged) {
118
+ ObjectGC::instance()->markOwnedObject(mObject);
119
+ }
120
+ }
121
+
122
+ void Pointer::defineClass()
123
+ {
124
+ WrapperRubyClass<Pointer> klass(RubyModule::fromPath("QML"), "Pointer");
125
+ klass.defineMethod("managed?", RUBYQML_MEMBER_FUNCTION_INFO(&Pointer::ext_isManaged));
126
+ klass.defineMethod("managed=", RUBYQML_MEMBER_FUNCTION_INFO(&Pointer::ext_setManaged));
127
+ klass.defineMethod("prefer_managed", RUBYQML_MEMBER_FUNCTION_INFO(&Pointer::ext_preferManaged));
128
+ klass.defineMethod("null?", RUBYQML_MEMBER_FUNCTION_INFO(&Pointer::ext_isNull));
129
+ klass.defineMethod("to_s", RUBYQML_MEMBER_FUNCTION_INFO(&Pointer::ext_toString));
130
+ klass.aliasMethod("inspect", "to_s");
131
+ }
132
+
133
+ } // namespace Ext
134
+ } // namespace RubyQml
@@ -0,0 +1,43 @@
1
+ #pragma once
2
+ #include "rubyclass.h"
3
+ #include <QPointer>
4
+ #include <QJSValue>
5
+
6
+ namespace RubyQml {
7
+ namespace Ext {
8
+
9
+ class Pointer
10
+ {
11
+ public:
12
+ Pointer(RubyValue self);
13
+ ~Pointer();
14
+
15
+ static RubyValue fromQObject(QObject *obj, bool owned);
16
+
17
+ QObject *qObject() { return mObject; }
18
+ QObject *fetchQObject();
19
+ void setQObject(QObject *obj, bool managed);
20
+ bool isManaged() const { return mIsManaged; }
21
+ void setManaged(bool managed);
22
+ void preferManaged(bool managed);
23
+
24
+ RubyValue ext_isManaged() const;
25
+ RubyValue ext_setManaged(RubyValue managed);
26
+ RubyValue ext_preferManaged(RubyValue managed);
27
+ RubyValue ext_isNull() const;
28
+ RubyValue ext_toString() const;
29
+
30
+ void gc_mark();
31
+
32
+ static void defineClass();
33
+
34
+ private:
35
+ const RubyValue self;
36
+
37
+ bool mIsManaged = false;
38
+ QPointer<QObject> mObject;
39
+ QJSValue mJSValue;
40
+ };
41
+
42
+ } // namespace Ext
43
+ } // namespace RubyQml
@@ -0,0 +1,42 @@
1
+ #include "ext_testutil.h"
2
+ #include "rubyclass.h"
3
+ #include "objectgc.h"
4
+
5
+ namespace RubyQml {
6
+ namespace Ext {
7
+ namespace TestUtil {
8
+
9
+ namespace {
10
+
11
+ RubyValue echoConversion(RubyValue self, RubyValue value)
12
+ {
13
+ Q_UNUSED(self);
14
+ auto variant = RubyValue(value).to<QVariant>();
15
+ return RubyValue::from(variant);
16
+ }
17
+
18
+ RubyValue gcDebugMessageEnabled(RubyValue self)
19
+ {
20
+ Q_UNUSED(self);
21
+ return RubyValue::from(ObjectGC::instance()->debugMessageEnabled());
22
+ }
23
+
24
+ RubyValue setGCDebugMessageEnabled(RubyValue self, RubyValue enabled)
25
+ {
26
+ ObjectGC::instance()->setDebugMessageEnabled(enabled.to<bool>());
27
+ return gcDebugMessageEnabled(self);
28
+ }
29
+
30
+ }
31
+
32
+ void defineModule()
33
+ {
34
+ RubyModule testUtil(RubyModule::fromPath("QML"), "TestUtil");
35
+ testUtil.defineModuleFunction("echo_conversion", RUBYQML_FUNCTION_INFO(&echoConversion));
36
+ testUtil.defineModuleFunction("gc_debug_message_enabled?", RUBYQML_FUNCTION_INFO(&gcDebugMessageEnabled));
37
+ testUtil.defineModuleFunction("gc_debug_message_enabled=", RUBYQML_FUNCTION_INFO(&setGCDebugMessageEnabled));
38
+ }
39
+
40
+ } // namespace TestUtil
41
+ } // namespace Ext
42
+ } // namespace RubyQml
@@ -0,0 +1,11 @@
1
+ #pragma once
2
+
3
+ namespace RubyQml {
4
+ namespace Ext {
5
+ namespace TestUtil {
6
+
7
+ void defineModule();
8
+
9
+ } // namespace TestUtil
10
+ } // namespace Ext
11
+ } // namespace RubyQml
@@ -0,0 +1,84 @@
1
+ require 'mkmf'
2
+ require 'pathname'
3
+
4
+ class Configurator
5
+
6
+ PKGS = %w{Qt5Core Qt5Gui Qt5Widgets Qt5Qml Qt5Quick libffi}
7
+ HEADERS = %w{QObject QVariant QApplication QQmlEngine QQmlComponent QQmlContext ffi.h}
8
+ CLASSES = %w{listmodel}
9
+
10
+ def initialize
11
+ find_dependencies
12
+ @cppflags = []
13
+ @ldflags = []
14
+ end
15
+
16
+ def find_dependencies
17
+ @pkgconfig = with_config('pkg-config') || find_executable('pkg-config')
18
+ abort 'pkg-config executable not found' unless @pkgconfig
19
+
20
+ @qt_path = with_config('qt-dir')
21
+ @qt_path &&= Pathname(@qt_path).realpath
22
+
23
+ @ffi_path = with_config('libffi-dir')
24
+ @ffi_path &&= Pathname(@ffi_path).realpath
25
+
26
+ [@qt_path, @ffi_path].compact.each do |path|
27
+ ENV['PKG_CONFIG_PATH'] = "#{path + 'lib/pkgconfig'}:#{ENV['PKG_CONFIG_PATH']}"
28
+ end
29
+
30
+ @qmake = @qt_path ? @qt_path + 'bin/qmake' : find_executable('qmake')
31
+ @moc = @qt_path ? @qt_path + 'bin/moc' : find_executable('moc')
32
+ abort 'qmake executable not found' unless @qmake
33
+ abort 'moc executable not found' unless @moc
34
+ end
35
+
36
+ def build_plugins
37
+ puts "building plugins..."
38
+ Pathname(__FILE__).+("../plugins").children.select(&:directory?).each do |dir|
39
+ Dir.chdir(dir) do
40
+ system("#{@qmake}") && system('make') or abort "failed to build plugin: #{dir.basename}"
41
+ end
42
+ end
43
+ end
44
+
45
+ def configure_extension
46
+ RbConfig::CONFIG['CPP'].gsub!(RbConfig::CONFIG['CC'], RbConfig::CONFIG['CXX'])
47
+
48
+ PKGS.each do |mod|
49
+ @cppflags << `#{@pkgconfig} --cflags #{mod}`.chomp
50
+ @ldflags << `#{@pkgconfig} --libs #{mod}`.chomp
51
+ end
52
+
53
+ qtversion = `#{@pkgconfig} --modversion Qt5Core`.chomp
54
+ `#{@pkgconfig} --cflags-only-I Qt5Core`.split.map { |i| Pathname(i.gsub("-I", "")) }.each do |dir|
55
+ private_dir = dir + "#{qtversion}/QtCore"
56
+ @cppflags << "-I#{private_dir}" if private_dir.exist?
57
+ end
58
+
59
+ $CPPFLAGS += " #{@cppflags.join(" ")}"
60
+ $LDFLAGS += " #{@ldflags.join(" ")}"
61
+ $CPPFLAGS += " -fPIC"
62
+
63
+ HEADERS.each do |h|
64
+ abort "header not found: #{h}" unless have_header(h)
65
+ end
66
+
67
+ $CPPFLAGS += " -std=c++11 -Wall -Wextra -pipe"
68
+ if enable_config('debug')
69
+ $CPPFLAGS += " -O0 -ggdb3"
70
+ else
71
+ $CPPFLAGS += " -O3"
72
+ end
73
+
74
+ CLASSES.each do |header|
75
+ File.write("moc_#{header}.cpp", `#{@moc} #{header}.h`)
76
+ end
77
+
78
+ create_makefile 'qml/qml'
79
+ end
80
+ end
81
+
82
+ configurator = Configurator.new
83
+ configurator.build_plugins
84
+ configurator.configure_extension