Skip to content

Commit b4f928a

Browse files
committed
wip: native home-screen
1 parent 2b55c26 commit b4f928a

File tree

14 files changed

+215
-88
lines changed

14 files changed

+215
-88
lines changed

application/apps/indexer/gui/application/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ chrono-tz.workspace = true
4040
dirs.workspace = true
4141
serialport.workspace = true
4242
dlt-core.workspace = true
43+
blake3.workspace = true
4344
rustc-hash = "2.1"
4445

4546
#TODO: Replace env logger with log4rs

application/apps/indexer/gui/application/src/host/command.rs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
use serde::Deserialize;
2+
use serde::ser::{Serialize, SerializeStruct, Serializer};
3+
14
use std::{path::PathBuf, sync::mpsc::Sender as StdSender};
25

36
use stypes::FileFormat;
@@ -50,9 +53,38 @@ pub struct DltStatisticsParam {
5053
pub source_paths: Vec<PathBuf>,
5154
}
5255

53-
#[derive(Debug, Clone)]
56+
/// The serialization of StartSessionParam is used for the recent files of home-screen.
57+
///
58+
/// Note: Only properties needed to recreate a session should be serialized.
59+
#[derive(Deserialize, Debug, Clone)]
5460
pub struct StartSessionParam {
5561
pub parser: ParserConfig,
5662
pub source: ByteSourceConfig,
63+
64+
#[serde(skip)]
5765
pub session_setup_id: Option<Uuid>,
5866
}
67+
68+
impl Serialize for StartSessionParam {
69+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
70+
where
71+
S: Serializer,
72+
{
73+
if matches!(self.parser, ParserConfig::Plugins) {
74+
return Err(serde::ser::Error::custom(
75+
"Plugin parser cannot be serialized",
76+
));
77+
}
78+
79+
if matches!(self.source, ByteSourceConfig::Stream(_)) {
80+
return Err(serde::ser::Error::custom(
81+
"Stream source cannot be serialized",
82+
));
83+
}
84+
85+
let mut state = serializer.serialize_struct("StartSessionParam", 2)?;
86+
state.serialize_field("parser", &self.parser)?;
87+
state.serialize_field("source", &self.source)?;
88+
state.end()
89+
}
90+
}

