Permalink
Browse files

Re-enable access to protected functions

This change enables the ability to emit protected signals. This is a
little controversial, because it makes protected methods public.

Features the infamous ugly C++ hack: #define protected public
  • Loading branch information...
1 parent 35828c7 commit 8e9ea60ac091af4107b2ae18ccdd8d12413945f8 @mkottman committed Jan 5, 2013
Showing with 88 additions and 36 deletions.
  1. +19 −15 generator/classes.lua
  2. +3 −0 generator/signalslot.lua
  3. +13 −21 generator/virtuals.lua
  4. +53 −0 test/protected_test.lua
View
@@ -616,14 +616,10 @@ function print_wrappers()
local meta = {}
local wrappers = ''
for _, f in ipairs(c.methods) do
- -- FIXME: should we really discard virtual functions?
- -- if the virtual overload in the shell uses rawget
- -- on the environment then we can leave these in the
- -- metatable
if f.wrapper_code and not f.ignore then
- local out = 'static int lqt_bind'..f.xarg.id
- ..' (lua_State *L) {\n'.. f.wrapper_code .. '}\n'
- if f.xarg.access=='public' then
+ if f.xarg.access~='private' then
+ local out = 'static int lqt_bind'..f.xarg.id
+ ..' (lua_State *L) {\n'.. f.wrapper_code .. '}\n'
--print_meta(out)
wrappers = wrappers .. out .. '\n'
meta[f] = f.xarg.name
@@ -633,9 +629,9 @@ function print_wrappers()
if not c.abstract then
for _, f in ipairs(c.constructors) do
if f.wrapper_code then
- local out = 'static int lqt_bind'..f.xarg.id
- ..' (lua_State *L) {\n'.. f.wrapper_code .. '}\n'
if f.xarg.access=='public' then
+ local out = 'static int lqt_bind'..f.xarg.id
+ ..' (lua_State *L) {\n'.. f.wrapper_code .. '}\n'
--print_meta(out)
wrappers = wrappers .. out .. '\n'
meta[f] = 'new'
@@ -767,10 +763,20 @@ function print_single_class(c)
print_meta(c.implicit.test)
print_meta(c.implicit.convert)
end
-
+
print_meta(c.wrappers)
- if c.virtual_overloads then
- print_meta(c.virtual_overloads)
+
+ local virtual_methods
+ if c.shell then
+ virtual_methods = virtuals.sort_by_index(c)
+ local shellname = 'lqt_shell_'..c.xarg.cname
+ for _, v in ipairs(virtual_methods) do
+ if v.virtual_overload then
+ local method = string.gsub(v.virtual_overload, ';;', shellname..'::', 1)
+ method = string.gsub(method, 'VIRTUAL_INDEX', v.virtual_index)
+ print_meta(method)
+ end
+ end
end
local getters_setters = 'NULL, NULL'
@@ -814,8 +820,7 @@ function print_single_class(c)
if VERBOSE_BUILD then
print_meta(' printf("Overriding \'%s\' in %s [%p]\\n", name, "'..shellname..'", self);')
end
- local virt = virtuals.sort_by_index(c)
- for _, v in pairs(virt) do
+ for _, v in ipairs(virtual_methods) do
print_meta(' if (!strcmp(name, "'..v.xarg.name..'")) {')
print_meta(' self->hasOverride.setBit('..v.virtual_index..');')
if VERBOSE_BUILD then
@@ -990,7 +995,6 @@ end
function output()
virtuals.print_shell_classes(classes) -- does that, and outputs headers
- virtuals.print_virtual_overloads(classes) -- does that
print_wrappers(classes) -- just compiles metatable list
print_metatables(classes) -- just collects the wrappers + generates dispatchers
View
@@ -10,6 +10,9 @@ function copy_signals(functions)
for f in pairs(functions) do
if f.xarg.signal=='1' then
signals[f] = true
+ if f.xarg.access == 'protected' then
+ f.xarg.access = 'public'
+ end
end
end
end
View
@@ -67,8 +67,8 @@ function fill_virtuals(classes)
local virtual_index = 0
for n, f in pairs(ret) do
- virtual_index = virtual_index + 1
f.virtual_index = virtual_index
+ virtual_index = virtual_index + 1
end
return ret, virtual_index
@@ -133,11 +133,11 @@ function virtual_overload(v)
'QThread::currentThreadId(), this, ' ..
'"'..v.xarg.member_of_class.. '", ' ..
'"'..v.xarg.name..'", '..
- v.virtual_index .. ', '..
- '(int)(bool)hasOverride[' .. v.virtual_index .. ']'..
+ 'VIRTUAL_INDEX, '..
+ '(int)(bool)hasOverride[VIRTUAL_INDEX]'..
');\n'
end
- ret = ret .. ' if (!hasOverride[' .. v.virtual_index .. ']) { \n'
+ ret = ret .. ' if (!hasOverride[VIRTUAL_INDEX]) { \n'
ret = ret .. ' ' .. fallback .. '\n }\n'
ret = ret .. [[
lqtL_pushudata(L, this, "]]..string.gsub(v.xarg.member_of_class, '::', '.')..[[*");
@@ -172,6 +172,7 @@ end
function fill_virtual_overloads(classes)
for c in pairs(classes) do
if c.virtuals then
+ local vidx = 0
for i, v in pairs(c.virtuals) do
if v.xarg.access~='private' then
local vret, err = virtual_overload(v)
@@ -269,6 +270,8 @@ function print_shell_classes(classes)
end
print_head('#ifndef LQT_HEAD_'..n)
print_head('#define LQT_HEAD_'..n)
+ print_head('/* ugly ugly ugly, but needed to access protected members from outside */')
+ print_head('#define protected public')
print_head(output_includes)
--print_head('#include <'..string.match(c.xarg.fullname, '^[^:]+')..'>')
print_head''
@@ -288,26 +291,15 @@ function print_shell_classes(classes)
return classes
end
-function print_virtual_overloads(classes)
- for c in pairs(classes) do
- if c.shell then
- local vo = ''
- local shellname = 'lqt_shell_'..c.xarg.cname
- for _,v in pairs(c.virtuals) do
- if v.virtual_overload then
- vo = vo .. string.gsub(v.virtual_overload, ';;', shellname..'::', 1)
- end
- end
- c.virtual_overloads = vo
- end
- end
- return classes
-end
-
function sort_by_index(c)
local res = {}
+ local vidx = 0
for name, virt in pairs(c.virtuals) do
- res[virt.virtual_index] = virt
+ virt.virtual_index = vidx
+ res[#res + 1] = virt
+ vidx = vidx + 1
end
+ table.sort(res, function(v1, v2) return v1.virtual_index < v2.virtual_index end)
+ c.nvirtuals = vidx
return res
end
View
@@ -0,0 +1,53 @@
+require "qtcore"
+require "qtgui"
+
+A = QApplication(1, {'Protected test'})
+
+-- We will implement our custom model
+M = QAbstractListModel()
+
+-- stored in the environment table of the userdata
+M.luaData = {'Hello', 'World'}
+
+-- these are implemented virtual methods
+function M:rowCount()
+ return #self.luaData
+end
+
+local empty = QVariant()
+function M:data(index, role)
+ if role == Qt.ItemDataRole.DisplayRole then
+ local row = index:row()
+ return QVariant(self.luaData[row + 1])
+ end
+ return empty
+end
+
+-- this is a custom helper function
+function M:addAnotherString(str)
+ table.insert(self.luaData, str)
+ local row = #self.luaData - 1
+ local index = self:createIndex(row, 0, 0)
+ self:dataChanged(index, index)
+end
+
+-- some simple layout - list and a button
+MW = QWidget()
+
+W = QListView()
+W:setModel(M)
+
+B = QPushButton('Add Lua data')
+local counter = 1
+B:connect('2clicked()', function()
+ M:addAnotherString('Added text ' .. counter)
+ counter = counter + 1
+end)
+
+L = QVBoxLayout()
+L:addWidget(W)
+L:addWidget(B)
+MW:setLayout(L)
+
+MW:show()
+A.exec()

2 comments on commit 8e9ea60

dmattp commented on 8e9ea60 Dec 18, 2013

"#define protected public" causes link errors (at least for Windows/VS2010; linux build was okay); mangled names show QAE rather than IAE. Is there a workaround for this? Does anybody have this working for windows build?

Owner

mkottman replied Dec 18, 2013

It is a known issue (https://groups.google.com/d/msg/lqt-bindings/YGBs2weiTKs/A3quoQPd12cJ), just remove the line for Microsoft compiler - it only works in GCC. In retrospect should have added an #ifdef around this line.

Please sign in to comment.