This commit is contained in:
Tsuki 2024-02-27 15:17:43 +08:00
parent ee271a8c26
commit c90c43e6b7
13 changed files with 693 additions and 34 deletions

291
Cargo.lock generated
View File

@ -103,6 +103,12 @@ version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "bytes"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223"
[[package]] [[package]]
name = "cairo-rs" name = "cairo-rs"
version = "0.17.10" version = "0.17.10"
@ -164,7 +170,27 @@ dependencies = [
"js-sys", "js-sys",
"num-traits", "num-traits",
"wasm-bindgen", "wasm-bindgen",
"windows-targets", "windows-targets 0.52.0",
]
[[package]]
name = "const-random"
version = "0.1.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5aaf16c9c2c612020bcfd042e170f6e32de9b9d75adb5277cdbbd2e2c8c8299a"
dependencies = [
"const-random-macro",
]
[[package]]
name = "const-random-macro"
version = "0.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e"
dependencies = [
"getrandom",
"once_cell",
"tiny-keccak",
] ]
[[package]] [[package]]
@ -182,6 +208,42 @@ dependencies = [
"cfg-if", "cfg-if",
] ]
[[package]]
name = "crunchy"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
[[package]]
name = "dirs"
version = "5.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225"
dependencies = [
"dirs-sys",
]
[[package]]
name = "dirs-sys"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c"
dependencies = [
"libc",
"option-ext",
"redox_users",
"windows-sys",
]
[[package]]
name = "dlv-list"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "442039f5147480ba31067cb00ada1adae6892028e40e45fc5de7b7df6dcc1b5f"
dependencies = [
"const-random",
]
[[package]] [[package]]
name = "equivalent" name = "equivalent"
version = "1.0.1" version = "1.0.1"
@ -797,6 +859,17 @@ dependencies = [
"pkg-config", "pkg-config",
] ]
[[package]]
name = "libredox"
version = "0.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8"
dependencies = [
"bitflags 2.4.2",
"libc",
"redox_syscall",
]
[[package]] [[package]]
name = "libssh2-sys" name = "libssh2-sys"
version = "0.3.0" version = "0.3.0"
@ -872,6 +945,17 @@ dependencies = [
"adler", "adler",
] ]
[[package]]
name = "mio"
version = "0.8.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09"
dependencies = [
"libc",
"wasi",
"windows-sys",
]
[[package]] [[package]]
name = "nanorand" name = "nanorand"
version = "0.7.0" version = "0.7.0"
@ -933,6 +1017,22 @@ dependencies = [
"vcpkg", "vcpkg",
] ]
[[package]]
name = "option-ext"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
[[package]]
name = "ordered-multimap"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4d6a8c22fc714f0c2373e6091bf6f5e9b37b1bc0b1184874b7e0a4e303d318f"
dependencies = [
"dlv-list",
"hashbrown",
]
[[package]] [[package]]
name = "pango" name = "pango"
version = "0.17.10" version = "0.17.10"
@ -959,6 +1059,29 @@ dependencies = [
"system-deps", "system-deps",
] ]
[[package]]
name = "parking_lot"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
dependencies = [
"lock_api",
"parking_lot_core",
]
[[package]]
name = "parking_lot_core"
version = "0.9.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"smallvec",
"windows-targets 0.48.5",
]
[[package]] [[package]]
name = "percent-encoding" name = "percent-encoding"
version = "2.3.1" version = "2.3.1"
@ -1065,6 +1188,26 @@ dependencies = [
"proc-macro2", "proc-macro2",
] ]
[[package]]
name = "redox_syscall"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
dependencies = [
"bitflags 1.3.2",
]
[[package]]
name = "redox_users"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4"
dependencies = [
"getrandom",
"libredox",
"thiserror",
]
[[package]] [[package]]
name = "regex" name = "regex"
version = "1.10.3" version = "1.10.3"
@ -1138,18 +1281,35 @@ name = "rsproject"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"chrono", "chrono",
"dirs",
"git2", "git2",
"glib-build-tools", "glib-build-tools",
"gtk4", "gtk4",
"lazy_static", "lazy_static",
"libadwaita", "libadwaita",
"once_cell",
"regex", "regex",
"relm4", "relm4",
"relm4-icons", "relm4-icons",
"rust-ini",
"serde",
"thiserror",
"tokio",
"toml",
"tracker", "tracker",
"validator", "validator",
] ]
[[package]]
name = "rust-ini"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e0698206bcb8882bf2a9ecb4c1e7785db57ff052297085a6efd4fe42302068a"
dependencies = [
"cfg-if",
"ordered-multimap",
]
[[package]] [[package]]
name = "rustc-demangle" name = "rustc-demangle"
version = "0.1.23" version = "0.1.23"
@ -1238,6 +1398,15 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "signal-hook-registry"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "slab" name = "slab"
version = "0.4.9" version = "0.4.9"
@ -1253,6 +1422,16 @@ version = "1.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7"
[[package]]
name = "socket2"
version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9"
dependencies = [
"libc",
"windows-sys",
]
[[package]] [[package]]
name = "spin" name = "spin"
version = "0.9.8" version = "0.9.8"
@ -1329,6 +1508,15 @@ dependencies = [
"syn 2.0.50", "syn 2.0.50",
] ]
[[package]]
name = "tiny-keccak"
version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237"
dependencies = [
"crunchy",
]
[[package]] [[package]]
name = "tinyvec" name = "tinyvec"
version = "1.6.0" version = "1.6.0"
@ -1351,8 +1539,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931"
dependencies = [ dependencies = [
"backtrace", "backtrace",
"bytes",
"libc",
"mio",
"num_cpus", "num_cpus",
"parking_lot",
"pin-project-lite", "pin-project-lite",
"signal-hook-registry",
"socket2",
"tokio-macros",
"windows-sys",
]
[[package]]
name = "tokio-macros"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.50",
] ]
[[package]] [[package]]
@ -1650,7 +1857,31 @@ version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
dependencies = [ dependencies = [
"windows-targets", "windows-targets 0.52.0",
]
[[package]]
name = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"windows-targets 0.48.5",
]
[[package]]
name = "windows-targets"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
dependencies = [
"windows_aarch64_gnullvm 0.48.5",
"windows_aarch64_msvc 0.48.5",
"windows_i686_gnu 0.48.5",
"windows_i686_msvc 0.48.5",
"windows_x86_64_gnu 0.48.5",
"windows_x86_64_gnullvm 0.48.5",
"windows_x86_64_msvc 0.48.5",
] ]
[[package]] [[package]]
@ -1659,51 +1890,93 @@ version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
dependencies = [ dependencies = [
"windows_aarch64_gnullvm", "windows_aarch64_gnullvm 0.52.0",
"windows_aarch64_msvc", "windows_aarch64_msvc 0.52.0",
"windows_i686_gnu", "windows_i686_gnu 0.52.0",
"windows_i686_msvc", "windows_i686_msvc 0.52.0",
"windows_x86_64_gnu", "windows_x86_64_gnu 0.52.0",
"windows_x86_64_gnullvm", "windows_x86_64_gnullvm 0.52.0",
"windows_x86_64_msvc", "windows_x86_64_msvc 0.52.0",
] ]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]] [[package]]
name = "windows_aarch64_gnullvm" name = "windows_aarch64_gnullvm"
version = "0.52.0" version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]] [[package]]
name = "windows_aarch64_msvc" name = "windows_aarch64_msvc"
version = "0.52.0" version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
[[package]]
name = "windows_i686_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]] [[package]]
name = "windows_i686_gnu" name = "windows_i686_gnu"
version = "0.52.0" version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
[[package]]
name = "windows_i686_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]] [[package]]
name = "windows_i686_msvc" name = "windows_i686_msvc"
version = "0.52.0" version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]] [[package]]
name = "windows_x86_64_gnu" name = "windows_x86_64_gnu"
version = "0.52.0" version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]] [[package]]
name = "windows_x86_64_gnullvm" name = "windows_x86_64_gnullvm"
version = "0.52.0" version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]] [[package]]
name = "windows_x86_64_msvc" name = "windows_x86_64_msvc"
version = "0.52.0" version = "0.52.0"

