|
|
@@ -0,0 +1,166 @@
|
|
|
+#include "MainWindow.hpp"
|
|
|
+#include <iostream>
|
|
|
+#include <filesystem>
|
|
|
+#include <archive.h>
|
|
|
+#include <archive_entry.h>
|
|
|
+#include <fcntl.h>
|
|
|
+#include <unistd.h>
|
|
|
+#include <cstdlib>
|
|
|
+
|
|
|
+namespace fs = std::filesystem;
|
|
|
+
|
|
|
+MainWindow::MainWindow()
|
|
|
+: m_MainLayout(Gtk::ORIENTATION_VERTICAL, 0),
|
|
|
+ m_VBoxBackup(Gtk::ORIENTATION_VERTICAL, 15),
|
|
|
+ m_LabelBackupInstruction("<span size='large' weight='bold'>Select what to backup:</span>"),
|
|
|
+ m_CheckThemesBackup("GTK Themes (~/.themes)"),
|
|
|
+ m_CheckIconsBackup("Icons (~/.icons)"),
|
|
|
+ m_CheckDconfBackup("GNOME Settings (dconf dump)"),
|
|
|
+ m_ButtonBackup("Start Backup"),
|
|
|
+ m_VBoxRestore(Gtk::ORIENTATION_VERTICAL, 15),
|
|
|
+ m_LabelRestoreInstruction("<span size='large' weight='bold'>Select what to restore:</span>"),
|
|
|
+ m_CheckThemesRestore("GTK Themes"),
|
|
|
+ m_CheckIconsRestore("Icons"),
|
|
|
+ m_CheckDconfRestore("GNOME Settings"),
|
|
|
+ m_ButtonRestore("Start Restore")
|
|
|
+{
|
|
|
+ // --- Force Dark Theme ---
|
|
|
+ auto settings = Gtk::Settings::get_default();
|
|
|
+ if (settings) {
|
|
|
+ settings->property_gtk_application_prefer_dark_theme() = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ set_default_size(550, 450);
|
|
|
+ set_border_width(0); // Removing window border to let layout handle it
|
|
|
+
|
|
|
+ // --- HeaderBar Setup (Modern GNOME look) ---
|
|
|
+ m_HeaderBar.set_title("Gnome-Vault");
|
|
|
+ m_HeaderBar.set_subtitle("System State Manager");
|
|
|
+ m_HeaderBar.set_show_close_button(true);
|
|
|
+ set_titlebar(m_HeaderBar);
|
|
|
+
|
|
|
+ // Allow markup in the instruction labels
|
|
|
+ m_LabelBackupInstruction.set_use_markup(true);
|
|
|
+ m_LabelBackupInstruction.set_halign(Gtk::ALIGN_START);
|
|
|
+ m_LabelRestoreInstruction.set_use_markup(true);
|
|
|
+ m_LabelRestoreInstruction.set_halign(Gtk::ALIGN_START);
|
|
|
+
|
|
|
+ // --- Backup Page Setup ---
|
|
|
+ m_VBoxBackup.set_border_width(20);
|
|
|
+ m_VBoxBackup.pack_start(m_LabelBackupInstruction, Gtk::PACK_SHRINK);
|
|
|
+ m_VBoxBackup.pack_start(m_CheckThemesBackup, Gtk::PACK_SHRINK);
|
|
|
+ m_VBoxBackup.pack_start(m_CheckIconsBackup, Gtk::PACK_SHRINK);
|
|
|
+ m_VBoxBackup.pack_start(m_CheckDconfBackup, Gtk::PACK_SHRINK);
|
|
|
+
|
|
|
+ m_CheckThemesBackup.set_active(true);
|
|
|
+
|
|
|
+ // Make the button chunkier
|
|
|
+ m_ButtonBackup.set_size_request(-1, 45);
|
|
|
+ m_ButtonBackup.signal_clicked().connect(sigc::mem_fun(*this, &MainWindow::on_button_backup_clicked));
|
|
|
+ m_VBoxBackup.pack_end(m_ButtonBackup, Gtk::PACK_SHRINK);
|
|
|
+
|
|
|
+ // --- Restore Page Setup ---
|
|
|
+ m_VBoxRestore.set_border_width(20);
|
|
|
+ m_VBoxRestore.pack_start(m_LabelRestoreInstruction, Gtk::PACK_SHRINK);
|
|
|
+ m_VBoxRestore.pack_start(m_CheckThemesRestore, Gtk::PACK_SHRINK);
|
|
|
+ m_VBoxRestore.pack_start(m_CheckIconsRestore, Gtk::PACK_SHRINK);
|
|
|
+ m_VBoxRestore.pack_start(m_CheckDconfRestore, Gtk::PACK_SHRINK);
|
|
|
+
|
|
|
+ m_ButtonRestore.set_size_request(-1, 45);
|
|
|
+ m_ButtonRestore.signal_clicked().connect(sigc::mem_fun(*this, &MainWindow::on_button_restore_clicked));
|
|
|
+ m_VBoxRestore.pack_end(m_ButtonRestore, Gtk::PACK_SHRINK);
|
|
|
+
|
|
|
+ // --- Notebook (Tabs) Setup ---
|
|
|
+ m_Notebook.append_page(m_VBoxBackup, "Backup");
|
|
|
+ m_Notebook.append_page(m_VBoxRestore, "Restore");
|
|
|
+
|
|
|
+ // --- Status Label Setup ---
|
|
|
+ m_StatusLabel.set_text("Ready.");
|
|
|
+ m_StatusLabel.set_halign(Gtk::ALIGN_START);
|
|
|
+ m_StatusLabel.set_margin_top(10);
|
|
|
+ m_StatusLabel.set_margin_bottom(10);
|
|
|
+ m_StatusLabel.set_margin_start(10);
|
|
|
+
|
|
|
+ // --- Main Layout Assembly ---
|
|
|
+ m_MainLayout.pack_start(m_Notebook, Gtk::PACK_EXPAND_WIDGET);
|
|
|
+ m_MainLayout.pack_end(m_StatusLabel, Gtk::PACK_SHRINK);
|
|
|
+
|
|
|
+ add(m_MainLayout);
|
|
|
+ show_all_children();
|
|
|
+}
|
|
|
+
|
|
|
+MainWindow::~MainWindow() {}
|
|
|
+
|
|
|
+bool MainWindow::create_tar_archive(const std::string& source_dir, const std::string& out_filename) {
|
|
|
+ struct archive *a;
|
|
|
+ struct archive *disk;
|
|
|
+ struct archive_entry *entry;
|
|
|
+ char buff[8192];
|
|
|
+ int len;
|
|
|
+ int fd;
|
|
|
+
|
|
|
+ a = archive_write_new();
|
|
|
+ archive_write_add_filter_gzip(a);
|
|
|
+ archive_write_set_format_pax_restricted(a);
|
|
|
+ archive_write_open_filename(a, out_filename.c_str());
|
|
|
+
|
|
|
+ disk = archive_read_disk_new();
|
|
|
+ archive_read_disk_set_standard_lookup(disk);
|
|
|
+
|
|
|
+ for (const auto& dirEntry : fs::recursive_directory_iterator(source_dir)) {
|
|
|
+ std::string path = dirEntry.path().string();
|
|
|
+ entry = archive_entry_new();
|
|
|
+ archive_entry_copy_pathname(entry, path.c_str());
|
|
|
+ archive_read_disk_entry_from_file(disk, entry, -1, nullptr);
|
|
|
+ archive_write_header(a, entry);
|
|
|
+
|
|
|
+ if (fs::is_regular_file(dirEntry)) {
|
|
|
+ fd = ::open(path.c_str(), O_RDONLY);
|
|
|
+ if (fd >= 0) {
|
|
|
+ len = ::read(fd, buff, sizeof(buff));
|
|
|
+ while (len > 0) {
|
|
|
+ archive_write_data(a, buff, len);
|
|
|
+ len = ::read(fd, buff, sizeof(buff));
|
|
|
+ }
|
|
|
+ ::close(fd);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ archive_entry_free(entry);
|
|
|
+ }
|
|
|
+ archive_read_free(disk);
|
|
|
+ archive_write_close(a);
|
|
|
+ archive_write_free(a);
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+void MainWindow::on_button_backup_clicked() {
|
|
|
+ m_StatusLabel.set_text("Initializing Backup Sequence...");
|
|
|
+ // Keep the cout for the terminal debugger
|
|
|
+ std::cout << ">>> Initializing Backup Sequence..." << std::endl;
|
|
|
+
|
|
|
+ std::string home_dir = getenv("HOME");
|
|
|
+
|
|
|
+ if (m_CheckThemesBackup.get_active()) {
|
|
|
+ std::string target = home_dir + "/.themes";
|
|
|
+ std::string out = home_dir + "/gnome_themes_backup.tar.gz";
|
|
|
+
|
|
|
+ if (fs::exists(target)) {
|
|
|
+ m_StatusLabel.set_text("Packing Themes into archive...");
|
|
|
+ create_tar_archive(target, out);
|
|
|
+ m_StatusLabel.set_text("Success: Packed ~/.themes into gnome_themes_backup.tar.gz");
|
|
|
+ } else {
|
|
|
+ m_StatusLabel.set_text("Warning: ~/.themes doesn't exist. Skipped.");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (m_CheckIconsBackup.get_active()) std::cout << " [x] Queuing Icons (TODO)..." << std::endl;
|
|
|
+ if (m_CheckDconfBackup.get_active()) std::cout << " [x] Queuing Dconf (TODO)..." << std::endl;
|
|
|
+}
|
|
|
+
|
|
|
+void MainWindow::on_button_restore_clicked() {
|
|
|
+ m_StatusLabel.set_text("Initializing Restore Sequence...");
|
|
|
+ std::cout << ">>> Initializing Restore Sequence..." << std::endl;
|
|
|
+ if (m_CheckThemesRestore.get_active()) std::cout << " [x] Preparing to overwrite Themes..." << std::endl;
|
|
|
+ if (m_CheckIconsRestore.get_active()) std::cout << " [x] Preparing to overwrite Icons..." << std::endl;
|
|
|
+ if (m_CheckDconfRestore.get_active()) std::cout << " [x] Preparing to inject Dconf..." << std::endl;
|
|
|
+}
|