about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRicky Kresslein <rk@lakoliu.com>2022-09-24 00:34:54 +0200
committerRicky Kresslein <rk@lakoliu.com>2022-09-24 00:34:54 +0200
commit87c05770789958e6786e6490eb1fa25cd116b361 (patch)
tree959c6344c99a0f85657759fd21618dff2e9673a1
parent54e7ba5b16045d4e653f392d38f045a4f7183732 (diff)
downloadFurtherance-87c05770789958e6786e6490eb1fa25cd116b361.tar.zst
Ability to change database location - #29
-rwxr-xr-xdata/com.lakoliu.Furtherance.gschema.xml3
-rwxr-xr-xsrc/application.rs21
-rwxr-xr-xsrc/database.rs25
-rwxr-xr-xsrc/gtk/preferences_window.ui21
-rwxr-xr-xsrc/gtk/window.ui8
-rwxr-xr-xsrc/settings_manager.rs6
-rwxr-xr-xsrc/ui/history_box.rs2
-rwxr-xr-xsrc/ui/preferences_window.rs58
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();
+
+        }));
     }
 }