Merge branch 'main' into feat/stardust

This commit is contained in:
Gabriele Musco 2024-01-07 14:23:42 +00:00
commit e8043de502
7 changed files with 145 additions and 138 deletions

View file

@ -22,7 +22,7 @@ cargo:test:
script:
- echo 'deb http://deb.debian.org/debian experimental main' > /etc/apt/sources.list.d/experimental.list
- apt-get update
- apt-get -t experimental install libgtk-4-dev libadwaita-1-dev libgtksourceview-5-dev libssl-dev libjxl-dev -y
- apt-get -t experimental install libgtk-4-dev libadwaita-1-dev libgtksourceview-5-dev libssl-dev libjxl-dev libvte-2.91-gtk4-dev -y
- apt-get install meson ninja-build git desktop-file-utils gettext file libusb-dev libusb-1.0-0-dev curl -y
- curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs -o /tmp/rustup.sh
- chmod +x /tmp/rustup.sh
@ -41,7 +41,7 @@ appimage:
script:
- echo 'deb http://deb.debian.org/debian experimental main' > /etc/apt/sources.list.d/experimental.list
- apt-get update
- apt-get -t experimental install libgtk-4-dev libadwaita-1-dev libgtksourceview-5-dev libssl-dev libjxl-dev -y
- apt-get -t experimental install libgtk-4-dev libadwaita-1-dev libgtksourceview-5-dev libssl-dev libjxl-dev libvte-2.91-gtk4-dev -y
- apt-get install meson ninja-build git desktop-file-utils gettext file libusb-dev libusb-1.0-0-dev curl -y
- curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs -o /tmp/rustup.sh
- chmod +x /tmp/rustup.sh

56
Cargo.lock generated
View file

