what?
This commit is contained in:
parent
f1b7de69a7
commit
a9034a3f36
5
.idea/.gitignore
vendored
5
.idea/.gitignore
vendored
@ -1,5 +0,0 @@
|
|||||||
# Default ignored files
|
|
||||||
/shelf/
|
|
||||||
/workspace.xml
|
|
||||||
# Editor-based HTTP Client requests
|
|
||||||
/httpRequests/
|
|
@ -2,7 +2,7 @@
|
|||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="ProjectModuleManager">
|
<component name="ProjectModuleManager">
|
||||||
<modules>
|
<modules>
|
||||||
<module fileurl="file://$PROJECT_DIR$/.idea/project-leoali.iml" filepath="$PROJECT_DIR$/.idea/project-leoali.iml" />
|
<module fileurl="file://$PROJECT_DIR$/.idea/pika-idk-manager.iml" filepath="$PROJECT_DIR$/.idea/pika-idk-manager.iml" />
|
||||||
</modules>
|
</modules>
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
@ -2,5 +2,6 @@
|
|||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="VcsDirectoryMappings">
|
<component name="VcsDirectoryMappings">
|
||||||
<mapping directory="" vcs="Git" />
|
<mapping directory="" vcs="Git" />
|
||||||
|
<mapping directory="$PROJECT_DIR$/target/debug/build/rust-apt-bdd275358b00de07/out/cxxbridge/crate/rust-apt" vcs="Git" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
122
.idea/workspace.xml
Normal file
122
.idea/workspace.xml
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="AutoImportSettings">
|
||||||
|
<option name="autoReloadType" value="ALL" />
|
||||||
|
</component>
|
||||||
|
<component name="CargoProjects">
|
||||||
|
<cargoProject FILE="$PROJECT_DIR$/Cargo.toml" />
|
||||||
|
</component>
|
||||||
|
<component name="ChangeListManager">
|
||||||
|
<list default="true" id="df2ca9e1-e07d-43f4-bc68-0a6113fc1fa2" name="Changes" comment="">
|
||||||
|
<change afterPath="$PROJECT_DIR$/locales/en_US.json" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/.idea/.gitignore" beforeDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/.idea/modules.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/modules.xml" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/.idea/project-leoali.iml" beforeDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/.idea/vcs.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/vcs.xml" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/Cargo.lock" beforeDir="false" afterPath="$PROJECT_DIR$/Cargo.lock" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/Cargo.toml" beforeDir="false" afterPath="$PROJECT_DIR$/Cargo.toml" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/gui/apt_package_row/imp.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/apt_package_row/imp.rs" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/gui/apt_package_row/mod.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/apt_package_row/mod.rs" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/gui/apt_update_page/mod.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/apt_update_page/mod.rs" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/gui/build_ui/mod.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/build_ui/mod.rs" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/gui/config.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/config.rs" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/gui/main.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/main.rs" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/gui/style.css" beforeDir="false" afterPath="$PROJECT_DIR$/src/style.css" afterDir="false" />
|
||||||
|
</list>
|
||||||
|
<option name="SHOW_DIALOG" value="false" />
|
||||||
|
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||||
|
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||||
|
<option name="LAST_RESOLUTION" value="IGNORE" />
|
||||||
|
</component>
|
||||||
|
<component name="Git.Settings">
|
||||||
|
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
|
||||||
|
</component>
|
||||||
|
<component name="MacroExpansionManager">
|
||||||
|
<option name="directoryName" value="rqc3l2bj" />
|
||||||
|
</component>
|
||||||
|
<component name="ProjectColorInfo">{
|
||||||
|
"associatedIndex": 8
|
||||||
|
}</component>
|
||||||
|
<component name="ProjectId" id="2iTBzsng9KVBd9K88mZWsKzuiQ1" />
|
||||||
|
<component name="ProjectViewState">
|
||||||
|
<option name="hideEmptyMiddlePackages" value="true" />
|
||||||
|
<option name="showLibraryContents" value="true" />
|
||||||
|
</component>
|
||||||
|
<component name="PropertiesComponent">{
|
||||||
|
"keyToString": {
|
||||||
|
"Cargo.Run apt_update.executor": "Run",
|
||||||
|
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||||
|
"RunOnceActivity.rust.reset.selective.auto.import": "true",
|
||||||
|
"git-widget-placeholder": "master",
|
||||||
|
"last_opened_file_path": "/home/ward/RustroverProjects/pika-idk-manager",
|
||||||
|
"node.js.detected.package.eslint": "true",
|
||||||
|
"node.js.selected.package.eslint": "(autodetect)",
|
||||||
|
"nodejs_package_manager_path": "npm",
|
||||||
|
"org.rust.cargo.project.model.PROJECT_DISCOVERY": "true",
|
||||||
|
"org.rust.first.attach.projects": "true"
|
||||||
|
}
|
||||||
|
}</component>
|
||||||
|
<component name="RecentsManager">
|
||||||
|
<key name="MoveFile.RECENT_KEYS">
|
||||||
|
<recent name="$PROJECT_DIR$" />
|
||||||
|
<recent name="$PROJECT_DIR$/src" />
|
||||||
|
<recent name="$PROJECT_DIR$/data" />
|
||||||
|
</key>
|
||||||
|
</component>
|
||||||
|
<component name="RunManager" selected="Cargo.Run apt_update">
|
||||||
|
<configuration name="Run apt_update" type="CargoCommandRunConfiguration" factoryName="Cargo Command">
|
||||||
|
<option name="command" value="run --package pika-idk-manager --bin pika-idk-manager" />
|
||||||
|
<option name="workingDirectory" value="file://$PROJECT_DIR$" />
|
||||||
|
<envs />
|
||||||
|
<option name="emulateTerminal" value="true" />
|
||||||
|
<option name="channel" value="DEFAULT" />
|
||||||
|
<option name="requiredFeatures" value="true" />
|
||||||
|
<option name="allFeatures" value="false" />
|
||||||
|
<option name="withSudo" value="false" />
|
||||||
|
<option name="buildTarget" value="REMOTE" />
|
||||||
|
<option name="backtrace" value="SHORT" />
|
||||||
|
<option name="isRedirectInput" value="false" />
|
||||||
|
<option name="redirectInputPath" value="" />
|
||||||
|
<method v="2">
|
||||||
|
<option name="CARGO.BUILD_TASK_PROVIDER" enabled="true" />
|
||||||
|
</method>
|
||||||
|
</configuration>
|
||||||
|
<configuration name="Test pika-idk-manager" type="CargoCommandRunConfiguration" factoryName="Cargo Command">
|
||||||
|
<option name="command" value="test --workspace" />
|
||||||
|
<option name="workingDirectory" value="file://$PROJECT_DIR$" />
|
||||||
|
<envs />
|
||||||
|
<option name="emulateTerminal" value="true" />
|
||||||
|
<option name="channel" value="DEFAULT" />
|
||||||
|
<option name="requiredFeatures" value="true" />
|
||||||
|
<option name="allFeatures" value="false" />
|
||||||
|
<option name="withSudo" value="false" />
|
||||||
|
<option name="buildTarget" value="REMOTE" />
|
||||||
|
<option name="backtrace" value="SHORT" />
|
||||||
|
<option name="isRedirectInput" value="false" />
|
||||||
|
<option name="redirectInputPath" value="" />
|
||||||
|
<method v="2">
|
||||||
|
<option name="CARGO.BUILD_TASK_PROVIDER" enabled="true" />
|
||||||
|
</method>
|
||||||
|
</configuration>
|
||||||
|
</component>
|
||||||
|
<component name="RustProjectSettings">
|
||||||
|
<option name="toolchainHomeDirectory" value="$USER_HOME$/.cargo/bin" />
|
||||||
|
</component>
|
||||||
|
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
|
||||||
|
<component name="TaskManager">
|
||||||
|
<task active="true" id="Default" summary="Default task">
|
||||||
|
<changelist id="df2ca9e1-e07d-43f4-bc68-0a6113fc1fa2" name="Changes" comment="" />
|
||||||
|
<created>1719504951223</created>
|
||||||
|
<option name="number" value="Default" />
|
||||||
|
<option name="presentableId" value="Default" />
|
||||||
|
<updated>1719504951223</updated>
|
||||||
|
<workItem from="1719504952240" duration="1363000" />
|
||||||
|
<workItem from="1719510804090" duration="7000" />
|
||||||
|
<workItem from="1719609702948" duration="2234000" />
|
||||||
|
</task>
|
||||||
|
<servers />
|
||||||
|
</component>
|
||||||
|
<component name="TypeScriptGeneratedFilesManager">
|
||||||
|
<option name="version" value="3" />
|
||||||
|
</component>
|
||||||
|
</project>
|
34
Cargo.lock
generated
34
Cargo.lock
generated
@ -1138,6 +1138,23 @@ version = "1.0.15"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
|
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pika-idk-manager"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"async-channel",
|
||||||
|
"async-trait",
|
||||||
|
"futures 0.3.30",
|
||||||
|
"gtk4",
|
||||||
|
"libadwaita",
|
||||||
|
"rust-apt",
|
||||||
|
"rust-i18n",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"tokio",
|
||||||
|
"tokio-uds",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pin-project-lite"
|
name = "pin-project-lite"
|
||||||
version = "0.2.14"
|
version = "0.2.14"
|
||||||
@ -1208,23 +1225,6 @@ dependencies = [
|
|||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "project-leoali"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"async-channel",
|
|
||||||
"async-trait",
|
|
||||||
"futures 0.3.30",
|
|
||||||
"gtk4",
|
|
||||||
"libadwaita",
|
|
||||||
"rust-apt",
|
|
||||||
"rust-i18n",
|
|
||||||
"serde",
|
|
||||||
"serde_json",
|
|
||||||
"tokio",
|
|
||||||
"tokio-uds",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.36"
|
version = "1.0.36"
|
||||||
|
@ -1,13 +1,9 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "project-leoali"
|
name = "pika-idk-manager"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
[[bin]]
|
|
||||||
name = "gui"
|
|
||||||
path = "src/gui/main.rs"
|
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "pika_unixsocket_tools"
|
name = "pika_unixsocket_tools"
|
||||||
path = "src/pika_unixsocket_tools/lib.rs"
|
path = "src/pika_unixsocket_tools/lib.rs"
|
||||||
|
6
locales/en_US.json
Normal file
6
locales/en_US.json
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"application_name": "Pika IDK yet Manager",
|
||||||
|
"installed_version_badge_text": "Installed",
|
||||||
|
"candidate_version_badge_text": "Upgradable",
|
||||||
|
"arch_label_label": "Arch"
|
||||||
|
}
|
260
src/apt_package_row/imp.rs
Normal file
260
src/apt_package_row/imp.rs
Normal file
@ -0,0 +1,260 @@
|
|||||||
|
use std::{cell::RefCell, default, sync::OnceLock};
|
||||||
|
|
||||||
|
use adw::*;
|
||||||
|
use adw::{prelude::*, subclass::prelude::*};
|
||||||
|
use glib::{subclass::Signal, Properties, clone};
|
||||||
|
use gtk::{Align, glib, Orientation, SizeGroupMode, SelectionMode, Widget};
|
||||||
|
use gtk::Orientation::Horizontal;
|
||||||
|
use crate::apt_update_page::AptPackageSocket;
|
||||||
|
use std::env;
|
||||||
|
|
||||||
|
// ANCHOR: custom_button
|
||||||
|
// Object holding the state
|
||||||
|
#[derive(Properties, Default)]
|
||||||
|
#[properties(wrapper_type = super::AptPackageRow)]
|
||||||
|
pub struct AptPackageRow {
|
||||||
|
#[property(get, set)]
|
||||||
|
package_name: RefCell<String>,
|
||||||
|
#[property(get, set)]
|
||||||
|
package_arch: RefCell<String>,
|
||||||
|
#[property(get, set)]
|
||||||
|
package_installed_version: RefCell<String>,
|
||||||
|
#[property(get, set)]
|
||||||
|
package_candidate_version: RefCell<String>
|
||||||
|
}
|
||||||
|
// ANCHOR_END: custom_button
|
||||||
|
|
||||||
|
// The central trait for subclassing a GObject
|
||||||
|
#[glib::object_subclass]
|
||||||
|
impl ObjectSubclass for AptPackageRow {
|
||||||
|
const NAME: &'static str = "AptPackageRow";
|
||||||
|
type Type = super::AptPackageRow;
|
||||||
|
type ParentType = adw::ExpanderRow;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ANCHOR: object_impl
|
||||||
|
// Trait shared by all GObjects
|
||||||
|
#[glib::derived_properties]
|
||||||
|
impl ObjectImpl for AptPackageRow {
|
||||||
|
fn signals() -> &'static [Signal] {
|
||||||
|
static SIGNALS: OnceLock<Vec<Signal>> = OnceLock::new();
|
||||||
|
SIGNALS.get_or_init(|| vec![Signal::builder("row-deleted").build()])
|
||||||
|
}
|
||||||
|
fn constructed(&self) {
|
||||||
|
let current_locale = match env::var_os("LANG") {
|
||||||
|
Some(v) => v.into_string().unwrap().chars()
|
||||||
|
.take_while(|&ch| ch != '.')
|
||||||
|
.collect::<String>(),
|
||||||
|
None => panic!("$LANG is not set"),
|
||||||
|
};
|
||||||
|
rust_i18n::set_locale(¤t_locale);
|
||||||
|
|
||||||
|
self.parent_constructed();
|
||||||
|
|
||||||
|
// Bind label to number
|
||||||
|
// `SYNC_CREATE` ensures that the label will be immediately set
|
||||||
|
let obj = self.obj();
|
||||||
|
|
||||||
|
let prefix_box = gtk::Box::new(Orientation::Vertical, 0);
|
||||||
|
|
||||||
|
let expandable_box = gtk::Box::new(Orientation::Vertical, 0);
|
||||||
|
expandable_box.add_css_class("linked");
|
||||||
|
|
||||||
|
obj.connect_package_name_notify(clone!(@weak prefix_box, @weak expandable_box, @strong obj => move |obj| {
|
||||||
|
remove_all_children(&prefix_box);
|
||||||
|
remove_all_children(&expandable_box);
|
||||||
|
//
|
||||||
|
let package_name = obj.package_name();
|
||||||
|
let package_arch = obj.package_arch();
|
||||||
|
let package_installed_version= obj.package_installed_version();
|
||||||
|
let package_candidate_version= obj.package_candidate_version();
|
||||||
|
//
|
||||||
|
let package_label = gtk::Label::builder()
|
||||||
|
.halign(Align::Start)
|
||||||
|
.margin_start(5)
|
||||||
|
.margin_end(5)
|
||||||
|
.margin_bottom(5)
|
||||||
|
.margin_top(5)
|
||||||
|
.label(package_name)
|
||||||
|
.build();
|
||||||
|
package_label.add_css_class("size-20-bold-text");
|
||||||
|
let version_box = gtk::Box::new(Orientation::Horizontal, 0);
|
||||||
|
version_box.append(&create_version_badge(package_installed_version, package_candidate_version));
|
||||||
|
version_box.append(&create_arch_badge(package_arch));
|
||||||
|
prefix_box.append(&package_label);
|
||||||
|
prefix_box.append(&version_box);
|
||||||
|
//
|
||||||
|
let expandable_page_selection_box = gtk::Box::builder()
|
||||||
|
.orientation(Orientation::Horizontal)
|
||||||
|
.hexpand(false)
|
||||||
|
.vexpand(false)
|
||||||
|
.halign(Align::Start)
|
||||||
|
.valign(Align::Start)
|
||||||
|
.build();
|
||||||
|
expandable_page_selection_box.add_css_class("linked");
|
||||||
|
let description_page_button = gtk::ToggleButton::builder()
|
||||||
|
.label("Description")
|
||||||
|
.active(true)
|
||||||
|
.build();
|
||||||
|
let changelog_page_button = gtk::ToggleButton::builder()
|
||||||
|
.label("Changelog")
|
||||||
|
.group(&description_page_button)
|
||||||
|
.build();
|
||||||
|
expandable_page_selection_box.append(&description_page_button);
|
||||||
|
expandable_page_selection_box.append(&changelog_page_button);
|
||||||
|
expandable_box.append(&expandable_page_selection_box);
|
||||||
|
}));
|
||||||
|
|
||||||
|
obj.add_prefix(&prefix_box);
|
||||||
|
obj.add_row(&expandable_box);
|
||||||
|
|
||||||
|
//let obj = self.obj();
|
||||||
|
//obj.bind_property("package-name", &package_label, "label")
|
||||||
|
// .sync_create()
|
||||||
|
// .bidirectional()
|
||||||
|
// .build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Trait shared by all widgets
|
||||||
|
impl WidgetImpl for AptPackageRow {}
|
||||||
|
|
||||||
|
// Trait shared by all buttons
|
||||||
|
// Trait shared by all buttons
|
||||||
|
|
||||||
|
impl ListBoxRowImpl for AptPackageRow {}
|
||||||
|
impl PreferencesRowImpl for AptPackageRow {}
|
||||||
|
impl ExpanderRowImpl for AptPackageRow {}
|
||||||
|
|
||||||
|
fn create_version_badge(installed_version: String, candidate_version: String) -> gtk::ListBox {
|
||||||
|
let (base_version, installed_diff, candidate_diff) = get_diff_by_prefix(installed_version, candidate_version);
|
||||||
|
|
||||||
|
let badge_box = gtk::Box::builder()
|
||||||
|
.halign(Align::Start)
|
||||||
|
.hexpand(false)
|
||||||
|
.orientation(Orientation::Horizontal)
|
||||||
|
.margin_start(5)
|
||||||
|
.margin_end(5)
|
||||||
|
.margin_bottom(5)
|
||||||
|
.margin_top(5)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
let installed_version_box = gtk::Box::builder()
|
||||||
|
.halign(Align::Start)
|
||||||
|
.hexpand(false)
|
||||||
|
.orientation(Orientation::Horizontal)
|
||||||
|
.tooltip_text(t!("installed_version_badge_text"))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
let installed_version_base_version_label = gtk::Label::builder()
|
||||||
|
.label(format!("{}: {}", t!("installed_version_badge_text"), &base_version))
|
||||||
|
.valign(Align::Center)
|
||||||
|
.halign(Align::Start)
|
||||||
|
.hexpand(false)
|
||||||
|
.vexpand(true)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
let installed_diff_label = gtk::Label::builder()
|
||||||
|
.label(installed_diff)
|
||||||
|
.valign(Align::Center)
|
||||||
|
.halign(Align::Start)
|
||||||
|
.hexpand(false)
|
||||||
|
.vexpand(true)
|
||||||
|
.build();
|
||||||
|
installed_diff_label.add_css_class("destructive-color-text");
|
||||||
|
|
||||||
|
installed_version_box.append(&installed_version_base_version_label.clone());
|
||||||
|
installed_version_box.append(&installed_diff_label);
|
||||||
|
|
||||||
|
let label_separator = gtk::Separator::builder()
|
||||||
|
.margin_start(5)
|
||||||
|
.margin_end(5)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
let candidate_version_box = gtk::Box::builder()
|
||||||
|
.halign(Align::Start)
|
||||||
|
.hexpand(false)
|
||||||
|
.orientation(Orientation::Horizontal)
|
||||||
|
.tooltip_text(t!("candidate_version_badge_text"))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
let candidate_version_base_version_label = gtk::Label::builder()
|
||||||
|
.label(format!("{}: {}", t!("candidate_version_badge_text"), &base_version))
|
||||||
|
.valign(Align::Center)
|
||||||
|
.halign(Align::Start)
|
||||||
|
.hexpand(false)
|
||||||
|
.vexpand(true)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
let candidate_diff_label = gtk::Label::builder()
|
||||||
|
.label(candidate_diff)
|
||||||
|
.valign(Align::Center)
|
||||||
|
.halign(Align::Start)
|
||||||
|
.hexpand(false)
|
||||||
|
.vexpand(true)
|
||||||
|
.build();
|
||||||
|
candidate_diff_label.add_css_class("success-color-text");
|
||||||
|
|
||||||
|
candidate_version_box.append(&candidate_version_base_version_label);
|
||||||
|
candidate_version_box.append(&candidate_diff_label);
|
||||||
|
|
||||||
|
badge_box.append(&installed_version_box);
|
||||||
|
badge_box.append(&label_separator);
|
||||||
|
badge_box.append(&candidate_version_box);
|
||||||
|
|
||||||
|
let boxedlist = gtk::ListBox::builder()
|
||||||
|
.selection_mode(SelectionMode::None)
|
||||||
|
.halign(Align::Start)
|
||||||
|
.valign(Align::End)
|
||||||
|
.margin_start(5)
|
||||||
|
.margin_end(5)
|
||||||
|
.margin_bottom(10)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
boxedlist.add_css_class("boxed-list");
|
||||||
|
boxedlist.append(&badge_box);
|
||||||
|
boxedlist
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_arch_badge(arch: String) -> gtk::ListBox {
|
||||||
|
let arch_label = gtk::Label::builder()
|
||||||
|
.halign(Align::Start)
|
||||||
|
.hexpand(false)
|
||||||
|
.label(format!("{}: {}", t!("arch_label_label"), arch))
|
||||||
|
.margin_start(5)
|
||||||
|
.margin_end(5)
|
||||||
|
.margin_bottom(5)
|
||||||
|
.margin_top(5)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
let boxedlist = gtk::ListBox::builder()
|
||||||
|
.selection_mode(SelectionMode::None)
|
||||||
|
.halign(Align::Start)
|
||||||
|
.valign(Align::End)
|
||||||
|
.margin_start(5)
|
||||||
|
.margin_end(5)
|
||||||
|
.margin_bottom(10)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
boxedlist.add_css_class("boxed-list");
|
||||||
|
boxedlist.append(&arch_label);
|
||||||
|
boxedlist
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remove_all_children(parent: &impl IsA<Widget>) where impl IsA<Widget>: libadwaita::prelude::IsA<ActionRow>, impl IsA<Widget>: libadwaita::prelude::IsA<CellArea>, impl IsA<Widget>: libadwaita::prelude::IsA<EntryRow>, impl IsA<Widget>: libadwaita::prelude::IsA<ExpanderRow>, impl IsA<Widget>: libadwaita::prelude::IsA<MultiFilter>, impl IsA<Widget>: libadwaita::prelude::IsA<PreferencesGroup>, impl IsA<Widget>: libadwaita::prelude::IsA<PreferencesPage>, impl IsA<Widget>: libadwaita::prelude::IsA<PreferencesWindow>, impl IsA<Widget>: libadwaita::prelude::IsA<TextView>, impl IsA<Widget>: libadwaita::prelude::IsA<gtk4::Box>, impl IsA<Widget>: libadwaita::prelude::IsA<gtk4::Fixed>, impl IsA<Widget>: libadwaita::prelude::IsA<gtk4::Grid> {
|
||||||
|
while let Some(child) = parent.last_child() {
|
||||||
|
parent.remove(&child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_diff_by_prefix(xs: String, ys: String) -> (String, String, String) {
|
||||||
|
let mut count = String::new();
|
||||||
|
for (x,y) in xs.chars().zip(ys.chars()) {
|
||||||
|
if x == y {
|
||||||
|
count.push(x)
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let count_clone0 = count.clone();
|
||||||
|
return(count_clone0, xs.trim_start_matches(&count.as_str()).to_string(), ys.trim_start_matches(&count.as_str()).to_string())
|
||||||
|
}
|
@ -6,7 +6,7 @@ use crate::apt_update_page::AptPackageSocket;
|
|||||||
|
|
||||||
glib::wrapper! {
|
glib::wrapper! {
|
||||||
pub struct AptPackageRow(ObjectSubclass<imp::AptPackageRow>)
|
pub struct AptPackageRow(ObjectSubclass<imp::AptPackageRow>)
|
||||||
@extends adw::ActionRow, gtk::Widget, gtk::ListBoxRow, adw::PreferencesRow,
|
@extends adw::ExpanderRow, gtk::Widget, gtk::ListBoxRow, adw::PreferencesRow,
|
||||||
@implements gtk::Accessible, gtk::Actionable, gtk::Buildable, gtk::ConstraintTarget;
|
@implements gtk::Accessible, gtk::Actionable, gtk::Buildable, gtk::ConstraintTarget;
|
||||||
}
|
}
|
||||||
|
|
@ -38,7 +38,7 @@ pub fn apt_update_page(window: adw::ApplicationWindow) -> gtk::Box {
|
|||||||
});
|
});
|
||||||
|
|
||||||
Command::new("pkexec")
|
Command::new("pkexec")
|
||||||
.args(["/home/ward/RustroverProjects/project-leoali/target/debug/apt_update"])
|
.args(["/home/ward/RustroverProjects/pika-idk-manager/target/debug/apt_update"])
|
||||||
.spawn();
|
.spawn();
|
||||||
|
|
||||||
let main_box = gtk::Box::builder()
|
let main_box = gtk::Box::builder()
|
||||||
@ -66,13 +66,6 @@ pub fn apt_update_page(window: adw::ApplicationWindow) -> gtk::Box {
|
|||||||
packages_boxedlist.add_css_class("boxed-list");
|
packages_boxedlist.add_css_class("boxed-list");
|
||||||
let rows_size_group = gtk::SizeGroup::new(SizeGroupMode::Both);
|
let rows_size_group = gtk::SizeGroup::new(SizeGroupMode::Both);
|
||||||
|
|
||||||
packages_boxedlist.append(&AptPackageRow::new(AptPackageSocket{
|
|
||||||
name: "name".to_string(),
|
|
||||||
arch: "arch".to_string(),
|
|
||||||
installed_version: "0.0".to_string(),
|
|
||||||
candidate_version: "0.0".to_string()
|
|
||||||
}));
|
|
||||||
|
|
||||||
let packages_viewport = gtk::ScrolledWindow::builder()
|
let packages_viewport = gtk::ScrolledWindow::builder()
|
||||||
.hscrollbar_policy(PolicyType::Never)
|
.hscrollbar_policy(PolicyType::Never)
|
||||||
.vexpand(true)
|
.vexpand(true)
|
||||||
@ -94,14 +87,16 @@ pub fn apt_update_page(window: adw::ApplicationWindow) -> gtk::Box {
|
|||||||
.hexpand(true)
|
.hexpand(true)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
apt_update_dialog_child_box.append(>k::Spinner::builder()
|
let apt_update_dialog_spinner = gtk::Spinner::builder()
|
||||||
.hexpand(true)
|
.hexpand(true)
|
||||||
.valign(Align::Start)
|
.valign(Align::Start)
|
||||||
.halign(Align::Center)
|
.halign(Align::Center)
|
||||||
.spinning(true)
|
.spinning(true)
|
||||||
.height_request(128)
|
.height_request(128)
|
||||||
.width_request(128)
|
.width_request(128)
|
||||||
.build());
|
.build();
|
||||||
|
|
||||||
|
apt_update_dialog_child_box.append(&apt_update_dialog_spinner);
|
||||||
apt_update_dialog_child_box.append(&apt_update_dialog_progress_bar);
|
apt_update_dialog_child_box.append(&apt_update_dialog_progress_bar);
|
||||||
|
|
||||||
let apt_update_dialog = adw::MessageDialog::builder()
|
let apt_update_dialog = adw::MessageDialog::builder()
|
||||||
@ -147,10 +142,14 @@ pub fn apt_update_page(window: adw::ApplicationWindow) -> gtk::Box {
|
|||||||
|
|
||||||
let update_status_server_context = MainContext::default();
|
let update_status_server_context = MainContext::default();
|
||||||
// The main loop executes the asynchronous block
|
// The main loop executes the asynchronous block
|
||||||
update_status_server_context.spawn_local(clone!(@weak apt_update_dialog => async move {
|
update_status_server_context.spawn_local(clone!(@weak apt_update_dialog, @weak apt_update_dialog_spinner => async move {
|
||||||
while let Ok(state) = update_status_receiver.recv().await {
|
while let Ok(state) = update_status_receiver.recv().await {
|
||||||
match state.as_ref() {
|
match state.as_ref() {
|
||||||
"FN_OVERRIDE_SUCCESSFUL" => {}
|
"FN_OVERRIDE_SUCCESSFUL" => {}
|
||||||
|
"FN_OVERRIDE_FAILED" => {
|
||||||
|
apt_update_dialog_spinner.set_spinning(false);
|
||||||
|
apt_update_dialog.set_body(&t!("apt_update_dialog_status_failed").to_string())
|
||||||
|
}
|
||||||
_ => apt_update_dialog.set_body(&state)
|
_ => apt_update_dialog.set_body(&state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -158,9 +157,14 @@ pub fn apt_update_page(window: adw::ApplicationWindow) -> gtk::Box {
|
|||||||
|
|
||||||
let get_upgradable_server_context = MainContext::default();
|
let get_upgradable_server_context = MainContext::default();
|
||||||
// The main loop executes the asynchronous block
|
// The main loop executes the asynchronous block
|
||||||
get_upgradable_server_context.spawn_local(clone!(@weak window => async move {
|
get_upgradable_server_context.spawn_local(clone!(@weak packages_boxedlist => async move {
|
||||||
while let Ok(state) = get_upgradable_receiver.recv().await {
|
while let Ok(state) = get_upgradable_receiver.recv().await {
|
||||||
println!("{}", state.name)
|
packages_boxedlist.append(&AptPackageRow::new(AptPackageSocket {
|
||||||
|
name: state.name,
|
||||||
|
arch: state.arch,
|
||||||
|
installed_version: state.installed_version,
|
||||||
|
candidate_version: state.candidate_version
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
@ -1,182 +0,0 @@
|
|||||||
use std::{cell::RefCell, default, sync::OnceLock};
|
|
||||||
|
|
||||||
use adw::*;
|
|
||||||
use adw::{prelude::*, subclass::prelude::*};
|
|
||||||
use glib::{subclass::Signal, Properties};
|
|
||||||
use gtk::{Align, glib, Orientation, SizeGroupMode, SelectionMode};
|
|
||||||
use gtk::Orientation::Horizontal;
|
|
||||||
use crate::apt_update_page::AptPackageSocket;
|
|
||||||
|
|
||||||
// ANCHOR: custom_button
|
|
||||||
// Object holding the state
|
|
||||||
#[derive(Properties, Default)]
|
|
||||||
#[properties(wrapper_type = super::AptPackageRow)]
|
|
||||||
pub struct AptPackageRow {
|
|
||||||
#[property(get, set)]
|
|
||||||
package_name: RefCell<String>,
|
|
||||||
#[property(get, set)]
|
|
||||||
package_arch: RefCell<String>,
|
|
||||||
#[property(get, set)]
|
|
||||||
package_installed_version: RefCell<String>,
|
|
||||||
#[property(get, set)]
|
|
||||||
package_candidate_version: RefCell<String>
|
|
||||||
}
|
|
||||||
// ANCHOR_END: custom_button
|
|
||||||
|
|
||||||
// The central trait for subclassing a GObject
|
|
||||||
#[glib::object_subclass]
|
|
||||||
impl ObjectSubclass for AptPackageRow {
|
|
||||||
const NAME: &'static str = "AptPackageRow";
|
|
||||||
type Type = super::AptPackageRow;
|
|
||||||
type ParentType = adw::ActionRow;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ANCHOR: object_impl
|
|
||||||
// Trait shared by all GObjects
|
|
||||||
#[glib::derived_properties]
|
|
||||||
impl ObjectImpl for AptPackageRow {
|
|
||||||
fn signals() -> &'static [Signal] {
|
|
||||||
static SIGNALS: OnceLock<Vec<Signal>> = OnceLock::new();
|
|
||||||
SIGNALS.get_or_init(|| vec![Signal::builder("row-deleted").build()])
|
|
||||||
}
|
|
||||||
fn constructed(&self) {
|
|
||||||
self.parent_constructed();
|
|
||||||
|
|
||||||
// Bind label to number
|
|
||||||
// `SYNC_CREATE` ensures that the label will be immediately set
|
|
||||||
let obj = self.obj();
|
|
||||||
|
|
||||||
let package_name = obj.package_name();
|
|
||||||
let package_arch = obj.package_arch();
|
|
||||||
let package_installed_version= obj.package_installed_version();
|
|
||||||
let package_candidate_version= obj.package_candidate_version();
|
|
||||||
|
|
||||||
println!("tetst {}" package_name);
|
|
||||||
|
|
||||||
let prefix_box = gtk::Box::new(Orientation::Vertical, 0);
|
|
||||||
|
|
||||||
let package_label = gtk::Label::builder()
|
|
||||||
.build();
|
|
||||||
package_label.add_css_class("size-20-bold-text");
|
|
||||||
|
|
||||||
prefix_box.append(&package_label);
|
|
||||||
prefix_box.append(&create_version_badge(package_installed_version, package_candidate_version));
|
|
||||||
|
|
||||||
obj.add_prefix(&prefix_box);
|
|
||||||
|
|
||||||
let obj = self.obj();
|
|
||||||
obj.bind_property("package-name", &package_label, "label")
|
|
||||||
.sync_create()
|
|
||||||
.bidirectional()
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Trait shared by all widgets
|
|
||||||
impl WidgetImpl for AptPackageRow {}
|
|
||||||
|
|
||||||
// Trait shared by all buttons
|
|
||||||
// Trait shared by all buttons
|
|
||||||
|
|
||||||
impl ListBoxRowImpl for AptPackageRow {}
|
|
||||||
impl PreferencesRowImpl for AptPackageRow {}
|
|
||||||
impl ActionRowImpl for AptPackageRow {}
|
|
||||||
|
|
||||||
fn create_version_badge(installed_version: String, candidate_version: String) -> gtk::ListBox {
|
|
||||||
let (base_version, installed_diff, candidate_diff) = get_diff_by_prefix(installed_version, candidate_version);
|
|
||||||
|
|
||||||
let badge_box = gtk::Box::builder()
|
|
||||||
.halign(Align::Start)
|
|
||||||
.hexpand(false)
|
|
||||||
.orientation(Orientation::Horizontal)
|
|
||||||
.margin_start(5)
|
|
||||||
.margin_end(5)
|
|
||||||
.margin_bottom(5)
|
|
||||||
.margin_top(5)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
let installed_version_box = gtk::Box::builder()
|
|
||||||
.halign(Align::Start)
|
|
||||||
.hexpand(false)
|
|
||||||
.orientation(Orientation::Horizontal)
|
|
||||||
.tooltip_text(t!("installed_version_box_tooltip_text"))
|
|
||||||
.build();
|
|
||||||
|
|
||||||
let installed_version_base_version_label = gtk::Label::builder()
|
|
||||||
.label(&base_version)
|
|
||||||
.valign(Align::Center)
|
|
||||||
.halign(Align::Start)
|
|
||||||
.hexpand(false)
|
|
||||||
.vexpand(true)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
let installed_diff_label = gtk::Label::builder()
|
|
||||||
.label(installed_diff)
|
|
||||||
.valign(Align::Center)
|
|
||||||
.halign(Align::Start)
|
|
||||||
.hexpand(false)
|
|
||||||
.vexpand(true)
|
|
||||||
.build();
|
|
||||||
installed_diff_label.add_css_class("destructive-color-text");
|
|
||||||
|
|
||||||
installed_version_box.append(&installed_version_base_version_label.clone());
|
|
||||||
installed_version_box.append(&installed_diff_label);
|
|
||||||
|
|
||||||
let label_separator = gtk::Separator::builder()
|
|
||||||
.margin_start(5)
|
|
||||||
.margin_end(5)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
let candidate_version_box = gtk::Box::builder()
|
|
||||||
.halign(Align::Start)
|
|
||||||
.hexpand(false)
|
|
||||||
.orientation(Orientation::Horizontal)
|
|
||||||
.tooltip_text(t!("candidate_version_box_tooltip_text"))
|
|
||||||
.build();
|
|
||||||
|
|
||||||
let candidate_version_base_version_label = gtk::Label::builder()
|
|
||||||
.label(base_version)
|
|
||||||
.valign(Align::Center)
|
|
||||||
.halign(Align::Start)
|
|
||||||
.hexpand(false)
|
|
||||||
.vexpand(true)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
let candidate_diff_label = gtk::Label::builder()
|
|
||||||
.label(candidate_diff)
|
|
||||||
.valign(Align::Center)
|
|
||||||
.halign(Align::Start)
|
|
||||||
.hexpand(false)
|
|
||||||
.vexpand(true)
|
|
||||||
.build();
|
|
||||||
candidate_diff_label.add_css_class("success-color-text");
|
|
||||||
|
|
||||||
candidate_version_box.append(&candidate_version_base_version_label);
|
|
||||||
candidate_version_box.append(&candidate_diff_label);
|
|
||||||
|
|
||||||
badge_box.append(&installed_version_box);
|
|
||||||
badge_box.append(&label_separator);
|
|
||||||
badge_box.append(&candidate_version_box);
|
|
||||||
|
|
||||||
let boxedlist = gtk::ListBox::builder()
|
|
||||||
.selection_mode(SelectionMode::None)
|
|
||||||
.halign(Align::Start)
|
|
||||||
.valign(Align::End)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
boxedlist.add_css_class("boxed-list");
|
|
||||||
boxedlist.append(&badge_box);
|
|
||||||
boxedlist
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_diff_by_prefix(xs: String, ys: String) -> (String, String, String) {
|
|
||||||
let mut count = String::new();
|
|
||||||
for (x,y) in xs.chars().zip(ys.chars()) {
|
|
||||||
if x == y {
|
|
||||||
count.push(x)
|
|
||||||
} else {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let count_clone0 = count.clone();
|
|
||||||
return(count_clone0, xs.trim_start_matches(&count.as_str()).to_string(), ys.trim_start_matches(&count.as_str()).to_string())
|
|
||||||
}
|
|
@ -21,10 +21,12 @@ i18n!("locales", fallback = "en_US");
|
|||||||
/// main function
|
/// main function
|
||||||
fn main() {
|
fn main() {
|
||||||
let current_locale = match env::var_os("LANG") {
|
let current_locale = match env::var_os("LANG") {
|
||||||
Some(v) => v.into_string().unwrap(),
|
Some(v) => v.into_string().unwrap().chars()
|
||||||
|
.take_while(|&ch| ch != '.')
|
||||||
|
.collect::<String>(),
|
||||||
None => panic!("$LANG is not set"),
|
None => panic!("$LANG is not set"),
|
||||||
};
|
};
|
||||||
rust_i18n::set_locale(current_locale.strip_suffix(".UTF-8").unwrap());
|
rust_i18n::set_locale(¤t_locale);
|
||||||
let application = adw::Application::new(
|
let application = adw::Application::new(
|
||||||
Some(APP_ID),
|
Some(APP_ID),
|
||||||
Default::default(),
|
Default::default(),
|
Loading…
Reference in New Issue
Block a user