View File

@ -16,6 +16,13 @@ git2 = "0.18.2"
validator = { version = "0.16.1",features=['derive'] } validator = { version = "0.16.1",features=['derive'] }
lazy_static = "1.4.0" lazy_static = "1.4.0"
regex = "1.10.3" regex = "1.10.3"
toml = "0.8.10"
dirs = "5.0.1"
serde = { version = "1.0.197",features = ["derive"] }
thiserror = "1.0.57"
once_cell = "1.19.0"
tokio = { version = "1.36.0",features = ["full"] }
rust-ini = "*"
[build-dependencies] [build-dependencies]
glib-build-tools = "0.17.0" glib-build-tools = "0.17.0"

160
src/components/alg_page.rs Normal file
View File

@ -0,0 +1,160 @@
use adw::prelude::*;
use gtk::prelude::*;
use relm4::{component, component::Component, ComponentParts, ComponentSender};
use relm4::{
factory::FactoryView,
prelude::{DynamicIndex, FactoryComponent},
typed_list_view::{LabelColumn, RelmColumn, TypedColumnView},
view, FactorySender, RelmObjectExt,
};
use std::collections::HashMap;
use ini::Ini;
use crate::utils::ini_to_table;
#[derive(Debug)]
pub struct AlgPage {
alg_list: TypedColumnView<AlgListItem, gtk::NoSelection>,
}
#[derive(Debug)]
pub enum AlgPageMsg {
New(Ini)
}
#[component(pub)]
impl Component for AlgPage {
type Output = ();
type Init = ();
type Input = AlgPageMsg;
type CommandOutput = ();
view! {
#[root]
gtk::Box{
gtk::ScrolledWindow{
#[local_ref]
#[wrap(Some)]
set_child=list_view -> gtk::ColumnView{
set_hexpand:true,
set_vexpand:true,
set_show_column_separators: true,
set_show_row_separators: true,
set_enable_rubberband:true,
}
}
}
}
fn init(
init: Self::Init,
root: &Self::Root,
sender: ComponentSender<Self>,
) -> ComponentParts<Self> {
let mut alg_list = TypedColumnView::new();
alg_list.append_column::<NameColumn>();
alg_list.append_column::<VersionColumn>();
alg_list.append_column::<DescriptionColumn>();
alg_list.append_column::<TagColumn>();
let model = AlgPage { alg_list };
let list_view = &model.alg_list.view;
let widgets = view_output!();
ComponentParts { model, widgets }
}
fn update(&mut self, message: Self::Input, sender: ComponentSender<Self>, root: &Self::Root) {
match message {
AlgPageMsg::New(ini) => {
let lists = ini_to_table(&ini);
for list in lists {
let item = AlgListItem::new(list.0,list.1,"".to_string(),"".to_string());
self.alg_list.append(item);
}
}
}
}
}
#[derive(Debug, PartialEq, Eq)]
pub(super) struct AlgListItem {
name: String,
description: String,
version: String,
tag: String,
}
impl AlgListItem {
pub fn new(name: String, version: String, description: String, tag: String) -> Self {
Self {
name,
version,
description,
tag,
}
}
}
pub(super) struct NameColumn;
pub(super) struct VersionColumn;
pub(super) struct DescriptionColumn;
pub(super) struct TagColumn;
impl LabelColumn for TagColumn {
type Item = AlgListItem;
type Value = String;
const COLUMN_NAME: &'static str = "Tag";
const ENABLE_SORT: bool = true;
fn get_cell_value(item: &Self::Item) -> Self::Value {
item.tag.clone()
}
fn format_cell_value(value: &Self::Value) -> String {
format!("{}", value)
}
}
impl LabelColumn for NameColumn {
type Item = AlgListItem;
type Value = String;
const COLUMN_NAME: &'static str = "Name";
const ENABLE_SORT: bool = true;
fn get_cell_value(item: &Self::Item) -> Self::Value {
item.name.clone()
}
fn format_cell_value(value: &Self::Value) -> String {
format!("{}", value)
}
}
impl LabelColumn for VersionColumn {
type Item = AlgListItem;
type Value = String;
const COLUMN_NAME: &'static str = "Version";
const ENABLE_SORT: bool = true;
fn get_cell_value(item: &Self::Item) -> Self::Value {
item.version.clone()
}
fn format_cell_value(value: &Self::Value) -> String {
format!("{}", value)
}
}
impl LabelColumn for DescriptionColumn {
type Item = AlgListItem;
type Value = String;
const COLUMN_NAME: &'static str = "Description";
const ENABLE_SORT: bool = true;
fn get_cell_value(item: &Self::Item) -> Self::Value {
item.description.clone()
}
fn format_cell_value(value: &Self::Value) -> String {
format!("{}", value)
}
}

