Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow implementing a GAction interface #1640

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

andy128k
Copy link
Contributor

@andy128k andy128k commented Jan 27, 2025

Closes #1636

gio/src/subclass/action.rs Outdated Show resolved Hide resolved
gio/src/subclass/action.rs Outdated Show resolved Hide resolved
@andy128k
Copy link
Contributor Author

Another issue I have is that GAction implies that an implementor had some properties.

(process:527349): GLib-GObject-CRITICAL **: 20:51:28.369: Object class ExampleRenamedAction doesn't implement property 'state-type' from interface 'GAction'

(process:527349): GLib-GObject-CRITICAL **: 20:51:28.369: Object class ExampleRenamedAction doesn't implement property 'state' from interface 'GAction'

(process:527349): GLib-GObject-CRITICAL **: 20:51:28.369: Object class ExampleRenamedAction doesn't implement property 'parameter-type' from interface 'GAction'

(process:527349): GLib-GObject-CRITICAL **: 20:51:28.369: Object class ExampleRenamedAction doesn't implement property 'enabled' from interface 'GAction'

I have no clue what would be an idiomatic way to use g_object_class_override_property in Rust.

@bilelmoussaoui
Copy link
Member

Another issue I have is that GAction implies that an implementor had some properties.

(process:527349): GLib-GObject-CRITICAL **: 20:51:28.369: Object class ExampleRenamedAction doesn't implement property 'state-type' from interface 'GAction'

(process:527349): GLib-GObject-CRITICAL **: 20:51:28.369: Object class ExampleRenamedAction doesn't implement property 'state' from interface 'GAction'

(process:527349): GLib-GObject-CRITICAL **: 20:51:28.369: Object class ExampleRenamedAction doesn't implement property 'parameter-type' from interface 'GAction'

(process:527349): GLib-GObject-CRITICAL **: 20:51:28.369: Object class ExampleRenamedAction doesn't implement property 'enabled' from interface 'GAction'

I have no clue what would be an idiomatic way to use g_object_class_override_property in Rust.

GtkEditable provides a method to automatically add the properties for you along with the get_property and set_property. Either the example implementing a custom Action would have to do that manually or you could add helpers that would do it automatically for you, see the EditableImpl in the gtk4-rs repo.


#[derive(glib::Properties, Default)]
#[properties(wrapper_type = super::RenamedAction)]
pub struct RenamedAction {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The properties macro allows overriding properties by the way

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I gave it a try but received an error

(process:718176): GLib-GObject-CRITICAL **: 22:59:07.010: When installing property: type 'ExampleRenamedAction' already has a property named 'name'

I guess it's because of the sequence of initialization. When I define a class and implement an interface then class installs properties first and interface fails to install them.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The way how you do it now should work or not?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does not work. I guess It works as expected in the cases like

class A implements IFace

class B extends A implements IFace {
   override property x of IFace
}

where initialization sequence is: A, IFace, B. So, when B is initializing IFace is already there and could be overriden.

but does not work for

class B implements IFace {
   override property x of IFace
}

where initialization sequence is: B, IFace. So, B has nothing to override yet.

@andy128k
Copy link
Contributor Author

@bilelmoussaoui Thanks for pointing a direction! Unfortunately Gio does not provide helpers similar to gtk_editable_*_delegate_*, so I needed to replicate C code myself.


I am not sure if I fully understand the subject but this line seems wrong. Gtk's doc uses NUM_PROPERTIES as a second parameter which is usually not an amount of properties but amount + 1 (props are numbered from 1). gtk_editable_install_properties does not add 1.

gio/src/subclass/action.rs Outdated Show resolved Hide resolved
glib::ffi::g_free(properties as *mut _);
let first_prop = first_prop.assume_init() + 1;

set_first_prop(instance_type, first_prop as usize);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a nice hack for the properties :)

gio/src/subclass/action.rs Outdated Show resolved Hide resolved
_pspec: &glib::ParamSpec,
) -> Option<glib::Value> {
let type_: glib::Type = self.obj().type_();
let property = ActionProperty::from_type(type_, prop_id)?;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you pass in Self::type_() here then you don't need to do all the parent type walking inside from_type() and always have directly the correct type

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's what I've found in GtkEditable's code.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bilelmoussaoui Why does it do things so complicated, do you remember? :)

let instance = &*(actionptr as *mut T::Instance);
let imp = instance.imp();

if let Some(parameter_type) = imp.parameter_type() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably be moved into the set_qdata() call. Now you'd get inconsistent behaviour if the function returns Some on the first call and None afterwards

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not directly forbidden by Gio's docs, but I think it could be insane if the type of a parameter would change during the action's lifetime.

A similar assumption is made in ActionGroup.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My personal approach here would be to either only call the function once to don't give the user a chance to do it wrong, or otherwise at least to add an assertion :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've changed this and other places (name, parameter_type and state_type) in the way that the function is called once.

gio/src/subclass/action.rs Outdated Show resolved Hide resolved
@andy128k andy128k marked this pull request as ready for review January 30, 2025 11:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[FEATURE REQUEST] Allow to implement gio::Action
3 participants