This commit is contained in:
Luke D. Jones
2024-02-27 14:39:46 +13:00
parent 7b0f037cba
commit a88c33c201
64 changed files with 3424 additions and 7019 deletions

View File

@@ -15,6 +15,7 @@ libappindicator = "0.9" # Tray icon
gtk = "0.18"
asusd = { path = "../asusd" }
config-traits = { path = "../config-traits" }
rog_anime = { path = "../rog-anime" }
rog_dbus = { path = "../rog-dbus" }
rog_aura = { path = "../rog-aura" }
@@ -28,12 +29,13 @@ env_logger.workspace = true
tokio.workspace = true
serde.workspace = true
toml.workspace = true
ron.workspace = true
serde_json.workspace = true
serde_derive.workspace = true
zbus.workspace = true
dirs.workspace = true
notify-rust.workspace = true
concat-idents.workspace = true
png_pong.workspace = true
@@ -50,7 +52,7 @@ winit = "*"
[dependencies.slint]
git = "https://github.com/flukejones/sixtyfps.git"
default-features = false
features = ["std", "compat-1-0", "backend-winit-wayland", "backend-linuxkms", "renderer-femtovg"]
features = ["std", "gettext", "compat-1-0", "backend-winit-wayland", "backend-linuxkms", "renderer-femtovg"]
[build-dependencies.slint-build]
git = "https://github.com/flukejones/sixtyfps.git"

View File

@@ -1,22 +1,11 @@
# App template
# ROGALOG
This is a trial app cut down to bare essentials to show how to create an app that can run in the background
with some user-config options.
### Translations
egui based. Keep in mind that this is very much a bit of a mess due to experimenting.
You can help with translations by following https://slint.dev/releases/1.1.0/docs/slint/src/concepts/translations#translate-the-strings
## Running
Begin by copying `rog-control-center/translations/en/rog-control-center.po` to `rog-control-center/translations/<YOUR LOCALE>/rog-control-center.po`, then edit that file.
Use `WINIT_UNIX_BACKEND=x11 rog-control-center`. `WINIT_UNIX_BACKEND` is required due to window decorations not updating and the window not really being set as visible/invisible on wayland.
Run `msgfmt rog-control-center/translations/<YOUR LOCALE>/rog-control-center.po -o rog-control-center/translations/<YOUR LOCALE>/LC_MESSAGES/rog-control-center.mo` to make the binary formatted translation where `<YOUR LOCALE>` is changed to your translation locale.
## Build features
For testing some features that are typically not available on all laptops:
```rust
cargo run --features mocking
```
## TODO
- Add notification watch for certain UI elements to enforce an update (for example when a user changes Aura via a hot key).
To test you local translations run `RUST_TRANSLATIONS=1 rog-control-center`.

View File