View File

@ -2,8 +2,7 @@ use crate::components::new_project::NewPageModel;
use adw::prelude::*; use adw::prelude::*;
use gtk::prelude::*; use gtk::prelude::*;
use gtk::Widget; use gtk::Widget;
use relm4::actions::RelmActionGroup; use relm4::{actions::RelmActionGroup, component::{AsyncComponentController, AsyncController}, Component, ComponentParts, ComponentSender};
use relm4::{actions::*, prelude::*, Component, ComponentParts, ComponentSender};
use std::{ use std::{
any::Any, any::Any,
borrow::{Borrow, BorrowMut}, borrow::{Borrow, BorrowMut},
@ -13,6 +12,7 @@ use std::{
rc::Rc, rc::Rc,
sync::{Arc, Mutex}, sync::{Arc, Mutex},
}; };
use crate::components::alg_page::AlgPage;
relm4::new_action_group!(FileActionGroup, "file"); relm4::new_action_group!(FileActionGroup, "file");
relm4::new_stateless_action!(OpenAction, FileActionGroup, "open"); relm4::new_stateless_action!(OpenAction, FileActionGroup, "open");
@ -23,7 +23,7 @@ pub enum AppMsg {
NewProject, NewProject,
} }
pub struct AppModel { pub struct AppModel {
new_page_model: Controller<NewPageModel>, new_page_model: AsyncController<NewPageModel>,
tracker: usize, tracker: usize,
} }
@ -139,9 +139,12 @@ impl Component for AppModel {
relm4_icons::initialize_icons(); relm4_icons::initialize_icons();
let app = relm4::main_application(); let app = relm4::main_application();
use relm4::component::AsyncComponent;
let new_page_model = NewPageModel::builder() let new_page_model = NewPageModel::builder()
.launch(()) .launch(())
.forward(sender.input_sender(), |a| AppMsg::NewProject); .forward(sender.input_sender(), |a| AppMsg::NewProject);
let model = AppModel { let model = AppModel {
new_page_model, new_page_model,
tracker: 0, tracker: 0,

View File

@ -0,0 +1 @@

View File

@ -1,3 +1,4 @@
mod alg_page;
mod app; mod app;
mod history_list; mod history_list;
mod new_project; mod new_project;

View File

@ -1,6 +1,8 @@
use crate::components::setting_item::{SettingItem, SettingType}; use crate::components::setting_item::{SettingItem, SettingType};
use crate::components::NewPageMsg::RadarEdit; use crate::components::NewPageMsg::RadarEdit;
use crate::config::{CommonConfig, RadarConfig}; use crate::config::{CommonConfig, RadarConfig};
use crate::utils::get_alg_lists;
use gtk::prelude::*;
use adw::prelude::*; use adw::prelude::*;
use adw::{glib, PreferencesPage}; use adw::{glib, PreferencesPage};
use gtk::ffi::gtk_content_fit_get_type; use gtk::ffi::gtk_content_fit_get_type;
@ -8,12 +10,17 @@ use gtk::glib::clone;
use gtk::prelude::{BoxExt, ButtonExt, GtkWindowExt, OrientableExt, ToggleButtonExt}; use gtk::prelude::{BoxExt, ButtonExt, GtkWindowExt, OrientableExt, ToggleButtonExt};
use gtk::ResponseType::No; use gtk::ResponseType::No;
use gtk::Widget; use gtk::Widget;
use relm4::component::{AsyncComponent, AsyncComponentParts, AsyncComponentSender};
use relm4::factory::FactoryVecDeque; use relm4::factory::FactoryVecDeque;
use relm4::loading_widgets::LoadingWidgets;
use relm4::{prelude::*, view}; use relm4::{prelude::*, view};
use std::cell::RefCell; use std::cell::RefCell;
use std::path::PathBuf; use std::path::PathBuf;
use std::rc::Rc; use std::rc::Rc;
use ini::Ini;
use validator::Validate; use validator::Validate;
use crate::components::alg_page::{AlgPage, AlgPageMsg};
use crate::components::AppMsg;
#[tracker::track] #[tracker::track]
#[derive(Debug)] #[derive(Debug)]
@ -22,20 +29,26 @@ pub struct NewPageModel {
radar_num: usize, radar_num: usize,
current_idx: usize, current_idx: usize,
radar_configs: Vec<Rc<RefCell<RadarConfig>>>, radar_configs: Vec<Rc<RefCell<RadarConfig>>>,
#[do_not_track]
alg_page_model: Controller<AlgPage>,
#[do_not_track]
alg_lists: Vec<PathBuf>
} }
#[derive(Debug)] #[derive(Debug)]
pub enum NewPageMsg { pub enum NewPageMsg {
ChangeName(String), ChangeName(String),
ChangeRadarNum(usize), ChangeRadarNum(usize),
ChangeAlgList(usize),
CheckRadarConfig, CheckRadarConfig,
SwitchToRadar(usize), SwitchToRadar(usize),
SwitchToAlgorithm, SwitchToAlgorithm,
RadarEdit(usize), RadarEdit(usize),
None,
} }
#[relm4::component(pub)] #[relm4::component(async, pub)]
impl Component for NewPageModel { impl AsyncComponent for NewPageModel {
type Init = (); type Init = ();
type Output = (); type Output = ();
type Input = NewPageMsg; type Input = NewPageMsg;
@ -98,6 +111,14 @@ impl Component for NewPageModel {
set_value: model.radar_num as f64, set_value: model.radar_num as f64,
set_numeric: true, set_numeric: true,
}, },
#[name = "alg_list_selection"]
add=&adw::ComboRow{
set_title: "Algorithm List",
connect_selected_notify[sender] => move |s| {
let s = s.selected();
sender.input(NewPageMsg::ChangeAlgList(s as usize));
}
}
}, },
add=&adw::PreferencesGroup{ add=&adw::PreferencesGroup{
add=&gtk::Grid{ add=&gtk::Grid{
@ -118,9 +139,6 @@ impl Component for NewPageModel {
}, },
} }
} }
},
algorithm_setting = gtk::Box{
}, },
radar_setting=gtk::Box{ radar_setting=gtk::Box{
set_orientation: gtk::Orientation::Vertical, set_orientation: gtk::Orientation::Vertical,
@ -131,34 +149,49 @@ impl Component for NewPageModel {
}, },
stack.add_titled(&common_setting, Some("Common"), "Common"), stack.add_titled(&common_setting, Some("Common"), "Common"),
stack.add_titled(&radar_setting, Some("Radar"), "Radar"), stack.add_titled(&radar_setting, Some("Radar"), "Radar"),
alg_page = stack.add_titled(&algorithm_setting, Some("Algorithm"), "Algorithm") -> gtk::StackPage{ alg_page = stack.add_titled(alg, Some("Algorithm"), "Algorithm") -> gtk::StackPage{
set_visible: false set_visible: false
}, },
} }
fn init( async fn init(
init: Self::Init, init: Self::Init,
root: &Self::Root, root: Self::Root,
sender: relm4::ComponentSender<Self>, sender: AsyncComponentSender<Self>,
) -> relm4::ComponentParts<Self> { ) -> AsyncComponentParts<Self> {
let config = CommonConfig::default(); let config = CommonConfig::default();
let alg_page_model = AlgPage::builder().launch(()).forward(sender.input_sender(), |a| NewPageMsg::None);
let mut model = NewPageModel { let mut model = NewPageModel {
alg_page_model,
project_name: format!("Project {}", 0), project_name: format!("Project {}", 0),
radar_num: 1, radar_num: 1,
alg_lists: Vec::new(),
radar_configs: Vec::new(), radar_configs: Vec::new(),
current_idx: 0, current_idx: 0,
// common_setting: config,
tracker: 0, tracker: 0,
}; };
let alg = model.alg_page_model.widget();
let widgets = view_output!(); let widgets = view_output!();
ComponentParts { model, widgets } let alg_lts_list = get_alg_lists().await.unwrap();
model.alg_lists = alg_lts_list;
let names = model.alg_lists
.iter()
.map(|p| {
let name = p.file_name().unwrap();
name.to_str().unwrap()
})
.collect::<Vec<_>>();
widgets
.alg_list_selection
.set_model(Some(&gtk::StringList::new(names.as_slice())));
AsyncComponentParts { model, widgets }
} }
fn update_with_view( async fn update_with_view(
&mut self, &mut self,
widgets: &mut Self::Widgets, widgets: &mut Self::Widgets,
msg: Self::Input, msg: Self::Input,
sender: ComponentSender<Self>, sender: AsyncComponentSender<Self>,
root: &Self::Root, root: &Self::Root,
) { ) {
self.reset(); self.reset();
@ -269,9 +302,17 @@ impl Component for NewPageModel {
} else { } else {
widgets.alg_page.set_visible(false); widgets.alg_page.set_visible(false);
let idx = un.first().unwrap(); let idx = un.first().unwrap();
widgets.radar_stack.set_visible_child_name(format!("{}", idx).as_str()); widgets
.radar_stack
.set_visible_child_name(format!("{}", idx).as_str());
} }
},
NewPageMsg::ChangeAlgList(idx) => {
let path = self.alg_lists.get(idx).unwrap();
let ini = Ini::load_from_file(path).unwrap();
self.alg_page_model.emit(AlgPageMsg::New(ini));
} }
_ => {}
} }
self.update_view(widgets, sender); self.update_view(widgets, sender);