application/apps/indexer/gui/application/src/host/service/mod.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ use crate::{
2525
message::HostMessage,
2626
notification::AppNotification,
2727
ui::{
28+
home::settings::SessionConfig,
2829
multi_setup::state::MultiFileState,
2930
session_setup::state::{
3031
SessionSetupState,
@@ -122,13 +123,16 @@ impl HostService {
122123
}
123124

124125
HostCommand::StartSession(start_params) => {
126+
let json = serde_json::to_string_pretty(&start_params).ok();
127+
125128
let StartSessionParam {
126129
parser,
127130
source,
128131
session_setup_id,
129132
} = *start_params;
130133

131-
self.start_session(source, parser, session_setup_id).await?;
134+
self.start_session(source, parser, json, session_setup_id)
135+
.await?;
132136
}
133137
HostCommand::CloseSessionSetup(id) => {
134138
// NOTE: We need to checks here for cleaning up session setups (Like cancelling
@@ -467,8 +471,11 @@ impl HostService {
467471
&self,
468472
source: ByteSourceConfig,
469473
parser: ParserConfig,
474+
json: Option<String>,
470475
session_setup_id: Option<Uuid>,
471476
) -> Result<(), HostError> {
477+
let description = format!("{}", parser);
478+
472479
let origin = match source {
473480
ByteSourceConfig::File(source_file_info) => ObserveOrigin::File(
474481
Uuid::new_v4().to_string(),
@@ -568,9 +575,17 @@ impl HostService {
568575

569576
let origin = ObserveOptions { origin, parser };
570577

571-
let session_params =
578+
let mut session_params =
572579
SessionService::spawn(self.communication.senders.get_shared_senders(), origin).await?;
573580

581+
if let Some(json) = json {
582+
session_params.session_info.config = Some(SessionConfig {
583+
id: blake3::hash(json.as_bytes()).to_hex().to_string(),
584+
description,
585+
json,
586+
});
587+
}
588+
574589
self.communication
575590
.senders
576591
.send_message(HostMessage::SessionCreated {

application/apps/indexer/gui/application/src/host/ui/home/mod.rs

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ use crate::common::phosphor::icons;
22
use crate::host::command::HostCommand;
33
use crate::host::common::parsers::ParserNames;
44
use crate::host::common::sources::StreamNames;
5+
use crate::host::notification::AppNotification;
56
use crate::host::ui::APP_SETTINGS;
7+
use crate::host::ui::StartSessionParam;
68
use crate::host::ui::UiActions;
79
use crate::host::ui::home::settings::FavoriteFolder;
810
use crate::host::ui::home::settings::HomeSettings;
@@ -61,7 +63,7 @@ pub fn home_screen(
6163
.resizable(true)
6264
.show_inside(ui, |ui| {
6365
ui.with_layout(Layout::top_down_justified(Align::LEFT), |ui| {
64-
draw_quick_actions(ui, actions, state, cmd_tx);
66+
draw_quick_actions(ui, actions, cmd_tx);
6567
});
6668
});
6769

@@ -80,15 +82,14 @@ pub fn home_screen(
8082
CentralPanel::default().show_inside(ui, |ui| {
8183
ui.with_layout(Layout::top_down_justified(Align::LEFT), |ui| {
8284
ui.heading("Recently opened");
83-
draw_recent_files(ui, state);
85+
draw_recent_files(ui, actions, state, cmd_tx);
8486
});
8587
});
8688
}
8789

8890
pub fn draw_quick_actions(
8991
ui: &mut egui::Ui,
9092
actions: &mut UiActions,
91-
state: &mut HomeSettings,
9293
cmd_tx: &Sender<HostCommand>,
9394
) {
9495
if let Some(paths) = actions.file_dialog.take_output(ACTION_FILES_ID)
@@ -175,15 +176,22 @@ fn action_button(
175176
});
176177
}
177178

178-
fn draw_recent_files(ui: &mut egui::Ui, state: &mut HomeSettings) {
179+
fn draw_recent_files(
180+
ui: &mut egui::Ui,
181+
actions: &mut UiActions,
182+
state: &mut HomeSettings,
183+
cmd_tx: &Sender<HostCommand>,
184+
) {
179185
egui::ScrollArea::vertical()
180186
.id_salt("recent_files_scroll")
181187
.show(ui, |ui| {
182188
ui.label("List of recently opened sources.");
183189
ui.add_space(5.0);
184190

191+
let mut remove_file: Option<String> = None;
192+
185193
for file in &mut state.recent_files {
186-
ui.collapsing(file.path.display().to_string(), |ui| {
194+
ui.collapsing(file.title.clone(), |ui| {
187195
ui.horizontal(|ui| {
188196
if ui
189197
.add(
@@ -193,7 +201,7 @@ fn draw_recent_files(ui: &mut egui::Ui, state: &mut HomeSettings) {
193201
.on_hover_text("Remove entry")
194202
.clicked()
195203
{
196-
print!("remove recent entry...");
204+
remove_file = Some(file.title.clone());
197205
}
198206

199207
if ui
@@ -207,6 +215,8 @@ fn draw_recent_files(ui: &mut egui::Ui, state: &mut HomeSettings) {
207215
}
208216
});
209217

218+
let mut remove_cfg: Option<String> = None;
219+
210220
for cfg in &file.configurations {
211221
ui.horizontal(|ui| {
212222
if ui
@@ -219,7 +229,7 @@ fn draw_recent_files(ui: &mut egui::Ui, state: &mut HomeSettings) {
219229
.on_hover_text("Open configuration")
220230
.clicked()
221231
{
222-
print!("open configuration...");
232+
open_configuration(actions, cmd_tx, &cfg.json);
223233
}
224234

225235
if ui
@@ -232,18 +242,37 @@ fn draw_recent_files(ui: &mut egui::Ui, state: &mut HomeSettings) {
232242
.on_hover_text("Remove configuration")
233243
.clicked()
234244
{
235-
print!("remove configuration...");
245+
remove_cfg = Some(cfg.id.clone());
236246
}
237247

238-
ui.label(&cfg.name);
239-
ui.label(&cfg.info());
248+
ui.label(&cfg.description);
240249
});
241250
}
251+
252+
if let Some(id) = remove_cfg {
253+
file.configurations.retain(|c| c.id != id);
254+
}
242255
});
243256
}
257+
258+
if let Some(title) = remove_file {
259+
state.recent_files.retain(|f| f.title != title);
260+
}
244261
});
245262
}
246263

264+
fn open_configuration(actions: &mut UiActions, cmd_tx: &Sender<HostCommand>, json: &String) {
265+
match serde_json::from_str::<StartSessionParam>(json) {
266+
Ok(param) => {
267+
let cmd = HostCommand::StartSession(Box::new(param));
268+
actions.try_send_command(cmd_tx, cmd);
269+
}
270+
Err(err) => {
271+
actions.add_notification(AppNotification::Error(err.to_string()));
272+
}
273+
}
274+
}
275+
247276
fn draw_favorite_folders(
248277
ui: &mut egui::Ui,
249278
actions: &mut UiActions,

application/apps/indexer/gui/application/src/host/ui/home/settings.rs

Lines changed: 10 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -34,69 +34,23 @@ impl HomeSettings {
3434
folder.scan_files();
3535
}
3636
}
37-
38-
pub fn with_test_data(mut self) -> HomeSettings {
39-
self.recent_files = vec![
40-
RecentFile {
41-
path: PathBuf::from("C:/Users/Example/Documents/file1.json"),
42-
last_opened: 1680000000,
43-
configurations: vec![
44-
FileConfiguration {
45-
name: "Default".to_string(),
46-
model: "Model A".to_string(),
47-
filter: "Filter X".to_string(),
48-
},
49-
FileConfiguration {
50-
name: "Custom".to_string(),
51-
model: "Model B".to_string(),
52-
filter: "Filter Y".to_string(),
53-
},
54-
],
55-
},
56-
RecentFile {
57-
path: PathBuf::from("C:/Users/Example/Documents/file2.json"),
58-
last_opened: 1685000000,
59-
configurations: vec![FileConfiguration {
60-
name: "Default".to_string(),
61-
model: "Model C".to_string(),
62-
filter: "Filter Z".to_string(),
63-
}],
64-
},
65-
];
66-
67-
self.favorite_folders = vec![
68-
FavoriteFolder {
69-
path: PathBuf::from("/Users/kevin.russ/EDF/_dlt"),
70-
files: vec![],
71-
},
72-
FavoriteFolder {
73-
path: PathBuf::from("/Users/kevin.russ/EDF/_mdf"),
74-
files: vec![],
75-
},
76-
];
77-
78-
self
79-
}
8037
}
8138

8239
#[derive(Serialize, Deserialize, Debug)]
8340
pub struct RecentFile {
84-
pub path: PathBuf,
41+
pub title: String,
8542
pub last_opened: u64,
86-
pub configurations: Vec<FileConfiguration>,
43+
pub configurations: Vec<SessionConfig>,
8744
}
8845

89-
#[derive(Serialize, Deserialize, Debug)]
90-
pub struct FileConfiguration {
91-
pub name: String,
92-
pub model: String,
93-
pub filter: String,
94-
}
95-
96-
impl FileConfiguration {
97-
pub fn info(&self) -> String {
98-
format!("{} - {}", self.model, self.filter) // TODO
99-
}
46+
#[derive(Serialize, Deserialize, Debug, Clone)]
47+
pub struct SessionConfig {
48+
/// Hash representing an unique config.
49+
pub id: String,
50+
/// Description of the config shown in UI.
51+
pub description: String,
52+
/// Serialized [StartSessionParam] of the config.
53+
pub json: String,
10054
}
10155

10256
#[derive(Serialize, Deserialize, Debug)]

application/apps/indexer/gui/application/src/host/ui/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ use state::HostState;
3232
pub use actions::{HostAction, UiActions};
3333

3434
pub mod actions;
35-
mod home;
35+
pub mod home;
3636
mod menu;
3737
pub mod multi_setup;
3838
mod notification;

application/apps/indexer/gui/application/src/host/ui/session_setup/state/parsers/dlt.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use rustc_hash::{FxHashMap, FxHashSet};
2+
use serde::{Deserialize, Serialize};
23
use std::{fmt::Display, path::PathBuf};
34
use stypes::{DltParserSettings, ObserveOrigin};
45

@@ -10,16 +11,20 @@ use super::FibexFileInfo;
1011
use crate::host::common::dlt_stats::{DltStatistics, LevelDistribution};
1112

1213
/// DLT Configurations to be used in front-end
13-
#[derive(Debug, Clone)]
14+
#[derive(Serialize, Deserialize, Debug, Clone)]
1415
pub struct DltParserConfig {
1516
pub with_storage_header: bool,
1617
pub log_level: DltLogLevel,
1718
pub source_paths: Option<Vec<PathBuf>>,
1819
pub fibex_files: Vec<FibexFileInfo>,
1920
pub timezone: Option<String>,
21+
#[serde(skip)]
2022
pub timezone_filter: String,
23+
#[serde(skip)]
2124
pub timezone_list: Vec<(String, i32)>,
25+
#[serde(skip)]
2226
pub dlt_statistics: Option<Box<DltStatistics>>,
27+
#[serde(skip)]
2328
pub dlt_summary: Box<DltSummary>,
2429
pub dlt_tables: Box<DltTables>,
2530
}
@@ -106,7 +111,7 @@ impl DltParserConfig {
106111
}
107112
}
108113

109-
#[derive(Debug, Clone, Default)]
114+
#[derive(Serialize, Deserialize, Debug, Clone, Default)]
110115
pub struct DltTables {
111116
pub app_table: TableConfig,
112117
pub ctx_table: TableConfig,
@@ -127,11 +132,14 @@ impl DltTables {
127132
}
128133
}
129134

130-
#[derive(Debug, Clone)]
135+
#[derive(Serialize, Deserialize, Debug, Clone)]
131136
pub struct TableConfig {
132137
pub selected_ids: FxHashSet<String>,
138+
#[serde(skip)]
133139
pub column_sort: Option<(usize, bool)>,
140+
#[serde(skip)]
134141
pub is_changed: bool,
142+
#[serde(skip)]
135143
pub is_collapsed: bool,
136144
}
137145

@@ -157,7 +165,7 @@ impl TableConfig {
157165
}
158166
}
159167

160-
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Ord, Eq)]
168+
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, PartialOrd, Ord, Eq)]
161169
pub enum DltLogLevel {
162170
Fatal = 1,
163171
Error = 2,

0 commit comments

Comments
 (0)