@@ -1,33 +1,7 @@
use std::path::PathBuf;
use std::str::FromStr;
// use std::fs::OpenOptions;
// use std::io::Write;
// use diter_protocol::ParameterDefinitions;
// use ron::ser::PrettyConfig;
// const LOCALE_EN: &str =
// include_str!("../data/localization/en/parameters.json"); const LOCALE_IT:
// &str = include_str!("../data/localization/it/parameters.json");
// const LOCALE_ZH: &str =
// include_str!("../data/localization/zh/parameters.json");
// fn write_locales() {
// let root = env!("CARGO_MANIFEST_DIR");
// let mut path = PathBuf::from_str(root).unwrap();
// path.push("src/locales.ron");
// let mut file = OpenOptions::new();
// file.truncate(true).create(true).write(true);
// let en: ParameterDefinitions = serde_json::from_str(LOCALE_EN).unwrap();
// let mut writer = file.open(path).unwrap();
// let en = ron::ser::to_string_pretty(&en,
// PrettyConfig::new().depth_limit(4)).unwrap(); writer.write_all(en.
// to_string().as_bytes()).unwrap();
// // let it: ParameterDefinitions =
// serde_json::from_str(LOCALE_IT).unwrap(); // let zh: ParameterDefinitions
// = serde_json::from_str(LOCALE_ZH).unwrap(); }
use slint_build::CompilerConfiguration;
fn main() {
// write_locales();
@@ -35,5 +9,9 @@ fn main() {
let root = env!("CARGO_MANIFEST_DIR");
let mut path = PathBuf::from_str(root).unwrap();
path.push("ui/main_window.slint");
slint_build::compile(path).unwrap();
slint_build::compile_with_config(
path,
CompilerConfiguration::new().with_style("cosmic-dark".into()),
)
.unwrap();
}

View File

@@ -1,10 +1,8 @@
use std::fs::{create_dir, OpenOptions};
use std::io::{Read, Write};
use std::fs::create_dir;
use log::{error, info, warn};
use config_traits::{StdConfig, StdConfigLoad1};
use serde_derive::{Deserialize, Serialize};
use crate::error::Error;
use crate::update_and_notify::EnabledNotifications;
const CFG_DIR: &str = "rog";
@@ -38,134 +36,32 @@ impl Default for Config {
}
}
impl Config {
pub fn load() -> Result<Config, Error> {
let mut path = if let Some(dir) = dirs::config_dir() {
info!("Found XDG config dir {dir:?}");
dir
} else {
error!("Could not get XDG config dir");
return Err(Error::XdgVars);
};
impl StdConfig for Config {
fn new() -> Self {
Config {
..Default::default()
}
}
fn config_dir() -> std::path::PathBuf {
let mut path = dirs::config_dir().unwrap_or_default();
path.push(CFG_DIR);
if !path.exists() {
create_dir(path.clone())?;
info!("Created {path:?}");
create_dir(path.clone())
.map_err(|e| log::error!("Could not create config dir: {e}"))
.ok();
log::info!("Created {path:?}");
}
path.push(CFG_FILE_NAME);
let mut file = OpenOptions::new()
.read(true)
.write(true)
.create(true)
.open(&path)?;
let mut buf = String::new();
// Lint to allow, because we want the above file behaviour
#[allow(clippy::verbose_file_reads)]
if let Ok(read_len) = file.read_to_string(&mut buf) {
if read_len == 0 {
warn!("Zero len read of Config file");
let default = Config::default();
let t = toml::to_string_pretty(&default).unwrap();
file.write_all(t.as_bytes())?;
return Ok(default);
} else if let Ok(data) = toml::from_str::<Config>(&buf) {
info!("Loaded config file {path:?}");
return Ok(data);
} else if let Ok(data) = toml::from_str::<Config461>(&buf) {
info!("Loaded old v4.6.1 config file {path:?}");
return Ok(data.into());
} else if let Ok(data) = toml::from_str::<Config460>(&buf) {
info!("Loaded old v4.6.0 config file {path:?}");
return Ok(data.into());
} else if let Ok(data) = toml::from_str::<Config455>(&buf) {
info!("Loaded old v4.5.5 config file {path:?}");
return Ok(data.into());
}
}
Err(Error::ConfigLoadFail)
path
}
pub fn save(&mut self, enabled_notifications: &EnabledNotifications) -> Result<(), Error> {
let mut path = if let Some(dir) = dirs::config_dir() {
dir
} else {
return Err(Error::XdgVars);
};
path.push(CFG_DIR);
if !path.exists() {
create_dir(path.clone())?;
info!("Created {path:?}");
}
path.push(CFG_FILE_NAME);
let mut file = OpenOptions::new()
.write(true)
.create(true)
.truncate(true)
.open(&path)?;
self.enabled_notifications = enabled_notifications.clone();
let t = toml::to_string_pretty(&self).unwrap();
file.write_all(t.as_bytes())?;
info!("Saved config file {path:?}");
Ok(())
fn file_name(&self) -> String {
CFG_FILE_NAME.to_owned()
}
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Config455 {
pub run_in_background: bool,
pub startup_in_background: bool,
pub enable_notifications: bool,
pub enabled_notifications: EnabledNotifications,
}
impl From<Config455> for Config {
fn from(c: Config455) -> Self {
Self {
run_in_background: c.run_in_background,
startup_in_background: c.startup_in_background,
enable_tray_icon: true,
enable_notifications: c.enable_notifications,
enabled_notifications: c.enabled_notifications,
dark_mode: true,
ac_command: String::new(),
bat_command: String::new(),
}
}
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Config460 {
pub run_in_background: bool,
pub startup_in_background: bool,
pub ac_command: String,
pub bat_command: String,
pub enable_notifications: bool,
pub enabled_notifications: EnabledNotifications,
}
impl From<Config460> for Config {
fn from(c: Config460) -> Self {
Self {
run_in_background: c.run_in_background,
startup_in_background: c.startup_in_background,
enable_tray_icon: true,
ac_command: c.ac_command,
bat_command: c.bat_command,
dark_mode: true,
enable_notifications: c.enable_notifications,
enabled_notifications: c.enabled_notifications,
}
}
}
impl StdConfigLoad1<Config461> for Config {}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Config461 {

View File

@@ -19,6 +19,7 @@ pub mod error;
pub mod mocking;
pub mod system_state;
pub mod tray;
pub mod ui_setup;
pub mod update_and_notify;
#[cfg(feature = "mocking")]

View File

@@ -3,9 +3,10 @@ use std::env::args;
use std::io::{Read, Write};
use std::path::{Path, PathBuf};
use std::sync::{Arc, Mutex};
use std::thread::{self, sleep, spawn};
use std::thread::{self, sleep};
use std::time::Duration;
use config_traits::{StdConfig, StdConfigLoad1};
use gumdrop::Options;
use log::LevelFilter;
use rog_control_center::cli_options::CliStart;
@@ -14,12 +15,12 @@ use rog_control_center::error::Result;
use rog_control_center::slint::ComponentHandle;
use rog_control_center::system_state::{AuraCreation, SystemState};
use rog_control_center::tray::init_tray;
use rog_control_center::ui_setup::setup_window;
use rog_control_center::update_and_notify::{start_notifications, EnabledNotifications};
use rog_control_center::{
get_ipc_file, on_tmp_dir_exists, print_versions, AvailableSystemProperties, MainWindow,
RogDbusClientBlocking, SystemPage, QUIT_APP, SHOWING_GUI, SHOW_GUI,
get_ipc_file, on_tmp_dir_exists, print_versions, MainWindow, RogDbusClientBlocking, QUIT_APP,
SHOWING_GUI, SHOW_GUI,
};
use rog_dbus::zbus_platform::{PlatformProxy, PlatformProxyBlocking};
use tokio::runtime::Runtime;
// use winit::monitor::VideoMode;
// use winit::window::{Fullscreen, WindowLevel};
@@ -76,12 +77,11 @@ fn main() -> Result<()> {
};
// Startup
let mut config = Config::load()?;
let mut config = Config::new().load();
if config.startup_in_background {
config.run_in_background = true;
let tmp = config.enabled_notifications.clone(); // ends up being a double clone, oh well.
config.save(&tmp)?;
config.write();
} else {
get_ipc_file().unwrap().write_all(&[SHOW_GUI, 0]).unwrap();
}
@@ -92,14 +92,27 @@ fn main() -> Result<()> {
// TODO: config mutex to share config in various places
let states = setup_page_state_and_notifs(aura_creation, &enabled_notifications, &config)?;
if config.enable_tray_icon {
init_tray(supported_properties, states.clone());
let enable_tray_icon = config.enable_tray_icon;
let startup_in_background = config.startup_in_background;
let config = Arc::new(Mutex::new(config));
if enable_tray_icon {
init_tray(supported_properties, states.clone(), config.clone());
}
thread_local! { pub static UI: std::cell::RefCell<Option<MainWindow>> = Default::default()};
i_slint_backend_selector::with_platform(|_| Ok(())).unwrap();
let mut do_once = !config.startup_in_background;
let mut do_once = !startup_in_background;
if std::env::var("RUST_TRANSLATIONS").is_ok() {
// don't care about content
log::debug!("---- Using local-dir translations");
slint::init_translations!("/usr/share/locale/");
} else {
log::debug!("Using system installed translations");
slint::init_translations!(concat!(env!("CARGO_MANIFEST_DIR"), "/translations/"));
}
thread::spawn(move || {
let mut buf = [0u8; 2];
// blocks until it is read, typically the read will happen after a second
@@ -113,7 +126,6 @@ fn main() -> Result<()> {
}
if buf[0] == SHOW_GUI {
println!("Should show window {buf:?}");
// There's a balancing act with read/write timing of IPC, there needs to be a
// small sleep after this to give any other process a chance to
// read the IPC before looping
@@ -123,7 +135,7 @@ fn main() -> Result<()> {
.unwrap();
sleep(Duration::from_millis(50));
let states = states.clone();
let config_copy = config.clone();
i_slint_core::api::invoke_from_event_loop(move || {
UI.with(|ui| {
let mut ui = ui.borrow_mut();
@@ -134,9 +146,8 @@ fn main() -> Result<()> {
slint::CloseRequestResponse::HideWindow
});
} else {
let newui = setup_window(states.clone());
let newui = setup_window(config_copy);
newui.window().show().unwrap();
println!("New window should be showing now"); // but it isn't
newui.window().on_close_requested(|| {
get_ipc_file().unwrap().write_all(&[0, 0]).unwrap();
slint::CloseRequestResponse::HideWindow
@@ -149,13 +160,13 @@ fn main() -> Result<()> {
} else if buf[1] == QUIT_APP {
slint::quit_event_loop().unwrap();
} else if buf[0] != SHOWING_GUI {
Config::load().unwrap();
if !config.run_in_background {
slint::quit_event_loop().unwrap();
return;
if let Ok(lock) = config.lock() {
if !lock.run_in_background {
slint::quit_event_loop().unwrap();
return;
}
}
println!("Should hide window {buf:?}");
i_slint_core::api::invoke_from_event_loop(move || {
UI.with(|ui| {
let mut ui = ui.take();
@@ -173,106 +184,6 @@ fn main() -> Result<()> {
Ok(())
}
fn setup_window(_states: Arc<Mutex<SystemState>>) -> MainWindow {
// slint::platform::set_platform(Box::new(i_slint_backend_winit::Backend::new().
// unwrap())).unwrap();
let ui = MainWindow::new().unwrap();
let handle = ui.as_weak();
ui.global::<SystemPage>().on_cancelled(move || {
handle.upgrade_in_event_loop(|_handle| {}).ok();
});
// TODO: macro
let conn = zbus::blocking::Connection::system().unwrap();
let proxy = PlatformProxyBlocking::new(&conn).unwrap();
let proxy2 = proxy.clone();
ui.global::<SystemPage>().on_set_charge_limit(move |limit| {
dbg!(limit);
proxy.set_charge_control_end_threshold(limit as u8).unwrap();
});
ui.global::<SystemPage>().on_set_panel_od(move |od| {
dbg!(od);
proxy2.set_panel_od(od).unwrap();
});
// let handle = ui.as_weak();
// ui.global::<SystemPage>().on_applied(move || {
// handle
// .upgrade_in_event_loop(|handle| {
// let data = handle.global::<SystemPage>();
// let charge_changed = data.get_charge_limit() as i32 !=
// data.get_last_charge_limit(); let charge =
// data.get_charge_limit() as u8; tokio::spawn(async move {
// let conn = zbus::Connection::system().await.unwrap();
// let proxy = PlatformProxy::new(&conn).await.unwrap();
// if charge_changed {
// proxy
// .set_charge_control_end_threshold(charge)
// .await
// .unwrap();
// }
// });
// })
// .ok();
// });
// or
// let handle = ui.as_weak();
// tokio::spawn(async move {
// // TODO: macro
// let conn = zbus::Connection::system().await.unwrap();
// let proxy = PlatformProxy::new(&conn).await.unwrap();
// let proxy2 = proxy.clone();
// handle.upgrade_in_event_loop(move |handle| {
// handle
// .global::<SystemPage>()
// .on_set_charge_limit(move |limit| {
// let proxy = proxy.clone();
// tokio::spawn(async move {
// dbg!(limit);
// proxy
// .set_charge_control_end_threshold(limit as u8)
// .await
// .unwrap();
// });
// });
// handle.global::<SystemPage>().on_set_panel_od(move |od| {
// let proxy2 = proxy2.clone();
// tokio::spawn(async move {
// dbg!(od);
// proxy2.set_panel_od(od).await.unwrap();
// });
// });
// }).ok();
// });
let props = AvailableSystemProperties {
ac_command: true,
bat_command: true,
charge_limit: true,
disable_nvidia_powerd_on_battery: true,
mini_led_mode: true,
nv_dynamic_boost: true,
nv_temp_target: true,
panel_od: true,
ppt_apu_sppt: true,
ppt_fppt: true,
ppt_pl1_spl: true,
ppt_pl2_sppt: true,
ppt_platform_sppt: true,
throttle_policy: true,
};
ui.global::<SystemPage>().set_available(props);
ui.on_exit_app(move || {
slint::quit_event_loop().unwrap();
});
ui
}
fn setup_page_state_and_notifs(
aura_creation: AuraCreation,
enabled_notifications: &Arc<Mutex<EnabledNotifications>>,

View File

@@ -16,6 +16,7 @@ use supergfxctl::pci_device::{GfxMode, GfxPower};
use supergfxctl::zbus_proxy::DaemonProxyBlocking as GfxProxyBlocking;
use versions::Versioning;
use crate::config::Config;
use crate::error::Result;
use crate::system_state::SystemState;
use crate::{get_ipc_file, SHOW_GUI};
@@ -86,7 +87,7 @@ impl ROGTray {
e
})?;
let gfx_proxy = GfxProxyBlocking::builder(&conn).build().map_err(|e| {
let gfx_proxy = GfxProxyBlocking::new(&conn).map_err(|e| {
error!("ROGTray: {e}");
e
})?;
@@ -438,7 +439,11 @@ impl ROGTray {
}
/// The tray is controlled somewhat by `Arc<Mutex<SystemState>>`
pub fn init_tray(supported_properties: Vec<Properties>, states: Arc<Mutex<SystemState>>) {
pub fn init_tray(
supported_properties: Vec<Properties>,
states: Arc<Mutex<SystemState>>,
config: Arc<Mutex<Config>>,
) {
std::thread::spawn(move || {
let gtk_init = gtk::init().map_err(|e| {
error!("ROGTray: gtk init {e}");
@@ -496,6 +501,12 @@ pub fn init_tray(supported_properties: Vec<Properties>, states: Arc<Mutex<System
info!("Started ROGTray");
loop {
if let Ok(lock) = config.try_lock() {
if !lock.enable_tray_icon {
break;
}
}
let states = tray.states.clone();
if let Ok(mut lock) = states.lock() {
if lock.tray_should_update {

View File

@@ -0,0 +1,691 @@
use std::sync::{Arc, Mutex};
use config_traits::StdConfig;
use rog_anime::Animations;
use rog_dbus::zbus_anime::AnimeProxy;
use rog_dbus::zbus_aura::AuraProxy;
use rog_dbus::zbus_platform::{PlatformProxy, PlatformProxyBlocking};
use rog_platform::platform::Properties;
use slint::{Color, ComponentHandle, Model, RgbaColor, SharedString, Weak};
use zbus::proxy::CacheProperties;
use crate::config::Config;
use crate::{
AnimePageData, AppSettingsPageData, AuraPageData, AvailableSystemProperties, MainWindow,
SystemPageData,
};
impl From<rog_aura::AuraEffect> for crate::slint_generatedMainWindow::AuraEffect {
fn from(m: rog_aura::AuraEffect) -> Self {
Self {
colour1: RgbaColor {
red: m.colour1.r,
green: m.colour1.g,
blue: m.colour1.b,
alpha: 255,
}
.into(),
colour2: RgbaColor {
red: m.colour2.r,
green: m.colour2.g,
blue: m.colour2.b,
alpha: 255,
}
.into(),
direction: m.direction.into(),
mode: m.mode.into(),
speed: m.speed.into(),
zone: m.zone.into(),
}
}
}
impl From<crate::slint_generatedMainWindow::AuraEffect> for rog_aura::AuraEffect {
fn from(m: crate::slint_generatedMainWindow::AuraEffect) -> Self {
let c1: RgbaColor<u8> = m.colour1.into();
let c2: RgbaColor<u8> = m.colour2.into();
Self {
colour1: rog_aura::Colour {
r: c1.red,
g: c1.green,
b: c1.blue,
},
colour2: rog_aura::Colour {
r: c2.red,
g: c2.green,
b: c2.blue,
},
direction: m.direction.into(),
mode: m.mode.into(),
speed: m.speed.into(),
zone: m.zone.into(),
}
}
}
// This macro expects are consistent naming between proxy calls and slint
// globals
macro_rules! set_ui_props_async {
($ui:ident, $proxy:ident, $global:ident, $proxy_fn:ident) => {
if let Ok(value) = $proxy.$proxy_fn().await {
$ui.upgrade_in_event_loop(move |handle| {
concat_idents::concat_idents!(set = set_, $proxy_fn {
handle.global::<$global>().set(value.into());
});
}).ok();
}
};
}
// this macro sets up:
// - a link from UI callback -> dbus proxy property
// - a link from dbus property signal -> UI state
// conv1 and conv2 are type conversion args
macro_rules! set_ui_callbacks {
($handle:ident, $data:ident($($conv1: tt)*),$proxy:ident.$proxy_fn:tt($($conv2: tt)*),$success:literal,$failed:literal) => {
let handle_copy = $handle.as_weak();
let proxy_copy = $proxy.clone();
let data = $handle.global::<$data>();
concat_idents::concat_idents!(on_set = on_set_, $proxy_fn {
data.on_set(move |value| {
let proxy_copy = proxy_copy.clone();
let handle_copy = handle_copy.clone();
tokio::spawn(async move {
concat_idents::concat_idents!(set = set_, $proxy_fn {
show_toast(
format!($success, value).into(),
$failed.into(),
handle_copy,
proxy_copy.set(value $($conv2)*).await,
);
});
});
});
});
let handle_copy = $handle.as_weak();
let proxy_copy = $proxy.clone();
concat_idents::concat_idents!(receive = receive_, $proxy_fn, _changed {
// spawn required since the while let never exits
tokio::spawn(async move {
let mut x = proxy_copy.receive().await;
concat_idents::concat_idents!(set = set_, $proxy_fn {
use zbus::export::futures_util::StreamExt;
while let Some(e) = x.next().await {
if let Ok(out) = e.get().await {
handle_copy.upgrade_in_event_loop(move |handle| {
handle.global::<$data>().set(out $($conv1)*);
}).ok();
}
}
});
});
});
};
}
pub fn setup_window(_config: Arc<Mutex<Config>>) -> MainWindow {
let ui = MainWindow::new().unwrap();
let conn = zbus::blocking::Connection::system().unwrap();
let platform = PlatformProxyBlocking::new(&conn).unwrap();
let interfaces = platform.supported_interfaces().unwrap();
log::debug!("Available interfaces: {interfaces:?}");
// "Anime", "Aura", "FanCurves", "Platform"
ui.set_sidebar_items_avilable(
[
// Needs to match the order of slint sidebar items
interfaces.contains(&"Platform".into()),
interfaces.contains(&"Aura".into()),
interfaces.contains(&"Anime".into()),
interfaces.contains(&"FanCurves".into()),
true,
true,
]
.into(),
);
ui.on_exit_app(move || {
slint::quit_event_loop().unwrap();
});
setup_app_settings_page(&ui, _config.clone());
setup_system_page(&ui, _config.clone());
setup_system_page_callbacks(&ui, _config.clone());
setup_aura_page(&ui, _config.clone());
setup_anime_page(&ui, _config);
ui
}
pub fn setup_app_settings_page(ui: &MainWindow, config: Arc<Mutex<Config>>) {
let config_copy = config.clone();
let global = ui.global::<AppSettingsPageData>();
global.on_set_run_in_background(move |enable| {
if let Ok(mut lock) = config_copy.try_lock() {
lock.run_in_background = enable;
lock.write();
}
});
let config_copy = config.clone();
global.on_set_startup_in_background(move |enable| {
if let Ok(mut lock) = config_copy.try_lock() {
lock.startup_in_background = enable;
lock.write();
}
});
let config_copy = config.clone();
global.on_set_enable_tray_icon(move |enable| {
if let Ok(mut lock) = config_copy.try_lock() {
lock.enable_tray_icon = enable;
lock.write();
}
});
let config_copy = config.clone();
global.on_set_enable_notifications(move |enable| {
if let Ok(mut lock) = config_copy.try_lock() {
lock.enable_notifications = enable;
lock.write();
}
});
if let Ok(lock) = config.try_lock() {
global.set_run_in_background(lock.run_in_background);
global.set_startup_in_background(lock.startup_in_background);
global.set_enable_tray_icon(lock.enable_tray_icon);
global.set_enable_notifications(lock.enable_notifications);
}
}
pub fn setup_system_page(ui: &MainWindow, _config: Arc<Mutex<Config>>) {
let conn = zbus::blocking::Connection::system().unwrap();
let platform = PlatformProxyBlocking::new(&conn).unwrap();
let sys_props = platform.supported_properties().unwrap();
log::debug!("Available system properties: {sys_props:?}");
let props = AvailableSystemProperties {
ac_command: true,
bat_command: true,
charge_control_end_threshold: sys_props.contains(&Properties::ChargeControlEndThreshold),
disable_nvidia_powerd_on_battery: true,
mini_led_mode: sys_props.contains(&Properties::MiniLedMode),
nv_dynamic_boost: sys_props.contains(&Properties::NvDynamicBoost),
nv_temp_target: sys_props.contains(&Properties::NvTempTarget),
panel_od: sys_props.contains(&Properties::PanelOd),
ppt_apu_sppt: sys_props.contains(&Properties::PptApuSppt),
ppt_fppt: sys_props.contains(&Properties::PptFppt),
ppt_pl1_spl: sys_props.contains(&Properties::PptPl1Spl),
ppt_pl2_sppt: sys_props.contains(&Properties::PptPl2Sppt),
ppt_platform_sppt: sys_props.contains(&Properties::PptPlatformSppt),
throttle_thermal_policy: sys_props.contains(&Properties::ThrottlePolicy),
};
ui.global::<SystemPageData>().set_available(props);
}
pub fn setup_system_page_callbacks(ui: &MainWindow, _states: Arc<Mutex<Config>>) {
// This tokio spawn exists only to prevent blocking the UI, and to enable use of
// async zbus interfaces
let handle = ui.as_weak();
tokio::spawn(async move {
// Create the connections/proxies here to prevent future delays in process
let conn = zbus::Connection::system().await.unwrap();
let platform = PlatformProxy::new(&conn).await.unwrap();
set_ui_props_async!(
handle,
platform,
SystemPageData,
charge_control_end_threshold
);
set_ui_props_async!(handle, platform, SystemPageData, throttle_thermal_policy);
set_ui_props_async!(handle, platform, SystemPageData, throttle_policy_linked_epp);
set_ui_props_async!(handle, platform, SystemPageData, throttle_balanced_epp);
set_ui_props_async!(handle, platform, SystemPageData, throttle_performance_epp);
set_ui_props_async!(handle, platform, SystemPageData, throttle_quiet_epp);
set_ui_props_async!(handle, platform, SystemPageData, throttle_policy_on_battery);
set_ui_props_async!(handle, platform, SystemPageData, throttle_policy_on_ac);
set_ui_props_async!(handle, platform, SystemPageData, panel_od);
set_ui_props_async!(handle, platform, SystemPageData, mini_led_mode);
set_ui_props_async!(handle, platform, SystemPageData, ppt_pl1_spl);
set_ui_props_async!(handle, platform, SystemPageData, ppt_pl2_sppt);
set_ui_props_async!(handle, platform, SystemPageData, ppt_fppt);
set_ui_props_async!(handle, platform, SystemPageData, ppt_apu_sppt);
set_ui_props_async!(handle, platform, SystemPageData, ppt_platform_sppt);
set_ui_props_async!(handle, platform, SystemPageData, nv_dynamic_boost);
set_ui_props_async!(handle, platform, SystemPageData, nv_temp_target);
let sys_props = platform.supported_properties().await.unwrap();
log::debug!("Available system properties: {sys_props:?}");
let props = AvailableSystemProperties {
ac_command: true,
bat_command: true,
charge_control_end_threshold: sys_props
.contains(&Properties::ChargeControlEndThreshold),
disable_nvidia_powerd_on_battery: true,
mini_led_mode: sys_props.contains(&Properties::MiniLedMode),
nv_dynamic_boost: sys_props.contains(&Properties::NvDynamicBoost),
nv_temp_target: sys_props.contains(&Properties::NvTempTarget),
panel_od: sys_props.contains(&Properties::PanelOd),
ppt_apu_sppt: sys_props.contains(&Properties::PptApuSppt),
ppt_fppt: sys_props.contains(&Properties::PptFppt),
ppt_pl1_spl: sys_props.contains(&Properties::PptPl1Spl),
ppt_pl2_sppt: sys_props.contains(&Properties::PptPl2Sppt),
ppt_platform_sppt: sys_props.contains(&Properties::PptPlatformSppt),
throttle_thermal_policy: sys_props.contains(&Properties::ThrottlePolicy),
};
handle
.upgrade_in_event_loop(move |handle| {
handle.global::<SystemPageData>().set_available(props);
set_ui_callbacks!(handle,
SystemPageData(as f32),
platform.charge_control_end_threshold(as u8),
"Charge limit successfully set to {}",
"Setting Charge limit failed"
);
set_ui_callbacks!(
handle,
SystemPageData(),
platform.panel_od(),
"Panel OverDrive successfully set to {}",
"Setting Panel OverDrive failed"
);
set_ui_callbacks!(
handle,
SystemPageData(),
platform.mini_led_mode(),
"MiniLED mode successfully set to {}",
"Setting MiniLED mode failed"
);
set_ui_callbacks!(handle,
SystemPageData(as i32),
platform.throttle_thermal_policy(.into()),
"Throttle policy set to {}",
"Setting Throttle policy failed"
);
set_ui_callbacks!(handle,
SystemPageData(as i32),
platform.throttle_balanced_epp(.into()),
"Throttle policy EPP set to {}",
"Setting Throttle policy EPP failed"
);
set_ui_callbacks!(handle,
SystemPageData(as i32),
platform.throttle_performance_epp(.into()),
"Throttle policy EPP set to {}",
"Setting Throttle policy EPP failed"
);
set_ui_callbacks!(handle,
SystemPageData(as i32),
platform.throttle_quiet_epp(.into()),
"Throttle policy EPP set to {}",
"Setting Throttle policy EPP failed"
);
set_ui_callbacks!(
handle,
SystemPageData(),
platform.throttle_policy_linked_epp(),
"Throttle policy linked to EPP: {}",
"Setting Throttle policy linked to EPP failed"
);
set_ui_callbacks!(handle,
SystemPageData(as i32),
platform.throttle_policy_on_ac(.into()),
"Throttle policy on AC set to {}",
"Setting Throttle policy on AC failed"
);
set_ui_callbacks!(handle,
SystemPageData(as i32),
platform.throttle_policy_on_battery(.into()),
"Throttle policy on abttery set to {}",
"Setting Throttle policy on battery failed"
);
set_ui_callbacks!(handle,
SystemPageData(as f32),
platform.ppt_pl1_spl(as u8),
"ppt_pl1_spl successfully set to {}",
"Setting ppt_pl1_spl failed"
);
set_ui_callbacks!(handle,
SystemPageData(as f32),
platform.ppt_pl2_sppt(as u8),
"ppt_pl2_sppt successfully set to {}",
"Setting ppt_pl2_sppt failed"
);
set_ui_callbacks!(handle,
SystemPageData(as f32),
platform.ppt_fppt(as u8),
"ppt_fppt successfully set to {}",
"Setting ppt_fppt failed"
);
set_ui_callbacks!(handle,
SystemPageData(as f32),
platform.ppt_apu_sppt(as u8),
"ppt_apu_sppt successfully set to {}",
"Setting ppt_apu_sppt failed"
);
set_ui_callbacks!(handle,
SystemPageData(as f32),
platform.ppt_platform_sppt(as u8),
"ppt_platform_sppt successfully set to {}",
"Setting ppt_platform_sppt failed"
);
set_ui_callbacks!(handle,
SystemPageData(as f32),
platform.nv_temp_target(as u8),
"nv_temp_target successfully set to {}",
"Setting nv_temp_target failed"
);
set_ui_callbacks!(handle,
SystemPageData(as f32),
platform.nv_dynamic_boost(as u8),
"nv_dynamic_boost successfully set to {}",
"Setting nv_dynamic_boost failed"
);
})
.unwrap();
});
}
fn decode_hex(s: &str) -> RgbaColor<u8> {
let s = s.trim_start_matches('#');
let c: Vec<u8> = (0..s.len())
.step_by(2)
.map(|i| u8::from_str_radix(&s[i..i + 2], 16).unwrap_or(164))
.collect();
RgbaColor {
alpha: 255,
red: *c.get(0).unwrap_or(&255),
green: *c.get(1).unwrap_or(&128),
blue: *c.get(2).unwrap_or(&32),
}
}
fn _rgb_hi(colour: Color) -> (f32, f32) {
let c1: RgbaColor<f32> = RgbaColor::from(colour);
let r = c1.red / 255.0;
let g = c1.green / 255.0;
let b = c1.blue / 255.0;
let min = r.min(g.min(b));
let max = r.max(g.max(b));
let delta = max - min;
let h = match delta == 0.0 {
true => 0.0,
false => {
if r == max {
(g - b) / delta
} else if g == max {
2.0 + (b - r) / delta
} else {
4.0 + (r - g) / delta
}
}
};
let h2 = ((h * 60.0) + 360.0) % 360.0;
let i = 0.2126 * c1.red + 0.7152 * c1.green + 0.0722 * c1.blue;
(h2, i)
}
fn setup_aura_page(ui: &MainWindow, _states: Arc<Mutex<Config>>) {
ui.global::<AuraPageData>().on_blend_colour(|c1, c2, f| {
let c1: RgbaColor<f32> = RgbaColor::from(c1);
let c2: RgbaColor<f32> = RgbaColor::from(c2);
let c1 = RgbaColor {
alpha: 1.0,
red: c1.red + (c2.red - c1.red) * f,
green: c1.green + (c2.green - c1.green) * f,
blue: c1.blue + (c2.blue - c1.blue) * f,
};
c1.into()
});
ui.global::<AuraPageData>().on_blend_lightness(|c1, f| {
let c1: RgbaColor<f32> = RgbaColor::from(c1);
let c = RgbaColor {
alpha: 1.0,
red: c1.red * f,
green: c1.green * f,
blue: c1.blue * f,
};
// dbg!(rgb_hi(c.into()));
c.into()
});
ui.global::<AuraPageData>().on_set_hex_from_colour(|c| {
format!("#{:02X}{:02X}{:02X}", c.red(), c.green(), c.blue()).into()
});
ui.global::<AuraPageData>()
.on_set_hex_to_colour(|s| decode_hex(s.as_str()).into());
let handle = ui.as_weak();
tokio::spawn(async move {
let conn = zbus::Connection::system().await.unwrap();
let aura = AuraProxy::builder(&conn)
.cache_properties(CacheProperties::Yes)
.build()
.await
.unwrap();
set_ui_props_async!(handle, aura, AuraPageData, brightness);
set_ui_props_async!(handle, aura, AuraPageData, led_mode);
set_ui_props_async!(handle, aura, AuraPageData, led_mode_data);
if let Ok(modes) = aura.supported_basic_modes().await {
log::debug!("Available LED modes {modes:?}");
handle
.upgrade_in_event_loop(move |handle| {
let m: Vec<i32> = modes.iter().map(|n| (*n).into()).collect();
handle
.global::<AuraPageData>()
.set_supported_basic_modes(m.as_slice().into());
// Get the translated names
let names = handle.global::<AuraPageData>().get_mode_names();
let res: Vec<SharedString> = names
.iter()
.enumerate()
.filter(|(n, _)| modes.contains(&(*n as i32).into()) && *n != 9)
.map(|(_, i)| i)
.collect();
handle
.global::<AuraPageData>()
.set_available_mode_names(res.as_slice().into());
})
.ok();
}
let proxy_copy = aura.clone();
handle
.upgrade_in_event_loop(move |handle| {
set_ui_callbacks!(handle,
AuraPageData(.into()),
aura.brightness(.into()),
"Keyboard LED brightness successfully set to {}",
"Setting keyboard LED brightness failed"
);
set_ui_callbacks!(handle,
AuraPageData(.into()),
aura.led_mode(.into()),
"Keyboard LED mode successfully set to {}",
"Setting keyboard LEDmode failed"
);
set_ui_callbacks!(handle,
AuraPageData(.into()),
aura.led_mode_data(.into()),
"Keyboard LED mode set to {:?}",
"Setting keyboard LED mode failed"
);
})
.ok();
// Need to update the UI if the mode changes
let handle_copy = handle.clone();
// spawn required since the while let never exits
tokio::spawn(async move {
let mut x = proxy_copy.receive_led_mode_data_changed().await;
use zbus::export::futures_util::StreamExt;
while let Some(e) = x.next().await {
if let Ok(out) = e.get().await {
handle_copy
.upgrade_in_event_loop(move |handle| {
handle
.global::<AuraPageData>()
.invoke_update_led_mode_data(out.into());
})
.ok();
}
}
});
});
}
fn setup_anime_page(ui: &MainWindow, _states: Arc<Mutex<Config>>) {
let handle = ui.as_weak();
tokio::spawn(async move {
let conn = zbus::Connection::system().await.unwrap();
let anime = AnimeProxy::new(&conn).await.unwrap();
set_ui_props_async!(handle, anime, AnimePageData, brightness);
set_ui_props_async!(handle, anime, AnimePageData, builtins_enabled);
set_ui_props_async!(handle, anime, AnimePageData, enable_display);
set_ui_props_async!(handle, anime, AnimePageData, off_when_lid_closed);
set_ui_props_async!(handle, anime, AnimePageData, off_when_suspended);
set_ui_props_async!(handle, anime, AnimePageData, off_when_unplugged);
let builtins = anime.builtin_animations().await.unwrap_or_default();
handle
.upgrade_in_event_loop(move |handle| {
{
let global = handle.global::<AnimePageData>();
global.set_boot_anim(builtins.boot as i32);
global.set_awake_anim(builtins.awake as i32);
global.set_sleep_anim(builtins.sleep as i32);
global.set_shutdown_anim(builtins.shutdown as i32);
let handle_copy = handle.as_weak();
let anime_copy = anime.clone();
global.on_set_builtin_animations(move |boot, awake, sleep, shutdown| {
let handle_copy = handle_copy.clone();
let anime_copy = anime_copy.clone();
tokio::spawn(async move {
show_toast(
"Anime builtin animations changed".into(),
"Failed to set Anime builtin animations".into(),
handle_copy,
anime_copy
.set_builtin_animations(Animations {
boot: boot.into(),
awake: awake.into(),
sleep: sleep.into(),
shutdown: shutdown.into(),
})
.await,
);
});
});
let handle_copy = handle.as_weak();
let anime_copy = anime.clone();
tokio::spawn(async move {
let mut x = anime_copy.receive_builtin_animations_changed().await;
use zbus::export::futures_util::StreamExt;
while let Some(e) = x.next().await {
if let Ok(out) = e.get().await {
handle_copy
.upgrade_in_event_loop(move |handle| {
handle
.global::<AnimePageData>()
.set_boot_anim(out.boot.into());
handle
.global::<AnimePageData>()
.set_awake_anim(out.awake.into());
handle
.global::<AnimePageData>()
.set_sleep_anim(out.sleep.into());
handle
.global::<AnimePageData>()
.set_shutdown_anim(out.shutdown.into());
})
.ok();
}
}
});
}
set_ui_callbacks!(handle,
AnimePageData(.into()),
anime.brightness(.into()),
"Anime LED brightness successfully set to {}",
"Setting Anime LED brightness failed"
);
set_ui_callbacks!(
handle,
AnimePageData(),
anime.builtins_enabled(),
"Keyboard LED mode successfully set to {}",
"Setting keyboard LEDmode failed"
);
set_ui_callbacks!(
handle,
AnimePageData(),
anime.enable_display(),
"Anime display successfully set to {}",
"Setting Anime display failed"
);
set_ui_callbacks!(
handle,
AnimePageData(),
anime.off_when_lid_closed(),
"Anime off_when_lid_closed successfully set to {}",
"Setting Anime off_when_lid_closed failed"
);
set_ui_callbacks!(
handle,
AnimePageData(),
anime.off_when_suspended(),
"Anime off_when_suspended successfully set to {}",
"Setting Anime off_when_suspended failed"
);
set_ui_callbacks!(
handle,
AnimePageData(),
anime.off_when_unplugged(),
"Anime off_when_unplugged successfully set to {}",
"Setting Anime off_when_unplugged failed"
);
})
.unwrap();
});
}
fn show_toast(
success: SharedString,
fail: SharedString,
handle: Weak<MainWindow>,
result: zbus::Result<()>,
) {
match result {
Ok(_) => {
slint::invoke_from_event_loop(move || handle.unwrap().invoke_show_toast(success)).ok()
}
Err(e) => slint::invoke_from_event_loop(move || {
log::warn!("{fail}: {e}");
handle.unwrap().invoke_show_toast(fail)
})
.ok(),
};
}

View File

@@ -0,0 +1,539 @@
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2024-03-02 10:44+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: \n"
"Plural-Forms: nplurals=1; plural=0;\n"
#: rog-control-center/ui/pages/anime.slint:7
msgctxt "Anime Brightness"
msgid "Off"
msgstr ""
#: rog-control-center/ui/pages/anime.slint:8
msgctxt "Anime Brightness"
msgid "Low"
msgstr ""
#: rog-control-center/ui/pages/anime.slint:9
msgctxt "Anime Brightness"
msgid "Med"
msgstr ""
#: rog-control-center/ui/pages/anime.slint:10
msgctxt "Anime Brightness"
msgid "High"
msgstr ""
#: rog-control-center/ui/pages/anime.slint:30
msgctxt "AnimePageData"
msgid "Glitch Construction"
msgstr ""
#: rog-control-center/ui/pages/anime.slint:30
msgctxt "AnimePageData"
msgid "Static Emergence"
msgstr ""
#: rog-control-center/ui/pages/anime.slint:32
msgctxt "AnimePageData"
msgid "Binary Banner Scroll"
msgstr ""
#: rog-control-center/ui/pages/anime.slint:32
msgctxt "AnimePageData"
msgid "Rog Logo Glitch"
msgstr ""
#: rog-control-center/ui/pages/anime.slint:34
msgctxt "AnimePageData"
msgid "Banner Swipe"
msgstr ""
#: rog-control-center/ui/pages/anime.slint:34
msgctxt "AnimePageData"
msgid "Starfield"
msgstr ""
#: rog-control-center/ui/pages/anime.slint:36
msgctxt "AnimePageData"
msgid "Glitch Out"
msgstr ""
#: rog-control-center/ui/pages/anime.slint:36
msgctxt "AnimePageData"
msgid "See Ya"
msgstr ""
#: rog-control-center/ui/pages/anime.slint:58
msgctxt "Anime Brightness"
msgid "Brightness"
msgstr ""
#: rog-control-center/ui/pages/anime.slint:74
msgctxt "PageAnime"
msgid "Enable display"
msgstr ""
#: rog-control-center/ui/pages/anime.slint:82 rog-control-center/ui/pages/anime.slint:105
msgctxt "PageAnime"
msgid "Advanced"
msgstr ""
#: rog-control-center/ui/pages/anime.slint:97
msgctxt "PageAnime"
msgid "Use built-in animations"
msgstr ""
#: rog-control-center/ui/pages/anime.slint:155
msgctxt "PageAnime"
msgid "Advanced Anime Display : TODO!"
msgstr ""
#: rog-control-center/ui/pages/anime.slint:159
msgctxt "Anime built-in selection"
msgid "Boot Animation"
msgstr ""
#: rog-control-center/ui/pages/anime.slint:169
msgctxt "Anime built-in selection"
msgid "Running Animation"
msgstr ""
#: rog-control-center/ui/pages/anime.slint:179
msgctxt "Anime built-in selection"
msgid "Sleep Animation"
msgstr ""
#: rog-control-center/ui/pages/anime.slint:189
msgctxt "Anime built-in selection"
msgid "Shutdown Animation"
msgstr ""
#: rog-control-center/ui/pages/anime.slint:230
msgctxt "PageAnime"
msgid "Advanced Display Settings"
msgstr ""
#: rog-control-center/ui/pages/anime.slint:235
msgctxt "PageAnime"
msgid "Off when lid closed"
msgstr ""
#: rog-control-center/ui/pages/anime.slint:244
msgctxt "PageAnime"
msgid "Off when suspended"
msgstr ""
#: rog-control-center/ui/pages/anime.slint:253
msgctxt "PageAnime"
msgid "Off when on battery"
msgstr ""
#: rog-control-center/ui/pages/aura.slint:24
msgctxt "Aura brightness"
msgid "Off"
msgstr ""
#: rog-control-center/ui/pages/aura.slint:25
msgctxt "Aura brightness"
msgid "Low"
msgstr ""
#: rog-control-center/ui/pages/aura.slint:26
msgctxt "Aura brightness"
msgid "Med"
msgstr ""
#: rog-control-center/ui/pages/aura.slint:27
msgctxt "Aura brightness"
msgid "High"
msgstr ""
#: rog-control-center/ui/pages/aura.slint:33 rog-control-center/ui/pages/aura.slint:48
msgctxt "Basic aura mode"
msgid "Static"
msgstr ""
#: rog-control-center/ui/pages/aura.slint:34 rog-control-center/ui/pages/aura.slint:49
msgctxt "Basic aura mode"
msgid "Breathe"
msgstr ""
#: rog-control-center/ui/pages/aura.slint:35 rog-control-center/ui/pages/aura.slint:50
msgctxt "Basic aura mode"
msgid "Strobe"
msgstr ""
#: rog-control-center/ui/pages/aura.slint:36
msgctxt "Basic aura mode"
msgid "Rainbow"
msgstr ""
#: rog-control-center/ui/pages/aura.slint:37
msgctxt "Basic aura mode"
msgid "Star"
msgstr ""
#: rog-control-center/ui/pages/aura.slint:38
msgctxt "Basic aura mode"
msgid "Rain"
msgstr ""
#: rog-control-center/ui/pages/aura.slint:39
msgctxt "Basic aura mode"
msgid "Highlight"
msgstr ""
#: rog-control-center/ui/pages/aura.slint:40
msgctxt "Basic aura mode"
msgid "Laser"
msgstr ""
#: rog-control-center/ui/pages/aura.slint:41
msgctxt "Basic aura mode"
msgid "Ripple"
msgstr ""
#: rog-control-center/ui/pages/aura.slint:42
msgctxt "Basic aura mode"
msgid "Nothing"
msgstr ""
#: rog-control-center/ui/pages/aura.slint:43
msgctxt "Basic aura mode"
msgid "Pulse"
msgstr ""
#: rog-control-center/ui/pages/aura.slint:44
msgctxt "Basic aura mode"
msgid "Comet"
msgstr ""
#: rog-control-center/ui/pages/aura.slint:45
msgctxt "Basic aura mode"
msgid "Flash"
msgstr ""
#: rog-control-center/ui/pages/aura.slint:59
msgctxt "Aura zone"
msgid "None"
msgstr ""
#: rog-control-center/ui/pages/aura.slint:60
msgctxt "Aura zone"
msgid "Key1"
msgstr ""
#: rog-control-center/ui/pages/aura.slint:61
msgctxt "Aura zone"
msgid "Key2"
msgstr ""
#: rog-control-center/ui/pages/aura.slint:62
msgctxt "Aura zone"
msgid "Key3"
msgstr ""
#: rog-control-center/ui/pages/aura.slint:63
msgctxt "Aura zone"
msgid "Key4"
msgstr ""
#: rog-control-center/ui/pages/aura.slint:64
msgctxt "Aura zone"
msgid "Logo"
msgstr ""
#: rog-control-center/ui/pages/aura.slint:65
msgctxt "Aura zone"
msgid "Lightbar Left"
msgstr ""
#: rog-control-center/ui/pages/aura.slint:66
msgctxt "Aura zone"
msgid "Lightbar Right"
msgstr ""
#: rog-control-center/ui/pages/aura.slint:71
msgctxt "Aura direction"
msgid "Right"
msgstr ""
#: rog-control-center/ui/pages/aura.slint:72
msgctxt "Aura direction"
msgid "Left"
msgstr ""
#: rog-control-center/ui/pages/aura.slint:73
msgctxt "Aura direction"
msgid "Up"
msgstr ""
#: rog-control-center/ui/pages/aura.slint:74
msgctxt "Aura direction"
msgid "Down"
msgstr ""
#: rog-control-center/ui/pages/aura.slint:79
msgctxt "Aura speed"
msgid "Low"
msgstr ""
#: rog-control-center/ui/pages/aura.slint:80
msgctxt "Aura speed"
msgid "Medium"
msgstr ""
#: rog-control-center/ui/pages/aura.slint:81
msgctxt "Aura speed"
msgid "High"
msgstr ""
#: rog-control-center/ui/pages/aura.slint:128
msgctxt "PageAura"
msgid "Brightness"
msgstr ""
#: rog-control-center/ui/pages/aura.slint:139
msgctxt "PageAura"
msgid "Aura mode"
msgstr ""
#: rog-control-center/ui/pages/aura.slint:156
msgctxt "PageAura"
msgid "Colour 1"
msgstr ""
#: rog-control-center/ui/pages/aura.slint:187
msgctxt "PageAura"
msgid "Colour 2"
msgstr ""
#: rog-control-center/ui/pages/aura.slint:224
msgctxt "PageAura"
msgid "Zone"
msgstr ""
#: rog-control-center/ui/pages/aura.slint:244
msgctxt "PageAura"
msgid "Direction"
msgstr ""
#: rog-control-center/ui/pages/aura.slint:264
msgctxt "PageAura"
msgid "Speed"
msgstr ""
#: rog-control-center/ui/pages/aura.slint:282
msgctxt "PageAura"
msgid "Apply"
msgstr ""
#: rog-control-center/ui/pages/system.slint:27
msgctxt "SystemPageData"
msgid "Balanced"
msgstr ""
#: rog-control-center/ui/pages/system.slint:27 rog-control-center/ui/pages/system.slint:32
msgctxt "SystemPageData"
msgid "Performance"
msgstr ""
#: rog-control-center/ui/pages/system.slint:27
msgctxt "SystemPageData"
msgid "Quiet"
msgstr ""
#: rog-control-center/ui/pages/system.slint:31
msgctxt "SystemPageData"
msgid "Default"
msgstr ""
#: rog-control-center/ui/pages/system.slint:33
msgctxt "SystemPageData"
msgid "BalancePerformance"
msgstr ""
#: rog-control-center/ui/pages/system.slint:34
msgctxt "SystemPageData"
msgid "BalancePower"
msgstr ""
#: rog-control-center/ui/pages/system.slint:35
msgctxt "SystemPageData"
msgid "Power"
msgstr ""
#: rog-control-center/ui/pages/system.slint:116
msgctxt "PageSystem"
msgid "Base system settings"
msgstr ""
#: rog-control-center/ui/pages/system.slint:121
msgctxt "PageSystem"
msgid "Charge limit"
msgstr ""
#: rog-control-center/ui/pages/system.slint:133
msgctxt "PageSystem"
msgid "Throttle Policy"
msgstr ""
#: rog-control-center/ui/pages/system.slint:143
msgctxt "PageSystem"
msgid "Advanced"
msgstr ""
#: rog-control-center/ui/pages/system.slint:155
msgctxt "PageSystem"
msgid "Panel Overdrive"
msgstr ""
#: rog-control-center/ui/pages/system.slint:163
msgctxt "PageSystem"
msgid "MiniLED Mode"
msgstr ""
#: rog-control-center/ui/pages/system.slint:181
msgctxt "PageSystem"
msgid "System performance settings"
msgstr ""
#: rog-control-center/ui/pages/system.slint:186
msgctxt "ppt_pl1_spl"
msgid "ppt_pl1_spl"
msgstr ""
#: rog-control-center/ui/pages/system.slint:196
msgctxt "ppt_pl2_sppt"
msgid "ppt_pl2_sppt"
msgstr ""
#: rog-control-center/ui/pages/system.slint:206
msgctxt "ppt_fppt"
msgid "ppt_fppt"
msgstr ""
#: rog-control-center/ui/pages/system.slint:216
msgctxt "ppt_apu_sppt"
msgid "ppt_apu_sppt"
msgstr ""
#: rog-control-center/ui/pages/system.slint:225
msgctxt "ppt_platform_sppt"
msgid "ppt_platform_sppt"
msgstr ""
#: rog-control-center/ui/pages/system.slint:235
msgctxt "nv_dynamic_boost"
msgid "nv_dynamic_boost"
msgstr ""
#: rog-control-center/ui/pages/system.slint:244
msgctxt "nv_temp_target"
msgid "nv_temp_target"
msgstr ""
#: rog-control-center/ui/pages/system.slint:290
msgctxt "PageSystem"
msgid "Energy Performance Preference linked to Throttle Policy"
msgstr ""
#: rog-control-center/ui/pages/system.slint:294
msgctxt "PageSystem"
msgid "Change EPP based on Throttle Policy"
msgstr ""
#: rog-control-center/ui/pages/system.slint:302
msgctxt "PageSystem"
msgid "EPP for Balanced Policy"
msgstr ""
#: rog-control-center/ui/pages/system.slint:312
msgctxt "PageSystem"
msgid "EPP for Performance Policy"
msgstr ""
#: rog-control-center/ui/pages/system.slint:322
msgctxt "PageSystem"
msgid "EPP for Quiet Policy"
msgstr ""
#: rog-control-center/ui/pages/system.slint:340
msgctxt "PageSystem"
msgid "Throttle Policy for power state"
msgstr ""
#: rog-control-center/ui/pages/system.slint:344
msgctxt "PageSystem"
msgid "Throttle Policy on Battery"
msgstr ""
#: rog-control-center/ui/pages/system.slint:354
msgctxt "PageSystem"
msgid "Throttle Policy on AC"
msgstr ""
#: rog-control-center/ui/pages/app_settings.slint:32
msgctxt "PageAppSettings"
msgid "Run in background after closing"
msgstr ""
#: rog-control-center/ui/pages/app_settings.slint:41
msgctxt "PageAppSettings"
msgid "Start app in background (UI closed)"
msgstr ""
#: rog-control-center/ui/pages/app_settings.slint:53
msgctxt "PageAppSettings"
msgid "Enable system tray icon"
msgstr ""
#: rog-control-center/ui/pages/app_settings.slint:62
msgctxt "PageAppSettings"
msgid "Enable change notifications"
msgstr ""
#: rog-control-center/ui/main_window.slint:42
msgctxt "MainWindow"
msgid "ROG"
msgstr ""
#: rog-control-center/ui/main_window.slint:44
msgctxt "Menu1"
msgid "System Control"
msgstr ""
#: rog-control-center/ui/main_window.slint:45
msgctxt "Menu2"
msgid "Keyboard Aura"
msgstr ""
#: rog-control-center/ui/main_window.slint:46
msgctxt "Menu3"
msgid "AniMe Matrix"
msgstr ""
#: rog-control-center/ui/main_window.slint:47
msgctxt "Menu4"
msgid "Fan Curves"
msgstr ""
#: rog-control-center/ui/main_window.slint:48
msgctxt "Menu5"
msgid "App Settings"
msgstr ""
#: rog-control-center/ui/main_window.slint:49
msgctxt "Menu6"
msgid "About"
msgstr ""

View File

@@ -1,84 +1,110 @@
import { VerticalBox , StandardButton, Button} from "std-widgets.slint";
import { VerticalBox , StandardButton, Button, HorizontalBox, ComboBox, Switch, Slider} from "std-widgets.slint";
import { Theme } from "globals.slint";
export component SquareImageButton inherits Rectangle {
callback clicked;
in-out property <image> img;
border-radius: 7px;
border-width: 2px;
border-color: Theme.control-outline;
background: Theme.image-button-background;
touch := TouchArea {
clicked => {
root.clicked();
export component RogItem inherits Rectangle {
background: Theme.background-color;
border-color: Colors.black;
border-width: 3px;
border-radius: 10px;
}
export component SystemSlider inherits RogItem {
in property <string> text;
in-out property <float> value;
in-out property <float> minimum;
in-out property <float> maximum;
callback released(int);
HorizontalLayout {
HorizontalBox {
width: 30%;
alignment: LayoutAlignment.start;
Text {
font-size: 16px;
vertical-alignment: TextVerticalAlignment.center;
color: Theme.text-foreground-color;
text <=> root.text;
}
Text {
font-size: 16px;
vertical-alignment: TextVerticalAlignment.center;
color: Theme.text-foreground-color;
text: ": \{Math.round(root.value)}";
}
}
}
Image {
height: 90%;
width: 90%;
x: (parent.width - self.width) / 2;
y: (parent.height - self.height) / 2;
source <=> root.img;
image-fit: contain;
// colorize: Theme.control-secondary;
HorizontalBox {
// alignment: LayoutAlignment.end;
padding-right: 20px;
Slider {
maximum: root.maximum;
minimum: root.minimum;
value <=> root.value;
released => {
root.released(Math.round(root.value))
}
}
}
}
}
export component RoundImageButton inherits Rectangle {
callback clicked;
in-out property <image> img;
in property <length> size;
width: self.size;
height: self.size;
border-radius: root.width / 2;
border-width: 6px;
border-color: Theme.control-outline;
background: Theme.image-button-background;
touch := TouchArea {
clicked => {
root.clicked();
export component SystemToggle inherits RogItem {
in property <string> text;
in-out property <bool> checked;
callback toggled(bool);
HorizontalLayout {
HorizontalBox {
alignment: LayoutAlignment.start;
Text {
font-size: 16px;
vertical-alignment: TextVerticalAlignment.center;
color: Theme.text-foreground-color;
text <=> root.text;
}
}
}
Image {
height: 60%;
width: 60%;
x: (parent.width - self.width) / 2;
y: (parent.height - self.height) / 2;
source <=> root.img;
image-fit: contain;
// colorize: Theme.control-secondary;
HorizontalBox {
alignment: LayoutAlignment.end;
padding-right: 20px;
Switch {
checked <=> root.checked;
toggled => {
root.toggled(root.checked)
}
}
}
}
}
export component SquareCharButton inherits Rectangle {
callback clicked;
in-out property <string> char;
border-radius: 7px;
border-width: 2px;
border-color: Theme.control-outline;
background: Theme.image-button-background;
touch := TouchArea {
clicked => {
root.clicked();
export component SystemDropdown inherits RogItem {
in property <string> text;
in-out property <int> current_index;
in-out property <string> current_value;
in-out property <[string]> model;
callback selected(int);
HorizontalLayout {
HorizontalBox {
alignment: LayoutAlignment.start;
Text {
font-size: 16px;
vertical-alignment: TextVerticalAlignment.center;
color: Theme.text-foreground-color;
text <=> root.text;
}
}
}
Text {
// height: 90%;
// width: 90%;
x: (parent.width - self.width) / 2;
y: (parent.height - self.height) / 2;
text: char;
font-size: 28px;
font-weight: 900;
horizontal-alignment: center;
vertical-alignment: center;
color: Theme.control-foreground;
HorizontalBox {
alignment: LayoutAlignment.end;
padding-right: 20px;
ComboBox {
model <=> root.model;
current-index <=> root.current_index;
current-value <=> root.current_value;
selected => {
root.selected(root.current_index)
}
}
}
}
}
@@ -87,33 +113,25 @@ export component ValueBar inherits Rectangle {
in property <float> value: 0.0;
in property <float> min: 0.0;
in property <float> max: 1.0;
function percentage(min: float, max: float, value: float) -> float{
function percentage(min: float, max: float, value: float) -> float {
if (min < 0.0 && max > 0.0) {
// do a percentage of each half as 0-50%
if (value >= max + min) {
return (value - (max + min) / 2) / (max - min);
}
return 0.50 - (value - (min - max) / 2) / (max - min);
}
return (value - min) / (max - min);
}
function set_x(min: float, max: float, value: float, width: length) -> length{
function set_x(min: float, max: float, value: float, width: length) -> length {
if (min < 0.0 && max > 0.0) {
if (value < max + min) {
return width / 2 - width * (percentage(min, max, value));
}
return width / 2;
}
return 0;
}
Rectangle {
border-radius: 3px;
background: Theme.neutral-box;
@@ -135,54 +153,6 @@ export component ValueBar inherits Rectangle {
}
}
// Single direction spinbox
export component SpinBoxUni inherits Rectangle {
in-out property <int> value;
in property <int> minimum;
in property <int> maximum: 100;
height: 32px;
HorizontalLayout {
spacing: 12px;
padding: 0;
SquareCharButton {
width: root.height - parent.padding * 2;
char: "-";
clicked => {
if (root.value > root.minimum) {
root.value -= 1;
}
}
}
Rectangle {
border-radius: 3px;
border-width: 2px;
border-color: Theme.control-outline;
// TODO: replace with visual min/max drawing
Text {
width: 100%;
height: 100%;
vertical-alignment: center;
horizontal-alignment: center;
text: root.value;
color: Theme.control-foreground;
}
}
SquareCharButton {
width: root.height - parent.padding * 2;
char: "+";
clicked => {
if (root.value < root.maximum) {
root.value += 1;
}
}
}
}
}
export component PopupNotification {
in property <string> heading;
in property <string> content;
@@ -238,7 +208,5 @@ export component PopupNotification {
public function show() {
_p.show();
}
}

View File

@@ -5,15 +5,15 @@ struct ButtonColours {
}
export global AppSize {
out property <length> width: 800px;
out property <length> height: 480px;
out property <length> width: 900px;
out property <length> height: 500px;
}
export global Theme {
out property <color> window-background: #000000;
out property <color> neutral-box: #BDC0D1;
// The background colour of pages and bars
out property <color> background-color: root.dark-mode ? #12387b : white;
out property <color> background-color: root.dark-mode ? #3a127b : white;
out property <color> text-foreground-color: root.dark-mode ? #F4F6FF : black;
out property <color> secondary-foreground-color: root.dark-mode ? #C1C3CA : #6C6E7A;
out property <color> image-button-background: root.dark-mode ? root.window-background : white;

View File

@@ -1,45 +1,63 @@
import { Button, VerticalBox } from "std-widgets.slint";
import { SpinBoxUni, ValueBar, SquareImageButton, RoundImageButton } from "common_widgets.slint";
import { Theme, AppSize } from "globals.slint";
import { PageSystem, AvailableSystemProperties, SystemPage } from "pages/system.slint";
import { PageSystem, AvailableSystemProperties, SystemPageData } from "pages/system.slint";
import { SideBar } from "widgets/sidebar.slint";
import { PageAbout } from "pages/about.slint";
import { PageGpu } from "pages/gpu.slint";
import { PageFans } from "pages/fans.slint";
import { PageAnime } from "pages/anime.slint";
import { PageAura } from "pages/aura.slint";
import { PageAnime, AnimePageData } from "pages/anime.slint";
import { PageAura, AuraPageData, AuraEffect } from "pages/aura.slint";
import { PageAppSettings, AppSettingsPageData } from "pages/app_settings.slint";
export { AppSize, Theme, AvailableSystemProperties, SystemPage }
export { AppSize, AuraEffect, Theme, AvailableSystemProperties, SystemPageData, AuraPageData, AnimePageData, AppSettingsPageData }
export component MainWindow inherits Window {
default-font-family: "DejaVu Sans";
in property <[bool]> sidebar_items_avilable: [true, true, true, true, true, true];
private property <bool> show-notif;
private property <bool> fade-cover;
private property <bool> toast: false;
private property <string> toast_text: "I show when something is waiting";
callback show_toast(string);
show_toast(text) => {
toast = text != "";
toast_text = text;
}
callback exit-app();
callback show-notification(bool);
show-notification(yes) => {
show-notif = yes;
fade-cover = yes;
}
in-out property <bool> charge-available;
height: AppSize.height;
width: AppSize.width;
background: Colors.orange;
min-height: AppSize.height;
min-width: AppSize.width;
background: Colors.black;
HorizontalLayout {
padding: 0px;
side-bar := SideBar {
title: @tr("ROG");
model: [
@tr("Menu" => "System Control"),
@tr("Menu" => "Keyboard Aura"),
@tr("Menu" => "AniMe Matrix"),
@tr("Menu" => "Fan Curves"),
@tr("Menu" => "GPU Control"),
@tr("Menu" => "About"),
];
VerticalLayout {
side-bar := SideBar {
title: @tr("ROG");
model: [
@tr("Menu1" => "System Control"),
@tr("Menu2" => "Keyboard Aura"),
@tr("Menu3" => "AniMe Matrix"),
@tr("Menu4" => "Fan Curves"),
@tr("Menu5" => "App Settings"),
@tr("Menu6" => "About"),
];
available: root.sidebar_items_avilable;
}
Button {
max-height: 20px;
text: "Quit";
clicked => {
root.exit-app();
}
}
}
Rectangle {
@@ -61,7 +79,7 @@ export component MainWindow inherits Window {
width: root.width - side-bar.width;
}
if(side-bar.current-item == 4): PageGpu {
if(side-bar.current-item == 4): PageAppSettings {
width: root.width - side-bar.width;
}
@@ -85,10 +103,33 @@ export component MainWindow inherits Window {
// toolbar-dropdown.close();
if (show-notif) {
show-notif = false;
}
fade-cover = false;
}
}
}
if toast: Rectangle {
x: 0px;
y: 0px;
width: root.width;
height: 32px;
opacity: 0.8;
TouchArea {
height: 100%;
width: 100%;
clicked => {
toast = false;
}
}
Rectangle {
height: 100%;
width: 100%;
background: #1a043d;
Text {
color: Theme.text-foreground-color;
text: root.toast_text;
}
}
}
@@ -105,7 +146,6 @@ export component MainWindow inherits Window {
clicked => {
show-notif = false;
exit-app();
}
}

View File

@@ -3,16 +3,18 @@ import { Theme } from "../globals.slint";
import { AboutSlint } from "std-widgets.slint";
export component PageAbout inherits VerticalLayout {
Rectangle {
clip: true;
// TODO: slow with border-radius
padding: 8px;
// height: parent.height - infobar.height - mainview.padding - self.padding * 2;
// TODO: border-radius: 8px;
mainview := VerticalLayout {
padding: 10px;
spacing: 10px;
AboutSlint {}
}
padding: 10px;
spacing: 10px;
Text {
vertical-alignment: TextVerticalAlignment.center;
horizontal-alignment: TextHorizontalAlignment.center;
text: "A UI for asusctl made with slint";
font-size: 22px;
}
Text {
vertical-alignment: TextVerticalAlignment.center;
horizontal-alignment: TextHorizontalAlignment.center;
text: "Work in progress";
font-size: 22px;
}
}

View File

@@ -1,49 +1,273 @@
import { ValueBar } from "../common_widgets.slint";
import { Theme } from "../globals.slint";
import { SystemDropdown, SystemToggle } from "../common_widgets.slint";
import { GroupBox, VerticalBox, Button, HorizontalBox } from "std-widgets.slint";
export component PageAnime inherits VerticalLayout {
Rectangle {
clip: true;
// TODO: slow with border-radius
export global AnimePageData {
in-out property <[string]> brightness_names: [
@tr("Anime Brightness" => "Off"),
@tr("Anime Brightness" => "Low"),
@tr("Anime Brightness" => "Med"),
@tr("Anime Brightness" => "High"),
];
in-out property <int> brightness;
callback set_brightness(int);
in-out property <bool> builtins_enabled;
callback set_builtins_enabled(bool);
in-out property <bool> enable_display;
callback set_enable_display(bool);
in-out property <bool> off_when_lid_closed;
callback set_off_when_lid_closed(bool);
in-out property <bool> off_when_suspended;
callback set_off_when_suspended(bool);
in-out property <bool> off_when_unplugged;
callback set_off_when_unplugged(bool);
in-out property <[string]> boot_anim_choices: [@tr("Glitch Construction"), @tr("Static Emergence")];
in property <int> boot_anim: 0;
in-out property <[string]> awake_anim_choices: [@tr("Binary Banner Scroll"), @tr("Rog Logo Glitch")];
in property <int> awake_anim: 0;
in-out property <[string]> sleep_anim_choices: [@tr("Banner Swipe"), @tr("Starfield")];
in property <int> sleep_anim: 0;
in-out property <[string]> shutdown_anim_choices: [@tr("Glitch Out"), @tr("See Ya")];
in property <int> shutdown_anim: 0;
callback set_builtin_animations(int, int, int, int);
}
export component PageAnime inherits Rectangle {
property <bool> show_fade_cover: false;
property <bool> show_display_advanced: false;
property <bool> show_builtin_advanced: false;
clip: true;
// TODO: slow with border-radius
padding: 8px;
// height: parent.height - infobar.height - mainview.padding - self.padding * 2;
// height: parent.height - infobar.height - mainview.padding - self.padding * 2;
// TODO: border-radius: 8px;
mainview := VerticalLayout {
padding: 10px;
VerticalLayout {
padding: 10px;
spacing: 10px;
HorizontalLayout {
spacing: 10px;
ValueBar {
height: 40px;
value: 10.5;
min: 0.0;
max: 100.0;
max-height: 32px;
SystemDropdown {
text: @tr("Anime Brightness" => "Brightness");
current_index <=> AnimePageData.brightness;
current_value: AnimePageData.brightness_names[AnimePageData.brightness];
model <=> AnimePageData.brightness_names;
selected => {
self.current_value = AnimePageData.brightness_names[AnimePageData.brightness];
AnimePageData.set_brightness(AnimePageData.brightness)
}
}
}
HorizontalLayout {
spacing: 10px;
max-height: 32px;
alignment: LayoutAlignment.stretch;
SystemToggle {
text: @tr("Enable display");
checked <=> AnimePageData.enable_display;
toggled => {
AnimePageData.set_enable_display(AnimePageData.enable_display)
}
}
ValueBar {
height: 40px;
value: -70;
min: -100;
max: 0;
Button {
text: @tr("Advanced");
width: 20%;
enabled <=> AnimePageData.enable_display;
clicked => {
root.show_fade_cover = true;
root.show_display_advanced = true;
}
}
}
HorizontalLayout {
spacing: 10px;
max-height: 32px;
alignment: LayoutAlignment.stretch;
SystemToggle {
text: @tr("Use built-in animations");
checked <=> AnimePageData.builtins_enabled;
toggled => {
AnimePageData.set_builtins_enabled(AnimePageData.builtins_enabled)
}
}
ValueBar {
height: 80px;
value: 40;
min: -50;
max: 50;
Button {
text: @tr("Advanced");
width: 20%;
enabled <=> AnimePageData.builtins_enabled;
clicked => {
root.show_fade_cover = true;
root.show_builtin_advanced = true;
}
}
}
}
ValueBar {
height: 80px;
value: -40;
min: -50;
max: 50;
if root.show_fade_cover: Rectangle {
width: 100%;
height: 100%;
background: Theme.background-color;
opacity: 0.8;
TouchArea {
height: 100%;
width: 100%;
// clicked => {
// // toolbar-dropdown.close();
// if (root.show_display_advanced) {
// root.show_display_advanced = false;
// }
// if (root.show_builtin_advanced) {
// root.show_builtin_advanced = false;
// }
// root.show_fade_cover = false;
// }
}
}
if root.show_builtin_advanced: Rectangle {
x: 0;
width: 100%;
height: 100%;
opacity: 1;
VerticalLayout {
padding: 50px;
spacing: 10px;
GroupBox {
height: 100px;
VerticalBox {
spacing: 10px;
alignment: LayoutAlignment.start;
Text {
font-size: 18px;
color: Theme.text-foreground-color;
horizontal-alignment: TextHorizontalAlignment.center;
text: @tr("Advanced Anime Display : TODO!");
}
SystemDropdown {
text: @tr("Anime built-in selection" => "Boot Animation");
current_index <=> AnimePageData.boot_anim;
current_value: AnimePageData.boot_anim_choices[AnimePageData.boot_anim];
model <=> AnimePageData.boot_anim_choices;
selected => {
AnimePageData.set_builtin_animations(AnimePageData.boot_anim, AnimePageData.awake_anim, AnimePageData.sleep_anim, AnimePageData.shutdown_anim)
}
}
SystemDropdown {
text: @tr("Anime built-in selection" => "Running Animation");
current_index <=> AnimePageData.awake_anim;
current_value: AnimePageData.awake_anim_choices[AnimePageData.awake_anim];
model <=> AnimePageData.awake_anim_choices;
selected => {
AnimePageData.set_builtin_animations(AnimePageData.boot_anim, AnimePageData.awake_anim, AnimePageData.sleep_anim, AnimePageData.shutdown_anim)
}
}
SystemDropdown {
text: @tr("Anime built-in selection" => "Sleep Animation");
current_index <=> AnimePageData.sleep_anim;
current_value: AnimePageData.sleep_anim_choices[AnimePageData.sleep_anim];
model <=> AnimePageData.sleep_anim_choices;
selected => {
AnimePageData.set_builtin_animations(AnimePageData.boot_anim, AnimePageData.awake_anim, AnimePageData.sleep_anim, AnimePageData.shutdown_anim)
}
}
SystemDropdown {
text: @tr("Anime built-in selection" => "Shutdown Animation");
current_index <=> AnimePageData.shutdown_anim;
current_value: AnimePageData.shutdown_anim_choices[AnimePageData.shutdown_anim];
model <=> AnimePageData.shutdown_anim_choices;
selected => {
AnimePageData.set_builtin_animations(AnimePageData.boot_anim, AnimePageData.awake_anim, AnimePageData.sleep_anim, AnimePageData.shutdown_anim)
}
}
}
}
}
ValueBar {
height: 80px;
value: -40;
min: -50;
max: 50;
Button {
x: root.width - self.width - 6px;
y: 6px;
text: "X";
height: 40px;
clicked => {
root.show_builtin_advanced = false;
root.show_fade_cover = false;
}
}
}
if root.show_display_advanced: Rectangle {
width: 100%;
height: 100%;
opacity: 1;
VerticalLayout {
padding: 50px;
spacing: 10px;
GroupBox {
height: 100px;
VerticalBox {
spacing: 10px;
alignment: LayoutAlignment.start;
Text {
font-size: 18px;
color: Theme.text-foreground-color;
horizontal-alignment: TextHorizontalAlignment.center;
text: @tr("Advanced Display Settings");
}
SystemToggle {
max-height: 42px;
text: @tr("Off when lid closed");
checked <=> AnimePageData.off_when_lid_closed;
toggled => {
AnimePageData.set_off_when_lid_closed(AnimePageData.off_when_lid_closed)
}
}
SystemToggle {
max-height: 42px;
text: @tr("Off when suspended");
checked <=> AnimePageData.off_when_suspended;
toggled => {
AnimePageData.set_off_when_suspended(AnimePageData.off_when_suspended)
}
}
SystemToggle {
max-height: 42px;
text: @tr("Off when on battery");
checked <=> AnimePageData.off_when_unplugged;
toggled => {
AnimePageData.set_off_when_unplugged(AnimePageData.off_when_unplugged)
}
}
}
}
}
Button {
x: root.width - self.width - 6px;
y: 6px;
text: "X";
height: 40px;
clicked => {
root.show_display_advanced = false;
root.show_fade_cover = false;
}
}
}

View File

@@ -0,0 +1,75 @@
import { Theme } from "../globals.slint";
import { SystemToggle } from "../common_widgets.slint";
export global AppSettingsPageData {
in-out property <bool> run_in_background;
callback set_run_in_background(bool);
in-out property <bool> startup_in_background;
callback set_startup_in_background(bool);
in-out property <bool> enable_tray_icon;
callback set_enable_tray_icon(bool);
in-out property <bool> enable_notifications;
callback set_enable_notifications(bool);
}
export component PageAppSettings inherits VerticalLayout {
Rectangle {
clip: true;
// TODO: slow with border-radius
padding: 8px;
// height: parent.height - infobar.height - mainview.padding - self.padding * 2;
// TODO: border-radius: 8px;
mainview := VerticalLayout {
padding: 10px;
spacing: 10px;
HorizontalLayout {
spacing: 10px;
max-height: 32px;
SystemToggle {
text: @tr("Run in background after closing");
checked <=> AppSettingsPageData.run_in_background;
toggled => {
AppSettingsPageData.set_run_in_background(AppSettingsPageData.run_in_background)
}
}
SystemToggle {
width: parent.width * 1px / 2px;
text: @tr("Start app in background (UI closed)");
checked <=> AppSettingsPageData.startup_in_background;
toggled => {
AppSettingsPageData.set_run_in_background(AppSettingsPageData.startup_in_background)
}
}
}
HorizontalLayout {
max-height: 32px;
spacing: 10px;
SystemToggle {
text: @tr("Enable system tray icon");
checked <=> AppSettingsPageData.enable_tray_icon;
toggled => {
AppSettingsPageData.set_enable_tray_icon(AppSettingsPageData.enable_tray_icon)
}
}
SystemToggle {
width: parent.width * 1px / 2px;
text: @tr("Enable change notifications");
checked <=> AppSettingsPageData.enable_notifications;
toggled => {
AppSettingsPageData.set_enable_notifications(AppSettingsPageData.enable_notifications)
}
}
}
Text {
text: "TODO";
}
}
}
}

View File

@@ -1,50 +1,290 @@
import { ValueBar } from "../common_widgets.slint";
import { SystemDropdown, RogItem } from "../common_widgets.slint";
import { Button, ComboBox, VerticalBox, GroupBox } from "std-widgets.slint";
import { StyleMetrics, Slider, HorizontalBox, TextEdit, SpinBox, LineEdit } from "std-widgets.slint";
import { ColorPicker, ColourSlider } from "../widgets/colour_picker.slint";
import { Theme } from "../globals.slint";
export struct AuraEffect {
/// The effect type
mode: int,
/// `AuraZone::None` for no zone or zoneless keyboards
zone: int,
/// Primary colour for all modes
colour1: color,
/// Secondary colour in some modes like Breathing or Stars
colour2: color,
/// One of three speeds for modes that support speed (most that animate)
speed: int,
/// Up, down, left, right. Only Rainbow mode seems to use this
direction: int,
}
export global AuraPageData {
in-out property <[string]> brightness_names: [
@tr("Aura brightness" => "Off"),
@tr("Aura brightness" => "Low"),
@tr("Aura brightness" => "Med"),
@tr("Aura brightness" => "High"),
];
in-out property <int> brightness;
callback set_brightness(int);
in-out property <[string]> mode_names: [
@tr("Basic aura mode" => "Static"),
@tr("Basic aura mode" => "Breathe"),
@tr("Basic aura mode" => "Strobe"),
@tr("Basic aura mode" => "Rainbow"),
@tr("Basic aura mode" => "Star"),
@tr("Basic aura mode" => "Rain"),
@tr("Basic aura mode" => "Highlight"),
@tr("Basic aura mode" => "Laser"),
@tr("Basic aura mode" => "Ripple"),
@tr("Basic aura mode" => "Nothing"),
@tr("Basic aura mode" => "Pulse"),
@tr("Basic aura mode" => "Comet"),
@tr("Basic aura mode" => "Flash"),
];
in-out property <[string]> available_mode_names: [
@tr("Basic aura mode" => "Static"),
@tr("Basic aura mode" => "Breathe"),
@tr("Basic aura mode" => "Strobe"),
];
in-out property <int> current_available_mode: 0;
in-out property <[int]> supported_basic_modes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12];
in-out property <int> led_mode;
callback set_led_mode(int);
in-out property <[string]> zone_names: [
@tr("Aura zone" => "None"),
@tr("Aura zone" => "Key1"),
@tr("Aura zone" => "Key2"),
@tr("Aura zone" => "Key3"),
@tr("Aura zone" => "Key4"),
@tr("Aura zone" => "Logo"),
@tr("Aura zone" => "Lightbar Left"),
@tr("Aura zone" => "Lightbar Right"),
];
in-out property <int> zone;
in-out property <[string]> direction_names: [
@tr("Aura direction" => "Right"),
@tr("Aura direction" => "Left"),
@tr("Aura direction" => "Up"),
@tr("Aura direction" => "Down"),
];
in-out property <int> direction;
in-out property <[string]> speed_names: [
@tr("Aura speed" => "Low"),
@tr("Aura speed" => "Medium"),
@tr("Aura speed" => "High"),
];
in-out property <int> speed;
in-out property <AuraEffect> led_mode_data: {
mode: 0,
zone: 0,
colour1: Colors.aquamarine,
colourbox1: Colors.aquamarine,
colour2: Colors.hotpink,
colourbox2: Colors.hotpink,
speed: 0,
direction: 0,
};
callback set_led_mode_data(AuraEffect);
in-out property <color> color1;
in-out property <brush> colorbox1;
in-out property <color> color2;
in-out property <brush> colorbox2;
callback update_led_mode_data(AuraEffect);
update_led_mode_data(data) => {
led_mode_data = data;
current_available_mode = data.mode;
zone = data.zone;
speed = data.speed;
direction = data.direction;
color1 = data.colour1;
color2 = data.colour2;
colorbox1 = data.colour1;
colorbox2 = data.colour2;
}
callback blend_colour(color, color, float) -> color;
callback blend_lightness(color, float) -> color;
callback set_hex_from_colour(color) -> string;
callback set_hex_to_colour(string) -> color;
}
export component PageAura inherits VerticalLayout {
Rectangle {
clip: true;
// TODO: slow with border-radius
padding: 8px;
// height: parent.height - infobar.height - mainview.padding - self.padding * 2;
// TODO: border-radius: 8px;
mainview := VerticalLayout {
padding: 10px;
spacing: 10px;
ValueBar {
height: 40px;
value: 10.5;
min: 0.0;
max: 100.0;
padding: 10px;
spacing: 10px;
alignment: LayoutAlignment.start;
HorizontalLayout {
spacing: 10px;
SystemDropdown {
text: @tr("Brightness");
current_index <=> AuraPageData.brightness;
current_value: AuraPageData.brightness_names[self.current-index];
model <=> AuraPageData.brightness_names;
selected => {
AuraPageData.set_brightness(AuraPageData.brightness)
}
}
ValueBar {
height: 40px;
value: -70;
min: -100;
max: 0;
}
ValueBar {
height: 80px;
value: 40;
min: -50;
max: 50;
}
ValueBar {
height: 80px;
value: -40;
min: -50;
max: 50;
}
ValueBar {
height: 80px;
value: -40;
min: -50;
max: 50;
SystemDropdown {
width: parent.width * 1px / 2px;
text: @tr("Aura mode");
current_index <=> AuraPageData.current_available_mode;
current_value: AuraPageData.available_mode_names[self.current-index];
model <=> AuraPageData.available_mode_names;
selected => {
AuraPageData.led_mode_data.mode = AuraPageData.current_available_mode;
self.current_value = AuraPageData.available_mode_names[self.current-index];
AuraPageData.set_led_mode(AuraPageData.current_available_mode);
}
}
}
RogItem {
HorizontalLayout {
spacing: 10px;
VerticalBox {
Text {
text: @tr("Colour 1");
vertical-alignment: TextVerticalAlignment.center;
horizontal-alignment: TextHorizontalAlignment.center;
}
HorizontalBox {
ColourSlider {
final_colour <=> AuraPageData.color1;
colourbox <=> AuraPageData.colorbox1;
set_hex_from_colour(c1) => {
return AuraPageData.set_hex_from_colour(c1);
}
blend_colour(c1, c2, f) => {
return AuraPageData.blend_colour(c1, c2, f);
}
blend_lightness(c1, f) => {
return AuraPageData.blend_lightness(c1, f);
}
hex_to_colour(s) => {
return AuraPageData.set_hex_to_colour(s);
}
init => {
self.colourbox = AuraPageData.led_mode_data.colour1;
self.final_colour = AuraPageData.led_mode_data.colour1;
}
}
}
}
VerticalBox {
Text {
text: @tr("Colour 2");
vertical-alignment: TextVerticalAlignment.center;
horizontal-alignment: TextHorizontalAlignment.center;
}
HorizontalBox {
ColourSlider {
final_colour <=> AuraPageData.color2;
colourbox <=> AuraPageData.colorbox2;
set_hex_from_colour(c1) => {
return AuraPageData.set_hex_from_colour(c1);
}
blend_colour(c1, c2, f) => {
return AuraPageData.blend_colour(c1, c2, f);
}
blend_lightness(c1, f) => {
return AuraPageData.blend_lightness(c1, f);
}
hex_to_colour(s) => {
return AuraPageData.set_hex_to_colour(s);
}
init => {
self.colourbox = AuraPageData.led_mode_data.colour2;
self.final_colour = AuraPageData.led_mode_data.colour2;
}
}
}
}
}
}
HorizontalLayout {
spacing: 10px;
RogItem {
padding: 0px;
VerticalBox {
Text {
text: @tr("Zone");
vertical-alignment: TextVerticalAlignment.center;
horizontal-alignment: TextHorizontalAlignment.center;
}
ComboBox {
current_index <=> AuraPageData.zone;
current_value: AuraPageData.zone_names[self.current-index];
model <=> AuraPageData.zone_names;
selected => {
AuraPageData.led_mode_data.zone = self.current-index;
}
}
}
}
RogItem {
padding: 0px;
VerticalBox {
Text {
text: @tr("Direction");
vertical-alignment: TextVerticalAlignment.center;
horizontal-alignment: TextHorizontalAlignment.center;
}
ComboBox {
current_index <=> AuraPageData.direction;
current_value: AuraPageData.direction_names[self.current-index];
model <=> AuraPageData.direction_names;
selected => {
AuraPageData.led_mode_data.direction = self.current-index;
}
}
}
}
RogItem {
padding: 0px;
VerticalBox {
Text {
text: @tr("Speed");
vertical-alignment: TextVerticalAlignment.center;
horizontal-alignment: TextHorizontalAlignment.center;
}
ComboBox {
current_index <=> AuraPageData.speed;
current_value: AuraPageData.speed_names[self.current-index];
model <=> AuraPageData.speed_names;
selected => {
AuraPageData.led_mode_data.speed = self.current-index;
}
}
}
}
}
Button {
text: @tr("Apply");
clicked => {
AuraPageData.led_mode_data.mode = AuraPageData.led_mode;
AuraPageData.led_mode_data.colour1 = AuraPageData.color1;
AuraPageData.led_mode_data.colour2 = AuraPageData.color2;
AuraPageData.set_led_mode_data(AuraPageData.led_mode_data);
}
}
}

View File

@@ -1,4 +1,3 @@
import { ValueBar } from "../common_widgets.slint";
import { Theme } from "../globals.slint";
export component PageFans inherits VerticalLayout {
@@ -11,39 +10,8 @@ export component PageFans inherits VerticalLayout {
mainview := VerticalLayout {
padding: 10px;
spacing: 10px;
ValueBar {
height: 40px;
value: 10.5;
min: 0.0;
max: 100.0;
}
ValueBar {
height: 40px;
value: -70;
min: -100;
max: 0;
}
ValueBar {
height: 80px;
value: 40;
min: -50;
max: 50;
}
ValueBar {
height: 80px;
value: -40;
min: -50;
max: 50;
}
ValueBar {
height: 80px;
value: -40;
min: -50;
max: 50;
Text {
text: "TODO";
}
}
}

View File

@@ -1,50 +0,0 @@
import { ValueBar } from "../common_widgets.slint";
import { Theme } from "../globals.slint";
export component PageGpu inherits VerticalLayout {
Rectangle {
clip: true;
// TODO: slow with border-radius
padding: 8px;
// height: parent.height - infobar.height - mainview.padding - self.padding * 2;
// TODO: border-radius: 8px;
mainview := VerticalLayout {
padding: 10px;
spacing: 10px;
ValueBar {
height: 40px;
value: 10.5;
min: 0.0;
max: 100.0;
}
ValueBar {
height: 40px;
value: -70;
min: -100;
max: 0;
}
ValueBar {
height: 80px;
value: 40;
min: -50;
max: 50;
}
ValueBar {
height: 80px;
value: -40;
min: -50;
max: 50;
}
ValueBar {
height: 80px;
value: -40;
min: -50;
max: 50;
}
}
}
}

View File

@@ -1,15 +1,15 @@
import { ValueBar, SquareCharButton } from "../common_widgets.slint";
import { SystemSlider, SystemDropdown, SystemToggle } from "../common_widgets.slint";
import { Theme } from "../globals.slint";
import { HorizontalBox , VerticalBox, ScrollView, Slider, Button, Switch} from "std-widgets.slint";
import { HorizontalBox , VerticalBox, ScrollView, Slider, Button, Switch, ComboBox, GroupBox} from "std-widgets.slint";
export struct AvailableSystemProperties {
charge_limit: bool,
charge_control_end_threshold: bool,
panel_od: bool,
mini_led_mode: bool,
disable_nvidia_powerd_on_battery: bool,
ac_command: bool,
bat_command: bool,
throttle_policy: bool,
throttle_thermal_policy: bool,
ppt_pl1_spl: bool,
ppt_pl2_sppt: bool,
ppt_fppt: bool,
@@ -19,186 +19,360 @@ export struct AvailableSystemProperties {
nv_temp_target: bool,
}
export struct SystemValues {
charge_limit: int,
last_charge_limit: int,
panel_od: bool,
mini_led_mode: bool,
disable_nvidia_powerd_on_battery: bool,
}
export global SystemPageData {
in-out property <float> charge_control_end_threshold: 30;
callback set_charge_control_end_threshold(/* charge limit */ int);
export global SystemPage {
in-out property <float> charge_limit;
in-out property <int> last_charge_limit;
callback set_charge_limit(/* charge limit */ int);
in-out property <int> throttle_thermal_policy: 0;
in-out property <[string]> throttle_policy_choices: [@tr("Balanced"), @tr("Performance"), @tr("Quiet")];
callback set_throttle_thermal_policy(int);
in-out property <[string]> energy_performance_choices: [
@tr("Default"),
@tr("Performance"),
@tr("BalancePerformance"),
@tr("BalancePower"),
@tr("Power")
];
in-out property <int> throttle_balanced_epp: 0;
callback set_throttle_balanced_epp(int);
in-out property <int> throttle_performance_epp: 0;
callback set_throttle_performance_epp(int);
in-out property <int> throttle_quiet_epp: 0;
callback set_throttle_quiet_epp(int);
// if the EPP should change with throttle
in-out property <bool> throttle_policy_linked_epp: true;
callback set_throttle_policy_linked_epp(bool);
in-out property <int> throttle_policy_on_ac: 0;
callback set_throttle_policy_on_ac(int);
in-out property <int> throttle_policy_on_battery: 0;
callback set_throttle_policy_on_battery(int);
in-out property <bool> panel_od;
in-out property <bool> last_panel_od;
callback set_panel_od(/* panel_od */ bool);
callback set_panel_od(bool);
callback applied();
callback cancelled();
in-out property <bool> mini_led_mode;
callback set_mini_led_mode(bool);
in-out property <AvailableSystemProperties> available;
in-out property <float> ppt_pl1_spl: 5;
callback set_ppt_pl1_spl(int);
in-out property <float> ppt_pl2_sppt: 5;
callback set_ppt_pl2_sppt(int);
in-out property <float> ppt_fppt: 5;
callback set_ppt_fppt(int);
in-out property <float> ppt_apu_sppt: 5;
callback set_ppt_apu_sppt(int);
in-out property <float> ppt_platform_sppt: 5;
callback set_ppt_platform_sppt(int);
in-out property <float> nv_dynamic_boost: 5;
callback set_nv_dynamic_boost(int);
in-out property <float> nv_temp_target: 75;
callback set_nv_temp_target(int);
in-out property <AvailableSystemProperties> available: {
charge_control_end_threshold: true,
panel_od: true,
mini_led_mode: true,
disable_nvidia_powerd_on_battery: true,
ac_command: true,
bat_command: true,
throttle_thermal_policy: true,
ppt_pl1_spl: true,
ppt_pl2_sppt: true,
ppt_fppt: true,
ppt_apu_sppt: true,
ppt_platform_sppt: true,
nv_dynamic_boost: true,
nv_temp_target: true,
};
}
export component PageSystem inherits Rectangle {
background: Theme.background-color;
VerticalLayout {
ScrollView {
VerticalLayout {
// padding: 10px;
property <bool> show_fade_cover: false;
property <bool> show_throttle_advanced: false;
clip: true;
padding: 8px;
ScrollView {
VerticalLayout {
padding: 10px;
spacing: 10px;
min-height: root.height;
if SystemPage.available.charge-limit: Rectangle {
background: Theme.background-color;
VerticalBox {
Rectangle {
background: Theme.background-color;
border-color: Colors.black;
border-width: 6px;
border-radius: 10px;
height: 40px;
Text {
font-size: 18px;
color: Theme.text-foreground-color;
horizontal-alignment: TextHorizontalAlignment.center;
text: @tr("Base system settings");
}
}
HorizontalBox {
alignment: LayoutAlignment.start;
Text {
color: Theme.text-foreground-color;
text: @tr("ChargeLimit" => "Charge limit");
}
Text {
color: Theme.text-foreground-color;
text: "\{Math.floor(SystemPage.charge_limit)}";
}
}
HorizontalBox {
TouchArea { }
charge_slider := Slider {
maximum: 100;
minimum: 20;
value <=> SystemPage.charge_limit;
if SystemPageData.available.charge-control-end-threshold: SystemSlider {
text: @tr("Charge limit");
minimum: 20;
maximum: 100;
value <=> SystemPageData.charge_control_end_threshold;
released => {
SystemPage.set_charge_limit(SystemPage.charge_limit)
}
}
}
}
}
if SystemPage.available.panel-od: Rectangle {
background: Theme.background-color;
VerticalBox {
HorizontalBox {
alignment: LayoutAlignment.start;
Text {
color: Theme.text-foreground-color;
text: @tr("PanelOverdrive" => "Panel Overdrive");
}
Switch {
checked <=> SystemPage.panel_od;
toggled => {
SystemPage.set_panel_od(SystemPage.panel_od)
}
}
}
Text {
color: Theme.text-foreground-color;
text: @tr("PerformanceProfile" => "Performance Profile");
}
}
}
Rectangle {
background: Theme.background-color;
VerticalBox {
Text {
color: Theme.text-foreground-color;
text: @tr("nv_dynamic_boost" => "nv_dynamic_boost");
}
Text {
color: Theme.text-foreground-color;
text: @tr("nv_temp_target" => "nv_temp_target");
}
Text {
color: Theme.text-foreground-color;
text: @tr("ppt_pl1_spl" => "ppt_pl1_spl");
}
Text {
color: Theme.text-foreground-color;
text: @tr("ppt_pl2_sppt" => "ppt_pl2_sppt");
}
}
}
Rectangle {
background: Theme.background-color;
VerticalBox {
Text {
color: Theme.text-foreground-color;
text: @tr("PanelOverdrive" => "Panel Overdrive");
}
Text {
color: Theme.text-foreground-color;
text: @tr("PerformanceProfile" => "Performance Profile");
}
}
}
Rectangle {
background: Theme.background-color;
VerticalBox {
Text {
color: Theme.text-foreground-color;
text: @tr("PanelOverdrive" => "Panel Overdrive");
}
Text {
color: Theme.text-foreground-color;
text: @tr("PerformanceProfile" => "Performance Profile");
}
}
}
Rectangle {
background: Theme.background-color;
VerticalBox {
Text {
color: Theme.text-foreground-color;
text: @tr("PanelOverdrive" => "Panel Overdrive");
}
Text {
color: Theme.text-foreground-color;
text: @tr("PerformanceProfile" => "Performance Profile");
}
}
}
}
}
HorizontalLayout {
Button {
text: "Apply";
clicked => {
if SystemPage.last_charge_limit != Math.floor(SystemPage.charge_limit) {
SystemPage.set_charge_limit(SystemPage.charge_limit);
SystemPage.last_charge_limit = Math.floor(SystemPage.charge_limit);
}
SystemPage.applied();
SystemPageData.set_charge_control_end_threshold(Math.round(SystemPageData.charge_control_end_threshold))
}
}
Button {
text: "Cancel";
clicked => {
SystemPage.charge_limit = SystemPage.last_charge_limit;
SystemPage.cancelled();
if SystemPageData.available.throttle-thermal-policy: HorizontalLayout {
spacing: 10px;
SystemDropdown {
text: @tr("Throttle Policy");
current_index <=> SystemPageData.throttle_thermal_policy;
current_value: SystemPageData.throttle_policy_choices[SystemPageData.throttle_thermal_policy];
model <=> SystemPageData.throttle_policy_choices;
selected => {
SystemPageData.set_throttle_thermal_policy(SystemPageData.throttle_thermal_policy)
}
}
Button {
text: @tr("Advanced");
clicked => {
root.show_fade_cover = true;
root.show_throttle_advanced = true;
}
}
}
HorizontalBox {
padding: 0px;
spacing: 10px;
if SystemPageData.available.panel-od: SystemToggle {
text: @tr("Panel Overdrive");
checked <=> SystemPageData.panel_od;
toggled => {
SystemPageData.set_panel_od(SystemPageData.panel_od)
}
}
if SystemPageData.available.mini-led-mode: SystemToggle {
text: @tr("MiniLED Mode");
checked <=> SystemPageData.mini_led_mode;
toggled => {
SystemPageData.set_mini_led_mode(SystemPageData.mini_led_mode)
}
}
}
Rectangle {
background: Theme.background-color;
border-color: Colors.black;
border-width: 6px;
border-radius: 10px;
height: 40px;
Text {
font-size: 18px;
color: Theme.text-foreground-color;
horizontal-alignment: TextHorizontalAlignment.center;
text: @tr("System performance settings");
}
}
if SystemPageData.available.ppt-pl1-spl: SystemSlider {
text: @tr("ppt_pl1_spl" => "ppt_pl1_spl");
minimum: 5;
maximum: 250;
value <=> SystemPageData.ppt_pl1_spl;
released => {
SystemPageData.set_ppt_pl1_spl(Math.round(SystemPageData.ppt_pl1_spl))
}
}
if SystemPageData.available.ppt-pl2-sppt: SystemSlider {
text: @tr("ppt_pl2_sppt" => "ppt_pl2_sppt");
minimum: 5;
maximum: 250;
value <=> SystemPageData.ppt_pl2_sppt;
released => {
SystemPageData.set_ppt_pl2_sppt(Math.round(SystemPageData.ppt_pl2_sppt))
}
}
if SystemPageData.available.ppt-fppt: SystemSlider {
text: @tr("ppt_fppt" => "ppt_fppt");
minimum: 5;
maximum: 250;
value <=> SystemPageData.ppt_fppt;
released => {
SystemPageData.set_ppt_fppt(Math.round(SystemPageData.ppt_fppt))
}
}
if SystemPageData.available.ppt-apu-sppt: SystemSlider {
text: @tr("ppt_apu_sppt" => "ppt_apu_sppt");
minimum: 5;
maximum: 130;
value <=> SystemPageData.ppt_apu_sppt;
released => {
SystemPageData.set_ppt_apu_sppt(Math.round(SystemPageData.ppt_apu_sppt))
}
}
if SystemPageData.available.ppt-platform-sppt: SystemSlider {
text: @tr("ppt_platform_sppt" => "ppt_platform_sppt");
maximum: 130;
minimum: 5;
value <=> SystemPageData.ppt_platform_sppt;
released => {
SystemPageData.set_ppt_platform_sppt(Math.round(SystemPageData.ppt_platform_sppt))
}
}
if SystemPageData.available.nv-dynamic-boost: SystemSlider {
text: @tr("nv_dynamic_boost" => "nv_dynamic_boost");
minimum: 5;
maximum: 25;
value <=> SystemPageData.nv_dynamic_boost;
released => {
SystemPageData.set_nv_dynamic_boost(Math.round(SystemPageData.nv_dynamic_boost))
}
}
if SystemPageData.available.nv-temp-target: SystemSlider {
text: @tr("nv_temp_target" => "nv_temp_target");
minimum: 75;
maximum: 87;
value <=> SystemPageData.nv_temp_target;
released => {
SystemPageData.set_nv_temp_target(Math.round(SystemPageData.nv_temp_target))
}
}
}
}
if root.show_fade_cover: Rectangle {
width: 100%;
height: 100%;
background: Theme.background-color;
opacity: 0.8;
TouchArea {
height: 100%;
width: 100%;
clicked => {
// toolbar-dropdown.close();
if (root.show_throttle_advanced) {
root.show_throttle_advanced = false;
}
root.show_fade_cover = false;
}
}
}
if root.show_throttle_advanced: Rectangle {
width: 100%;
height: 100%;
opacity: 1;
ScrollView {
VerticalLayout {
padding: 50px;
padding-top: 5px;
spacing: 10px;
GroupBox {
VerticalBox {
spacing: 10px;
Text {
font-size: 18px;
horizontal-alignment: TextHorizontalAlignment.center;
vertical-alignment: TextVerticalAlignment.center;
text: @tr("Energy Performance Preference linked to Throttle Policy");
}
SystemToggle {
text: @tr("Change EPP based on Throttle Policy");
checked <=> SystemPageData.throttle_policy_linked_epp;
toggled => {
SystemPageData.set_throttle_policy_linked_epp(SystemPageData.throttle_policy_linked_epp)
}
}
SystemDropdown {
text: @tr("EPP for Balanced Policy");
current_index <=> SystemPageData.throttle_balanced_epp;
current_value: SystemPageData.energy_performance_choices[SystemPageData.throttle_balanced_epp];
model <=> SystemPageData.energy_performance_choices;
selected => {
SystemPageData.set_throttle_balanced_epp(SystemPageData.throttle_balanced_epp)
}
}
SystemDropdown {
text: @tr("EPP for Performance Policy");
current_index <=> SystemPageData.throttle_performance_epp;
current_value: SystemPageData.energy_performance_choices[SystemPageData.throttle_performance_epp];
model <=> SystemPageData.energy_performance_choices;
selected => {
SystemPageData.set_throttle_performance_epp(SystemPageData.throttle_performance_epp)
}
}
SystemDropdown {
text: @tr("EPP for Quiet Policy");
current_index <=> SystemPageData.throttle_quiet_epp;
current_value: SystemPageData.energy_performance_choices[SystemPageData.throttle_quiet_epp];
model <=> SystemPageData.energy_performance_choices;
selected => {
SystemPageData.set_throttle_quiet_epp(SystemPageData.throttle_quiet_epp)
}
}
}
}
GroupBox {
VerticalBox {
spacing: 10px;
Text {
font-size: 18px;
horizontal-alignment: TextHorizontalAlignment.center;
vertical-alignment: TextVerticalAlignment.center;
text: @tr("Throttle Policy for power state");
}
SystemDropdown {
text: @tr("Throttle Policy on Battery");
current_index <=> SystemPageData.throttle_policy_on_battery;
current_value: SystemPageData.throttle_policy_choices[SystemPageData.throttle_policy_on_battery];
model <=> SystemPageData.throttle_policy_choices;
selected => {
SystemPageData.set_throttle_policy_on_battery(SystemPageData.throttle_policy_on_battery)
}
}
SystemDropdown {
text: @tr("Throttle Policy on AC");
current_index <=> SystemPageData.throttle_policy_on_ac;
current_value: SystemPageData.throttle_policy_choices[SystemPageData.throttle_policy_on_ac];
model <=> SystemPageData.throttle_policy_choices;
selected => {
SystemPageData.set_throttle_policy_on_ac(SystemPageData.throttle_policy_on_ac)
}
}
}
}
}
}
Button {
x: root.width - self.width - 6px;
y: 6px;
text: "X";
height: 40px;
clicked => {
root.show_throttle_advanced = false;
root.show_fade_cover = false;
}
}
}
}

View File

@@ -0,0 +1,282 @@
import { Slider, HorizontalBox, Button, LineEdit } from "std-widgets.slint";
export component ColourSlider inherits VerticalLayout {
spacing: 10px;
property <string> hex: "#FF0000";
property <color> base_colour: Colors.red;
in-out property <color> final_colour: Colors.red;
in-out property <brush> colourbox: final_colour;
callback hex_to_colour(string) -> color;
// required
callback set_hex_from_colour(color) -> string;
/// This callback is required until slint adds direct acces to color channels
callback blend_colour(color, color, float) -> color;
callback blend_lightness(color, float) -> color;
property <[color]> base_colours: [
Colors.rgb( 255, 0, 0),
Colors.rgb( 255, 128, 0),
Colors.rgb( 255, 255, 0),
Colors.rgb( 128, 255, 0),
Colors.rgb( 0, 255, 0),
Colors.rgb( 0, 255, 128),
Colors.rgb( 0, 255, 255),
Colors.rgb( 0, 128, 255),
Colors.rgb( 0, 0, 255),
Colors.rgb( 127, 0, 255),
Colors.rgb( 255, 0, 255),
Colors.rgb( 255, 0, 127),
Colors.rgb( 128, 128, 128)
];
property <[color]> base_shade: [
base_colour.with-alpha(100%),
base_colour.with-alpha(90%),
base_colour.with-alpha(80%),
base_colour.with-alpha(70%),
base_colour.with-alpha(60%),
base_colour.with-alpha(50%),
base_colour.with-alpha(40%),
base_colour.with-alpha(30%),
base_colour.with-alpha(20%),
base_colour.with-alpha(10%),
base_colour.with-alpha(0%)
];
function set_base_colour() {
// base_colour = base_colours[c1.value].mix(base_colours[c1.value+1], _index_rem);
root.base_colour = blend_colour(base_colours[c1.value], base_colours[c1.value + 1], c1.value - Math.floor(c1.value));
root.final_colour = blend_lightness(base_colour, (base_shade.length - c2.value) / base_shade.length);
root.colourbox = root.final_colour;
}
Rectangle {
height: 32px;
// 13 colours
background: @linear-gradient(90deg, base_colours[0], base_colours[1], base_colours[2], base_colours[3], base_colours[4], base_colours[5], base_colours[6], base_colours[7], base_colours[8], base_colours[9], base_colours[10], base_colours[11], base_colours[12]);
clip: true;
border-radius: 6px;
c1 := Slider {
width: parent.width;
height: parent.height;
minimum: 0;
maximum: 12;
changed => {
set_base_colour();
hex = set_hex_from_colour(final_colour);
}
}
}
Rectangle {
height: 32px;
// 11 colours
background: @linear-gradient(90deg, base_shade[0], base_shade[1], base_shade[2], base_shade[3], base_shade[4], base_shade[5], base_shade[6], base_shade[7], base_shade[8], base_shade[9], base_shade[10]);
clip: true;
border-radius: 6px;
c2 := Slider {
width: parent.width;
height: parent.height;
minimum: 0;
maximum: 11;
changed => {
set_base_colour();
hex = set_hex_from_colour(final_colour);
}
}
}
HorizontalLayout {
LineEdit {
// width: 50%;
text <=> root.hex;
edited => {
base_colour = hex_to_colour(self.text);
root.colourbox = base_colour;
}
}
Rectangle {
width: self.height;
background <=> root.colourbox;
}
}
}
component ColorButton {
callback select<=>i_touch_area.clicked;
in property <brush> color<=> i_container.background;
in property <bool> selected;
height: self.width;
i_container := Rectangle {
border_width: 2px;
}
i_touch_area := TouchArea { }
states [
selected when selected: {
i_container.border_color: Colors.black;
}
]
}
export component ColorPicker {
height: palette.length * 1px / colors_per_row / 1px * color_size;
private property <int> selected_color_index;
in-out property <float> colors_per_row: 13.0;
private property <length> color_size: self.width / colors_per_row;
out property <color> selected_color: palette[selected_color_index];
callback selected(color);
in property <[color]> palette: [
Colors.rgb(51,0,0),
Colors.rgb(51,25,0),
Colors.rgb(51,51,0),
Colors.rgb(25,51,0),
Colors.rgb(0,51,0),
Colors.rgb(0,51,25),
Colors.rgb(0,51,51),
Colors.rgb(0,25,51),
Colors.rgb(0,0,51),
Colors.rgb(25,0,51),
Colors.rgb(51,0,51),
Colors.rgb(51,0,25),
Colors.rgb(0,0,0),
//
Colors.rgb(102,0,0),
Colors.rgb(102,51,0),
Colors.rgb(102,102,0),
Colors.rgb(51,102,0),
Colors.rgb(0,102,0),
Colors.rgb(0,102,51),
Colors.rgb(0,102,102),
Colors.rgb(0,51,102),
Colors.rgb(0,0,102),
Colors.rgb(51,0,102),
Colors.rgb(102,0,102),
Colors.rgb(102,0,51),
Colors.rgb(32,32,32),
//
Colors.rgb(153,0,0),
Colors.rgb(153,76,0),
Colors.rgb(153,153,0),
Colors.rgb(76,153,0),
Colors.rgb(0,153,0),
Colors.rgb(0,153,76),
Colors.rgb(0,153,153),
Colors.rgb(0,76,153),
Colors.rgb(0,0,153),
Colors.rgb(76,0,153),
Colors.rgb(153,0,153),
Colors.rgb(153,0,76),
Colors.rgb(64,64,64),
//
Colors.rgb(204,0,0),
Colors.rgb(204,102,0),
Colors.rgb(204,204,0),
Colors.rgb(102,204,0),
Colors.rgb(0,204,0),
Colors.rgb(0,204,102),
Colors.rgb(0,204,204),
Colors.rgb(0,102,204),
Colors.rgb(0,0,204),
Colors.rgb(102,0,204),
Colors.rgb(204,0,204),
Colors.rgb(204,0,102),
Colors.rgb(96,96,96),
//
Colors.rgb(255,0,0),
Colors.rgb(255,128,0),
Colors.rgb(255,255,0),
Colors.rgb(128,255,0),
Colors.rgb(0,255,0),
Colors.rgb(0,255,128),
Colors.rgb(0,255,255),
Colors.rgb(0,128,255),
Colors.rgb(0,0,255),
Colors.rgb(128,0,255),
Colors.rgb(255,0,255),
Colors.rgb(255,0,128),
Colors.rgb(128,128,128),
//
Colors.rgb(255,51,51),
Colors.rgb(255,153,51),
Colors.rgb(255,255,51),
Colors.rgb(153,255,51),
Colors.rgb(51,255,51),
Colors.rgb(51,255,153),
Colors.rgb(51,255,255),
Colors.rgb(51,153,255),
Colors.rgb(51,51,255),
Colors.rgb(153,51,255),
Colors.rgb(255,51,255),
Colors.rgb(255,51,153),
Colors.rgb(160,160,160),
//
Colors.rgb(255,102,102),
Colors.rgb(255,178,102),
Colors.rgb(255,255,102),
Colors.rgb(178,255,102),
Colors.rgb(102,255,102),
Colors.rgb(102,255,178),
Colors.rgb(102,255,255),
Colors.rgb(102,178,255),
Colors.rgb(102,102,255),
Colors.rgb(178,102,255),
Colors.rgb(255,102,255),
Colors.rgb(255,102,178),
Colors.rgb(192,192,192),
//
Colors.rgb(255,153,153),
Colors.rgb(255,204,153),
Colors.rgb(255,255,153),
Colors.rgb(204,255,153),
Colors.rgb(153,255,153),
Colors.rgb(153,255,204),
Colors.rgb(153,255,255),
Colors.rgb(153,204,255),
Colors.rgb(153,153,255),
Colors.rgb(204,153,255),
Colors.rgb(255,153,255),
Colors.rgb(255,153,204),
Colors.rgb(224,224,224),
//
Colors.rgb(255,204,204),
Colors.rgb(255,229,204),
Colors.rgb(255,255,204),
Colors.rgb(229,255,204),
Colors.rgb(204,255,204),
Colors.rgb(204,255,229),
Colors.rgb(204,255,255),
Colors.rgb(204,229,255),
Colors.rgb(204,204,255),
Colors.rgb(229,204,255),
Colors.rgb(255,204,255),
Colors.rgb(255,204,229),
Colors.rgb(224,224,224),
];
Rectangle {
border_width: 1px;
border_color: Colors.black;
for color[index] in palette: ColorButton {
x: color_size * mod(index, colors_per_row);
y: color_size * floor(index / colors_per_row);
width: color_size;
color: color;
selected: index == selected_color_index;
select => {
selected_color_index = index;
// debug(Math.mod(selected_color_index, colors_per_row)); // X pos
// debug(Math.floor(selected_color_index / colors_per_row)); // Y pos
return selected(Math.mod(selected_color_index, colors_per_row) == colors_per_row - 1 ? Colors.rgb(255 / (palette.length / colors_per_row - 1) * Math.floor(selected_color_index / colors_per_row),0,0) : selected_color);
}
}
}
}

View File

@@ -8,10 +8,10 @@ component SideBarItem inherits Rectangle {
in property <bool> has-focus;
in-out property <string> text<=> label.text;
callback clicked<=>touch.clicked;
min-height: l.preferred-height;
min-height: self.visible ? l.preferred-height : 0px;
states [
pressed when touch.pressed: {
state.opacity: 0.8;
state.opacity: 0.8;
}
hover when touch.has-hover: {
state.opacity: 0.6;
@@ -22,14 +22,14 @@ component SideBarItem inherits Rectangle {
focused when root.has-focus: {
state.opacity: 0.8;
}
]
state := Rectangle {
]state := Rectangle {
opacity: 0;
border-width: 2px;
border-radius: 10px;
border-color: StyleMetrics.default-text-color;
background: StyleMetrics.window-background;
animate opacity{ duration: 150ms;
}
animate opacity { duration: 150ms; }
animate border-width { duration: 150ms; }
}
l := HorizontalLayout {
@@ -50,6 +50,7 @@ component SideBarItem inherits Rectangle {
export component SideBar inherits Rectangle {
in property <[string]> model: [];
in property <[bool]> available: [];
in property <string> title<=> label.text;
out property <int> current-item: 0;
out property <int> current-focused: fs.has-focus ? fs.focused-tab : -1;
@@ -65,22 +66,22 @@ export component SideBar inherits Rectangle {
key-pressed(event) => {
if (event.text == "\n") {
root.current-item = root.current-focused;
return accept;
return accept;
}
if (event.text == Key.UpArrow) {
self.focused-tab = Math.max(self.focused-tab - 1, 0);
return accept;
return accept;
}
if (event.text == Key.DownArrow) {
self.focused-tab = Math.min(self.focused-tab + 1, root.model.length - 1);
return accept;
return accept;
}
return reject;
}
key-released(event) => {
if (event.text == " ") {
root.current-item = root.current-focused;
return accept;
return accept;
}
return reject;
}
@@ -92,8 +93,7 @@ export component SideBar inherits Rectangle {
}
VerticalLayout {
padding-top: StyleMetrics.layout-padding;
padding-bottom: StyleMetrics.layout-padding;
padding: StyleMetrics.layout-padding;
spacing: StyleMetrics.layout-spacing;
alignment: start;
label := Text {
@@ -102,15 +102,17 @@ export component SideBar inherits Rectangle {
}
navigation := VerticalLayout {
spacing: 10px;
alignment: start;
vertical-stretch: 0;
for item [index] in root.model: SideBarItem {
clicked => {
root.current-item = index;
}
has-focus: index == root.current-focused;
text: item;
selected: index == root.current-item;
for item[index] in root.model: SideBarItem {
visible: root.available[index];
clicked => {
root.current-item = index;
}
has-focus: index == root.current-focused;
text: item;
selected: index == root.current-item;
}
}