qml 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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