qt 0.1.9 → 0.2.0
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 +4 -4
- data/ext/qt_ruby_bridge/extconf.rb +1 -0
- data/ext/qt_ruby_bridge/qt_ruby_runtime.hpp +6 -0
- data/ext/qt_ruby_bridge/runtime_events.cpp +8 -3
- data/ext/qt_ruby_bridge/runtime_value_types.cpp +22 -0
- data/lib/qt/event_runtime_dispatch.rb +2 -0
- data/lib/qt/value_wrapper.rb +26 -0
- data/lib/qt/version.rb +1 -1
- data/lib/qt.rb +1 -0
- data/scripts/generate_bridge/auto_methods.rb +39 -9
- data/scripts/generate_bridge/cpp_method_return_emitter.rb +60 -24
- data/scripts/generate_bridge/ffi_api.rb +16 -0
- data/scripts/generate_bridge/free_function_specs.rb +6 -1
- data/scripts/generate_bridge/spec_discovery.rb +2 -1
- data/scripts/generate_bridge.rb +36 -1
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c0e7757f47bb17be90f64d3bcdd28ba17e5e8099a505062a7e7c3dd71aaedf37
|
|
4
|
+
data.tar.gz: cbf55606a5a16e12cb4ef47b73756a1f3ef3b65c1e500583928a44a4d28b97c4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1e5e470938bc069179be121de52a5e2986479a7fa8dec030d743de246fef73812729bc57ea67d4958c076e42e8d23ef703c0931e51544f206352e3ba45a3c463
|
|
7
|
+
data.tar.gz: bc3d7083a9617ad49b2b139d0948bec69257ad5991be08525de8228e87aa3457bdd9d4d2745b399bf20f0266143428565e3fb5d88e039255687eb90b38c7efe9
|
|
@@ -60,6 +60,7 @@ runtime_hpp = File.expand_path('../../ext/qt_ruby_bridge/qt_ruby_runtime.hpp', _
|
|
|
60
60
|
runtime_cpp_files = %w[
|
|
61
61
|
runtime_events.cpp
|
|
62
62
|
runtime_signals.cpp
|
|
63
|
+
runtime_value_types.cpp
|
|
63
64
|
].map { |name| File.expand_path("../../ext/qt_ruby_bridge/#{name}", __dir__) }
|
|
64
65
|
|
|
65
66
|
unless File.exist?(generated_cpp)
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
#pragma once
|
|
2
2
|
|
|
3
3
|
#include <QApplication>
|
|
4
|
+
#include <QList>
|
|
5
|
+
#include <QVariant>
|
|
4
6
|
|
|
5
7
|
namespace QtRubyRuntime {
|
|
6
8
|
using EventCallback = int (*)(void*, int, const char*);
|
|
@@ -13,6 +15,10 @@ QApplication* qapplication_new(const char* argv0);
|
|
|
13
15
|
// Returns false when teardown is rejected by runtime safety checks.
|
|
14
16
|
bool qapplication_delete(void* app_handle);
|
|
15
17
|
|
|
18
|
+
// FFI-safe conversion for public Qt QList<int> API parameters and results.
|
|
19
|
+
QList<int> qint_list_from_variant(const QVariant& value);
|
|
20
|
+
QVariant qvariant_from_qint_list(const QList<int>& value);
|
|
21
|
+
|
|
16
22
|
void set_event_callback(void* callback_ptr);
|
|
17
23
|
void watch_qobject_event(void* object_handle, int event_type);
|
|
18
24
|
void unwatch_qobject_event(void* object_handle, int event_type);
|
|
@@ -19,6 +19,7 @@ namespace QtRubyRuntime {
|
|
|
19
19
|
constexpr int kEventCallbackIgnore = 0;
|
|
20
20
|
constexpr int kEventCallbackContinue = 1;
|
|
21
21
|
constexpr int kEventCallbackConsume = 2;
|
|
22
|
+
constexpr int kEventCallbackReject = 3;
|
|
22
23
|
|
|
23
24
|
EventCallback& event_callback_ref() {
|
|
24
25
|
static EventCallback callback = nullptr;
|
|
@@ -234,6 +235,10 @@ class EventFilter : public QObject {
|
|
|
234
235
|
event->accept();
|
|
235
236
|
return true;
|
|
236
237
|
}
|
|
238
|
+
if (callback_result == kEventCallbackReject) {
|
|
239
|
+
event->ignore();
|
|
240
|
+
return true;
|
|
241
|
+
}
|
|
237
242
|
return QObject::eventFilter(watched, event);
|
|
238
243
|
}
|
|
239
244
|
};
|
|
@@ -244,10 +249,10 @@ EventFilter* event_filter_instance() {
|
|
|
244
249
|
}
|
|
245
250
|
|
|
246
251
|
void ensure_event_filter_installed() {
|
|
247
|
-
static
|
|
248
|
-
if (
|
|
252
|
+
static QApplication* installed_on = nullptr;
|
|
253
|
+
if (qApp && installed_on != qApp) {
|
|
249
254
|
qApp->installEventFilter(event_filter_instance());
|
|
250
|
-
|
|
255
|
+
installed_on = qApp;
|
|
251
256
|
}
|
|
252
257
|
}
|
|
253
258
|
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#include "qt_ruby_runtime.hpp"
|
|
2
|
+
|
|
3
|
+
namespace QtRubyRuntime {
|
|
4
|
+
QList<int> qint_list_from_variant(const QVariant& value) {
|
|
5
|
+
QList<int> result;
|
|
6
|
+
const QVariantList values = value.toList();
|
|
7
|
+
result.reserve(values.size());
|
|
8
|
+
for (const QVariant& entry : values) {
|
|
9
|
+
result.append(entry.toInt());
|
|
10
|
+
}
|
|
11
|
+
return result;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
QVariant qvariant_from_qint_list(const QList<int>& value) {
|
|
15
|
+
QVariantList result;
|
|
16
|
+
result.reserve(value.size());
|
|
17
|
+
for (int entry : value) {
|
|
18
|
+
result.append(entry);
|
|
19
|
+
}
|
|
20
|
+
return result;
|
|
21
|
+
}
|
|
22
|
+
} // namespace QtRubyRuntime
|
|
@@ -7,6 +7,7 @@ module Qt
|
|
|
7
7
|
EVENT_RESULT_IGNORE = 0
|
|
8
8
|
EVENT_RESULT_CONTINUE = 1
|
|
9
9
|
EVENT_RESULT_CONSUME = 2
|
|
10
|
+
EVENT_RESULT_REJECT = 3
|
|
10
11
|
|
|
11
12
|
module_function
|
|
12
13
|
|
|
@@ -20,6 +21,7 @@ module Qt
|
|
|
20
21
|
return EVENT_RESULT_CONTINUE unless handlers && !handlers.empty?
|
|
21
22
|
|
|
22
23
|
results = handlers.map { |handler| handler.call(payload) }
|
|
24
|
+
return EVENT_RESULT_REJECT if results.include?(:reject)
|
|
23
25
|
return EVENT_RESULT_CONSUME if results.any? { |result| result == true || result == :consume }
|
|
24
26
|
return EVENT_RESULT_IGNORE if results.any? { |result| result == false || result == :ignore }
|
|
25
27
|
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Qt
|
|
4
|
+
# Owns copied Qt value objects returned through opaque FFI handles.
|
|
5
|
+
module ValueWrapper
|
|
6
|
+
module_function
|
|
7
|
+
|
|
8
|
+
def wrap(handle, qt_class, delete_method)
|
|
9
|
+
return nil if handle.nil? || handle.null?
|
|
10
|
+
|
|
11
|
+
wrapper = Qt.const_get(qt_class).allocate
|
|
12
|
+
wrapper.instance_variable_set(:@handle, handle)
|
|
13
|
+
ObjectSpace.define_finalizer(wrapper, finalizer(delete_method, handle))
|
|
14
|
+
wrapper
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def finalizer(delete_method, handle)
|
|
18
|
+
proc do
|
|
19
|
+
Qt::Native.public_send(delete_method, handle) if Qt::Native.available?
|
|
20
|
+
rescue StandardError
|
|
21
|
+
nil
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
private_class_method :finalizer
|
|
25
|
+
end
|
|
26
|
+
end
|
data/lib/qt/version.rb
CHANGED
data/lib/qt.rb
CHANGED
|
@@ -24,6 +24,7 @@ require_relative 'qt/date_time_codec'
|
|
|
24
24
|
require_relative 'qt/key_sequence_codec'
|
|
25
25
|
require_relative 'qt/object_list_codec'
|
|
26
26
|
require_relative 'qt/variant_codec'
|
|
27
|
+
require_relative 'qt/value_wrapper'
|
|
27
28
|
require_relative 'qt/inspectable'
|
|
28
29
|
require_relative 'qt/object_wrapper'
|
|
29
30
|
require_relative 'qt/application_lifecycle'
|
|
@@ -38,7 +38,7 @@ def map_cpp_intlike_arg_type(type_name, qt_class, int_cast_types)
|
|
|
38
38
|
map_qualified_intlike_arg_type(type_name, qt_class, int_cast_types)
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
-
def map_cpp_arg_type(type_name, qt_class: nil, int_cast_types: nil)
|
|
41
|
+
def map_cpp_arg_type(type_name, qt_class: nil, int_cast_types: nil, ast: nil)
|
|
42
42
|
raw = type_name.to_s.strip
|
|
43
43
|
return nil if raw.end_with?('&') && !raw.start_with?('const ')
|
|
44
44
|
|
|
@@ -46,7 +46,7 @@ def map_cpp_arg_type(type_name, qt_class: nil, int_cast_types: nil)
|
|
|
46
46
|
|
|
47
47
|
type = raw
|
|
48
48
|
type = type.sub(/\Aconst\s+/, '').sub(/\s*&\z/, '').strip
|
|
49
|
-
return
|
|
49
|
+
return { ffi: :string, cast: :qint_list_from_variant } if type == 'QList<int>'
|
|
50
50
|
return { ffi: :string, cast: :qstring } if type == 'QString'
|
|
51
51
|
return { ffi: :string, cast: :qdatetime_from_utf8 } if type == 'QDateTime'
|
|
52
52
|
return { ffi: :string, cast: :qdate_from_utf8 } if type == 'QDate'
|
|
@@ -58,6 +58,12 @@ def map_cpp_arg_type(type_name, qt_class: nil, int_cast_types: nil)
|
|
|
58
58
|
return { ffi: :string, cast: :qvariant_from_utf8 } if type == 'QVariant'
|
|
59
59
|
return { ffi: :string } if compact_raw.match?(/\Aconst\s+char\s*\*\z/)
|
|
60
60
|
|
|
61
|
+
if ast_qt_value_class?(ast, type)
|
|
62
|
+
return { ffi: :pointer, cast: :qt_value_ref, value_class: type }
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
return nil if unsupported_cpp_type?(type)
|
|
66
|
+
|
|
61
67
|
map_cpp_pointer_arg_type(type, qt_class) || map_cpp_intlike_arg_type(type, qt_class, int_cast_types)
|
|
62
68
|
end
|
|
63
69
|
|
|
@@ -70,11 +76,25 @@ end
|
|
|
70
76
|
|
|
71
77
|
def map_cpp_return_type(type_name, ast: nil)
|
|
72
78
|
raw = type_name.to_s.strip
|
|
79
|
+
type = raw.sub(/\Aconst\s+/, '').sub(/\s*&\z/, '').strip
|
|
80
|
+
return { ffi_return: :string, return_cast: :qint_list_to_variant } if type == 'QList<int>'
|
|
73
81
|
return nil if unsupported_cpp_type?(raw)
|
|
74
82
|
return nil if raw.start_with?('const ') && raw.end_with?('*')
|
|
75
83
|
|
|
76
|
-
type
|
|
77
|
-
|
|
84
|
+
map_scalar_cpp_return_type(type) || map_pointer_cpp_return_type(type, ast: ast) || map_qt_value_return_type(type, ast: ast)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def ast_qt_value_class?(ast, type)
|
|
88
|
+
return false unless ast && type.match?(/\AQ[A-Z]\w*\z/)
|
|
89
|
+
return false unless ast_class_index(ast)[:methods_by_class].key?(type)
|
|
90
|
+
|
|
91
|
+
!class_inherits?(ast, type, 'QObject')
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def map_qt_value_return_type(type, ast:)
|
|
95
|
+
return nil unless ast_qt_value_class?(ast, type)
|
|
96
|
+
|
|
97
|
+
{ ffi_return: :pointer, return_cast: :qt_value_copy, value_class: type }
|
|
78
98
|
end
|
|
79
99
|
|
|
80
100
|
def map_scalar_cpp_return_type(type)
|
|
@@ -135,7 +155,7 @@ def parse_method_signature(method_decl)
|
|
|
135
155
|
}
|
|
136
156
|
end
|
|
137
157
|
|
|
138
|
-
def build_auto_method_args(parsed, entry, qt_class, int_cast_types)
|
|
158
|
+
def build_auto_method_args(parsed, entry, qt_class, int_cast_types, ast)
|
|
139
159
|
arg_cast_overrides = Array(entry[:arg_casts])
|
|
140
160
|
params = parsed[:params]
|
|
141
161
|
required_arg_count = 0
|
|
@@ -143,7 +163,7 @@ def build_auto_method_args(parsed, entry, qt_class, int_cast_types)
|
|
|
143
163
|
|
|
144
164
|
params.each_with_index do |param, idx|
|
|
145
165
|
cast_override = arg_cast_overrides[idx]
|
|
146
|
-
arg_info = map_cpp_arg_type(param[:type], qt_class: qt_class, int_cast_types: int_cast_types)
|
|
166
|
+
arg_info = map_cpp_arg_type(param[:type], qt_class: qt_class, int_cast_types: int_cast_types, ast: ast)
|
|
147
167
|
arg_info ||= { ffi: :int } if cast_override
|
|
148
168
|
unless arg_info
|
|
149
169
|
return nil unless skip_unsupported_optional_tail?(params, idx, param)
|
|
@@ -151,7 +171,12 @@ def build_auto_method_args(parsed, entry, qt_class, int_cast_types)
|
|
|
151
171
|
break
|
|
152
172
|
end
|
|
153
173
|
|
|
154
|
-
args << {
|
|
174
|
+
args << {
|
|
175
|
+
name: param[:name],
|
|
176
|
+
ffi: arg_info[:ffi],
|
|
177
|
+
cast: cast_override || arg_info[:cast],
|
|
178
|
+
value_class: arg_info[:value_class]
|
|
179
|
+
}.compact
|
|
155
180
|
required_arg_count += 1 unless param[:has_default]
|
|
156
181
|
end
|
|
157
182
|
|
|
@@ -174,6 +199,7 @@ def build_auto_method_hash(entry, ret_info, args, required_arg_count)
|
|
|
174
199
|
}
|
|
175
200
|
method[:return_cast] = ret_info[:return_cast] if ret_info[:return_cast]
|
|
176
201
|
method[:pointer_class] = ret_info[:pointer_class] if ret_info[:pointer_class]
|
|
202
|
+
method[:value_class] = ret_info[:value_class] if ret_info[:value_class]
|
|
177
203
|
method
|
|
178
204
|
end
|
|
179
205
|
|
|
@@ -184,7 +210,7 @@ def build_auto_method_from_decl(method_decl, entry, qt_class:, int_cast_types:,
|
|
|
184
210
|
ret_info = map_cpp_return_type(parsed[:return_type], ast: ast)
|
|
185
211
|
return nil unless ret_info
|
|
186
212
|
|
|
187
|
-
args, required_arg_count = build_auto_method_args(parsed, entry, qt_class, int_cast_types)
|
|
213
|
+
args, required_arg_count = build_auto_method_args(parsed, entry, qt_class, int_cast_types, ast)
|
|
188
214
|
return nil unless args
|
|
189
215
|
|
|
190
216
|
build_auto_method_hash(entry, ret_info, args, required_arg_count)
|
|
@@ -352,7 +378,11 @@ def resolve_auto_method(ast, qt_class, auto_entry)
|
|
|
352
378
|
built = resolve_auto_method_built_candidates(ast, qt_class, entry)
|
|
353
379
|
return per_ast_cache[cache_key] = nil unless built
|
|
354
380
|
|
|
355
|
-
per_ast_cache[cache_key] = built.min_by
|
|
381
|
+
per_ast_cache[cache_key] = built.min_by do |candidate|
|
|
382
|
+
method = candidate[:method]
|
|
383
|
+
value_arg_count = method[:args].count { |arg| arg[:cast] == :qt_value_ref }
|
|
384
|
+
[value_arg_count, method[:args].length]
|
|
385
|
+
end[:method]
|
|
356
386
|
end
|
|
357
387
|
|
|
358
388
|
def auto_entries_for_spec(spec, ast)
|
|
@@ -10,6 +10,8 @@ class CppMethodReturnEmitter
|
|
|
10
10
|
|
|
11
11
|
def emit
|
|
12
12
|
return emit_void if method[:ffi_return] == :void
|
|
13
|
+
return emit_qt_value_copy if method[:return_cast] == :qt_value_copy
|
|
14
|
+
return emit_qint_list if method[:return_cast] == :qint_list_to_variant
|
|
13
15
|
return emit_qstring if qstring_return?
|
|
14
16
|
return emit_qobject_list if qobject_list_return?
|
|
15
17
|
return emit_qdatetime if qdatetime_return?
|
|
@@ -54,52 +56,86 @@ class CppMethodReturnEmitter
|
|
|
54
56
|
end
|
|
55
57
|
|
|
56
58
|
def emit_qstring
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
lines <<
|
|
60
|
-
lines <<
|
|
59
|
+
result = unique_local_name('result')
|
|
60
|
+
utf8 = unique_local_name('utf8')
|
|
61
|
+
lines << " const QString #{result} = #{invocation};"
|
|
62
|
+
lines << " thread_local QByteArray #{utf8};"
|
|
63
|
+
lines << " #{utf8} = #{result}.toUtf8();"
|
|
64
|
+
lines << " return #{utf8}.constData();"
|
|
61
65
|
end
|
|
62
66
|
|
|
63
67
|
def emit_qvariant
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
lines <<
|
|
67
|
-
lines <<
|
|
68
|
+
result = unique_local_name('result')
|
|
69
|
+
utf8 = unique_local_name('utf8')
|
|
70
|
+
lines << " const QVariant #{result} = #{invocation};"
|
|
71
|
+
lines << " thread_local QByteArray #{utf8};"
|
|
72
|
+
lines << " #{utf8} = qvariant_to_bridge_string(#{result}).toUtf8();"
|
|
73
|
+
lines << " return #{utf8}.constData();"
|
|
68
74
|
end
|
|
69
75
|
|
|
70
76
|
def emit_qobject_list
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
lines <<
|
|
74
|
-
lines <<
|
|
77
|
+
result = unique_local_name('result')
|
|
78
|
+
utf8 = unique_local_name('utf8')
|
|
79
|
+
lines << " const QObjectList #{result} = #{invocation};"
|
|
80
|
+
lines << " thread_local QByteArray #{utf8};"
|
|
81
|
+
lines << " #{utf8} = qobject_list_to_bridge_string(#{result}).toUtf8();"
|
|
82
|
+
lines << " return #{utf8}.constData();"
|
|
75
83
|
end
|
|
76
84
|
|
|
77
85
|
def emit_qdatetime
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
lines <<
|
|
81
|
-
lines <<
|
|
86
|
+
result = unique_local_name('result')
|
|
87
|
+
utf8 = unique_local_name('utf8')
|
|
88
|
+
lines << " const QDateTime #{result} = #{invocation};"
|
|
89
|
+
lines << " thread_local QByteArray #{utf8};"
|
|
90
|
+
lines << " #{utf8} = qdatetime_to_bridge_string(#{result}).toUtf8();"
|
|
91
|
+
lines << " return #{utf8}.constData();"
|
|
82
92
|
end
|
|
83
93
|
|
|
84
94
|
def emit_qdate
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
lines <<
|
|
88
|
-
lines <<
|
|
95
|
+
result = unique_local_name('result')
|
|
96
|
+
utf8 = unique_local_name('utf8')
|
|
97
|
+
lines << " const QDate #{result} = #{invocation};"
|
|
98
|
+
lines << " thread_local QByteArray #{utf8};"
|
|
99
|
+
lines << " #{utf8} = qdate_to_bridge_string(#{result}).toUtf8();"
|
|
100
|
+
lines << " return #{utf8}.constData();"
|
|
89
101
|
end
|
|
90
102
|
|
|
91
103
|
def emit_qtime
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
lines <<
|
|
95
|
-
lines <<
|
|
104
|
+
result = unique_local_name('result')
|
|
105
|
+
utf8 = unique_local_name('utf8')
|
|
106
|
+
lines << " const QTime #{result} = #{invocation};"
|
|
107
|
+
lines << " thread_local QByteArray #{utf8};"
|
|
108
|
+
lines << " #{utf8} = qtime_to_bridge_string(#{result}).toUtf8();"
|
|
109
|
+
lines << " return #{utf8}.constData();"
|
|
96
110
|
end
|
|
97
111
|
|
|
98
112
|
def emit_pointer
|
|
99
113
|
lines << " return const_cast<void*>(static_cast<const void*>(#{invocation}));"
|
|
100
114
|
end
|
|
101
115
|
|
|
116
|
+
def emit_qt_value_copy
|
|
117
|
+
lines << " return new #{method[:value_class]}(#{invocation});"
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def emit_qint_list
|
|
121
|
+
result = unique_local_name('result')
|
|
122
|
+
variant = unique_local_name('variant')
|
|
123
|
+
utf8 = unique_local_name('utf8')
|
|
124
|
+
lines << " const QList<int> #{result} = #{invocation};"
|
|
125
|
+
lines << " const QVariant #{variant} = QtRubyRuntime::qvariant_from_qint_list(#{result});"
|
|
126
|
+
lines << " thread_local QByteArray #{utf8};"
|
|
127
|
+
lines << " #{utf8} = qvariant_to_bridge_string(#{variant}).toUtf8();"
|
|
128
|
+
lines << " return #{utf8}.constData();"
|
|
129
|
+
end
|
|
130
|
+
|
|
102
131
|
def emit_value
|
|
103
132
|
lines << " return #{invocation};"
|
|
104
133
|
end
|
|
134
|
+
|
|
135
|
+
def unique_local_name(suffix)
|
|
136
|
+
used = Array(method[:args]).map { |arg| arg[:name].to_s }.to_set
|
|
137
|
+
candidate = "qt_ruby_#{suffix}"
|
|
138
|
+
candidate += '_' while used.include?(candidate)
|
|
139
|
+
candidate
|
|
140
|
+
end
|
|
105
141
|
end
|
|
@@ -15,9 +15,25 @@ def all_ffi_functions(specs, free_function_specs:)
|
|
|
15
15
|
append_method_ffi_functions(fns, spec)
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
+
value_wrapper_classes(specs, free_function_specs: free_function_specs).each do |qt_class|
|
|
19
|
+
fns << { name: qt_value_delete_function_name(qt_class), ffi_return: :void, args: [:pointer] }
|
|
20
|
+
end
|
|
21
|
+
|
|
18
22
|
fns
|
|
19
23
|
end
|
|
20
24
|
|
|
25
|
+
def value_wrapper_classes(specs, free_function_specs: [])
|
|
26
|
+
spec_classes = specs.flat_map do |spec|
|
|
27
|
+
spec[:methods].filter_map { |method| method[:value_class] if method[:return_cast] == :qt_value_copy }
|
|
28
|
+
end
|
|
29
|
+
free_classes = free_function_specs.filter_map { |spec| spec[:value_class] }
|
|
30
|
+
(spec_classes + free_classes).uniq.sort
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def qt_value_delete_function_name(qt_class)
|
|
34
|
+
"qt_ruby_#{to_snake(qt_class)}_value_delete"
|
|
35
|
+
end
|
|
36
|
+
|
|
21
37
|
def append_constructor_ffi_function(fns, spec)
|
|
22
38
|
return if spec[:constructor][:mode] == :wrap_only
|
|
23
39
|
|
|
@@ -215,6 +215,8 @@ def build_qapplication_static_free_function_spec(ast, qt_name, int_cast_types)
|
|
|
215
215
|
cpp_body =
|
|
216
216
|
if candidate[:ffi_return] == :void
|
|
217
217
|
["QApplication::#{qt_name}();"]
|
|
218
|
+
elsif candidate[:return_cast] == :qt_value_copy
|
|
219
|
+
["return new #{candidate[:value_class]}(QApplication::#{qt_name}());"]
|
|
218
220
|
elsif candidate[:enum_cast]
|
|
219
221
|
["return static_cast<int>(QApplication::#{qt_name}());"]
|
|
220
222
|
elsif candidate[:ffi_return] == :string
|
|
@@ -231,6 +233,7 @@ def build_qapplication_static_free_function_spec(ast, qt_name, int_cast_types)
|
|
|
231
233
|
{
|
|
232
234
|
name: "qt_ruby_#{native_name}",
|
|
233
235
|
ffi_return: candidate[:ffi_return],
|
|
236
|
+
value_class: candidate[:value_class],
|
|
234
237
|
args: [],
|
|
235
238
|
cpp_return: ffi_return_to_cpp(candidate[:ffi_return]),
|
|
236
239
|
cpp_args: '',
|
|
@@ -240,7 +243,8 @@ def build_qapplication_static_free_function_spec(ast, qt_name, int_cast_types)
|
|
|
240
243
|
native: native_name,
|
|
241
244
|
args: [],
|
|
242
245
|
return_cast: candidate[:return_cast],
|
|
243
|
-
pointer_class: candidate[:pointer_class]
|
|
246
|
+
pointer_class: candidate[:pointer_class],
|
|
247
|
+
value_class: candidate[:value_class]
|
|
244
248
|
}
|
|
245
249
|
}
|
|
246
250
|
end
|
|
@@ -271,6 +275,7 @@ def qapplication_static_return_info(return_type, int_cast_types, ast:)
|
|
|
271
275
|
ffi_return: mapped[:ffi_return],
|
|
272
276
|
return_cast: mapped[:return_cast],
|
|
273
277
|
pointer_class: mapped[:pointer_class],
|
|
278
|
+
value_class: mapped[:value_class],
|
|
274
279
|
enum_cast: false
|
|
275
280
|
}
|
|
276
281
|
end
|
|
@@ -300,7 +300,8 @@ def discover_target_qt_classes(ast, scope)
|
|
|
300
300
|
discover_related_value_classes(ast, base_targets, all_classes, template_classes).sort
|
|
301
301
|
end
|
|
302
302
|
wrapper_targets = timed("discover_target_qt_classes/#{scope}/related_qobject_wrappers") do
|
|
303
|
-
|
|
303
|
+
seed_classes = (targets + ['QApplication']).uniq
|
|
304
|
+
discover_related_qobject_wrapper_classes(ast, seed_classes, all_classes, template_classes, scope).sort
|
|
304
305
|
end
|
|
305
306
|
targets = (targets + wrapper_targets).uniq.sort
|
|
306
307
|
debug_log(
|
data/scripts/generate_bridge.rb
CHANGED
|
@@ -250,7 +250,9 @@ def arg_expr(arg)
|
|
|
250
250
|
when :qicon_ref then "*static_cast<QIcon*>(#{arg[:name]})"
|
|
251
251
|
when :qany_string_view then "QAnyStringView(as_qstring(#{arg[:name]}))"
|
|
252
252
|
when :qvariant_from_utf8 then "qvariant_from_bridge_value(#{arg[:name]})"
|
|
253
|
+
when :qint_list_from_variant then "QtRubyRuntime::qint_list_from_variant(qvariant_from_bridge_value(#{arg[:name]}))"
|
|
253
254
|
when :alignment then "static_cast<Qt::Alignment>(#{arg[:name]})"
|
|
255
|
+
when :qt_value_ref then "*static_cast<#{arg[:value_class]}*>(#{arg[:name]})"
|
|
254
256
|
when String then "static_cast<#{arg[:cast]}>(#{arg[:name]})"
|
|
255
257
|
else
|
|
256
258
|
arg[:name]
|
|
@@ -335,6 +337,15 @@ def generate_cpp_delete(lines)
|
|
|
335
337
|
lines << '}'
|
|
336
338
|
end
|
|
337
339
|
|
|
340
|
+
def generate_cpp_qt_value_deletes(lines, specs, free_function_specs)
|
|
341
|
+
value_wrapper_classes(specs, free_function_specs: free_function_specs).each do |qt_class|
|
|
342
|
+
lines << "extern \"C\" void #{qt_value_delete_function_name(qt_class)}(void* handle) {"
|
|
343
|
+
lines << " delete static_cast<#{qt_class}*>(handle);"
|
|
344
|
+
lines << '}'
|
|
345
|
+
lines << ''
|
|
346
|
+
end
|
|
347
|
+
end
|
|
348
|
+
|
|
338
349
|
def cpp_method_signature(method)
|
|
339
350
|
['void* handle'] + method[:args].map { |arg| "#{ffi_to_cpp_type(arg[:ffi])} #{arg[:name]}" }
|
|
340
351
|
end
|
|
@@ -381,6 +392,7 @@ def generate_cpp_bridge(specs, free_function_specs)
|
|
|
381
392
|
|
|
382
393
|
specs.each { |spec| append_cpp_spec_methods(lines, spec) }
|
|
383
394
|
|
|
395
|
+
generate_cpp_qt_value_deletes(lines, specs, free_function_specs)
|
|
384
396
|
generate_cpp_delete(lines)
|
|
385
397
|
"#{lines.join("\n")}\n"
|
|
386
398
|
end
|
|
@@ -640,6 +652,7 @@ def optional_arg_replacement(arg, safe)
|
|
|
640
652
|
when :bool then "(#{safe}.nil? ? false : #{safe})"
|
|
641
653
|
when :pointer then safe
|
|
642
654
|
when :string
|
|
655
|
+
return "(#{safe}.nil? ? Qt::VariantCodec.encode([]) : Qt::VariantCodec.encode(#{safe}))" if arg[:cast] == :qint_list_from_variant
|
|
643
656
|
return "(#{safe}.nil? ? '' : Qt::VariantCodec.encode(#{safe}))" if arg[:cast] == :qvariant_from_utf8
|
|
644
657
|
return "(#{safe}.nil? ? '' : Qt::DateTimeCodec.encode_qdatetime(#{safe}))" if arg[:cast] == :qdatetime_from_utf8
|
|
645
658
|
return "(#{safe}.nil? ? '' : Qt::DateTimeCodec.encode_qdate(#{safe}))" if arg[:cast] == :qdate_from_utf8
|
|
@@ -653,8 +666,13 @@ def optional_arg_replacement(arg, safe)
|
|
|
653
666
|
end
|
|
654
667
|
|
|
655
668
|
def ruby_arg_call_value(arg, safe, optional:)
|
|
669
|
+
if arg[:cast] == :qt_value_ref
|
|
670
|
+
return optional ? "(#{safe}.nil? ? nil : #{safe}.handle)" : "#{safe}.handle"
|
|
671
|
+
end
|
|
672
|
+
|
|
656
673
|
return "Qt::StringCodec.to_qt_text(#{safe})" if text_bridge_arg?(arg) && !optional
|
|
657
674
|
return "Qt::VariantCodec.encode(#{safe})" if arg[:cast] == :qvariant_from_utf8 && !optional
|
|
675
|
+
return "Qt::VariantCodec.encode(#{safe})" if arg[:cast] == :qint_list_from_variant && !optional
|
|
658
676
|
return "Qt::DateTimeCodec.encode_qdatetime(#{safe})" if arg[:cast] == :qdatetime_from_utf8 && !optional
|
|
659
677
|
return "Qt::DateTimeCodec.encode_qdate(#{safe})" if arg[:cast] == :qdate_from_utf8 && !optional
|
|
660
678
|
return "Qt::DateTimeCodec.encode_qtime(#{safe})" if arg[:cast] == :qtime_from_utf8 && !optional
|
|
@@ -698,9 +716,14 @@ def ruby_native_method_body(method, rewritten_native_call)
|
|
|
698
716
|
return "Qt::ObjectListCodec.decode(#{rewritten_native_call}, '#{method[:object_list_class]}')"
|
|
699
717
|
end
|
|
700
718
|
return "Qt::VariantCodec.decode(#{rewritten_native_call})" if method[:return_cast] == :qvariant_to_utf8
|
|
719
|
+
return "Qt::VariantCodec.decode(#{rewritten_native_call})" if method[:return_cast] == :qint_list_to_variant
|
|
701
720
|
return "Qt::DateTimeCodec.decode_qdatetime(#{rewritten_native_call})" if method[:return_cast] == :qdatetime_to_utf8
|
|
702
721
|
return "Qt::DateTimeCodec.decode_qdate(#{rewritten_native_call})" if method[:return_cast] == :qdate_to_utf8
|
|
703
722
|
return "Qt::DateTimeCodec.decode_qtime(#{rewritten_native_call})" if method[:return_cast] == :qtime_to_utf8
|
|
723
|
+
if method[:return_cast] == :qt_value_copy
|
|
724
|
+
delete_method = qt_value_delete_function_name(method[:value_class])
|
|
725
|
+
return "Qt::ValueWrapper.wrap(#{rewritten_native_call}, '#{method[:value_class]}', :#{delete_method})"
|
|
726
|
+
end
|
|
704
727
|
return "Qt::ObjectWrapper.wrap(#{rewritten_native_call}, '#{method[:pointer_class]}')" if method[:pointer_class]
|
|
705
728
|
|
|
706
729
|
rewritten_native_call
|
|
@@ -899,6 +922,11 @@ def qapplication_class_method_body(method, native_call)
|
|
|
899
922
|
return " Qt::DateTimeCodec.decode_qdatetime(#{native_call})" if method[:return_cast] == :qdatetime_to_utf8
|
|
900
923
|
return " Qt::DateTimeCodec.decode_qdate(#{native_call})" if method[:return_cast] == :qdate_to_utf8
|
|
901
924
|
return " Qt::DateTimeCodec.decode_qtime(#{native_call})" if method[:return_cast] == :qtime_to_utf8
|
|
925
|
+
return " Qt::VariantCodec.decode(#{native_call})" if method[:return_cast] == :qint_list_to_variant
|
|
926
|
+
if method[:return_cast] == :qt_value_copy
|
|
927
|
+
delete_method = qt_value_delete_function_name(method[:value_class])
|
|
928
|
+
return " Qt::ValueWrapper.wrap(#{native_call}, '#{method[:value_class]}', :#{delete_method})"
|
|
929
|
+
end
|
|
902
930
|
return " Qt::ObjectWrapper.wrap(#{native_call}, '#{method[:pointer_class]}')" if method[:pointer_class]
|
|
903
931
|
|
|
904
932
|
" #{native_call}"
|
|
@@ -1173,6 +1201,7 @@ def collect_qt_scoped_enum_constants(ast, warnings = [])
|
|
|
1173
1201
|
next unless owner.match?(/\AQ[A-Z]\w*\z/)
|
|
1174
1202
|
next if owner == 'Qt' || owner == 'QEvent'
|
|
1175
1203
|
|
|
1204
|
+
next_value = 0
|
|
1176
1205
|
Array(node['inner']).each do |entry|
|
|
1177
1206
|
next unless entry['kind'] == 'EnumConstantDecl'
|
|
1178
1207
|
|
|
@@ -1181,7 +1210,13 @@ def collect_qt_scoped_enum_constants(ast, warnings = [])
|
|
|
1181
1210
|
|
|
1182
1211
|
raw_value = ast_extract_first_value(entry)
|
|
1183
1212
|
value = parse_ast_integer_value(raw_value)
|
|
1184
|
-
|
|
1213
|
+
value = next_value if value.nil? && !next_value.nil?
|
|
1214
|
+
if value.nil?
|
|
1215
|
+
next_value = nil
|
|
1216
|
+
next
|
|
1217
|
+
end
|
|
1218
|
+
|
|
1219
|
+
next_value = value + 1
|
|
1185
1220
|
|
|
1186
1221
|
append_constant_with_conflict_warning(
|
|
1187
1222
|
constants_by_owner[owner],
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: qt
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Maksim Veynberg
|
|
@@ -47,6 +47,7 @@ files:
|
|
|
47
47
|
- ext/qt_ruby_bridge/qt_ruby_runtime.hpp
|
|
48
48
|
- ext/qt_ruby_bridge/runtime_events.cpp
|
|
49
49
|
- ext/qt_ruby_bridge/runtime_signals.cpp
|
|
50
|
+
- ext/qt_ruby_bridge/runtime_value_types.cpp
|
|
50
51
|
- lib/qt.rb
|
|
51
52
|
- lib/qt/application_lifecycle.rb
|
|
52
53
|
- lib/qt/bridge.rb
|
|
@@ -66,6 +67,7 @@ files:
|
|
|
66
67
|
- lib/qt/object_wrapper.rb
|
|
67
68
|
- lib/qt/shortcut_compat.rb
|
|
68
69
|
- lib/qt/string_codec.rb
|
|
70
|
+
- lib/qt/value_wrapper.rb
|
|
69
71
|
- lib/qt/variant_codec.rb
|
|
70
72
|
- lib/qt/version.rb
|
|
71
73
|
- scripts/generate_bridge.rb
|