-
-
Notifications
You must be signed in to change notification settings - Fork 127
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 all commits
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) { | ||
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 ( 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 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 :) 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 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 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 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, whenB
is initializingIFace
is already there and could be overriden.but does not work for
where initialization sequence is:
B
,IFace
. So,B
has 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)