diff --git a/citadel-realms-ui/Cargo.toml b/citadel-realms-ui/Cargo.toml deleted file mode 100644 index d99e15d..0000000 --- a/citadel-realms-ui/Cargo.toml +++ /dev/null @@ -1,19 +0,0 @@ -[package] -name = "citadel-realms-ui" -description = "Citadel Realms UI" -version = "0.1.0" -authors = ["Bruce Leidl "] -edition = "2018" -homepage = "https://subgraph,com" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -dbus = "0.8" -nix = "0.17.0" -fuzzy-matcher = "0.3.7" -gtk = "0.9.0" -gdk = "0.13.2" -gio = "0.9.1" -glib = "0.10.2" -pango = "0.9.1" diff --git a/citadel-realms-ui/citadel-realms-ui_0.1.0.bb b/citadel-realms-ui/citadel-realms-ui_0.1.0.bb deleted file mode 100644 index 12f90f6..0000000 --- a/citadel-realms-ui/citadel-realms-ui_0.1.0.bb +++ /dev/null @@ -1,202 +0,0 @@ -# Auto-Generated by cargo-bitbake 0.3.14 -# -inherit cargo - -# If this is git based prefer versioned ones if they exist -# DEFAULT_PREFERENCE = "-1" - -# how to get citadel-realms-ui could be as easy as but default to a git checkout: -# SRC_URI += "crate://crates.io/citadel-realms-ui/0.1.0" -SRC_URI += "git://github.com/mckinney-subgraph/citadel-tools;protocol=https;nobranch=1;branch=installer_ui" -SRCREV = "695dc9da2115f5f3f731b711b4b127b45d7a137f" -S = "${WORKDIR}/git" -CARGO_SRC_DIR = "citadel-realms-ui" -PV_append = ".AUTOINC+695dc9da21" - -# please note if you have entries that do not begin with crate:// -# you must change them to how that package can be fetched -SRC_URI += " \ - crate://crates.io/addr2line/0.12.1 \ - crate://crates.io/adler32/1.1.0 \ - crate://crates.io/ansi_term/0.11.0 \ - crate://crates.io/anyhow/1.0.33 \ - crate://crates.io/arc-swap/0.4.7 \ - crate://crates.io/array-macro/1.0.3 \ - crate://crates.io/atk-sys/0.10.0 \ - crate://crates.io/atk/0.9.0 \ - crate://crates.io/atty/0.2.14 \ - crate://crates.io/autocfg/1.0.0 \ - crate://crates.io/backtrace/0.3.49 \ - crate://crates.io/bincode/1.2.1 \ - crate://crates.io/bitflags/1.2.1 \ - crate://crates.io/block-buffer/0.9.0 \ - crate://crates.io/block-cipher/0.7.1 \ - crate://crates.io/blowfish/0.5.0 \ - crate://crates.io/byteorder/1.3.4 \ - crate://crates.io/cairo-rs/0.9.1 \ - crate://crates.io/cairo-sys-rs/0.10.0 \ - crate://crates.io/cc/1.0.54 \ - crate://crates.io/cfg-if/0.1.10 \ - crate://crates.io/chrono/0.4.11 \ - crate://crates.io/clap/2.33.1 \ - crate://crates.io/cpuid-bool/0.1.2 \ - crate://crates.io/crc32fast/1.2.0 \ - crate://crates.io/crossbeam-channel/0.3.9 \ - crate://crates.io/crossbeam-utils/0.6.6 \ - crate://crates.io/crypto-mac/0.8.0 \ - crate://crates.io/cursive/0.11.0 \ - crate://crates.io/dbus/0.6.5 \ - crate://crates.io/dbus/0.8.4 \ - crate://crates.io/digest/0.9.0 \ - crate://crates.io/either/1.6.1 \ - crate://crates.io/enum-map-derive/0.4.3 \ - crate://crates.io/enum-map-internals/0.1.3 \ - crate://crates.io/enum-map/0.5.0 \ - crate://crates.io/enumset/0.3.19 \ - crate://crates.io/enumset_derive/0.3.2 \ - crate://crates.io/failure/0.1.8 \ - crate://crates.io/failure_derive/0.1.8 \ - crate://crates.io/filetime/0.2.10 \ - crate://crates.io/futures-channel/0.3.6 \ - crate://crates.io/futures-core/0.3.6 \ - crate://crates.io/futures-executor/0.3.6 \ - crate://crates.io/futures-io/0.3.6 \ - crate://crates.io/futures-macro/0.3.6 \ - crate://crates.io/futures-sink/0.3.6 \ - crate://crates.io/futures-task/0.3.6 \ - crate://crates.io/futures-util/0.3.6 \ - crate://crates.io/futures/0.3.6 \ - crate://crates.io/fuzzy-matcher/0.3.7 \ - crate://crates.io/gdk-pixbuf-sys/0.10.0 \ - crate://crates.io/gdk-pixbuf/0.9.0 \ - crate://crates.io/gdk-sys/0.10.0 \ - crate://crates.io/gdk/0.13.2 \ - crate://crates.io/generic-array/0.14.4 \ - crate://crates.io/getrandom/0.1.15 \ - crate://crates.io/gimli/0.21.0 \ - crate://crates.io/gio-sys/0.10.1 \ - crate://crates.io/gio/0.9.1 \ - crate://crates.io/glib-macros/0.10.1 \ - crate://crates.io/glib-sys/0.10.1 \ - crate://crates.io/glib/0.10.2 \ - crate://crates.io/gobject-sys/0.10.0 \ - crate://crates.io/gtk-sys/0.10.0 \ - crate://crates.io/gtk/0.9.2 \ - crate://crates.io/heck/0.3.1 \ - crate://crates.io/hermit-abi/0.1.14 \ - crate://crates.io/hex/0.4.2 \ - crate://crates.io/hmac/0.8.1 \ - crate://crates.io/inotify-sys/0.1.3 \ - crate://crates.io/inotify/0.8.3 \ - crate://crates.io/itertools/0.9.0 \ - crate://crates.io/lazy_static/1.4.0 \ - crate://crates.io/libc/0.2.71 \ - crate://crates.io/libdbus-sys/0.2.1 \ - crate://crates.io/libflate/0.1.27 \ - crate://crates.io/libsodium-sys/0.2.5 \ - crate://crates.io/log/0.4.8 \ - crate://crates.io/md-5/0.9.1 \ - crate://crates.io/memchr/2.3.3 \ - crate://crates.io/miniz_oxide/0.3.7 \ - crate://crates.io/nix/0.17.0 \ - crate://crates.io/num-complex/0.2.4 \ - crate://crates.io/num-integer/0.1.43 \ - crate://crates.io/num-iter/0.1.41 \ - crate://crates.io/num-rational/0.2.4 \ - crate://crates.io/num-traits/0.2.12 \ - crate://crates.io/num/0.2.1 \ - crate://crates.io/numtoa/0.1.0 \ - crate://crates.io/object/0.20.0 \ - crate://crates.io/once_cell/1.4.0 \ - crate://crates.io/opaque-debug/0.2.3 \ - crate://crates.io/opaque-debug/0.3.0 \ - crate://crates.io/owning_ref/0.4.1 \ - crate://crates.io/pango-sys/0.10.0 \ - crate://crates.io/pango/0.9.1 \ - crate://crates.io/pin-project-internal/0.4.22 \ - crate://crates.io/pin-project/0.4.22 \ - crate://crates.io/pin-utils/0.1.0 \ - crate://crates.io/pkg-config/0.3.17 \ - crate://crates.io/ppv-lite86/0.2.9 \ - crate://crates.io/proc-macro-crate/0.1.5 \ - crate://crates.io/proc-macro-error-attr/1.0.4 \ - crate://crates.io/proc-macro-error/1.0.4 \ - crate://crates.io/proc-macro-hack/0.5.16 \ - crate://crates.io/proc-macro-nested/0.1.6 \ - crate://crates.io/proc-macro2/0.4.30 \ - crate://crates.io/proc-macro2/1.0.18 \ - crate://crates.io/pwhash/0.3.1 \ - crate://crates.io/quote/0.6.13 \ - crate://crates.io/quote/1.0.7 \ - crate://crates.io/rand/0.7.3 \ - crate://crates.io/rand_chacha/0.2.2 \ - crate://crates.io/rand_core/0.5.1 \ - crate://crates.io/rand_hc/0.2.0 \ - crate://crates.io/redox_syscall/0.1.56 \ - crate://crates.io/redox_termios/0.1.1 \ - crate://crates.io/rle-decode-fast/1.0.1 \ - crate://crates.io/rpassword/4.0.5 \ - crate://crates.io/rustc-demangle/0.1.16 \ - crate://crates.io/same-file/1.0.6 \ - crate://crates.io/serde/1.0.112 \ - crate://crates.io/serde_derive/1.0.112 \ - crate://crates.io/sha-1/0.9.1 \ - crate://crates.io/sha2/0.9.1 \ - crate://crates.io/signal-hook-registry/1.2.0 \ - crate://crates.io/signal-hook/0.1.16 \ - crate://crates.io/slab/0.4.2 \ - crate://crates.io/sodiumoxide/0.2.5 \ - crate://crates.io/stable_deref_trait/1.1.1 \ - crate://crates.io/strsim/0.8.0 \ - crate://crates.io/strum/0.18.0 \ - crate://crates.io/strum_macros/0.18.0 \ - crate://crates.io/subtle/2.3.0 \ - crate://crates.io/syn/0.15.44 \ - crate://crates.io/syn/1.0.31 \ - crate://crates.io/synstructure/0.12.4 \ - crate://crates.io/system-deps/1.3.2 \ - crate://crates.io/take_mut/0.2.2 \ - crate://crates.io/tar/0.4.29 \ - crate://crates.io/termion/1.5.5 \ - crate://crates.io/textwrap/0.11.0 \ - crate://crates.io/thiserror-impl/1.0.21 \ - crate://crates.io/thiserror/1.0.21 \ - crate://crates.io/thread_local/1.0.1 \ - crate://crates.io/time/0.1.43 \ - crate://crates.io/toml/0.4.10 \ - crate://crates.io/toml/0.5.6 \ - crate://crates.io/typenum/1.12.0 \ - crate://crates.io/unicode-segmentation/1.6.0 \ - crate://crates.io/unicode-width/0.1.7 \ - crate://crates.io/unicode-xid/0.1.0 \ - crate://crates.io/unicode-xid/0.2.0 \ - crate://crates.io/vcpkg/0.2.10 \ - crate://crates.io/vec_map/0.8.2 \ - crate://crates.io/version-compare/0.0.10 \ - crate://crates.io/version_check/0.9.2 \ - crate://crates.io/void/1.0.2 \ - crate://crates.io/walkdir/2.3.1 \ - crate://crates.io/wasi/0.9.0+wasi-snapshot-preview1 \ - crate://crates.io/winapi-i686-pc-windows-gnu/0.4.0 \ - crate://crates.io/winapi-util/0.1.5 \ - crate://crates.io/winapi-x86_64-pc-windows-gnu/0.4.0 \ - crate://crates.io/winapi/0.3.9 \ - crate://crates.io/xattr/0.2.2 \ - crate://crates.io/xi-unicode/0.1.0 \ -" - - - -# FIXME: update generateme with the real MD5 of the license file -LIC_FILES_CHKSUM = " \ - " - -SUMMARY = "Citadel Realms UI" -HOMEPAGE = "https://subgraph,com" -LICENSE = "CLOSED" - -# includes this file if it exists but does not fail -# this is useful for anything you may want to override from -# what cargo-bitbake generates. -include citadel-realms-ui-${PV}.inc -include citadel-realms-ui.inc diff --git a/citadel-realms-ui/data/config-dialog.ui b/citadel-realms-ui/data/config-dialog.ui deleted file mode 100644 index bd3a293..0000000 --- a/citadel-realms-ui/data/config-dialog.ui +++ /dev/null @@ -1,216 +0,0 @@ - - - - - - 600 - False - True - - - - - - True - False - 20 - 20 - 20 - 30 - vertical - - - True - False - 10 - 20 - 10 - - - True - False - 10 - computer - 3 - - - False - True - 1 - - - - - True - False - - - - False - True - 2 - - - - - False - True - 0 - - - - - True - False - start - 10 - Options - - - - False - True - 1 - - - - - True - False - 20 - 20 - 20 - vertical - - - - - - - - - - - - False - True - 2 - - - - - True - False - 60 - - - True - False - start - RealmFS - - - - 0 - 0 - - - - - True - False - start - - - 1 - 0 - - - - - True - False - start - Overlay - - - - 0 - 1 - - - - - True - False - start - - None - TmpFS - Storage Partition - - - - 1 - 1 - - - - - True - False - start - Terminal Theme - - - - 0 - 2 - - - - - True - True - True - - - 1 - 2 - - - - - False - True - 3 - - - - - - - - - - - - - - - diff --git a/citadel-realms-ui/data/config-option.ui b/citadel-realms-ui/data/config-option.ui deleted file mode 100644 index 88a2649..0000000 --- a/citadel-realms-ui/data/config-option.ui +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - True - False - - - True - True - False - True - - - False - True - 0 - - - - - True - False - Hehehehe - - - - False - True - 1 - - - - - diff --git a/citadel-realms-ui/data/config.ui b/citadel-realms-ui/data/config.ui deleted file mode 100644 index 0482d2c..0000000 --- a/citadel-realms-ui/data/config.ui +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - vertical - - - vertical - - - - - - - diff --git a/citadel-realms-ui/data/main.ui b/citadel-realms-ui/data/main.ui deleted file mode 100644 index 156fc59..0000000 --- a/citadel-realms-ui/data/main.ui +++ /dev/null @@ -1,95 +0,0 @@ - - - - - 600 - False - True - center - - - - - vertical - 20 - 20 - 20 - 20 - 20 - - - - horizontal - 10 - - - - computer - - - False - False - 0 - - - - - - start - - - - False - False - 1 - - - - - False - False - 0 - - - - - - - - - - - True - True - 1 - - - - - - - - vertical - True - - - - False - True - 2 - - - - - - - - diff --git a/citadel-realms-ui/data/result.ui b/citadel-realms-ui/data/result.ui deleted file mode 100644 index 5b7ffd6..0000000 --- a/citadel-realms-ui/data/result.ui +++ /dev/null @@ -1,63 +0,0 @@ - - - - - 25 - - - - - 20 - - - False - - - - - - vertical - 5 - - - - - - start - - - - True - False - - - - - - True - start - 10 - - - - False - - - - - - True - True - - - - diff --git a/citadel-realms-ui/data/style.css b/citadel-realms-ui/data/style.css deleted file mode 100644 index 3946321..0000000 --- a/citadel-realms-ui/data/style.css +++ /dev/null @@ -1,121 +0,0 @@ -/** - * App Window - */ -@define-color bg_color #3C4141; -@define-color window_bg @bg_color; -@define-color window_border_color #3A3A3A; - -/** - * Current realm - */ -@define-color realm_name #FFFDF7; - -/** - * Input - */ -@define-color selected_bg_color #4675ab; -@define-color selected_fg_color #d5eaff; -@define-color input_color #ddd; -@define-color caret_color darker(@input_color); - -/** - * Result items - */ -@define-color item_name #ddd; -@define-color item_text #999; -@define-color item_box_selected #285C99; -@define-color item_text_selected #99ccff; -@define-color item_name_selected #eee; - -@binding-set ConfigFocus -{ - bind "j" { "move-focus" (down) }; - bind "k" { "move-focus" (up) }; -} - -checkbutton:focus + label { - border-bottom-style: solid; - border-bottom-width: 1px; - border-bottom-color: #008cb3; -} - -.config-main-box { - -gtk-key-bindings: ConfigFocus; -} -.config-dialog { - -gtk-key-bindings: ConfigFocus; -} - -.main-window { - background-color: @window_bg; - border-color: @window_border_color; - border-radius: 5px; -} - -.input-entry { - color: @input_color; -} - -/** - * Selected text in input - */ -.input-entry *:selected, -.input-entry *:focus, -*:selected:focus { - background-color: alpha (@selected_bg_color, 0.9); - color: @selected_fg_color; -} - -.config-heading { -/* - padding-top: 10px; - padding-bottom: 10px; - */ - font: 20px Sans; -} - -.config-realm-name { - font: 20px Sans; - color: @realm_name; -} - -.current-realm { - font: 20px Sans; - color: @realm_name; -} - -.item-text { - color: @item_text; -} -.item-name { - color: @item_name; -} - -.config-option.selected { - background-color: #56f9a0; -} - -.selected.item-entry { - background-color: @item_box_selected; -} - -.selected.item-entry .item-text { - color: @item_text_selected; -} - -.selected.item-entry .item-name { - color: @item_name_selected; -} - -.no-window-shadow { - margin: -20px; -} - -window entry { - font: 30px Sans -} - -.item-name { - font: 30px Sans -} - diff --git a/citadel-realms-ui/src/builder.rs b/citadel-realms-ui/src/builder.rs deleted file mode 100644 index d998fd0..0000000 --- a/citadel-realms-ui/src/builder.rs +++ /dev/null @@ -1,55 +0,0 @@ - -use gtk::prelude::*; -use crate::{Error, Result}; - -pub struct Builder { - builder: gtk::Builder, -} - -impl Builder { - pub fn new(source: &str) -> Self { - let builder = gtk::Builder::from_string(source); - Builder { builder } - } - - fn ok_or_err(type_name: &str, name: &str, object: Option) -> Result { - object.ok_or(Error::Builder(format!("failed to load {} {}", type_name, name))) - } - - pub fn get_window(&self, name: &str) -> Result { - Self::ok_or_err("GtkWindow", name, self.builder.get_object(name)) - } - - pub fn get_entry(&self, name: &str) -> Result { - Self::ok_or_err("GtkEntry", name, self.builder.get_object(name)) - } - - pub fn get_box(&self, name: &str) -> Result { - Self::ok_or_err("GtkBox", name, self.builder.get_object(name)) - } - - pub fn get_check_button(&self, name: &str) -> Result { - Self::ok_or_err("GtkCheckButton", name, self.builder.get_object(name)) - } - - pub fn get_button(&self, name: &str) -> Result { - Self::ok_or_err("GtkButton", name, self.builder.get_object(name)) - } - - pub fn get_grid(&self, name: &str) -> Result { - Self::ok_or_err("GtkGrid", name, self.builder.get_object(name)) - } - - - pub fn get_label(&self, name: &str) -> Result { - Self::ok_or_err("GtkLabel", name, self.builder.get_object(name)) - } - - pub fn get_image(&self, name: &str) -> Result { - Self::ok_or_err("GtkImage", name, self.builder.get_object(name)) - } - - pub fn get_combo_box_text(&self, name: &str) -> Result { - Self::ok_or_err("GtkComboBoxText", name, self.builder.get_object(name)) - } -} diff --git a/citadel-realms-ui/src/config.rs b/citadel-realms-ui/src/config.rs deleted file mode 100644 index 94932ba..0000000 --- a/citadel-realms-ui/src/config.rs +++ /dev/null @@ -1,121 +0,0 @@ - -use gtk::prelude::*; -use gdk::ModifierType; -use gdk::keys::constants; -use crate::{Result,Builder}; -use crate::realms::Entity; -use std::collections::HashMap; - -static CONFIG_FLAGS: &[(&str, &str)] = &[ - ("use-gpu", "Use GPU in Realm"), - ("use-wayland", "Use Wayland in Realm"), - ("use-x11", "Use X11 in Realm"), - ("use-sound", "Use Sound in Realm"), - ("use-shared-dir", "Mount /Shared directory in Realm"), - ("use-network", "Realm has network access"), - ("use-kvm", "Use KVM (/dev/kvm) in Realm"), - ("use-ephemeral-home", "Use ephemeral tmpfs mount for home directory"), -]; - -const CONFIG_DIALOG: &str = include_str!("../data/config-dialog.ui"); -const CONFIG_OPTION: &str = include_str!("../data/config-option.ui"); - -#[allow(dead_code)] -struct ConfigOption { - name: &'static str, - option: gtk::Box, - check: gtk::CheckButton, - style: gtk::StyleContext, -} - -impl ConfigOption { - fn create(name: &'static str, description: &str, val: bool) -> Result { - let builder = Builder::new(CONFIG_OPTION); - let option = builder.get_box("config-option")?; - - let check = builder.get_check_button("config-option-check")?; - check.set_active(val); - let label = builder.get_label("config-option-label")?; - label.set_text(description); - let style = option.get_style_context(); - Ok(ConfigOption { name, option, check, style }) - } -} - -#[allow(dead_code)] -pub struct ConfigDialog { - options: Vec, -} - -impl ConfigDialog { - - pub fn open(realm: &Entity, config: HashMap, parent: >k::Window) -> Result { - let builder = Builder::new(CONFIG_DIALOG); - let window = builder.get_window("config-dialog")?; - let option_list = builder.get_box("config-option-list")?; - let name_label = builder.get_label("config-realm-name")?; - - name_label.set_text(realm.name()); - window.set_decorated(false); - - let mut options = Vec::new(); - for (name,desc) in CONFIG_FLAGS { - let val = match config.get(*name).map(|s| s.as_str()) { - Some("true") => true, - Some("false") => false, - _ => false, - }; - let option = ConfigOption::create(name, desc, val)?; - option_list.pack_start(&option.option, false, false, 5); - options.push(option); - } - - let overlay = builder.get_combo_box_text("config-overlay-combo")?; - println!("config: {:?}", config); - let overlay_id = match config.get("overlay").map(|s| s.as_str()) { - Some("tmpfs") => "overlay-tmpfs", - Some("storage") => "overlay-storage", - _ => "overlay-none" - }; - overlay.set_active_id(Some(overlay_id)); - - let realmfs = builder.get_combo_box_text("config-realmfs-combo")?; - for fs in realm.realmfs_list() { - println!("adding {}", fs.name()); - // realmfs.append(Some(fs.name()), fs.name()); - ComboBoxTextExt::append(&realmfs, Some(fs.name()), fs.name()); - } - - let scheme = builder.get_button("theme-choose-button")?; - if let Some(name) = config.get("terminal-scheme") { - // scheme.set_label(name); - ButtonExt::set_label(&scheme, name); - } - - window.set_opacity(0.85); - window.set_transient_for(Some(parent)); - parent.hide(); - window.show_all(); - window.connect_key_press_event({ - let win = window.clone(); - let parent = parent.clone(); - move |_,key| { - let state = key.get_state(); - let keyval = key.get_keyval(); - let esc = keyval == constants::Escape || - (state == ModifierType::CONTROL_MASK && keyval.to_unicode().unwrap() == '['); - if esc { - parent.show(); - unsafe { - win.destroy(); - } - } - Inhibit(false) - - } - }); - - Ok(ConfigDialog { options }) - } -} - diff --git a/citadel-realms-ui/src/error.rs b/citadel-realms-ui/src/error.rs deleted file mode 100644 index 6107ecb..0000000 --- a/citadel-realms-ui/src/error.rs +++ /dev/null @@ -1,13 +0,0 @@ - -use std::result; - -use dbus; - -pub type Result = result::Result; - -#[derive(Debug)] -pub enum Error { - Dbus(dbus::Error), - Nix(nix::Error), - Builder(String), -} diff --git a/citadel-realms-ui/src/instance.rs b/citadel-realms-ui/src/instance.rs deleted file mode 100644 index 225f9dd..0000000 --- a/citadel-realms-ui/src/instance.rs +++ /dev/null @@ -1,110 +0,0 @@ -use std::os::unix::io::RawFd; -use std::thread; - -use glib::Continue; -use nix::unistd::close; -use nix::errno::Errno; -use nix::sys::socket::{ - socket,listen,bind,connect,accept,AddressFamily,SockType,SockFlag,SockAddr,UnixAddr -}; - -use crate::{Error,Result}; - -static SOCKET_NAME: &[u8] = b"citadel-realms-ui"; - -enum BindResult { - BindOk, - BindFailed(Error), - BindAddrInUse, -} - -/// -/// Determine if another instance is already running and if so signal it to quit. -/// -/// This window is launched from a GNOME shortcut key that is meant to 'toggle' the -/// window so that if the shortcut key is used while the window is already open the -/// running instance will close. -/// -/// This class will attempt to create a Unix domain stream socket in the abstract -/// namespace bound to the fixed name `SOCKET_NAME`. If no other instance is running -/// then this name will be available and the bind will succeed. In this case a thread -/// is spawned to listen for connections to the socket and the process will exit -/// the main GTK loop by calling `gtk::main_quit()` upon a connection to the listening -/// socket. -/// -/// If the bind fails because the socket name is already in use, then another instance is -/// running. A connection is then made to the socket to signal the running instance to exit. -/// -pub struct InstanceTracker { - fd: RawFd, -} - -impl InstanceTracker { - pub fn create() -> Result { - let fd = socket(AddressFamily::Unix, SockType::Stream, SockFlag::empty(), None) - .map_err(Error::Nix)?; - Ok(InstanceTracker { fd } ) - } - - fn addr() -> SockAddr { - SockAddr::Unix(UnixAddr::new_abstract(SOCKET_NAME) - .expect("UnixAddr::new_abstract()")) - } - - fn try_bind(&self) -> BindResult { - let addr = Self::addr(); - match bind(self.fd, &addr) { - Err(nix::Error::Sys(Errno::EADDRINUSE)) => BindResult::BindAddrInUse, - Err(err) => BindResult::BindFailed(Error::Nix(err)), - Ok(()) => BindResult::BindOk, - } - } - - fn connect(&self) -> bool { - let addr = Self::addr(); - if let Err(err) = connect(self.fd, &addr) { - println!("Failed to connect to instance socket: {}", err); - return false; - } - if let Err(err) = close(self.fd) { - println!("error closing socket: {}", err); - } - true - } - - fn spawn_reader(&self) { - thread::spawn({ - let fd = self.fd; - move || { - let _ = listen(fd, 1); - let _ = accept(fd); - glib::idle_add(|| { - gtk::main_quit(); - Continue(false) - }); - } - }); - } - - pub fn bind(&self, toggle: bool) -> bool { - match self.try_bind() { - BindResult::BindAddrInUse => { - if toggle { - self.connect(); - } - false - }, - - BindResult::BindOk => { - self.spawn_reader(); - true - } - BindResult::BindFailed(err) => { - println!("error binding: {:?}", err); - false - } - } - } -} - - diff --git a/citadel-realms-ui/src/main.rs b/citadel-realms-ui/src/main.rs deleted file mode 100644 index 63dacac..0000000 --- a/citadel-realms-ui/src/main.rs +++ /dev/null @@ -1,40 +0,0 @@ -mod config; -mod error; -mod builder; -mod instance; -mod matcher; -mod realms; -mod results; -mod ui; - -use ui::Ui; - -pub use error::{Result,Error}; -pub use builder::Builder; -pub use config::ConfigDialog; - -fn main() { - - let tracker = match instance::InstanceTracker::create() { - Ok(tracker) => tracker, - Err(err) => { - eprintln!("Failed to create instance tracker: {:?}", err); - return; - } - }; - if !tracker.bind(true) { - return; - } - if let Err(err) = gtk::init() { - eprintln!("Failed to initialize GTK: {:?}", err); - return; - } - let ui = match Ui::build() { - Ok(ui) => ui, - Err(err) => { - eprintln!("Error: {:?}", err); - return; - } - }; - ui.run(); -} diff --git a/citadel-realms-ui/src/matcher.rs b/citadel-realms-ui/src/matcher.rs deleted file mode 100644 index 857571d..0000000 --- a/citadel-realms-ui/src/matcher.rs +++ /dev/null @@ -1,177 +0,0 @@ - -use std::rc::Rc; -use fuzzy_matcher::FuzzyMatcher; -use fuzzy_matcher::skim::SkimMatcherV2; - -use crate::results::{ResultList, ResultType}; -use crate::realms::{Realms,Entity}; -use crate::Result; -use std::cmp::Ordering; - -struct RealmMatcher<'a> { - matcher: SkimMatcherV2, - query: &'a str, - rtype: ResultType, - match_all: bool, - match_current: bool, - match_system: bool, - match_running_only: bool, -} - -impl <'a> RealmMatcher<'a> { - fn new(query: &'a str, rtype: ResultType, match_all: bool, match_current: bool, match_running_only: bool) -> Self { - RealmMatcher { - matcher: SkimMatcherV2::default(), - query, rtype, match_all, match_current, match_running_only, - match_system: false, - } - } - - fn terminal_matcher(query: &'a str) -> Self { - RealmMatcher::new(query, ResultType::Terminal, false, true, false) - } - - fn stop_realm_matcher(query: &'a str) -> Self { - RealmMatcher::new(query, ResultType::StopRealm, false, true, true) - } - - fn restart_realm_matcher(query: &'a str) -> Self { - RealmMatcher::new(query, ResultType::RestartRealm, false, true, true) - } - - fn config_realm_matcher(query: &'a str) -> Self { - RealmMatcher::new(query, ResultType::ConfigRealm, false, true, false) - } - - fn update_realmfs_matcher(query: &'a str) -> Self { - RealmMatcher::new(query, ResultType::UpdateRealmFS, false, true, false) - } - - fn all_realms_matcher() -> Self { - RealmMatcher::new("", ResultType::Realm, true, false, false) - } - - fn realms_matcher(query: &'a str) -> Self { - RealmMatcher::new(query, ResultType::Realm, false, false, false) - } - - fn match_realm_query(&self, realm: &Entity) -> Option { - self.matcher.fuzzy_indices(realm.name(), self.query) - .map(|(score, indices)| - realm.clone_with_match_info(score, indices)) - } - - fn match_realm_flags(&self, realm: &Entity) -> bool { - if !self.match_current && realm.is_current() { - false - } else if !self.match_system && realm.is_system_realm() { - false - } else if self.match_running_only && !realm.is_running() { - false - } else { - true - } - } - - fn match_realm(&self, realm: &Entity) -> Option { - let flags_ok = self.match_realm_flags(realm); - if self.match_all && flags_ok { - Some(realm.clone()) - } else if flags_ok { - self.match_realm_query(realm) - } else { - None - } - } - - fn sort_realms(&self, realms: &mut Vec) { - realms.sort_by(|a, b| { - if a.is_running() && !b.is_running() { - Ordering::Less - } else if b.is_running() && !a.is_running() { - Ordering::Greater - } else { - a.match_score().cmp(&b.match_score()) - } - }) - } - - fn is_realmfs_update(&self) -> bool { - self.rtype == ResultType::UpdateRealmFS - } - - fn _match_realmfs(&self, _realms: &[Entity], _realmfs: &[Entity]) -> (Vec, Vec) { - (Vec::new(), Vec::new()) - } - - fn match_realm_list(&self, realms: &[Entity]) -> Vec { - let mut matched = Vec::new(); - - for r in realms { - if let Some(realm) = self.match_realm(r) { - matched.push(realm); - } - } - self.sort_realms(&mut matched); - matched - } - - fn result_type(&self) -> ResultType { - self.rtype - } -} - -#[derive(Clone)] -pub struct Matcher { - realms: Rc, -} - -impl Matcher { - pub fn new() -> Result { - let mut realms = Realms::connect()?; - realms.reload_realms()?; - let realms = Rc::new(realms); - - Ok(Matcher { realms }) - } - - pub fn current_realm(&self) -> Option<&Entity> { - self.realms.current_realm() - } - - fn parse(text: &str) -> RealmMatcher { - if text == "*" { - return RealmMatcher::all_realms_matcher(); - } - if let Some(idx) = text.find(' ') { - let (a, b) = text.split_at(idx); - let b = &b[1..]; - match a { - "t" => RealmMatcher::terminal_matcher(b), - "s" => RealmMatcher::stop_realm_matcher(b), - "r" => RealmMatcher::restart_realm_matcher(b), - "c" => RealmMatcher::config_realm_matcher(b), - "u" => RealmMatcher::update_realmfs_matcher(b), - _ => RealmMatcher::realms_matcher(text) - } - } else { - RealmMatcher::realms_matcher(text) - } - } - - pub fn update(&self, text: &str, results: &ResultList) { - results.clear_list(); - if text.is_empty() { - return; - } - - let matcher = Self::parse(text); - if matcher.is_realmfs_update() { - let realms = matcher.match_realm_list(self.realms.realmfs()); - results.create_result_items(matcher.result_type(), realms); - } else { - let realms = matcher.match_realm_list(self.realms.realms()); - results.create_result_items(matcher.result_type(), realms); - } - } -} diff --git a/citadel-realms-ui/src/realms.rs b/citadel-realms-ui/src/realms.rs deleted file mode 100644 index f735bfb..0000000 --- a/citadel-realms-ui/src/realms.rs +++ /dev/null @@ -1,244 +0,0 @@ - -use std::time::Duration; -use std::rc::Rc; -use std::cell::RefCell; - -use dbus::blocking::{Connection,Proxy}; -use crate::{Result, Error, ConfigDialog}; -use std::collections::HashMap; - - -#[derive(Clone,PartialEq)] -enum EntityType{ - Realm, - RealmFS, -} - -#[derive(Clone)] -pub struct Entity { - realms: RefCell, - etype: EntityType, - name: String, - description: Option, - realmfs: Option, - flags: Option, - match_score: i64, - match_indices: Option>, -} - -impl Entity { - fn new_realm(realms: Realms, (name, description, realmfs, flags): (String, String, String, u8)) -> Self { - Self::new(realms, EntityType::Realm, name, Some(description), Some(realmfs), Some(flags as usize)) - } - - fn new_realmfs(realms: Realms, name: String) -> Self { - Self::new(realms, EntityType::RealmFS, name, None, None, None) - } - - fn new(realms: Realms, etype: EntityType, name: String, description: Option, realmfs: Option, flags: Option) -> Self { - let realms = RefCell::new(realms); - let match_score = 0; - let match_indices = None; - Entity { realms, etype, name, description, realmfs, flags, match_score, match_indices } - } - - pub fn name(&self) -> &str { - &self.name - } - - pub fn description(&self) -> &str { - self.description.as_ref().map(|s| s.as_str()).unwrap_or("") - } - - fn has_flag(&self, flag: usize) -> bool { - self.flags.map(|v| v & flag != 0).unwrap_or(false) - } - pub fn is_running(&self) -> bool { - self.has_flag(0x01) - } - - pub fn is_system_realm(&self) -> bool { - self.has_flag(0x04) - } - - pub fn is_current(&self) -> bool { - self.has_flag(0x02) - } - - pub fn is_realm(&self) -> bool { - self.etype == EntityType::Realm - } - - pub fn realmfs_list(&self) -> Vec { - self.realms.borrow().cached_realmfs.clone() - } - - fn with_realm(&self, f: F) -> bool - where F: Fn(&str) -> Result<()> - { - if !self.is_realm() { - return false; - } - if let Err(err) = f(self.name()) { - println!("error calling dbus method: {:?}", err); - } - true - } - - pub fn activate(&self) -> bool { - self.with_realm(|name| self.realms.borrow().set_current_realm(name)) - } - pub fn open_terminal(&self) -> bool { - self.with_realm(|name| self.realms.borrow().open_terminal(name)) - } - - pub fn stop_realm(&self) -> bool { - self.with_realm(|name| self.realms.borrow().stop_realm(name)) - } - pub fn restart_realm(&self) -> bool { - self.with_realm(|name| self.realms.borrow().restart_realm(name)) - } - - pub fn config_realm(&self, window: >k::Window) -> bool { - if !self.is_realm() { - return false; - } - let config = match self.realms.borrow().get_realm_config(self.name()) { - Ok(config) => config, - Err(err) => { - println!("Error requesting realm config for {}: {:?}", self.name(), err); - return false; - } - }; - let config: HashMap = config.into_iter().collect(); - let _c = ConfigDialog::open(self, config, window); - false - } - - pub fn update_realmfs(&self) -> bool { - if self.is_realm() { - return false; - } - if let Err(err) = self.realms.borrow().update_realmfs(self.name()) { - println!("error calling dbus method: {:?}", err); - } - true - } - - - pub fn clone_with_match_info(&self, score: i64, indices: Vec) -> Self { - let mut e = self.clone(); - e.match_score = score; - e.match_indices = Some(indices); - e - } - - pub fn match_indices(&self) -> Option<&[usize]> { - self.match_indices.as_ref().map(|v| v.as_slice()) - } - - pub fn match_score(&self) -> i64 { - self.match_score - } - -} - - - -#[derive(Clone)] -pub struct Realms { - conn: Rc, - cached_realms: Vec, - cached_realmfs: Vec, -} - -impl Realms { - - pub fn connect() -> Result { - let conn = Connection::new_system().map_err(Error::Dbus)?; - let conn = Rc::new(conn); - let cached_realms = Vec::new(); - let cached_realmfs = Vec::new(); - Ok(Realms { conn, cached_realms, cached_realmfs }) - } - - pub fn current_realm(&self) -> Option<&Entity> { - self.cached_realms.iter().find(|r| r.is_current()) - } - - - fn with_proxy<'a>(&self) -> Proxy<'a, &Connection> { - self.conn.with_proxy("com.subgraph.realms", - "/com/subgraph/realms", - Duration::from_millis(5000)) - } - - pub fn realms(&self) -> &[Entity] { - &self.cached_realms - } - - pub fn realmfs(&self) -> &[Entity] { - &self.cached_realmfs - } - - pub fn reload_realms(&mut self) -> Result<()> { - let realms = self.list()?; - self.cached_realms.clear(); - self.cached_realms.extend_from_slice(&realms); - - let realmfs = self.get_realmfs_list()?; - self.cached_realmfs.clear(); - self.cached_realmfs.extend_from_slice(&realmfs); - Ok(()) - } - - pub fn list(&self) -> Result> { - let (list,): (Vec<(String, String, String, u8)>,) = self.with_proxy().method_call("com.subgraph.realms.Manager", "List", ()).map_err(Error::Dbus)?; - let realms = list.into_iter() - .map(|(n,d,fs, f)| Entity::new_realm(self.clone(), (n,d,fs,f))) - .collect(); - Ok(realms) - } - - pub fn open_terminal(&self, realm: &str) -> Result<()> { - self.with_proxy().method_call("com.subgraph.realms.Manager", "Terminal", (realm,)) - .map_err(Error::Dbus)?; - Ok(()) - } - - pub fn stop_realm(&self, realm: &str) -> Result<()> { - self.with_proxy().method_call("com.subgraph.realms.Manager", "Stop", (realm,)) - .map_err(Error::Dbus)?; - Ok(()) - } - - pub fn restart_realm(&self, realm: &str) -> Result<()> { - self.with_proxy().method_call("com.subgraph.realms.Manager", "Restart", (realm,)) - .map_err(Error::Dbus)?; - Ok(()) - } - - pub fn set_current_realm(&self, realm: &str) -> Result<()> { - self.with_proxy().method_call("com.subgraph.realms.Manager", "SetCurrent", (realm,)) - .map_err(Error::Dbus)?; - Ok(()) - } - - pub fn update_realmfs(&self, realmfs: &str) -> Result<()> { - self.with_proxy().method_call("com.subgraph.realms.Manager", "UpdateRealmFS", (realmfs,)) - .map_err(Error::Dbus)?; - Ok(()) - } - - pub fn get_realm_config(&self, realm: &str) -> Result> { - let (config,): (Vec<(String,String)>,) = self.with_proxy().method_call("com.subgraph.realms.Manager", "RealmConfig", (realm, )) - .map_err(Error::Dbus)?; - Ok(config) - } - - pub fn get_realmfs_list(&self) -> Result> { - let (list,): (Vec,) = self.with_proxy().method_call("com.subgraph.realms.Manager", "ListRealmFS", ()) - .map_err(Error::Dbus)?; - Ok(list.into_iter().map(|name| Entity::new_realmfs(self.clone(), name)).collect()) - } -} diff --git a/citadel-realms-ui/src/results.rs b/citadel-realms-ui/src/results.rs deleted file mode 100644 index ccb7aca..0000000 --- a/citadel-realms-ui/src/results.rs +++ /dev/null @@ -1,292 +0,0 @@ -use std::rc::Rc; -use std::cell::{RefCell,RefMut}; - - -use gtk::prelude::*; -use gtk::{IconSize}; - -use crate::realms::Entity; -use crate::{Result,Builder}; - -const UI: &str = include_str!("../data/result.ui"); - -#[derive(Debug,Copy,Clone,PartialEq)] -pub enum ResultType { - ConfigRealm, - Realm, - Terminal, - StopRealm, - RestartRealm, - UpdateRealmFS, -} - -#[derive(Clone)] -struct ResultItem { - entity: Entity, - item: gtk::Box, - style: gtk::StyleContext, - result_type: ResultType, -} - -impl ResultItem { - - pub fn create(result_type: ResultType, entity: &Entity, parent: >k::Box) -> Result { - let entity = entity.clone(); - let builder = Builder::new(UI); - let item = builder.get_box("item-entry")?; - let icon = builder.get_image("item-icon")?; - let name = builder.get_label("item-name")?; - let desc = builder.get_label("item-description")?; - - if entity.is_realm() { - name.set_text(entity.name()); - } else { - name.set_text(&format!("{}-realmfs", entity.name())); - } - - match result_type { - ResultType::ConfigRealm => { - icon.set_from_icon_name(Some("emblem-system"), IconSize::Dialog); - desc.set_text("Configure Realm"); - if let Some(indices) = entity.match_indices() { - Self::highlight_indices(&name, indices); - } - }, - ResultType::Realm => { - icon.set_from_icon_name(Some("computer"), IconSize::Dialog); - icon.set_sensitive(entity.is_running()); - if let Some(indices) = entity.match_indices() { - Self::highlight_indices(&name, indices); - } - - if entity.description().is_empty() { - unsafe { - desc.destroy(); - } - } else { - desc.set_text(entity.description()); - } - }, - ResultType::Terminal => { - desc.set_text("Open Terminal"); - icon.set_from_icon_name(Some("utilities-terminal"), IconSize::Dialog); - icon.set_sensitive(entity.is_running()); - if let Some(indices) = entity.match_indices() { - Self::highlight_indices(&name, indices); - } - } - ResultType::StopRealm => { - desc.set_text("Stop Realm"); - icon.set_from_icon_name(Some("system-shutdown-symbolic"), IconSize::Dialog); - if let Some(indices) = entity.match_indices() { - Self::highlight_indices(&name, indices); - } - } - ResultType::RestartRealm => { - desc.set_text("Restart Realm"); - icon.set_from_icon_name(Some("system-reboot-symbolic"), IconSize::Dialog); - if let Some(indices) = entity.match_indices() { - Self::highlight_indices(&name, indices); - } - } - - ResultType::UpdateRealmFS => { - desc.set_text("Update RealmFS"); - icon.set_from_icon_name(Some("drive-harddisk-symbolic"), IconSize::Dialog); - if let Some(indices) = entity.match_indices() { - Self::highlight_indices(&name, indices); - } - - } - } - - parent.pack_start(&item, false, true, 0); - let style = item.get_style_context(); - item.show_all(); - Ok(ResultItem { entity, item, style, result_type }) - } - - fn highlight_range(attrs: &pango::AttrList, start: u32, end: u32) { - let mut a = pango::Attribute::new_foreground(40000, 40000, 40000).unwrap(); - a.set_start_index(start); - a.set_end_index(end); - attrs.insert(a); - } - - fn indices_to_ranges(indices: &[usize]) -> Vec<(u32, u32)> { - let mut ranges = Vec::new(); - if indices.is_empty() { - return ranges; - } - - let first = indices[0] as u32; - let mut current = (first, first); - - for i in &indices[1..] { - let idx = *i as u32; - if current.1 + 1 == idx { - current.1 = idx; - } else { - ranges.push(current); - current = (idx, idx); - } - } - ranges.push(current); - ranges - } - - fn highlight_indices(label: >k::Label, indices: &[usize]) { - if indices.is_empty() { - return; - } - let ranges = Self::indices_to_ranges(indices); - let attrs = pango::AttrList::new(); - for (start, end) in ranges { - Self::highlight_range(&attrs, start, end + 1); - } - LabelExt::set_attributes(label, Some(&attrs)); - } - - - fn set_selected(&self) { - self.style.add_class("selected"); - } - - fn set_unselected(&self) { - self.style.remove_class("selected"); - } - - fn activate(&self, window: >k::Window) -> bool { - match self.result_type { - ResultType::Realm => self.entity.activate(), - ResultType::Terminal => self.entity.open_terminal(), - ResultType::StopRealm => self.entity.stop_realm(), - ResultType::RestartRealm => self.entity.restart_realm(), - ResultType::ConfigRealm => self.entity.config_realm(window), - ResultType::UpdateRealmFS => self.entity.update_realmfs(), - } - } -} - -struct ResultItems { - items: Vec, - selected: Option, -} - -impl ResultItems { - fn new() -> Self { - ResultItems { - items: Vec::new(), - selected: None, - } - } - - fn clear(&mut self, parentbox: >k::Box) { - self.selected = None; - for item in self.items.drain(..) { - ContainerExt::remove(parentbox, &item.item); - } - } - - pub fn create_item(&mut self, rtype: ResultType, realm: &Entity, parent: >k::Box) -> Result<()> { - let item = ResultItem::create(rtype, realm, parent)?; - self.items.push(item); - if self.selected.is_none() { - self.select(0); - } - Ok(()) - } - - fn select(&mut self, idx: usize) { - if let Some(selected) = self.selected { - if let Some(item) = self.items.get(selected) { - item.set_unselected(); - } - } - if let Some(item) = self.items.get(idx) { - item.set_selected(); - self.selected = Some(idx); - } - } - - fn is_empty(&self) -> bool { - self.items.is_empty() - } - - fn selection_down(&mut self) { - if self.is_empty() { - return; - } - let idx = match self.selected { - Some(idx) => (idx + 1) % self.items.len(), - None => 0 - }; - self.select(idx); - } - - fn selection_up(&mut self) { - if self.is_empty() { - return; - } - let idx = match self.selected { - Some(0) => self.items.len() - 1, - Some(idx) => idx - 1, - None => self.items.len() - 1, - }; - self.select(idx); - } - - fn activate_selected(&self, window: >k::Window) -> bool { - if let Some(idx) = self.selected { - if let Some(item) = self.items.get(idx) { - return item.activate(window); - } - } - false - } -} - -#[derive(Clone)] -pub struct ResultList { - result_box: gtk::Box, - items: Rc>, -} - -impl ResultList { - pub fn new(result_box: gtk::Box) -> Self { - ResultList { - result_box, - items: Rc::new(RefCell::new(ResultItems::new())), - } - } - - fn items_mut(&self) -> RefMut { - self.items.borrow_mut() - } - - pub fn clear_list(&self) { - self.items_mut().clear(&self.result_box); - self.result_box.set_margin_top(0); - self.result_box.set_margin_bottom(0); - } - - pub fn selection_down(&self) { - self.items_mut().selection_down(); - } - - pub fn selection_up(&self) { - self.items_mut().selection_up(); - } - - pub fn create_result_items(&self, rtype: ResultType, entities: Vec) { - for r in &entities { - if let Err(err) = self.items.borrow_mut().create_item(rtype, r, &self.result_box) { - println!("failed to create {:?} item for realm {}: {:?}", rtype, r.name(), err); - } - } - } - - pub fn activate_selected(&self, window: >k::Window) -> bool { - self.items.borrow().activate_selected(window) - } -} diff --git a/citadel-realms-ui/src/ui.rs b/citadel-realms-ui/src/ui.rs deleted file mode 100644 index cb02a03..0000000 --- a/citadel-realms-ui/src/ui.rs +++ /dev/null @@ -1,152 +0,0 @@ - -use gtk::prelude::*; -use gtk::StyleContext; -use gdk::ModifierType; -use gdk::keys::constants; - -use crate::matcher::Matcher; -use crate::results::ResultList; -use crate::{Result,Builder}; - -const STYLE: &str = include_str!("../data/style.css"); -const MAIN_UI: &str = include_str!("../data/main.ui"); - - -#[derive(Clone)] -pub struct Ui { - window: gtk::Window, - window_size: (i32, i32), - input: gtk::Entry, - result_list: ResultList, - matcher: Matcher, -} - -impl Ui { - pub fn run(&self) { - gtk::main(); - } - - pub fn build() -> Result { - let builder = Builder::new(MAIN_UI); - let window = builder.get_window("main-window")?; - let current = builder.get_label("current-realm")?; - let input = builder.get_entry("input-entry")?; - let result_box = builder.get_box("result-box")?; - - window.set_opacity(0.85); - window.set_icon_name(Some("cs-privacy")); - - window.show_all(); - - let window_size = window.get_size(); - - let matcher = Matcher::new()?; - if let Some(realm) = matcher.current_realm() { - current.set_text(realm.name()); - } else { - current.hide(); - } - - let result_list = ResultList::new(result_box); - - let ui = Ui { - window, window_size, input, result_list, matcher, - }; - ui.setup_signals(); - ui.setup_style(); - Ok(ui) - } - - - fn setup_signals(&self) { - let ui = self.clone(); - self.input.connect_activate(move |_| { ui.on_activate() }); - let ui = self.clone(); - self.input.connect_changed(move |e| { - let s = e.get_text(); - ui.on_entry_changed(s.to_string().as_str()); - }); - let ui = self.clone(); - self.input.connect_key_press_event(move |_,k| { - ui.on_key_press(k); - Inhibit(false) - }); - - - /* - self.window.connect_focus_out_event(move |_,_| { - gtk::idle_add(|| { - gtk::main_quit(); - Continue(false) - }); - Inhibit(false) - - }); - - */ - - } - - fn setup_style(&self) { - if let Some(settings) = gtk::Settings::get_default() { - settings.set_property_gtk_application_prefer_dark_theme(true); - } - let css = gtk::CssProvider::new(); - - if let Err(err) = css.load_from_data(STYLE.as_bytes()) { - println!("Error parsing CSS style: {}", err); - return; - } - if let Some(screen) = gdk::Screen::get_default() { - StyleContext::add_provider_for_screen(&screen, &css, gtk::STYLE_PROVIDER_PRIORITY_USER); - } - } - - fn on_activate(&self) { - if self.result_list.activate_selected(&self.window) { - println!("activated"); - self.input.set_text(""); - glib::idle_add_local({ - let (w,h) = self.window_size; - let window = self.window.clone(); - move || { - window.resize(w, h); - gtk::main_quit(); - Continue(false) - } - }); - } - } - - fn on_entry_changed(&self, text: &str) { - self.matcher.update(text, &self.result_list); - let (w,h) = self.window_size; - self.window.resize(w, h); - } - - fn is_escape_key(keyval: gdk::keys::Key, state: ModifierType) -> bool { - keyval == constants::Escape || - (state == ModifierType::CONTROL_MASK && keyval.to_unicode().unwrap() == '[') - } - - fn on_key_press(&self, key: &gdk::EventKey) { - let state = key.get_state(); - let keyval = key.get_keyval(); - - if Self::is_escape_key(key.get_keyval(), key.get_state()) { - gtk::main_quit(); - } - if keyval == constants::Up { - self.result_list.selection_up(); - } else if keyval == constants::Down { - self.result_list.selection_down(); - } else if state == ModifierType::CONTROL_MASK { - match keyval.to_unicode().unwrap() { - 'n'|'j' => self.result_list.selection_down(), - 'p'|'k' => self.result_list.selection_up(), - _ => {}, - } - } - } - -}