diff --git a/Cargo.toml b/Cargo.toml index d953158..600532b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ lto = true [dependencies] gettext-rs = { version = "0.7", features = ["gettext-system"] } -gtk = { version = "0.7", package = "gtk4", features = ["v4_10"] } +gtk = { version = "0.7", package = "gtk4", features = ["v4_12"] } tracing = "0.1.37" tracing-subscriber = "0.3" reqwest = { version = "0.11", features = ["json", "blocking"] } diff --git a/data/dev.mnts.ModManager.gschema.xml.in b/data/dev.mnts.ModManager.gschema.xml.in index 7a38785..cb3182f 100644 --- a/data/dev.mnts.ModManager.gschema.xml.in +++ b/data/dev.mnts.ModManager.gschema.xml.in @@ -13,10 +13,9 @@ false Window maximized state - - {} - Dictionary of games being managed. First string is game name second is path to mods - folder. + + [] + Games \ No newline at end of file diff --git a/data/resources/ui/windows/main/pages/games_and_mods.blp b/data/resources/ui/windows/main/pages/games_and_mods.blp index 496fe8a..346eb9b 100644 --- a/data/resources/ui/windows/main/pages/games_and_mods.blp +++ b/data/resources/ui/windows/main/pages/games_and_mods.blp @@ -10,18 +10,14 @@ template $GamesAndMods: Adw.Bin { Adw.ToolbarView { [top] Adw.HeaderBar { + [end] + Button add_new_game { + label: "Add game"; + } } - content: Box { - Label { - label: "The Sims 4"; - } - Label { - label: "The Sims 3"; - } - Label { - label: "The Sims 2"; - } + content: ListBox games_list { + styles ["navigation-sidebar"] }; } }; @@ -32,12 +28,18 @@ template $GamesAndMods: Adw.Bin { Adw.ToolbarView { [top] Adw.HeaderBar { + [title] + SearchEntry search { + } } content: Box { Label { label: "Mods"; } + Button remove_all_games { + label: "Remove all games"; + } }; } }; diff --git a/src/application.rs b/src/application.rs index e3abe65..59ce71f 100644 --- a/src/application.rs +++ b/src/application.rs @@ -25,11 +25,16 @@ use tracing::{debug, info}; use crate::config::VERSION; use crate::config::{APP_ID, PKGDATADIR, PROFILE}; +use crate::settings::ModManagerSettings; use crate::windows::main::ModManagerWindowMain; use crate::windows::main::Welcome; mod imp { + use games_and_mods::GamesAndMods; + + use crate::windows::games_and_mods; + use super::*; #[derive(Debug, Default)] @@ -47,14 +52,6 @@ mod imp { self.parent_constructed(); let obj = self.obj(); obj.set_accels_for_action("app.quit", &["q"]); - - //let settings = ModManagerSettings::default(); - // let games = settings.games(); - - //let settings = gio::Settings::new(APP_ID); - //let games = settings.string("games"); - - //println!("Games: {:?}", games); } } @@ -70,9 +67,7 @@ mod imp { let window = if let Some(window) = application.active_window() { window } else { - // TODO: Figure our if show welcome or games_and_mods. - let welcome = Welcome::new(); - let window = ModManagerWindowMain::new(&*application, &welcome.upcast()); + let window = ModManagerWindowMain::new(&*application); window.upcast() }; diff --git a/src/main.rs b/src/main.rs index 4258ff9..65c9847 100644 --- a/src/main.rs +++ b/src/main.rs @@ -19,13 +19,13 @@ mod api; mod application; mod components; mod config; +mod settings; mod windows; use self::application::ModManagerApplication; use config::{GETTEXT_PACKAGE, LOCALEDIR, RESOURCES_FILE}; use gettextrs::{gettext, LocaleCategory}; -use gtk::prelude::*; use gtk::{gio, glib}; fn main() -> glib::ExitCode { diff --git a/src/mods_list.rs b/src/mods_list.rs deleted file mode 100644 index e8f6f08..0000000 --- a/src/mods_list.rs +++ /dev/null @@ -1,66 +0,0 @@ -/* welcome.rs - * - * Copyright 2023 Tine - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -use adw::subclass::prelude::*; -use gtk::{gio, glib}; -use gtk::{glib::clone, prelude::*}; - -mod imp { - use super::*; - - #[derive(Debug, Default, gtk::CompositeTemplate)] - #[template(resource = "/dev/mnts/ModManager/components/mods_list.ui")] - pub struct ModsList { - } - - #[glib::object_subclass] - impl ObjectSubclass for ModsList { - const NAME: &'static str = "ModsList"; - type Type = super::ModsList; - type ParentType = adw::NavigationPage; - - fn class_init(klass: &mut Self::Class) { - klass.bind_template(); - } - - fn instance_init(obj: &glib::subclass::InitializingObject) { - obj.init_template(); - } - } - - impl ObjectImpl for ModsList { - fn constructed(&self) { - } - } - impl WidgetImpl for ModsList {} - impl NavigationPageImpl for ModsList {} -} - -glib::wrapper! { - pub struct ModsList(ObjectSubclass) - @extends gtk::Widget, gtk::Buildable, adw::NavigationPage, - @implements gio::ActionGroup, gio::ActionMap; -} - -impl ModsList { - pub fn new() -> Self { - glib::Object::builder().build() - } -} diff --git a/src/settings.rs b/src/settings.rs index 9a23c3c..00d46f0 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -6,11 +6,6 @@ use std::collections::HashMap; use crate::config::APP_ID; #[gen_settings(file = "./data/dev.mnts.ModManager.gschema.xml.in")] -#[gen_settings_define( - key_name = "games", - arg_type = "HashMap", - ret_type = "HashMap" -)] pub struct ModManagerSettings; impl Default for ModManagerSettings { diff --git a/src/windows/add_new_game/add_new_game.rs b/src/windows/add_new_game/add_new_game.rs index ab996c7..e035ca7 100644 --- a/src/windows/add_new_game/add_new_game.rs +++ b/src/windows/add_new_game/add_new_game.rs @@ -20,10 +20,12 @@ use adw::subclass::prelude::*; use glib::clone; +use gtk::glib::subclass::types::FromObject; use gtk::prelude::*; use gtk::{gio, glib}; use crate::api::*; +use crate::settings::ModManagerSettings; mod imp { use super::*; @@ -71,26 +73,43 @@ impl ModManagerWindowAddNewGame { glib::Object::builder().build() } + pub fn show() -> Self { + let welcome = ModManagerWindowAddNewGame::new(); + welcome.setup(); + welcome.set_modal(true); + welcome.present(); + + return welcome; + } + pub fn setup(&self) { let games = games::get_games(); let games_strs: Vec<&str> = games.iter().map(|s| s.as_str()).collect(); let games_list = >k::StringList::new(&games_strs); - let complete_button = &imp::ModManagerWindowAddNewGame::from_obj(self).complete_button; - let games_dropdown = &imp::ModManagerWindowAddNewGame::from_obj(self).games_dropdown; + let obj = self.imp(); - games_dropdown.set_property("model", games_list); + obj.games_dropdown.set_property("model", games_list); let instance = self; - complete_button.connect_clicked(clone!(@strong instance => move |_| { - //let selected_game = games_dropdown.selected_item(); + obj.complete_button + .connect_clicked(clone!(@strong instance, @strong games_list => move |_| { + //let selected_game = games_dropdown.selected_item(); - println!("complete button clicked"); + let settings = ModManagerSettings::default(); + let game_selected = games_list.string(instance.imp().games_dropdown.selected()).unwrap().to_string(); + println!("complete button clicked, selected game: {:?}", &game_selected); - //if let Some(selected_game) = selected_game { - instance.hide() - //} - })); + let mut selected = settings.games().to_vec(); + selected.push(game_selected); + + settings.set_strv("games", selected); + + + //if let Some(selected_game) = selected_game { + instance.hide() + //} + })); } } diff --git a/src/windows/main/main.rs b/src/windows/main/main.rs index 0eab520..89b3406 100644 --- a/src/windows/main/main.rs +++ b/src/windows/main/main.rs @@ -18,11 +18,18 @@ along with this program. If not, see . use adw::subclass::prelude::*; use gtk::prelude::*; use gtk::{gio, glib}; +use tracing::{debug, info}; use crate::config::PROFILE; +use crate::settings::ModManagerSettings; +use crate::windows::GamesAndMods; + +use super::Welcome; mod imp { + use gtk::glib::clone; + use super::*; #[derive(Debug, Default, gtk::CompositeTemplate)] @@ -53,6 +60,27 @@ mod imp { if PROFILE == "Devel" { obj.add_css_class("devel"); } + + let settings = ModManagerSettings::default(); + settings.connect_games_changed(clone!(@strong obj, @strong settings => move |_| { + info!("Games changed, deciding on initial page."); + + let page: gtk::Widget = if settings.games().len() > 0 { + GamesAndMods::new().upcast() + } else { + Welcome::new().upcast() + }; + + obj.set_property("content", page); + })); + + let page: gtk::Widget = if settings.games().len() > 0 { + GamesAndMods::new().upcast() + } else { + Welcome::new().upcast() + }; + + obj.set_property("content", page) } } @@ -69,10 +97,9 @@ glib::wrapper! { } impl ModManagerWindowMain { - pub fn new>(application: &P, content: >k::Widget) -> Self { + pub fn new>(application: &P) -> Self { glib::Object::builder() .property("application", application) - .property("content", content) .build() } } diff --git a/src/windows/main/pages/games_and_mods.rs b/src/windows/main/pages/games_and_mods.rs index 33d747d..18c0d23 100644 --- a/src/windows/main/pages/games_and_mods.rs +++ b/src/windows/main/pages/games_and_mods.rs @@ -21,11 +21,26 @@ use gtk::{gio, glib}; mod imp { + use adw::prelude::PreferencesRowExt; + use gtk::glib::clone; + use tracing::info; + + use crate::{api::games, settings::ModManagerSettings, windows::ModManagerWindowAddNewGame}; + use super::*; #[derive(Debug, Default, gtk::CompositeTemplate)] #[template(resource = "/dev/mnts/ModManager/ui/windows/main/pages/games_and_mods.ui")] - pub struct GamesAndMods {} + pub struct GamesAndMods { + #[template_child] + pub add_new_game: TemplateChild, + + #[template_child] + pub remove_all_games: TemplateChild, + + #[template_child] + pub games_list: TemplateChild, + } #[glib::object_subclass] impl ObjectSubclass for GamesAndMods { @@ -42,7 +57,42 @@ mod imp { } } - impl ObjectImpl for GamesAndMods {} + impl ObjectImpl for GamesAndMods { + fn constructed(&self) { + self.parent_constructed(); + let obj = self.obj(); + + self.remove_all_games.connect_clicked(|_| { + let settings = ModManagerSettings::default(); + settings.set_games(&[]); + println!("Remove all games button clicked"); + }); + + self.add_new_game.connect_clicked(|_| { + ModManagerWindowAddNewGame::show(); + }); + + let settings = ModManagerSettings::default(); + + for game in settings.games() { + info!("Adding game {} to list", game); + let row = adw::ActionRow::new(); + row.set_title(&game); + obj.imp().games_list.append(&row); + } + + settings.connect_games_changed(clone!(@weak obj, @strong settings => move |_| { + info!("Games changed, modifying list"); + obj.imp().games_list.remove_all(); + for game in settings.games() { + info!("Adding game {} to list", game); + let row = adw::ActionRow::new(); + row.set_title(&game); + obj.imp().games_list.append(&row); + } + })); + } + } impl WidgetImpl for GamesAndMods {} impl BinImpl for GamesAndMods {} } diff --git a/src/windows/main/pages/welcome.rs b/src/windows/main/pages/welcome.rs index 2ed9f4a..2dc1784 100644 --- a/src/windows/main/pages/welcome.rs +++ b/src/windows/main/pages/welcome.rs @@ -52,10 +52,7 @@ mod imp { self.parent_constructed(); self.add_new_game.connect_clicked(|_| { - let welcome = ModManagerWindowAddNewGame::new(); - welcome.setup(); - welcome.set_modal(true); - welcome.present(); + ModManagerWindowAddNewGame::show(); }); } }