From 8e9ea60ac091af4107b2ae18ccdd8d12413945f8 Mon Sep 17 00:00:00 2001 From: Michal Kottman Date: Sat, 5 Jan 2013 18:35:20 +0100 Subject: [PATCH] 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 --- generator/classes.lua | 34 +++++++++++++++++-------------- generator/signalslot.lua | 3 +++ generator/virtuals.lua | 34 ++++++++++++------------------- test/protected_test.lua | 53 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 88 insertions(+), 36 deletions(-) create mode 100644 test/protected_test.lua diff --git a/generator/classes.lua b/generator/classes.lua index e103733..6756a39 100644 --- a/generator/classes.lua +++ b/generator/classes.lua @@ -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 diff --git a/generator/signalslot.lua b/generator/signalslot.lua index 7437ce4..8e41b8d 100644 --- a/generator/signalslot.lua +++ b/generator/signalslot.lua @@ -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 diff --git a/generator/virtuals.lua b/generator/virtuals.lua index 0aba34c..0ea36a3 100644 --- a/generator/virtuals.lua +++ b/generator/virtuals.lua @@ -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 \ No newline at end of file diff --git a/test/protected_test.lua b/test/protected_test.lua new file mode 100644 index 0000000..90ead6f --- /dev/null +++ b/test/protected_test.lua @@ -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.11.4.GIT