summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorEmmanuel Gil Peyrot <linkmauve@linkmauve.fr>2022-02-09 22:47:38 +0100
committerEmmanuel Gil Peyrot <linkmauve@linkmauve.fr>2022-02-10 01:45:37 +0100
commitd35c0564b3f5dd10f6e23bf462bbfabd3084e486 (patch)
tree4354ccef627717e05ea4cf8abea50ab1f105b58a /tools
parent9735b6d6dc5ff6b5d577d2ba7511d74a9de99f38 (diff)
downloadpoezio-d35c0564b3f5dd10f6e23bf462bbfabd3084e486.tar.gz
poezio-d35c0564b3f5dd10f6e23bf462bbfabd3084e486.tar.bz2
poezio-d35c0564b3f5dd10f6e23bf462bbfabd3084e486.tar.xz
poezio-d35c0564b3f5dd10f6e23bf462bbfabd3084e486.zip
Add a /sticker plugin
This plugin currently uploads the selected sticker every time, to the HTTP File Upload service of the server (see XEP-0363), a future optimisation would be to use XEP-0231 instead, for better caching on the recipient side. It relies on a helper tool to select the wanted sticker inside the pack, a sample one is provided in tools/sticker-picker/, but it is not built by default.
Diffstat (limited to 'tools')
-rw-r--r--tools/sticker-picker/Cargo.toml16
-rw-r--r--tools/sticker-picker/src/main.rs93
-rw-r--r--tools/sticker-picker/src/sticker.rs106
3 files changed, 215 insertions, 0 deletions
diff --git a/tools/sticker-picker/Cargo.toml b/tools/sticker-picker/Cargo.toml
new file mode 100644
index 00000000..fdba8144
--- /dev/null
+++ b/tools/sticker-picker/Cargo.toml
@@ -0,0 +1,16 @@
+[package]
+name = "poezio-sticker-picker"
+version = "0.1.0"
+edition = "2021"
+authors = ["Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>"]
+license = "Zlib"
+description = "Helper tool for selecting a sticker inside a pack"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+gtk = { package = "gtk4", version = "0.4", features = ["v4_6"] }
+gdk = { package = "gdk4", version = "0.4", features = ["v4_6"] }
+glib = "0.15"
+gio = "0.15"
+once_cell = "1.9.0"
diff --git a/tools/sticker-picker/src/main.rs b/tools/sticker-picker/src/main.rs
new file mode 100644
index 00000000..49795f4d
--- /dev/null
+++ b/tools/sticker-picker/src/main.rs
@@ -0,0 +1,93 @@
+// This file is part of Poezio.
+//
+// Poezio is free software: you can redistribute it and/or modify
+// it under the terms of the zlib license. See the COPYING file.
+
+mod sticker;
+
+use gtk::prelude::*;
+use sticker::StickerType as Sticker;
+
+fn main() {
+ let app = gtk::Application::builder()
+ .application_id("io.poez.StickerPicker")
+ .flags(gio::ApplicationFlags::HANDLES_OPEN)
+ .build();
+
+ let quit = gio::SimpleAction::new("quit", None);
+ app.set_accels_for_action("app.quit", &["<Control>q"]);
+ app.add_action(&quit);
+ quit.connect_activate(glib::clone!(@weak app => move |_, _| app.quit()));
+
+ app.connect_open(move |app, directories, _| {
+ let path = match directories {
+ [directory] => directory.path().unwrap(),
+ _ => {
+ eprintln!("Only a single directory is allowed!");
+ std::process::exit(1);
+ }
+ };
+
+ let window = gtk::ApplicationWindow::builder()
+ .application(app)
+ .default_width(1280)
+ .default_height(720)
+ .title("Poezio Sticker Picker")
+ .build();
+
+ let sw = gtk::ScrolledWindow::builder()
+ .has_frame(true)
+ .hscrollbar_policy(gtk::PolicyType::Always)
+ .vscrollbar_policy(gtk::PolicyType::Always)
+ .vexpand(true)
+ .build();
+ window.set_child(Some(&sw));
+
+ let store = gio::ListStore::new(Sticker::static_type());
+
+ for dir_entry in std::fs::read_dir(path).unwrap() {
+ let dir_entry = dir_entry.unwrap();
+ let file_name = dir_entry.file_name().into_string().unwrap();
+ let sticker = Sticker::new(file_name, &dir_entry.path());
+ store.append(&sticker);
+ }
+
+ let factory = gtk::SignalListItemFactory::new();
+ factory.connect_setup(|_, item| {
+ let picture = gtk::Picture::builder()
+ .alternative_text("Sticker")
+ .can_shrink(false)
+ .build();
+ item.set_child(Some(&picture));
+ });
+ factory.connect_bind(|_, list_item| {
+ if let Some(child) = list_item.child() {
+ if let Some(item) = list_item.item() {
+ let picture: gtk::Picture = child.downcast().unwrap();
+ let sticker: Sticker = item.downcast().unwrap();
+ picture.set_paintable(sticker.texture().as_ref());
+ }
+ }
+ });
+
+ let selection = gtk::SingleSelection::new(Some(&store));
+ let grid_view = gtk::GridView::builder()
+ .single_click_activate(true)
+ .model(&selection)
+ .factory(&factory)
+ .build();
+ grid_view.connect_activate(move |_, position| {
+ let item = store.item(position).unwrap();
+ let sticker: Sticker = item.downcast().unwrap();
+ if let Some(filename) = sticker.filename() {
+ println!("{}", filename);
+ std::process::exit(0);
+ }
+ });
+ sw.set_child(Some(&grid_view));
+
+ window.show();
+ });
+
+ app.run();
+}
diff --git a/tools/sticker-picker/src/sticker.rs b/tools/sticker-picker/src/sticker.rs
new file mode 100644
index 00000000..7fb44e8e
--- /dev/null
+++ b/tools/sticker-picker/src/sticker.rs
@@ -0,0 +1,106 @@
+// This file is part of Poezio.
+//
+// Poezio is free software: you can redistribute it and/or modify
+// it under the terms of the zlib license. See the COPYING file.
+
+use gtk::prelude::*;
+use gtk::subclass::prelude::*;
+use std::cell::RefCell;
+use std::path::Path;
+
+#[derive(Debug, Default)]
+pub struct Sticker {
+ filename: RefCell<Option<String>>,
+ texture: RefCell<Option<gdk::Texture>>,
+}
+
+#[glib::object_subclass]
+impl ObjectSubclass for Sticker {
+ const NAME: &'static str = "Sticker";
+ type Type = StickerType;
+}
+
+impl ObjectImpl for Sticker {
+ fn properties() -> &'static [glib::ParamSpec] {
+ use once_cell::sync::Lazy;
+ static PROPERTIES: Lazy<Vec<glib::ParamSpec>> = Lazy::new(|| {
+ vec![
+ glib::ParamSpecString::new(
+ "filename",
+ "Filename",
+ "Filename",
+ None,
+ glib::ParamFlags::READWRITE | glib::ParamFlags::CONSTRUCT_ONLY,
+ ),
+ glib::ParamSpecObject::new(
+ "texture",
+ "Texture",
+ "Texture",
+ gdk::Texture::static_type(),
+ glib::ParamFlags::READWRITE | glib::ParamFlags::CONSTRUCT_ONLY,
+ ),
+ ]
+ });
+ PROPERTIES.as_ref()
+ }
+
+ fn set_property(
+ &self,
+ _obj: &StickerType,
+ _id: usize,
+ value: &glib::Value,
+ pspec: &glib::ParamSpec,
+ ) {
+ match pspec.name() {
+ "filename" => {
+ let filename = value.get().unwrap();
+ self.filename.replace(filename);
+ }
+ "texture" => {
+ let texture = value.get().unwrap();
+ self.texture.replace(texture);
+ }
+ _ => unimplemented!(),
+ }
+ }
+
+ fn property(&self, _obj: &StickerType, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
+ match pspec.name() {
+ "filename" => self.filename.borrow().to_value(),
+ "texture" => self.texture.borrow().to_value(),
+ _ => unimplemented!(),
+ }
+ }
+}
+
+glib::wrapper! {
+ pub struct StickerType(ObjectSubclass<Sticker>);
+}
+
+impl StickerType {
+ pub fn new(filename: String, path: &Path) -> StickerType {
+ let texture = gdk::Texture::from_filename(path).unwrap();
+ glib::Object::new(&[("filename", &filename), ("texture", &texture)])
+ .expect("Failed to create Sticker")
+ }
+
+ pub fn filename(&self) -> Option<String> {
+ let imp = self.imp();
+ let filename = imp.filename.borrow();
+ if let Some(filename) = filename.as_ref() {
+ Some(filename.clone())
+ } else {
+ None
+ }
+ }
+
+ pub fn texture(&self) -> Option<gdk::Texture> {
+ let imp = self.imp();
+ let texture = imp.texture.borrow();
+ if let Some(texture) = texture.as_ref() {
+ Some(texture.clone())
+ } else {
+ None
+ }
+ }
+}