lgi-devs / lgi

Dynamic Lua binding to GObject libraries using GObject-Introspection
MIT License
436 stars 69 forks source link

No 'label' or 'icon' property when defined in custom class #253

Open RossComputerGuy opened 4 years ago

RossComputerGuy commented 4 years ago

My custom class: https://github.com/ExpidusOS/shell/blob/master/share/expidus-shell/expidus/widgets/app-button.lua

local lgi = require('lgi')
local Gtk = lgi.Gtk
local GObject = lgi.GObject
local Expidus = lgi.package('Expidus')

Expidus:class('AppButton', Gtk.FlowBoxChild)

Expidus.AppButton._property.label = GObject.ParamSpecString('label', 'Application label', 'Label', 'App', { 'READABLE', 'WRITABLE', 'CONSTRUCT' })
Expidus.AppButton._property.icon = GObject.ParamSpecString('icon', 'Application icon', 'Icon', 'app-icon-unknown', { 'READABLE', 'WRITABLE', 'CONSTRUCT' })

function Expidus.AppButton:_init()
end

function Expidus.AppButton:_class_init()
end

return Expidus.AppButton

Code that calls my class: https://github.com/ExpidusOS/shell/blob/master/share/expidus-shell/expidus/launcher.lua

ExpidusAppButton{
  label = entry.label,
  icon = entry.icon
}

Result:

2020-11-03 19:57:07 E: awesome: Error during a protected call: ./expidus/launcher.lua:55: Expidus.AppButton: no `label'
stack traceback:
        [C]: in function 'error'
        /usr/share/lua/5.3/lgi/component.lua:160: in function </usr/share/lua/5.3/lgi/component.lua:156>
        [C]: in metamethod '__newindex'
        ./expidus/launcher.lua:55: in upvalue 'callback'
        /usr/share/awesome/lib/menubar/menu_gen.lua:128: in function </usr/share/awesome/lib/menubar/menu_gen.lua:93>
        (...tail calls...)
        /usr/share/awesome/lib/menubar/utils.lua:409: in function </usr/share/awesome/lib/menubar/utils.lua:406>
        [C]: in function 'xpcall'
        /usr/share/awesome/lib/gears/protected_call.lua:36: in function </usr/share/awesome/lib/gears/protected_call.lua:35>
        (...tail calls...)

Note that I've reduced the calling code down so I don't have the entire file pasted.

psychon commented 4 years ago

I have no idea about this code (CC @TingPing do you happen to have some more clue here?). Random comment that might or might not be helpful: The example in https://github.com/pavouk/lgi/blob/master/docs/guide.md#382-installing-new-properties also defines a function in a _property_set table.

RossComputerGuy commented 4 years ago

By default, the value of the property is mirrored in priv table of the instance. However, it is possible to specify custom getter and setter method in _property_set and _property_get tables. Both approaches are illustrated in the following example with property called my_label

Adding a function to _property_set is not needed.

Miqueas commented 3 years ago

@RossComputerGuy I tried to do what the LGI documentation says and it didn't work. However, there is still another way to do this, by doing it just as it is done in C:

local lgi = require('lgi')
local Gtk = lgi.Gtk
local GObject = lgi.GObject
local Expidus = lgi.package('Expidus')

Expidus:class('AppButton', Gtk.FlowBoxChild)

function Expidus.AppButton:_class_init(klass)
  function klass:set_property(id, value, pspec)
    if id == 1 then
      self.priv.label = value:get_string()
    elseif id == 2 then
      self.priv.icon = value:get_string()
    else
      GObject.OBJECT_WARN_INVALID_PROPERTY_ID(self, id, pspec)
    end
  end

  function klass:get_property(id, value, pspec)
    if id == 1 then
      value:set_string(self.priv.label)
    elseif id == 2 then
      value:set_string(self.priv.icon)
    else
      GObject.OBJECT_WARN_INVALID_PROPERTY_ID(self, id, pspec)
    end
  end

  klass:install_property(1, GObject.ParamSpecString(
      "label", "Label", "Application label", "App",
      { 'READWRITE', 'CONSTRUCT' }
    )
  )

  klass:install_property(2, GObject.ParamSpecString(
      "icon", "Icon", "Application icon", "app-icon-unknown",
      { 'READWRITE', 'CONSTRUCT' }
    )
  )
end

local btn = Expidus.AppButton{
  label = "ExpBtn",
  icon = "go-home-symbolic"
}

print(btn.label, btn.icon)

-- Default values:
print(Expidus.AppButton().label)
print(Expidus.AppButton().icon)

Note that with this method it is mandatory to assign the functions set_property and get_property.

Miqueas commented 3 years ago

Please, close this if no activity or is solved

RossComputerGuy commented 3 years ago

@M1que4s but we need it fixed

Miqueas commented 3 years ago

@RossComputerGuy I left an answer with a solution to the problem above

RossComputerGuy commented 3 years ago

I tried to do what the LGI documentation says and it didn't work. However, there is still another way to do this, by doing it just as it is done in C

This sounds more like a temporary fix until this issue is fixed.

Miqueas commented 3 years ago

@RossComputerGuy The way in which properties are created with LGI is specific to the library. On the other hand, the way I have done it is the way it is done according to GObject, that is, more C-style.

I wouldn't say it's a temporary solution

RossComputerGuy commented 3 years ago

Well the way it is documented should work because its documented as a feature.

Miqueas commented 3 years ago

@RossComputerGuy Here you can see how subclassing is done with GObject in C: https://developer.gnome.org/SubclassGObject/

Miqueas commented 3 years ago

Well the way it is documented should work because its documented as a feature.

Yes, you are right. However, I'm honestly not sure why it doesn't work

Miqueas commented 3 years ago

@RossComputerGuy Anyway, I hope my comment was helpful