feat: SoftwarePage in blueprint

feat: PageSection
This commit is contained in:
Ilya Zlobintsev
2023-11-17 22:23:23 +02:00
parent 92ba99fc16
commit 6c2d4b1ff1
16 changed files with 309 additions and 137 deletions

View File

@@ -0,0 +1,72 @@
use gtk::glib::{self, Object};
glib::wrapper! {
pub struct InfoRow(ObjectSubclass<imp::InfoRow>)
@extends gtk::Box, gtk::Widget,
@implements gtk::Orientable, gtk::Accessible, gtk::Buildable;
}
impl InfoRow {
pub fn new(name: &str, value: &str) -> Self {
Object::builder()
.property("name", name)
.property("value", value)
.build()
}
}
mod imp {
use glib::Properties;
use gtk::{
glib::{self, subclass::InitializingObject},
pango::AttrList,
prelude::*,
subclass::{
prelude::*,
widget::{CompositeTemplateClass, WidgetImpl},
},
CompositeTemplate, Label, TemplateChild,
};
use std::{cell::RefCell, str::FromStr};
#[derive(CompositeTemplate, Default, Properties)]
#[properties(wrapper_type = super::InfoRow)]
#[template(file = "ui/info_row.blp")]
pub struct InfoRow {
#[property(get, set)]
name: RefCell<String>,
#[property(get, set)]
value: RefCell<String>,
#[template_child]
value_label: TemplateChild<Label>,
}
#[glib::object_subclass]
impl ObjectSubclass for InfoRow {
const NAME: &'static str = "InfoRow";
type Type = super::InfoRow;
type ParentType = gtk::Box;
fn class_init(class: &mut Self::Class) {
class.bind_template();
}
fn instance_init(obj: &InitializingObject<Self>) {
obj.init_template();
}
}
#[glib::derived_properties]
impl ObjectImpl for InfoRow {
fn constructed(&self) {
self.parent_constructed();
let attr_list = AttrList::from_str("0 -1 weight bold").unwrap();
self.value_label.set_attributes(Some(&attr_list));
}
}
impl WidgetImpl for InfoRow {}
impl BoxImpl for InfoRow {}
}

View File

@@ -1,5 +1,7 @@
mod apply_revealer;
mod header;
mod info_row;
mod page_section;
mod root_stack;
use crate::{APP_ID, GUI_VERSION};

View File

@@ -0,0 +1,70 @@
use gtk::glib::{self, Object};
glib::wrapper! {
pub struct PageSection(ObjectSubclass<imp::PageSection>)
@extends gtk::Box, gtk::Widget,
@implements gtk::Orientable, gtk::Accessible, gtk::Buildable;
}
impl PageSection {
pub fn new(name: &str) -> Self {
Object::builder().property("name", name).build()
}
}
mod imp {
use glib::Properties;
use gtk::{
glib::{self, subclass::InitializingObject},
prelude::*,
subclass::{
prelude::*,
widget::{CompositeTemplateClass, WidgetImpl},
},
CompositeTemplate, Label, TemplateChild,
};
use std::cell::RefCell;
#[derive(CompositeTemplate, Default, Properties)]
#[properties(wrapper_type = super::PageSection)]
#[template(file = "ui/page_section.blp")]
pub struct PageSection {
#[template_child]
section_label: TemplateChild<Label>,
#[property(get, set)]
name: RefCell<String>,
}
#[glib::object_subclass]
impl ObjectSubclass for PageSection {
const NAME: &'static str = "PageSection";
type Type = super::PageSection;
type ParentType = gtk::Box;
fn class_init(class: &mut Self::Class) {
class.bind_template();
}
fn instance_init(obj: &InitializingObject<Self>) {
obj.init_template();
}
}
#[glib::derived_properties]
impl ObjectImpl for PageSection {
fn constructed(&self) {
self.parent_constructed();
let obj = self.obj();
obj.bind_property("name", &self.section_label.get(), "label")
.transform_to(|_, value: String| {
Some(format!("<span font_desc='13'><b>{value}</b></span>"))
})
.build();
}
}
impl WidgetImpl for PageSection {}
impl BoxImpl for PageSection {}
}

View File

