-
-
Notifications
You must be signed in to change notification settings - Fork 133
Allow implementing a GAction interface #1640
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
base: main
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,89 @@ | ||
| use gio::{prelude::*, subclass::prelude::*}; | ||
|
|
||
| mod imp { | ||
| use super::*; | ||
| use std::cell::OnceCell; | ||
|
|
||
| #[derive(glib::Properties, Default)] | ||
| #[properties(wrapper_type = super::RenamedAction)] | ||
| pub struct RenamedAction { | ||
| #[property(get, construct_only)] | ||
| pub new_name: OnceCell<glib::GString>, | ||
|
|
||
| #[property(get, construct_only)] | ||
| pub action: OnceCell<gio::Action>, | ||
| } | ||
|
|
||
| #[glib::object_subclass] | ||
| impl ObjectSubclass for RenamedAction { | ||
| const NAME: &'static str = "ExampleRenamedAction"; | ||
| type Type = super::RenamedAction; | ||
| type Interfaces = (gio::Action,); | ||
| } | ||
|
|
||
| #[glib::derived_properties] | ||
| impl ObjectImpl for RenamedAction { | ||
| fn properties() -> &'static [glib::ParamSpec] { | ||
| Self::derived_properties() | ||
| } | ||
|
|
||
| fn set_property(&self, id: usize, value: &glib::Value, pspec: &glib::ParamSpec) { | ||
| if !self.delegate_set_property(id, value, pspec) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If multiple interfaces like this are implemented, the method name would probably conflict. Should we write the interface name in the method name (
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So far there are only Actions and Editable.i rather keep it this way until we find more cases like this
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You'd already have this problem then if you implement both interfaces in the same type :)
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is 0 use case for that. You would rather implement GActionMap instead
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure, but if we want to solve this problem later we need to change API in even more places so it seems useful to figure this out from the beginning. I'm not going to block this PR on this though, just don't tell me in a few years that I didn't warn you :P
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My goal is to basically make the derived_properties macro automatically generate those bits for you. I will send a patch for it once this PR lands
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sounds good |
||
| self.derived_set_property(id, value, pspec); | ||
| } | ||
| } | ||
|
|
||
| fn property(&self, id: usize, pspec: &glib::ParamSpec) -> glib::Value { | ||
| self.delegate_get_property(id, pspec) | ||
| .unwrap_or_else(|| self.derived_property(id, pspec)) | ||
| } | ||
| } | ||
|
|
||
| impl ActionImpl for RenamedAction { | ||
| fn name(&self) -> glib::GString { | ||
| self.obj().new_name() | ||
| } | ||
|
|
||
| fn parameter_type(&self) -> Option<glib::VariantType> { | ||
| self.obj().action().parameter_type() | ||
| } | ||
|
|
||
| fn state_type(&self) -> Option<glib::VariantType> { | ||
| self.obj().action().state_type() | ||
| } | ||
|
|
||
| fn state_hint(&self) -> Option<glib::Variant> { | ||
| self.obj().action().state_hint() | ||
| } | ||
|
|
||
| fn is_enabled(&self) -> bool { | ||
| self.obj().action().is_enabled() | ||
| } | ||
|
|
||
| fn state(&self) -> Option<glib::Variant> { | ||
| self.obj().action().state() | ||
| } | ||
|
|
||
| fn change_state(&self, value: glib::Variant) { | ||
| self.obj().action().change_state(&value); | ||
| } | ||
|
|
||
| fn activate(&self, parameter: Option<glib::Variant>) { | ||
| self.obj().action().activate(parameter.as_ref()); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| glib::wrapper! { | ||
| pub struct RenamedAction(ObjectSubclass<imp::RenamedAction>) | ||
| @implements gio::Action; | ||
| } | ||
|
|
||
| impl RenamedAction { | ||
| pub fn new(name: &str, action: &impl IsA<gio::Action>) -> Self { | ||
| glib::Object::builder() | ||
| .property("new-name", name) | ||
| .property("action", action) | ||
| .build() | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| mod action; | ||
|
|
||
| use gio::prelude::*; | ||
|
|
||
| fn main() { | ||
| let action = gio::SimpleAction::new("bark", Some(glib::VariantTy::STRING)); | ||
| action.connect_activate(|_, p| { | ||
| let target = p.unwrap().str().unwrap(); | ||
| println!("Woof, {}!", target); | ||
| }); | ||
|
|
||
| let renamed_action = action::RenamedAction::new("meow", &action); | ||
|
|
||
| let group = gio::SimpleActionGroup::new(); | ||
| group.add_action(&action); | ||
| group.add_action(&renamed_action); | ||
|
|
||
| println!("actions = {:?}", group.list_actions()); | ||
|
|
||
| group.activate_action("bark", Some(&"postman".to_variant())); | ||
| group.activate_action("meow", Some(&"milkman".to_variant())); | ||
| } |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
where initialization sequence is:
A,IFace,B. So, whenBis initializingIFaceis already there and could be overriden.but does not work for
where initialization sequence is:
B,IFace. So,Bhas nothing to override yet.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You didn't find a solution to this yet, right? This probably should be solved independent of this PR (please create an issue with all you remember)