View File

@ -1,11 +1,11 @@
use adw::glib::gobject_ffi::GValue;
use adw::glib::GString;
use adw::prelude::*; use adw::prelude::*;
use gtk::prelude::*; use gtk::prelude::*;
use gtk::{StringList, Widget}; use gtk::{StringList, Widget};
use relm4::{factory::FactoryView, gtk, prelude::*, FactorySender, RelmObjectExt}; use relm4::{factory::FactoryView, gtk, prelude::*, FactorySender, RelmObjectExt};
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
use std::rc::Rc; use std::rc::Rc;
use adw::glib::gobject_ffi::GValue;
use adw::glib::GString;
#[derive(Debug)] #[derive(Debug)]
pub enum Msg {} pub enum Msg {}
@ -69,7 +69,7 @@ impl SettingItem {
s.remove_css_class("error"); s.remove_css_class("error");
} }
if let Some(buffer) = buffer.as_ref(){ if let Some(buffer) = buffer.as_ref() {
buffer(text.as_str()); buffer(text.as_str());
} }
}); });

View File

@ -12,7 +12,6 @@ lazy_static! {
r"^\s*(0|[1-9]\d*)(\.\d+)?\s*,\s*(0|[1-9]\d*)(\.\d+)?\s*,\s*(0|[1-9]\d*)(\.\d+)?\s*$" r"^\s*(0|[1-9]\d*)(\.\d+)?\s*,\s*(0|[1-9]\d*)(\.\d+)?\s*,\s*(0|[1-9]\d*)(\.\d+)?\s*$"
) )
.unwrap(); .unwrap();
static ref RADAR_TYPES: Vec<&'static str> = vec!["X", "S", "C"]; static ref RADAR_TYPES: Vec<&'static str> = vec!["X", "S", "C"];
} }