@@ -1,12 +1,12 @@
mod vulkan_info;
use super::{label_row, values_grid};
use crate::app::page_section::PageSection;
use gtk::prelude::*;
use gtk::*;
use lact_client::schema::{DeviceInfo, DeviceStats};
use vulkan_info::VulkanInfoFrame;
use super::{label_row, section_box, values_grid};
#[derive(Clone)]
pub struct InformationPage {
pub container: ScrolledWindow,
@@ -34,7 +34,7 @@ impl InformationPage {
pub fn new() -> Self {
let vbox = Box::new(Orientation::Vertical, 15);
let info_container = section_box("Hardware Information");
let info_container = PageSection::new("Hardware Information");
let values_grid = values_grid();
@@ -69,7 +69,7 @@ impl InformationPage {
info_container.append(&values_grid);
vbox.append(&info_container);
let vulkan_container = section_box("Vulkan Information");
let vulkan_container = PageSection::new("Vulkan Information");
let vulkan_info_frame = VulkanInfoFrame::new();
vulkan_container.append(&vulkan_info_frame.container);

View File

@@ -3,13 +3,9 @@ mod oc_page;
mod software_page;
mod thermals_page;
use gtk::{
prelude::IsA,
traits::{BoxExt, GridExt},
*,
};
use gtk::{prelude::IsA, traits::GridExt, *};
use self::software_page::software_page;
use self::software_page::SoftwarePage;
use info_page::InformationPage;
use lact_client::schema::SystemInfo;
use oc_page::OcPage;
@@ -44,7 +40,7 @@ impl RootStack {
container.add_titled(&thermals_page.container, Some("thermals_page"), "Thermals");
let software_page = software_page(system_info, embedded_daemon);
let software_page = SoftwarePage::new(system_info, embedded_daemon);
container.add_titled(&software_page, Some("software_page"), "Software");
Self {
@@ -80,26 +76,6 @@ fn label_row(title: &str, parent: &Grid, row: i32, column_offset: i32, selectabl
value_label
}
fn section_box(title: &str) -> Box {
let container = Box::builder()
.orientation(Orientation::Vertical)
.spacing(5)
.margin_start(5)
.margin_end(5)
.build();
let label = Label::builder()
.use_markup(true)
.label(format!("<span font_desc='13'><b>{title}</b></span>"))
.halign(Align::Start)
.margin_top(5)
.margin_bottom(5)
.build();
container.append(&label);
container
}
fn values_grid() -> Grid {
Grid::builder()
.margin_start(10)

View File

@@ -1,4 +1,4 @@
use crate::app::root_stack::section_box;
use crate::app::page_section::PageSection;
use glib::clone;
use gtk::prelude::*;
use gtk::*;
@@ -14,7 +14,7 @@ const WARNING_TEXT: &str = "Warning: changing these values may lead to system in
// The AtomicBool stores if the value was changed
#[derive(Clone)]
pub struct ClocksFrame {
pub container: Box,
pub container: PageSection,
tweaking_grid: Grid,
modes_switcher_box: Box,
basic_togglebutton: ToggleButton,
@@ -34,7 +34,7 @@ pub struct ClocksFrame {
impl ClocksFrame {
pub fn new() -> Self {
let container = section_box("Clockspeed and voltage");
let container = PageSection::new("Clockspeed and voltage");
let warning_label = Label::builder()
.label(WARNING_TEXT)

View File

@@ -38,8 +38,6 @@ impl OcPage {
let vbox = Box::builder()
.orientation(Orientation::Vertical)
.spacing(15)
.margin_start(5)
.margin_end(5)
.build();
let mut enable_overclocking_button = None;

View File

@@ -1,4 +1,4 @@
use crate::app::root_stack::section_box;
use crate::app::page_section::PageSection;
use glib::clone;
use gtk::prelude::*;
use gtk::*;
@@ -9,7 +9,7 @@ use std::{cell::RefCell, rc::Rc, str::FromStr};
#[derive(Clone)]
pub struct PerformanceFrame {
pub container: Box,
pub container: PageSection,
level_drop_down: DropDown,
mode_drop_down: DropDown,
description_label: Label,
@@ -20,7 +20,7 @@ pub struct PerformanceFrame {
impl PerformanceFrame {
pub fn new() -> Self {
let container = section_box("Performance");
let container = PageSection::new("Performance");
let levels_model: StringList = ["Automatic", "Highest Clocks", "Lowest Clocks", "Manual"]
.into_iter()

View File

@@ -1,5 +1,5 @@
use super::oc_adjustment::OcAdjustment;
use crate::app::root_stack::section_box;
use crate::app::page_section::PageSection;
use gtk::*;
use gtk::{glib::clone, prelude::*};
use std::{cell::Cell, rc::Rc};
@@ -7,14 +7,14 @@ use tracing::error;
#[derive(Clone)]
pub struct PowerCapFrame {
pub container: Box,
pub container: PageSection,
default_cap: Rc<Cell<Option<f64>>>,
adjustment: OcAdjustment,
}
impl PowerCapFrame {
pub fn new() -> Self {
let container = section_box("Power Usage Limit");
let container = PageSection::new("Power Usage Limit");
let default_cap = Rc::new(Cell::new(None));
let value_suffix = "W";

View File

@@ -1,11 +1,11 @@
use crate::app::root_stack::{label_row, section_box};
use crate::app::{page_section::PageSection, root_stack::label_row};
use gtk::prelude::*;
use gtk::*;
use lact_client::schema::{ClockspeedStats, DeviceStats, PowerStats, VoltageStats, VramStats};
#[derive(Clone)]
pub struct StatsFrame {
pub container: Box,
pub container: PageSection,
vram_usage_bar: LevelBar,
vram_usage_label: Label,
gpu_clock_label: Label,
@@ -18,7 +18,7 @@ pub struct StatsFrame {
impl StatsFrame {
pub fn new() -> Self {
let container = section_box("Statistics");
let container = PageSection::new("Statistics");
let vram_usage_hbox = Box::new(Orientation::Horizontal, 5);

View File

@@ -1,92 +1,83 @@
use crate::GUI_VERSION;
use gtk::prelude::*;
use gtk::*;
use gtk::glib::{self, Object};
use lact_client::schema::SystemInfo;
pub fn software_page(system_info: SystemInfo, embedded: bool) -> Grid {
let container = Grid::new();
container.set_margin_start(5);
container.set_margin_end(5);
container.set_margin_bottom(5);
container.set_margin_top(5);
container.set_column_spacing(5);
container.attach(
&{
let label = Label::new(None);
label.set_markup("LACT Daemon:");
label.set_halign(Align::End);
label.set_hexpand(true);
label
},
0,
0,
1,
1,
);
let mut daemon_version = format!("{}-{}", system_info.version, system_info.profile);
if embedded {
daemon_version.push_str("-embedded");
}
let daemon_version_label = Label::builder()
.use_markup(true)
.label(format!("<b>{daemon_version}</b>"))
.hexpand(true)
.halign(Align::Start)
.build();
container.attach(&daemon_version_label, 1, 0, 1, 1);
container.attach(
&{
let label = Label::new(None);
label.set_markup("LACT GUI:");
label.set_halign(Align::End);
label.set_hexpand(true);
label
},
0,
1,
1,
1,
);
let gui_profile = if cfg!(debug_assertions) {
"debug"
} else {
"release"
};
let gui_version = format!("{GUI_VERSION}-{gui_profile}");
let gui_version_label = Label::builder()
.use_markup(true)
.label(format!("<b>{gui_version}</b>"))
.hexpand(true)
.halign(Align::Start)
.build();
container.attach(&gui_version_label, 1, 1, 1, 1);
container.attach(
&Label::builder()
.label("Kernel version:")
.halign(Align::End)
.hexpand(true)
.build(),
0,
2,
1,
1,
);
let kernel_version_label = Label::builder()
.use_markup(true)
.label(format!("<b>{}</b>", system_info.kernel_version))
.hexpand(true)
.halign(Align::Start)
.build();
container.attach(&kernel_version_label, 1, 2, 1, 1);
container
glib::wrapper! {
pub struct SoftwarePage(ObjectSubclass<imp::SoftwarePage>)
@extends gtk::Box, gtk::Widget,
@implements gtk::Orientable, gtk::Accessible, gtk::Buildable;
}
impl SoftwarePage {
pub fn new(system_info: SystemInfo, embedded: bool) -> Self {
let mut daemon_version = format!("{}-{}", system_info.version, system_info.profile);
if embedded {
daemon_version.push_str("-embedded");
}
let gui_profile = if cfg!(debug_assertions) {
"debug"
} else {
"release"
};
let gui_version = format!("{GUI_VERSION}-{gui_profile}");
Object::builder()
.property("daemon-version", daemon_version)
.property("gui-version", gui_version)
.property("kernel-version", system_info.kernel_version)
.build()
}
}
mod imp {
#![allow(clippy::enum_variant_names)]
use crate::app::{info_row::InfoRow, page_section::PageSection};
use glib::Properties;
use gtk::{
glib::{self, subclass::InitializingObject},
prelude::*,
subclass::{
prelude::*,
widget::{CompositeTemplateClass, WidgetImpl},
},
CompositeTemplate,
};
use std::cell::RefCell;
#[derive(CompositeTemplate, Default, Properties)]
#[properties(wrapper_type = super::SoftwarePage)]
#[template(file = "ui/software_page.blp")]
pub struct SoftwarePage {
#[property(get, set)]
daemon_version: RefCell<String>,
#[property(get, set)]
gui_version: RefCell<String>,
#[property(get, set)]
kernel_version: RefCell<String>,
}
#[glib::object_subclass]
impl ObjectSubclass for SoftwarePage {
const NAME: &'static str = "SoftwarePage";
type Type = super::SoftwarePage;
type ParentType = gtk::Box;
fn class_init(class: &mut Self::Class) {
InfoRow::ensure_type();
PageSection::ensure_type();
class.bind_template();
}
fn instance_init(obj: &InitializingObject<Self>) {
obj.init_template();
}
}
#[glib::derived_properties]
impl ObjectImpl for SoftwarePage {}
impl WidgetImpl for SoftwarePage {}
impl BoxImpl for SoftwarePage {}
}

View File

@@ -5,9 +5,11 @@ use gtk::prelude::*;
use gtk::*;
use lact_client::schema::{default_fan_curve, DeviceStats, FanControlMode, FanCurveMap};
use crate::app::page_section::PageSection;
use self::fan_curve_frame::FanCurveFrame;
use super::{label_row, section_box, values_grid};
use super::{label_row, values_grid};
#[derive(Debug)]
pub struct ThermalsSettings {
@@ -32,7 +34,7 @@ impl ThermalsPage {
pub fn new() -> Self {
let container = Box::new(Orientation::Vertical, 15);
let stats_section = section_box("Statistics");
let stats_section = PageSection::new("Statistics");
let stats_grid = values_grid();
let temperatures_label = label_row("Temperatures:", &stats_grid, 0, 0, false);
@@ -51,7 +53,7 @@ impl ThermalsPage {
.build();
let fan_static_speed_adjustment = static_speed_adj(&fan_static_speed_frame);
let fan_control_section = section_box("Fan control");
let fan_control_section = PageSection::new("Fan control");
let fan_control_mode_stack = Stack::builder().build();
let fan_control_mode_stack_switcher = StackSwitcher::builder()

View File

@@ -8,7 +8,7 @@ use tracing::{error, info, metadata::LevelFilter};
use tracing_subscriber::EnvFilter;
const GUI_VERSION: &str = env!("CARGO_PKG_VERSION");
const APP_ID: &str = "io.github.lact-linux1";
const APP_ID: &str = "io.github.lact-linux";
pub fn run(args: GuiArgs) -> anyhow::Result<()> {
let env_filter = EnvFilter::builder()

21
lact-gui/ui/info_row.blp Normal file
View File

@@ -0,0 +1,21 @@
using Gtk 4.0;
using Pango 1.0;
template $InfoRow: Box {
orientation: horizontal;
hexpand: true;
margin-start: 10;
margin-end: 10;
Label {
label: bind template.name;
halign: start;
hexpand: true;
}
Label value_label {
label: bind template.value;
halign: end;
selectable: true;
}
}

View File

@@ -0,0 +1,15 @@
using Gtk 4.0;
template $PageSection: Box {
orientation: vertical;
spacing: 5;
margin-start: 5;
margin-end: 5;
Label section_label {
halign: start;
use-markup: true;
margin-top: 5;
margin-bottom: 5;
}
}

View File

@@ -0,0 +1,25 @@
using Gtk 4.0;
template $SoftwarePage: Box {
orientation: vertical;
spacing: 10;
margin-start: 5;
margin-end: 5;
margin-top: 5;
margin-bottom: 5;
$InfoRow {
name: "LACT Daemon:";
value: bind template.daemon_version;
}
$InfoRow {
name: "LACT GUI:";
value: bind template.gui_version;
}
$InfoRow {
name: "Kernel Version:";
value: bind template.kernel_version;
}
}