There are QVariant:setValue() and QVariant:value() to work over the
limitations of the automated generator. These bindings are hand-made
and handle all object types supported by QVariant. Unfortunately you
cannot store a Lua table in a QVariant, but you can assign custom Lua
data directly to the QVariant itself, this is redirected to a Lua
table which an empty table environment table [1] for the userdata
(this is true for any lqt-created object):
local q = QVariant()
q.abcd = 'hello'
q.efgh = 'world'
> Also, I wonder why you have to manually manage memory in lqt while in
> Qt bindings for other languages you simply forget about memory
> management. Why can't lqt do the same?
You do not have to manage memory if you do not want to. Just use this
form of construction:
local mainWindow = QMainWindow()
This is the default and expected way to work with items. It uses Lua
GC mechanism to delete the object when it is no longer referenced.
If you need to create an object so that Lua does not tamper with it
(may happen), you can use something like QObject.new(parent) and let
Qt handle the memory management (parent-child relationship), which is
useful in MVC classes like list views and models together with items.
At last, there is also an item:delete() method which explicitly calls
the destructor (may be needed sometimes).
Ok, I've just realized that the documentation is not really clear with
this, which may be the source of confusion. The default "managed" mode
by writing QObject() should work fine most of the time.
Still you have to realize that Qt does its own bookkeeping if you use
the parent-child mechanism (or it is forced onto you), and you have to
know where to look when items suddenly start disappearing from your
lists etc. This happened to me a few time - I didn't keep Lua
references to auto-managed list items, and Lua GC was deleting them
during GC (they remove themselves from the parent widget on
destruction).
Hmm, well, yes, this would be a problem. lqt caches pointers to
objects, so if you create a Qt object in Lua, pass it to Qt and then
retrieve it later from some other method, if the pointer does not
change, you get the original Lua-created object. But since QVariants
are passed by value, the object you get back will be different, hence
you lose the Lua table associated with the object.
I guess I'll have to create a custom QVariant type which will lock the
Lua table in registry and keep a reference to it, allowing you to
retrieve the Lua table elsewhere, unfortunately currently I have no
time to hack on lqt.
>> You do not have to manage memory if you do not want to. Just use this
>> form of construction:
>>
>> local mainWindow = QMainWindow()
>>
>> This is the default and expected way to work with items. It uses Lua
>> GC mechanism to delete the object when it is no longer referenced.
>
> What if I do this:
>
> function build_ui(win)
> local layout = QVBoxLayout()
> win:setLayout(layout)
> win.button = QPushButton('test')
> layout:addWidget(win.button)
> end
>
> Will the layout be destroyed when the function ends, even when it's
> still in use by the window object?
It will not be destroyed when the function ends, but when the GC kicks
in. Which may be immediately, or it may be until you move your mouse,
etc. Either way you will lose your layout. Lua GC has no way of
knowing that Qt still needs this object. To Lua, that object is
garbage once the function ends. This is why you should rely on the Qt
parent-child relationship, and use the .new() allocation together with
parent object. You get the best of both worlds - everything works and
everything is nicely deallocated when necessary.
function build_ui(win)
local layout = QVBoxLayout.new(win)
win:setLayout(layout)
win.button = QPushButton('test') -- notice that this is Lua
reference, hence Lua GC will know about this
layout:addWidget(win.button)
end
You can definitely try it out if this works for you:
QVBoxLayout.__gc = function(self)
if not self:parent() then self:delete() end
end
And then allocate you object using QVBoxLayout and see if it behaves
as expected. If it works fine, then I will think about updating lqt
memory management.
To be honest the whole dependency chain still makes my head turn
around. I am not the original author of the code, I just needed to
quickly fix some problems for my diploma project, that's why the
hacks. I do not remember why the error(SUPER) was needed, I guess it
was because of protected methods were not bound outside of the class,
and there was no way to call them from Lua.
But AFAIK, I have already bound protected method, so you should be
able to call them using the nicer BaseClass.method(args) syntax. I
guess I'll need to do a major cleanup in summer...