diff options
author | Ricky Kresslein <rk@lakoliu.com> | 2022-09-22 21:28:50 +0200 |
---|---|---|
committer | Ricky Kresslein <rk@lakoliu.com> | 2022-09-22 21:28:50 +0200 |
commit | 83e992c2077a4fb5281a461c74fc6f7265a24bde (patch) | |
tree | 8f7199a9bf49fb41defd0c61e7d4fb307a74da30 | |
parent | e72813df2bb343ec4ce683baa7af2befc1ae6f80 (diff) | |
download | Furtherance-83e992c2077a4fb5281a461c74fc6f7265a24bde.tar.zst |
Backup database
-rw-r--r-- | Cargo.lock | 17 | ||||
-rwxr-xr-x | Cargo.toml | 2 | ||||
-rwxr-xr-x | src/application.rs | 44 | ||||
-rwxr-xr-x | src/database.rs | 10 | ||||
-rwxr-xr-x | src/gtk/window.ui | 14 |
5 files changed, 72 insertions, 15 deletions
diff --git a/Cargo.lock b/Cargo.lock index 7006d82..496cb94 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -647,18 +647,18 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.11.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" dependencies = [ "ahash", ] [[package]] name = "hashlink" -version = "0.7.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7249a3129cbc1ffccd74857f81464a323a152173cdb134e0fd81bc803b29facf" +checksum = "69fe1fcf8b4278d860ad0548329f892a3631fb63f82574df68275f34cdbe0ffa" dependencies = [ "hashbrown", ] @@ -777,9 +777,9 @@ dependencies = [ [[package]] name = "libsqlite3-sys" -version = "0.24.2" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "898745e570c7d0453cc1fbc4a701eb6c662ed54e8fec8b7d14be137ebeeb9d14" +checksum = "9f0455f2c1bc9a7caa792907026e469c1d91761fb0ea37cbb16427c77280cf35" dependencies = [ "pkg-config", "vcpkg", @@ -1062,16 +1062,15 @@ checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" [[package]] name = "rusqlite" -version = "0.27.0" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85127183a999f7db96d1a976a309eebbfb6ea3b0b400ddd8340190129de6eb7a" +checksum = "01e213bc3ecb39ac32e81e51ebe31fd888a940515173e3a18a35f8c6e896422a" dependencies = [ "bitflags", "fallible-iterator", "fallible-streaming-iterator", "hashlink", "libsqlite3-sys", - "memchr", "smallvec", ] diff --git a/Cargo.toml b/Cargo.toml index d2a7987..bf0b557 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ log = "0.4" num-derive = "0.3.3" num-traits = "0.2.14" once_cell = "1.12.0" -rusqlite = "0.27.0" +rusqlite = { version = "0.28.0", features = ["backup"] } serde = { version = "1.0", features = ["derive"] } [dependencies.gtk] diff --git a/src/application.rs b/src/application.rs index bfa53e2..b0972ec 100755 --- a/src/application.rs +++ b/src/application.rs @@ -131,6 +131,12 @@ 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 discard_idle_action = gio::SimpleAction::new("discard-idle-action", None); discard_idle_action.connect_activate(clone!(@weak self as app => move |_, _| { let window = FurtheranceWindow::default(); @@ -318,6 +324,44 @@ impl FurtheranceApplication { self.withdraw_notification("idle"); self.send_notification(Some("pomodoro"), ¬ification); } + + pub fn backup_database(&self) { + let window = self.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_bkup.db"); + + dialog.connect_response( + clone!(@strong dialog, @weak self as this => 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()); + } + dialog.close(); + } else { + dialog.close(); + } + }), + ); + + dialog.show(); + + } } impl Default for FurtheranceApplication { diff --git a/src/database.rs b/src/database.rs index 6c2649c..090814e 100755 --- a/src/database.rs +++ b/src/database.rs @@ -16,10 +16,11 @@ use chrono::{DateTime, Local}; use directories::ProjectDirs; -use rusqlite::{Connection, Result}; +use rusqlite::{Connection, Result, backup}; use std::convert::TryFrom; use std::fs::create_dir_all; use std::path::PathBuf; +use std::time::Duration; #[derive(Clone, Debug, serde::Serialize, serde::Deserialize)] pub struct Task { @@ -337,3 +338,10 @@ pub fn delete_all() -> Result<()> { Ok(()) } + +pub fn backup_db(backup_file: String) -> Result<()> { + let mut bkup_conn = Connection::open(backup_file)?; + let conn = Connection::open(get_directory())?; + let backup = backup::Backup::new(&conn, &mut bkup_conn)?; + backup.run_to_completion(5, Duration::from_millis(250), None) +} diff --git a/src/gtk/window.ui b/src/gtk/window.ui index ed18063..87317d9 100755 --- a/src/gtk/window.ui +++ b/src/gtk/window.ui @@ -94,16 +94,22 @@ <attribute name="action">app.report</attribute> </item> <item> - <attribute name="label" translatable="yes">_Export as CSV</attribute> - <attribute name="action">app.export-csv</attribute> - </item> - <item> <attribute name="label" translatable="yes">_Delete history</attribute> <attribute name="action">app.delete-history</attribute> </item> </section> <section> <item> + <attribute name="label" translatable="yes">Back up</attribute> + <attribute name="action">app.backup-database</attribute> + </item> + <item> + <attribute name="label" translatable="yes">_Export as CSV</attribute> + <attribute name="action">app.export-csv</attribute> + </item> + </section> + <section> + <item> <attribute name="label" translatable="yes">_Preferences</attribute> <attribute name="action">app.preferences</attribute> </item> |