ferrix_app/
pages.rs

1/* pages.rs
2 *
3 * Copyright 2025 Michail Krasnov <mskrasnov07@ya.ru>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
17 *
18 * SPDX-License-Identifier: GPL-3.0-or-later
19 */
20
21//! Pages with information about hardware and software
22
23use iced::{
24    Alignment::{self, Center},
25    Element,
26    widget::{center, column, container, row, rule, svg::Handle, text},
27};
28
29use crate::{
30    Ferrix, Message, fl,
31    icons::ERROR_ICON,
32    widgets::{header_text, link_button},
33};
34
35mod battery;
36mod cpu;
37mod cpu_freq;
38mod dashboard;
39mod distro;
40mod dmi;
41mod drm;
42mod env;
43mod export;
44mod groups;
45mod kernel;
46mod ram;
47mod settings;
48mod soft;
49mod storage;
50mod sysmon;
51mod system;
52mod systemd;
53mod users;
54mod vulnerabilities;
55
56pub use sysmon::*;
57
58#[derive(Debug, Clone, Copy, Default, Eq, PartialEq)]
59pub enum Page {
60    /************************************
61     *       Hardware & dashboard       *
62     ************************************/
63    #[default]
64    Dashboard,
65    Processors,
66    CPUFrequency,
67    CPUVulnerabilities,
68    SystemMonitor,
69    Memory,
70    FileSystems,
71    DMI,
72    Battery,
73    Screen,
74
75    /************************************
76     *          Administration          *
77     ************************************/
78    Distro,
79    SystemMisc,
80    Users,
81    Groups,
82    SystemManager,
83    Software,
84    Environment,
85    Sensors,
86
87    /************************************
88     *               Kernel             *
89     ************************************/
90    Kernel,
91    KModules,
92    Development,
93
94    /************************************
95     *              Service             *
96     ************************************/
97    Settings,
98    About,
99    Export,
100    Todo,
101}
102
103impl From<&str> for Page {
104    fn from(value: &str) -> Self {
105        match value {
106            "dash" | "dashboard" => Self::Dashboard,
107            "sysmon" | "monitor" | "system" | "system-monitor" => Self::SystemMonitor,
108            "proc" | "cpu" | "processors" => Self::Processors,
109            "cpu-frequency" | "cpufreq" => Self::CPUFrequency,
110            "cpu-vuln" | "vulnerabilities" => Self::CPUVulnerabilities,
111            "memory" | "mem" | "ram" => Self::Memory,
112            "storage" => Self::FileSystems,
113            "dmi" => Self::DMI,
114            "battery" | "bat" => Self::Battery,
115            "edid" | "screen" => Self::Screen,
116            "distro" => Self::Distro,
117            "users" => Self::Users,
118            "groups" => Self::Groups,
119            "misc" => Self::SystemMisc,
120            "systemd" => Self::SystemManager,
121            "software" | "soft" | "pkg" | "pkgs" => Self::Software,
122            "env" => Self::Environment,
123            "sensors" => Self::Sensors,
124            "kernel" | "linux" => Self::Kernel,
125            "kmods" | "mod" | "modules" => Self::KModules,
126            "dev" => Self::Development,
127            "settings" => Self::Settings,
128            "about" | "version" | "--version" | "-V" | "-v" => {
129                println!("FSM (Ferrix System Monitor) v{}", env!("CARGO_PKG_VERSION"));
130
131                eprintln!(" *** If you are from Russia, you can send me a donation:");
132                eprintln!("     2202 2062 5233 5406\n Thank you!");
133
134                Self::About
135            }
136            "export" => Self::Export,
137            _ => {
138                eprintln!("ERROR: Unknown page name: \"{value}\"!\n");
139                eprintln!(" *** If you are from Russia, you can send me a donation:");
140                eprintln!("     2202 2062 5233 5406\n Thank you!");
141
142                Self::default()
143            }
144        }
145    }
146}
147
148impl<'a> Page {
149    pub fn title(&'a self) -> iced::widget::Column<'a, Message> {
150        header_text(self.title_str())
151    }
152
153    pub fn title_str(&self) -> String {
154        match self {
155            Self::Dashboard => fl!("page-dashboard"),
156            Self::Processors => fl!("page-procs"),
157            Self::CPUFrequency => fl!("page-cpufreq"),
158            Self::CPUVulnerabilities => fl!("page-vuln"),
159            Self::SystemMonitor => fl!("page-sysmon"),
160            Self::Memory => fl!("page-memory"),
161            Self::FileSystems => fl!("page-fsystems"),
162            Self::DMI => fl!("page-dmi"),
163            Self::Battery => fl!("page-battery"),
164            Self::Screen => fl!("page-screen"),
165            Self::Distro => fl!("page-distro"),
166            Self::Users => fl!("page-users"),
167            Self::Groups => fl!("page-groups"),
168            Self::SystemManager => fl!("page-sysmgr"),
169            Self::Software => fl!("page-software"),
170            Self::Environment => fl!("page-env"),
171            Self::Sensors => fl!("page-sensors"),
172            Self::Kernel => fl!("page-kernel"),
173            Self::KModules => fl!("page-kmods"),
174            Self::Development => fl!("page-dev"),
175            Self::SystemMisc => fl!("page-sysmisc"),
176            Self::Settings => fl!("page-settings"),
177            Self::About => fl!("page-about"),
178            Self::Export => fl!("page-export"),
179            Self::Todo => fl!("page-todo"),
180        }
181    }
182
183    pub fn page(&'a self, state: &'a Ferrix) -> Element<'a, Message> {
184        let page = match self {
185            Self::Dashboard => dashboard::dashboard(state).into(),
186            Self::SystemMonitor => {
187                sysmon::usage_charts_page(&state, &state.curr_proc_stat, &state.prev_proc_stat)
188                    .into()
189            }
190            Self::Processors => cpu::proc_page(&state.proc_data).into(),
191            Self::CPUFrequency => cpu_freq::cpu_freq_page(&state.cpu_freq).into(),
192            Self::CPUVulnerabilities => {
193                vulnerabilities::vulnerabilities_page(&state.cpu_vulnerabilities).into()
194            }
195            Self::Memory => ram::ram_page(&state.ram_data, &state.swap_data).into(),
196            Self::FileSystems => storage::storage_page(&state.storages).into(),
197            Self::DMI => dmi::dmi_page(&state.dmi_data).into(),
198            Self::Battery => battery::bat_page(&state.bat_data).into(),
199            Self::Screen => drm::drm_page(&state.drm_data).into(),
200            Self::Distro => distro::distro_page(&state.osrel_data).into(),
201            Self::Kernel => kernel::kernel_page(&state.kernel_data).into(),
202            Self::KModules => kernel::kmods_page(&state.kmods_data).into(),
203            Self::SystemMisc => system::system_page(&state.system).into(),
204            Self::Users => users::users_page(&state.users_list).into(),
205            Self::Groups => groups::groups_page(&state.groups_list).into(),
206            Self::SystemManager => systemd::services_page(&state.sysd_services_list).into(),
207            Self::Software => soft::soft_page(&state.installed_pkgs_list).into(),
208            Self::Environment => env::env_page(&state.system).into(),
209            Self::Settings => settings::settings_page(&state).into(),
210            Self::Export => export::export_page().into(),
211            Self::About => self.about_page().into(),
212            _ => self.todo_page(),
213        };
214
215        column![self.title(), page,].spacing(5).into()
216    }
217
218    fn todo_page(&self) -> Element<'a, Message> {
219        container(center(
220            text(fl!("page-todo-msg")).size(16).style(text::secondary),
221        ))
222        .into()
223    }
224
225    fn about_page(&'a self) -> container::Container<'a, Message> {
226        let img = iced::widget::svg("/usr/share/Ferrix/com.mskrasnov.Ferrix.svg")
227            .width(128)
228            .height(128);
229        let header = row![
230            img,
231            column![
232                text(fl!("about-hdr")).size(24),
233                text(format!(
234                    "{}: {}, {}: {}",
235                    fl!("about-ferrix"),
236                    env!("CARGO_PKG_VERSION"),
237                    fl!("about-flib"),
238                    ferrix_lib::FX_LIB_VERSION,
239                ))
240                .size(14),
241            ]
242            .spacing(5),
243        ]
244        .align_y(Center)
245        .spacing(5);
246
247        let about_info = row![
248            column![
249                text(fl!("about-author-hdr")).style(text::secondary),
250                text(fl!("about-feedback-hdr")).style(text::secondary),
251                text(fl!("about-source-hdr")).style(text::secondary),
252                text("crates.io:").style(text::secondary),
253                text(fl!("about-blog")).style(text::secondary),
254            ]
255            .align_x(Alignment::End)
256            .spacing(3),
257            column![
258                row![
259                    text(fl!("about-author")),
260                    link_button("(GitHub)", "https://github.com/mskrasnov"),
261                ]
262                .spacing(5),
263                link_button("mskrasnov07 at ya dot ru", "mailto:mskrasnov07@ya.ru"),
264                link_button("GitHub", "https://github.com/mskrasnov/Ferrix"),
265                row![
266                    link_button("ferrix-app", "https://crates.io/crates/ferrix-app"),
267                    text(", "),
268                    link_button("ferrix-lib", "https://crates.io/crates/ferrix-lib"),
269                ],
270                link_button("mskrasnov", "https://boosty.to/mskrasnov"),
271            ]
272            .spacing(3),
273        ]
274        .spacing(5);
275
276        let donate = column![
277            text(fl!("about-donate")),
278            link_button(fl!("about-donate-lbl"), "https://boosty.to/mskrasnov"),
279        ]
280        .spacing(5);
281
282        let contents = column![
283            column![header, rule::horizontal(1)].spacing(2),
284            about_info,
285            row![
286                text(fl!("about-support")).style(text::warning).size(16),
287                rule::horizontal(1)
288            ]
289            .align_y(Center)
290            .spacing(5),
291            donate,
292        ]
293        .spacing(5);
294
295        container(contents)
296    }
297}
298
299fn loading_page<'a>() -> container::Container<'a, Message> {
300    container(center(
301        text(fl!("ldr-page-tooltip"))
302            .style(text::secondary)
303            .size(14),
304    ))
305}
306
307fn error_page<'a>(etext: &'a str) -> container::Container<'a, Message> {
308    container(center(
309        column![
310            row![
311                iced::widget::svg(Handle::from_memory(ERROR_ICON))
312                    .width(20)
313                    .height(20),
314                text(fl!("err-page-tooltip")).size(20),
315            ]
316            .align_y(Center)
317            .spacing(5),
318            text(etext).style(text::secondary).size(14),
319        ]
320        .align_x(Center)
321        .spacing(5),
322    ))
323}