21
src/error.rs Normal file
View File

@ -0,0 +1,21 @@
use thiserror::Error;
#[derive(Debug, Error)]
pub enum SettingError {
#[error("IO Error: {0}")]
IOErr(#[from] std::io::Error),
#[error("Config Format is wrong;")]
FormatError(#[from] toml::de::Error),
#[error("Can't locate default config;")]
CantLocateDefaultConfig,
}
#[derive(Debug, Error)]
pub enum SourceError {
#[error("IO Error: {0}")]
IOErr(#[from] std::io::Error),
#[error("can't sync cause of {0}")]
SyncError(#[from] git2::Error),
#[error("can't sync cause of {0}")]
TokioError(#[from] tokio::task::JoinError),
}

View File

@ -1,15 +1,23 @@
#![allow(unused)] #![allow(unused)]
#![allow(dead_code)] #![allow(dead_code)]
use gtk::{ use gtk::{
gio::{self, Settings}, gio::{self},
prelude::SettingsExt, prelude::SettingsExt,
}; };
use std::{ptr, sync::Mutex};
mod components; mod components;
mod config; mod config;
mod error;
mod setting;
mod utils;
mod widgets; mod widgets;
use crate::setting::Config;
use components::AppModel; use components::AppModel;
use once_cell::{sync::Lazy as SafeLazy, unsync::Lazy as UnsafeLazy};
use std::sync::Mutex;
static CONFIG: SafeLazy<Mutex<Config>> = SafeLazy::new(|| Mutex::new(Config::from_env().unwrap()));
const APP_ID: &str = "org.tsuki.rsproject"; const APP_ID: &str = "org.tsuki.rsproject";
fn main() { fn main() {

67
src/setting.rs Normal file
View File

@ -0,0 +1,67 @@
use crate::error::SettingError;
use dirs::home_dir;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::env;
use std::io::Write;
use std::path::{Path, PathBuf};
#[derive(Debug, Serialize, Deserialize)]
pub struct Config {
pub alg_list_repo: String,
pub source_list_loc: PathBuf,
}
impl Default for Config {
fn default() -> Self {
let default_source_list_loc = home_dir().unwrap().join(".cache/rsp/lts");
Self {
alg_list_repo: "http://192.168.1.70:6020/awesomeradaralgorithms/lts.git".to_string(),
source_list_loc: default_source_list_loc,
}
}
}
impl Config {
fn from_file(path: impl AsRef<std::path::Path>) -> Result<Self, SettingError> {
let file = std::fs::read_to_string(path)?;
let config = toml::from_str(&file)?;
Ok(config)
}
pub fn from_env() -> Result<Self, SettingError> {
if let Some(dir_path) = env::var("RADARG_CONFIG")
.ok()
.map(|x| PathBuf::from(x))
.or(dirs::config_dir())
{
let path = dir_path.join("rsp.toml");
if path.exists() {
return Ok(Self::from_file(path)?);
} else {
let default_config = Config::default();
let mut file = std::fs::File::create(path)?;
let ser_config = toml::to_string_pretty(&default_config).unwrap();
file.write_all(ser_config.as_bytes());
return Ok(default_config);
}
}
Err(SettingError::CantLocateDefaultConfig)
}
pub fn save(&self) -> Result<(), SettingError> {
if let Some(dir_path) = env::var("RADARG_CONFIG")
.ok()
.map(|x| PathBuf::from(x))
.or(dirs::config_dir())
{
let path = dir_path.join("rsp.toml");
let mut file = std::fs::File::create(path)?;
let ser_config = toml::to_string_pretty(&self).unwrap();
file.write_all(ser_config.as_bytes());
Ok(())
} else {
Err(SettingError::CantLocateDefaultConfig)
}
}
}

78
src/utils.rs Normal file
View File

@ -0,0 +1,78 @@
use crate::error::SourceError;
use crate::CONFIG;
use git2::{Cred, FetchOptions, RemoteCallbacks, Repository};
use std::path::PathBuf;
use ini::Ini;
use tokio::task;
pub async fn get_alg_lists() -> Result<Vec<PathBuf>, SourceError> {
let (repo, loc) = {
let config = CONFIG.lock().unwrap();
(config.alg_list_repo.clone(), config.source_list_loc.clone())
};
let loc_cp = loc.clone();
let handler = task::spawn_blocking(move || {
if loc.exists() && loc.is_dir() {
let repo = Repository::open(loc);
{
if let Ok(repo) = repo.as_ref() {
let mut fetch_options = FetchOptions::new();
let mut callbacks = RemoteCallbacks::new();
callbacks.credentials(|_url, username_from_url, _allowed_types| {
Cred::ssh_key(
username_from_url.unwrap(),
None,
std::path::Path::new(&format!(
"{}/.ssh/id_rsa",
std::env::var("HOME").unwrap()
)),
None,
)
});
fetch_options.remote_callbacks(callbacks);
let mut remote = repo.find_remote("origin").unwrap();
remote
.fetch(
&["refs/heads/*:refs/heads/*"],
Some(&mut fetch_options),
None,
)
.unwrap();
}
}
repo
} else {
Repository::clone(&repo, loc)
}
});
let repo = handler.await??;
let mut list = Vec::new();
for entry in std::fs::read_dir(&loc_cp)? {
let entry = entry?;
let path = entry.path();
if path.is_file() && path.extension().and_then(|s| s.to_str()) == Some("ini") {
list.push(path);
}
}
Ok(list)
}
pub fn ini_to_table(ini: &Ini) -> Vec<(String,String)> {
let mut result = Vec::new();
let lib_sec = ini.section(Some("lib"));
let alg_sec = ini.section(Some("algorithms"));
if let Some(lib) = lib_sec{
for (key,value) in lib.iter(){
result.push((key.to_string(), value.to_string()));
}
}
if let Some(alg) = alg_sec{
for (key,value) in alg.iter(){
result.push((key.to_string(), value.to_string()));
}
}
result
}