@ -304,6 +304,7 @@ dependencies = [
"sourceview5",
"tracker",
"uuid",
"zoha-vte4",
]
[[package]]
@ -591,9 +592,9 @@ checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0"
[[package]]
name = "gio"
version = "0.18.2"
version = "0.18.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57052f84e8e5999b258e8adf8f5f2af0ac69033864936b8b6838321db2f759b1"
checksum = "d4fc8f532f87b79cbc51a79748f16a6828fb784be93145a322fa14d06d354c73"
dependencies = [
"futures-channel",
"futures-core",
@ -638,9 +639,9 @@ dependencies = [
[[package]]
name = "glib"
version = "0.18.2"
version = "0.18.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c316afb01ce8067c5eaab1fc4f2cd47dc21ce7b6296358605e2ffab23ccbd19"
checksum = "233daaf6e83ae6a12a52055f568f9d7cf4671dabb78ff9560ab6da230ce00ee5"
dependencies = [
"bitflags 2.4.0",
"futures-channel",
@ -961,6 +962,17 @@ dependencies = [
"hashbrown 0.14.0",
]
[[package]]
name = "io-lifetimes"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
dependencies = [
"hermit-abi",
"libc",
"windows-sys",
]
[[package]]
name = "ipnet"
version = "2.8.0"
@ -1375,9 +1387,9 @@ dependencies = [
[[package]]
name = "pango"
version = "0.18.0"
version = "0.18.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06a9e54b831d033206160096b825f2070cf5fda7e35167b1c01e9e774f9202d1"
checksum = "7ca27ec1eb0457ab26f3036ea52229edbdb74dee1edd29063f5b9b010e7ebee4"
dependencies = [
"gio",
"glib",
@ -2417,3 +2429,35 @@ dependencies = [
"cfg-if",
"windows-sys",
]
[[package]]
name = "zoha-vte4"
version = "0.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e09b58dbfab3b62c5544cafadc504db3b7d12f21ac6e55048489dbf90c979caf"
dependencies = [
"bitflags 1.3.2",
"gdk4",
"gio",
"glib",
"gtk4",
"io-lifetimes",
"libc",
"pango",
"zoha-vte4-sys",
]
[[package]]
name = "zoha-vte4-sys"
version = "0.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "749df284a2c2e68c2c359762b277854d533a4d50c7a216a3adf45cd5e5ee2993"
dependencies = [
"gdk4-sys",
"gio-sys",
"glib",
"gtk4-sys",
"libc",
"pango-sys",
"system-deps",
]

View file

@ -41,3 +41,4 @@ sourceview5 = { version = "0.7.1", features = [
] }
tracker = "0.2.1"
uuid = { version = "1.4.1", features = ["v4", "fast-rng"] }
zoha-vte4 = { version = "0.0.2", features = ["v0_72"] }

View file

@ -1,11 +1,12 @@
use crate::log_level::LogLevel;
use crate::log_parser::MonadoLog;
use crate::ui::app::{DebugOpenDataAction, DebugOpenPrefixAction};
use crate::ui::util::copy_text;
use gtk::glib::clone;
use gtk::prelude::*;
use relm4::prelude::*;
use relm4::{ComponentSender, SimpleComponent};
use sourceview5::prelude::*;
use zoha_vte4::{Terminal, TerminalExt};
#[derive(Debug)]
pub enum SearchDirection {
@ -17,7 +18,8 @@ pub enum SearchDirection {
pub enum DebugViewMsg {
LogUpdated(Vec<String>),
ClearLog,
FilterLog(SearchDirection),
DoSearch,
SearchFindMatch(SearchDirection),
LogLevelChanged(LogLevel),
XRServiceActiveChanged(bool),
SetColorScheme,
@ -27,30 +29,20 @@ pub enum DebugViewMsg {
pub struct DebugView {
xrservice_active: bool,
#[tracker::do_not_track]
textbuf: sourceview5::Buffer,
#[tracker::do_not_track]
textview: Option<sourceview5::View>,
#[tracker::do_not_track]
searchbar: Option<gtk::SearchBar>,
#[tracker::do_not_track]
search_entry: Option<gtk::SearchEntry>,
#[tracker::do_not_track]
dropdown: Option<gtk::DropDown>,
#[tracker::do_not_track]
scrolledwin: Option<gtk::ScrolledWindow>,
#[tracker::do_not_track]
search_ctx: sourceview5::SearchContext,
#[tracker::do_not_track]
search_settings: sourceview5::SearchSettings,
#[tracker::do_not_track]
search_mark: Option<gtk::TextMark>,
#[tracker::do_not_track]
log_level: LogLevel,
#[tracker::do_not_track]
vte_terminal: Terminal,
}
pub struct DebugViewInit {}
const MAX_SCROLLBACK: i32 = 2000;
const MAX_SCROLLBACK: u32 = 2000;
#[relm4::component(pub)]
impl SimpleComponent for DebugView {
@ -68,11 +60,10 @@ impl SimpleComponent for DebugView {
}
view! {
gtk::Box {
set_orientation: gtk::Orientation::Vertical,
adw::ToolbarView {
set_hexpand: true,
set_vexpand: true,
adw::HeaderBar {
add_top_bar: hb = &adw::HeaderBar {
set_hexpand: true,
set_vexpand: false,
add_css_class: "flat",
@ -87,8 +78,7 @@ impl SimpleComponent for DebugView {
},
pack_start: &log_level_dropdown,
},
#[name(searchbar)]
gtk::SearchBar {
add_top_bar: searchbar = &gtk::SearchBar {
set_margin_start: 1,
set_hexpand: true,
#[chain(flags(gtk::glib::BindingFlags::BIDIRECTIONAL).build())]
@ -102,44 +92,34 @@ impl SimpleComponent for DebugView {
gtk::SearchEntry {
set_hexpand: true,
connect_changed[sender] => move |_| {
sender.input(Self::Input::FilterLog(SearchDirection::Forward));
sender.input(Self::Input::DoSearch);
},
connect_activate[sender] => move |_| {
sender.input(Self::Input::FilterLog(SearchDirection::Forward));
sender.input(Self::Input::SearchFindMatch(SearchDirection::Forward));
},
},
gtk::Button {
set_icon_name: "go-up-symbolic",
set_tooltip_text: Some("Previous Match"),
connect_clicked[sender] => move |_| {
sender.input(Self::Input::FilterLog(SearchDirection::Backward))
sender.input(Self::Input::SearchFindMatch(SearchDirection::Backward))
},
},
gtk::Button {
set_icon_name: "go-down-symbolic",
set_tooltip_text: Some("Next Match"),
connect_clicked[sender] => move |_| {
sender.input(Self::Input::FilterLog(SearchDirection::Forward))
sender.input(Self::Input::SearchFindMatch(SearchDirection::Forward))
},
},
},
connect_entry: &search_entry,
},
#[name(scrolledwin)]
gtk::ScrolledWindow {
#[wrap(Some)]
set_content: sw = &gtk::ScrolledWindow {
set_hexpand: true,
set_vexpand: true,
add_css_class: "undershoot-top",
#[name(textview)]
sourceview5::View {
add_css_class: "sourceview-transparent-bg",
set_margin_start: 1,
set_hexpand: true,
set_vexpand: true,
set_editable: false,
set_monospace: true,
set_buffer: Some(&model.textbuf),
},
model.vte_terminal.clone(),
}
}
}
@ -157,85 +137,51 @@ impl SimpleComponent for DebugView {
Self::Input::LogLevelChanged(lvl) => {
self.log_level = lvl;
}
Self::Input::FilterLog(direction) => {
Self::Input::DoSearch => {
let searchbar = self.searchbar.as_ref().unwrap().clone();
let search_entry = self.search_entry.as_ref().unwrap().clone();
let search_text = search_entry.text().to_string();
if searchbar.is_search_mode() && !search_text.is_empty() {
self.search_settings
.set_search_text(Some(search_text.as_str()));
self.search_mark = Some(self.textbuf.get_insert());
let mut iter = self
.textbuf
.iter_at_mark(self.search_mark.as_ref().unwrap());
iter.forward_char();
let search_res = match direction {
SearchDirection::Forward => self.search_ctx.forward(&iter),
SearchDirection::Backward => self.search_ctx.backward(&iter),
};
match search_res {
None => {
// TODO: mark search entry red
}
Some((start, end, _)) => {
self.textbuf.move_mark(
self.search_mark.as_ref().unwrap(),
match direction {
SearchDirection::Forward => &end,
SearchDirection::Backward => &start,
},
);
self.textbuf.select_range(&start, &end);
self.textview
.as_ref()
.unwrap()
.scroll_mark_onscreen(&self.textbuf.create_mark(None, &end, false));
}
if let Ok(regex) = zoha_vte4::Regex::for_search(&search_text, 0) {
self.vte_terminal.search_set_regex(Some(&regex), 0);
}
} else {
self.search_settings.set_search_text(None);
self.vte_terminal.search_set_regex(None, 0);
}
}
Self::Input::SearchFindMatch(direction) => match direction {
SearchDirection::Forward => {
self.vte_terminal.search_find_next();
}
SearchDirection::Backward => {
self.vte_terminal.search_find_previous();
}
},
Self::Input::LogUpdated(n_log) => {
for row in n_log {
let txt = match MonadoLog::new_from_str(row.as_str()) {
Some(o) => match o.level >= self.log_level {
false => None,
true => Some(format!(
"{lvl}\t[{file}:{func}]\n\t{msg}\n",
"{lvl}\t[{file}:{func}]\r\n\t{msg}\r\n",
lvl = o.level,
file = o.file,
func = o.func,
msg = o.message
msg = o.message.replace("\n", "\r\n")
)),
},
None => Some(row),
};
if let Some(t) = txt {
self.textbuf
.insert(&mut self.textbuf.end_iter(), t.as_str());
self.vte_terminal.feed(t.as_bytes())
}
}
if !self.searchbar.as_ref().unwrap().is_search_mode() {
let textbuf = self.textbuf.clone();
let textview = self.textview.as_ref().unwrap().clone();
gtk::glib::idle_add_local_once(move || {
let end_mark = textbuf.create_mark(None, &textbuf.end_iter(), false);
textview.scroll_mark_onscreen(&end_mark);
});
}
while self.textbuf.line_count() > MAX_SCROLLBACK {
let mut start = self.textbuf.start_iter();
let mut end = self.textbuf.start_iter();
end.forward_line();
self.textbuf.delete(&mut start, &mut end);
}
}
Self::Input::ClearLog => {
self.textbuf.set_text("");
self.vte_terminal.feed("\x1bc".as_bytes());
}
Self::Input::SetColorScheme => {
Self::set_color_scheme(&self.textbuf);
Self::set_color_scheme(&self.vte_terminal);
}
}
}
@ -245,19 +191,6 @@ impl SimpleComponent for DebugView {
root: &Self::Root,
sender: ComponentSender<Self>,
) -> ComponentParts<Self> {
let textbuf = sourceview5::Buffer::builder()
.highlight_syntax(false)
.enable_undo(false)
.build();
let search_settings = sourceview5::SearchSettings::builder()
.wrap_around(true)
.case_sensitive(false)
.build();
let search_ctx = sourceview5::SearchContext::builder()
.buffer(&textbuf)
.settings(&search_settings)
.build();
let log_level_dropdown = gtk::DropDown::from_strings(
LogLevel::iter()
.map(|lvl| lvl.to_string())
@ -282,46 +215,67 @@ impl SimpleComponent for DebugView {
adw::StyleManager::default().connect_dark_notify(clone!(@strong sender => move |_| {
sender.input(Self::Input::SetColorScheme);
}));
Self::set_color_scheme(&textbuf);
let mut model = Self {
xrservice_active: false,
tracker: 0,
textbuf,
textview: None,
searchbar: None,
search_entry: None,
dropdown: None,
scrolledwin: None,
search_settings,
search_ctx,
search_mark: None,
log_level: LogLevel::Trace,
vte_terminal: {
let t = Terminal::builder()
.scroll_on_output(true)
.scrollback_lines(MAX_SCROLLBACK)
.scroll_unit_is_pixels(true)
.vexpand(true)
.hexpand(true)
.build();
t.set_clear_background(false);
t.search_set_wrap_around(true);
Self::set_color_scheme(&t);
t
},
};
{
let sc = gtk::ShortcutController::new();
let term = model.vte_terminal.clone();
sc.add_shortcut(gtk::Shortcut::new(
gtk::ShortcutTrigger::parse_string("<Control>c"),
Some(gtk::CallbackAction::new(move |_, _| {
if let Some(text) = term.text_selected(zoha_vte4::Format::Text) {
copy_text(text.as_str());
}
true
})),
));
let term = model.vte_terminal.clone();
sc.add_shortcut(gtk::Shortcut::new(
gtk::ShortcutTrigger::parse_string("<Control>a"),
Some(gtk::CallbackAction::new(move |_, _| {
term.select_all();
true
})),
));
model.vte_terminal.add_controller(sc);
}
let widgets = view_output!();
model.searchbar = Some(widgets.searchbar.clone());
model.search_entry = Some(widgets.search_entry.clone());
model.textview = Some(widgets.textview.clone());
model.dropdown = Some(log_level_dropdown.clone());
model.scrolledwin = Some(widgets.scrolledwin.clone());
ComponentParts { model, widgets }
}
}
impl DebugView {
fn set_color_scheme(textbuf: &sourceview5::Buffer) {
let sourceview_scheme_name = if adw::StyleManager::default().is_dark() {
"Adwaita-dark"
fn set_color_scheme(term: &Terminal) {
if adw::StyleManager::default().is_dark() {
term.set_color_foreground(&gtk::gdk::RGBA::new(1.0, 1.0, 1.0, 1.0));
} else {
"Adwaita"
};
if let Some(scheme) = &sourceview5::StyleSchemeManager::new().scheme(sourceview_scheme_name)
{
textbuf.set_style_scheme(Some(scheme));
} else {
println!("gtksourceview style scheme not found")
term.set_color_foreground(&gtk::gdk::RGBA::new(0.0, 0.0, 0.0, 1.0));
}
}
}

View file

@ -20,7 +20,7 @@ use crate::ui::app::{
use crate::ui::profile_editor::ProfileEditorInit;
use crate::ui::stardust::stardust_view::StardustViewInit;
use crate::ui::steamvr_calibration_box::SteamVrCalibrationBoxMsg;
use crate::ui::util::{limit_dropdown_width, warning_heading};
use crate::ui::util::{copy_text, limit_dropdown_width, warning_heading};
use crate::xr_devices::XRDevice;
use gtk::prelude::*;
use relm4::adw::traits::MessageDialogExt;
@ -325,10 +325,9 @@ impl SimpleComponent for MainView {
set_valign: gtk::Align::Center,
connect_clicked => move |_| {
if let Some(GpuSysDrm::Amd(d)) = get_first_amd_gpu() {
gtk::gdk::Display::default()
.expect("Could not find default display")
.clipboard()
.set_text(get_set_amd_vr_pow_prof_cmd(d.as_str()).as_str());
copy_text(
&get_set_amd_vr_pow_prof_cmd(d.as_str())
)
}
}
},

View file

@ -1,3 +1,4 @@
use super::util::copy_text;
use crate::{constants::APP_NAME, profile::Profile};
use gtk::prelude::*;
use relm4::prelude::*;
@ -100,10 +101,7 @@ impl SimpleComponent for SteamLaunchOptionsBox {
self.set_launch_options(prof.get_steam_launch_options());
}
Self::Input::CopyLaunchOptions => {
gtk::gdk::Display::default()
.expect("Could not find default display")
.clipboard()
.set_text(self.launch_options.as_str());
copy_text(self.launch_options.as_str());
}
}
}

View file

@ -1,4 +1,4 @@
use gtk4::{gio, prelude::*};
use gtk4::{gdk, gio, prelude::*};
pub fn limit_dropdown_width(dd: &gtk4::DropDown, chars: i32) {
let mut dd_child = dd
@ -50,3 +50,14 @@ pub fn open_with_default_handler(uri: &str) {
eprintln!("Error opening uri {}: {}", uri, e)
};
}
pub fn copy_text(txt: &str) {
match gdk::Display::default() {
None => {
eprintln!("Warning: could not get default gdk display")
}
Some(d) => {
d.clipboard().set_text(txt);
}
}
}