diff options
-rwxr-xr-x | data/com.lakoliu.Furtherance.gschema.xml | 3 | ||||
-rwxr-xr-x | src/application.rs | 21 | ||||
-rwxr-xr-x | src/database.rs | 25 | ||||
-rwxr-xr-x | src/gtk/preferences_window.ui | 21 | ||||
-rwxr-xr-x | src/gtk/window.ui | 8 | ||||
-rwxr-xr-x | src/settings_manager.rs | 6 | ||||
-rwxr-xr-x | src/ui/history_box.rs | 2 | ||||
-rwxr-xr-x | src/ui/preferences_window.rs | 58 |
8 files changed, 127 insertions, 17 deletions
diff --git a/data/com.lakoliu.Furtherance.gschema.xml b/data/com.lakoliu.Furtherance.gschema.xml index 880d4e4..615a6cf 100755 --- a/data/com.lakoliu.Furtherance.gschema.xml +++ b/data/com.lakoliu.Furtherance.gschema.xml @@ -40,5 +40,8 @@ <key name="autosave-time" type="i"> <default>5</default> </key> + <key name="database-loc" type="s"> + <default>"default"</default> + </key> </schema> </schemalist> diff --git a/src/application.rs b/src/application.rs index 1646a34..12ea49b 100755 --- a/src/application.rs +++ b/src/application.rs @@ -131,12 +131,6 @@ impl FurtheranceApplication { })); self.add_action(&about_action); - let backup_database_action = gio::SimpleAction::new("backup-database", None); - backup_database_action.connect_activate(clone!(@weak self as app => move |_, _| { - app.backup_database(); - })); - self.add_action(&backup_database_action); - let import_database_action = gio::SimpleAction::new("import-database", None); import_database_action.connect_activate(clone!(@weak self as app => move |_, _| { app.import_database(); @@ -275,6 +269,18 @@ impl FurtheranceApplication { } } + pub fn backup_database_enabled(&self, enabled: bool) { + if enabled { + let backup_database_action = gio::SimpleAction::new("backup-database", None); + backup_database_action.connect_activate(clone!(@weak self as app => move |_, _| { + app.backup_database(); + })); + self.add_action(&backup_database_action); + } else { + self.remove_action("backup-database"); + } + } + pub fn update_light_dark(&self) { let manager = adw::StyleManager::default(); @@ -332,7 +338,6 @@ impl FurtheranceApplication { } pub fn backup_database(&self) { - // TODO Disable if db is empty let window = self.active_window().unwrap(); let dialog = gtk::FileChooserDialog::new( Some(&gettext("Backup Database")), @@ -378,7 +383,7 @@ impl FurtheranceApplication { gtk::FileChooserAction::Open, &[ (&gettext("Cancel"), gtk::ResponseType::Reject), - (&gettext("Save"), gtk::ResponseType::Accept), + (&gettext("Open"), gtk::ResponseType::Accept), ] ); dialog.set_modal(true); diff --git a/src/database.rs b/src/database.rs index 1f7b762..589ff2d 100755 --- a/src/database.rs +++ b/src/database.rs @@ -27,6 +27,7 @@ use std::path::PathBuf; use std::time::Duration; use crate::ui::FurtheranceWindow; +use crate::settings_manager; #[derive(Clone, Debug, serde::Serialize, serde::Deserialize)] pub struct Task { @@ -121,12 +122,26 @@ impl TaskSort { } pub fn get_directory() -> PathBuf { - if let Some(proj_dirs) = ProjectDirs::from("com", "lakoliu", "Furtherance") { - let mut path = PathBuf::from(proj_dirs.data_dir()); - create_dir_all(path.clone()).expect("Unable to create database directory"); - path.extend(&["furtherance.db"]); - return path; + let dir_from_settings = settings_manager::get_string("database-loc"); + + if dir_from_settings != "default" && PathBuf::from(dir_from_settings.clone()).exists() { + return PathBuf::from(dir_from_settings); + } else { + if let Some(proj_dirs) = ProjectDirs::from("com", "lakoliu", "Furtherance") { + let mut path = PathBuf::from(proj_dirs.data_dir()); + create_dir_all(path.clone()).expect("Unable to create database directory"); + path.extend(&["furtherance.db"]); + + let path_str = path.to_string_lossy().to_string(); + if path_str != dir_from_settings { + let settings = settings_manager::get_settings(); + let _ = settings.set_string("database-loc", &path_str); + } + + return path; + } } + PathBuf::new() } diff --git a/src/gtk/preferences_window.ui b/src/gtk/preferences_window.ui index e6fd65b..168d614 100755 --- a/src/gtk/preferences_window.ui +++ b/src/gtk/preferences_window.ui @@ -206,6 +206,27 @@ </child> </object> </child> + <child> + <object class="AdwPreferencesGroup" id="database_group"> + <property name="title" translatable="yes">Database</property> + <property name="visible">True</property> + <child> + <object class="AdwActionRow" id="database_loc_row"> + <property name="title" translatable="yes">Database location</property> + <property name="subtitle" translatable="no">/location/</property> + <child> + <object class="GtkButton" id="database_browse_btn"> + <property name="valign">center</property> + <property name="label" translatable="yes">Browse</property> + <style> + <class name="flat"/> + </style> + </object> + </child> + </object> + </child> + </object> + </child> </object> </child> </template> diff --git a/src/gtk/window.ui b/src/gtk/window.ui index f11d3ef..b268ff7 100755 --- a/src/gtk/window.ui +++ b/src/gtk/window.ui @@ -93,10 +93,6 @@ <attribute name="label" translatable="yes">_Generate Report</attribute> <attribute name="action">app.report</attribute> </item> - <item> - <attribute name="label" translatable="yes">_Delete history</attribute> - <attribute name="action">app.delete-history</attribute> - </item> </section> <section> <item> @@ -111,6 +107,10 @@ <attribute name="label" translatable="yes">Import</attribute> <attribute name="action">app.import-database</attribute> </item> + <item> + <attribute name="label" translatable="yes">_Delete history</attribute> + <attribute name="action">app.delete-history</attribute> + </item> </section> <section> <item> diff --git a/src/settings_manager.rs b/src/settings_manager.rs index d6ff17d..18c341f 100755 --- a/src/settings_manager.rs +++ b/src/settings_manager.rs @@ -41,3 +41,9 @@ pub fn get_int(key: &str) -> i32 { let settings = get_settings(); settings.int(key) } + +#[allow(dead_code)] +pub fn get_string(key: &str) -> String { + let settings = get_settings(); + settings.string(key).to_string() +} diff --git a/src/ui/history_box.rs b/src/ui/history_box.rs index 510db07..b36808e 100755 --- a/src/ui/history_box.rs +++ b/src/ui/history_box.rs @@ -94,6 +94,7 @@ impl FurHistoryBox { let app = FurtheranceApplication::default(); app.delete_enabled(false); app.export_csv_enabled(false); + app.backup_database_enabled(false); imp.spinner.set_spinning(false); let name = match view { @@ -105,6 +106,7 @@ impl FurHistoryBox { View::Tasks => { app.delete_enabled(true); app.export_csv_enabled(true); + app.backup_database_enabled(true); "tasks" } }; diff --git a/src/ui/preferences_window.rs b/src/ui/preferences_window.rs index 188a478..6507ee3 100755 --- a/src/ui/preferences_window.rs +++ b/src/ui/preferences_window.rs @@ -16,6 +16,8 @@ use adw::prelude::*; use adw::subclass::prelude::*; +use gettextrs::*; +use glib::clone; use gtk::glib; use gtk::subclass::prelude::*; use gtk::CompositeTemplate; @@ -23,6 +25,7 @@ use gtk::CompositeTemplate; use crate::settings_manager; use crate::ui::FurtheranceWindow; use crate::FurtheranceApplication; +use crate::database; mod imp { use super::*; @@ -69,6 +72,11 @@ mod imp { pub autosave_expander: TemplateChild<adw::ExpanderRow>, #[template_child] pub autosave_spin: TemplateChild<gtk::SpinButton>, + + #[template_child] + pub database_loc_row: TemplateChild<adw::ActionRow>, + #[template_child] + pub database_browse_btn: TemplateChild<gtk::Button>, } #[glib::object_subclass] @@ -127,6 +135,9 @@ impl FurPreferencesWindow { let manager = adw::StyleManager::default(); let support_darkmode = manager.system_supports_color_schemes(); imp.appearance_group.set_visible(!support_darkmode); + + let db_dir = database::get_directory().to_string_lossy().to_string(); + imp.database_loc_row.set_subtitle(&db_dir); } fn setup_signals(&self) { @@ -211,5 +222,52 @@ impl FurPreferencesWindow { let window = FurtheranceWindow::default(); window.refresh_timer(); }); + + imp.database_browse_btn.connect_clicked(clone!(@weak self as this => move |_| { + let window = FurtheranceApplication::default().active_window().unwrap(); + let dialog = gtk::FileChooserDialog::new( + Some(&gettext("Backup Database")), + Some(&window), + gtk::FileChooserAction::Save, + &[ + (&gettext("Cancel"), gtk::ResponseType::Reject), + (&gettext("Save"), gtk::ResponseType::Accept), + ] + ); + dialog.set_modal(true); + + // Set a filter to show only SQLite files + let filter = gtk::FileFilter::new(); + gtk::FileFilter::set_name(&filter, Some("*.db")); + filter.add_mime_type("application/x-sqlite3"); + dialog.add_filter(&filter); + dialog.set_current_name("furtherance.db"); + + dialog.connect_response( + clone!(@strong dialog, @weak this as this2 => move |filechooser, resp| { + if resp == gtk::ResponseType::Accept { + if let Some(path) = filechooser.file().and_then(|file| file.path()) { + let path = &path.to_string_lossy(); + let _bkup = database::backup_db(path.to_string()); + + let settings = settings_manager::get_settings(); + let _ = settings.set_string("database-loc", &path.to_string()); + + let imp2 = imp::FurPreferencesWindow::from_instance(&this2); + imp2.database_loc_row.set_subtitle(&path.to_string()); + + let window = FurtheranceWindow::default(); + window.reset_history_box(); + } + dialog.close(); + } else { + dialog.close(); + } + }), + ); + + dialog.show(); + + })); } } |