diff --git a/src/Model/Study.py b/src/Model/Study.py index 6c6141f2..d0ba7747 100644 --- a/src/Model/Study.py +++ b/src/Model/Study.py @@ -104,9 +104,13 @@ class Study(SQLModel): logger.error(e) fname = fname + "." + str(self._old_save_id) - filename = os.path.join(fdir, "_PAMHYR_", "__old__", fname) - shutil.copy(self.filename, filename) - self._old_save_id += 1 + if os.path.exists(self.filename) and ".backup" not in self.filename: + filename = os.path.join(fdir, "_PAMHYR_", "__old__", fname) + logger.debug(f"Backup previous version copy: {filename}") + shutil.copy(self.filename, filename) + self._old_save_id += 1 + else: + self._init_db_file(self.filename, is_new=True) # Save self.last_save_date = datetime.now() @@ -128,6 +132,16 @@ class Study(SQLModel): @filename.setter def filename(self, filename): + if filename is None: + self._filename = None + self.status.modified() + return + + if self._filename is not None and self._filename != "": + self._filename = str(filename) + self.status.modified() + return + self._filename = str(filename) self._init_db_file(filename, is_new=True) self.status.modified() diff --git a/src/View/Configure/Window.py b/src/View/Configure/Window.py index 255c6011..4a9788bf 100644 --- a/src/View/Configure/Window.py +++ b/src/View/Configure/Window.py @@ -123,11 +123,11 @@ class ConfigureWindow(PamhyrDialog): def setup_data(self): # Backup self.set_check_box("checkBox_backup", self._config.backup_enable) - self.set_line_edit_text("lineEdit_backup_path", - self._config.backup_path) + # self.set_line_edit_text("lineEdit_backup_path", + # self._config.backup_path) self.set_time_edit("timeEdit_backup_frequence", self._config.backup_frequence) - self.set_spin_box("spinBox_backup_max", self._config.backup_max) + # self.set_spin_box("spinBox_backup_max", self._config.backup_max) # Editor self.set_line_edit_text("lineEdit_editor_cmd", @@ -155,12 +155,12 @@ class ConfigureWindow(PamhyrDialog): "pushButton_stricklers_del": self.del_stricklers, "pushButton_stricklers_sort": self.sort_stricklers, # Others - "pushButton_backup_path": lambda: self.file_dialog( - select_file=False, - callback=lambda f: self.set_line_edit_text( - "lineEdit_backup_path", f[0] - ) - ), + # "pushButton_backup_path": lambda: self.file_dialog( + # select_file=False, + # callback=lambda f: self.set_line_edit_text( + # "lineEdit_backup_path", f[0] + # ) + # ), } for button in buttons: @@ -172,11 +172,12 @@ class ConfigureWindow(PamhyrDialog): # Backup self._config.backup_enable = self.get_check_box("checkBox_backup") - self._config.backup_path = self.get_line_edit_text( - "lineEdit_backup_path") + # self._config.backup_path = self.get_line_edit_text( + # "lineEdit_backup_path") self._config.backup_frequence = self.get_time_edit( - "timeEdit_backup_frequence") - self._config.backup_max = self.get_spin_box("spinBox_backup_max") + "timeEdit_backup_frequence" + ) + # self._config.backup_max = self.get_spin_box("spinBox_backup_max") # Stricklers self._config.stricklers = deepcopy(self._stricklers) diff --git a/src/View/MainWindow.py b/src/View/MainWindow.py index 3fa718e2..bf0a3651 100644 --- a/src/View/MainWindow.py +++ b/src/View/MainWindow.py @@ -21,6 +21,9 @@ import sys import logging import subprocess from queue import Queue +from functools import reduce +from platformdirs import user_cache_dir +from tools import logger_exception from PyQt5 import QtGui from PyQt5.QtGui import ( @@ -365,6 +368,10 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): self.set_debug_lvl(debug=False) def setup_timer(self): + self.setup_timer_propagation() + self.setup_timer_backup() + + def setup_timer_propagation(self): self._init_propagation_keys() self._propagation_timer = QTimer(self) @@ -374,6 +381,32 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): self._do_propagate_update ) + def get_config_backup_freq_to_sec(self): + v = self.conf.backup_frequence.split(":") + m = [ + (60 * 60), # Hour to sec + 60, # Minute to sec + 1 # Sec + ] + + ts = reduce( + lambda acc, x: acc + x, + map( + lambda v, m: int(v) * int(m), + v, m + ) + ) + + return ts + + def setup_timer_backup(self): + self._backup_timer = QTimer(self) + + ts = self.get_config_backup_freq_to_sec() + self._backup_timer.start(ts * 1000) + + self._backup_timer.timeout.connect(self._backup) + def _init_propagation_keys(self): self._propagation_keys = Modules(0) @@ -523,11 +556,12 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): progress.setWindowModality(Qt.WindowModal) progress.setValue(0) - logger.info("Save...") + logger.info(f"Save ({self._study.filename})...") self._study.save( progress=lambda: progress.setValue(progress.value() + 1) ) logger.info("Done") + self.conf.set_last_study(self._study.filename) def save_as_study(self): """Save current study as new file @@ -569,11 +603,53 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): progress.setWindowModality(Qt.WindowModal) progress.setValue(0) - logger.info("Save...") + logger.info(f"Save ({self._study.filename})...") self._study.save( progress=lambda: progress.setValue(progress.value() + 1) ) logger.info("Done") + self.conf.set_last_study(self._study.filename) + + def _backup(self): + if not self.conf.backup_enable: + return + + if self._study is None: + return + + old = self._study.filename + file_name = "" + if old == "" or old is None: + file_name = os.path.join( + user_cache_dir("pamhyr"), + "unsaved.pamhyr.backup" + ) + # Set backup at last study open + self.conf.set_last_study(file_name) + else: + file_name = self._study.filename + ".backup" + + self._study.filename = file_name + + try: + sql_request_count = self._study.sql_save_request_count() + progress = QProgressDialog( + "Saving...", None, + 0, sql_request_count, + parent=self + ) + progress.setWindowModality(Qt.WindowModal) + progress.setValue(0) + + logger.info(f"Backup ({self._study.filename})...") + self._study.save( + progress=lambda: progress.setValue(progress.value() + 1) + ) + logger.info("Done") + except Exception as e: + logger_exception(e) + + self._study.filename = old ################## # MSG AND DIALOG # diff --git a/src/View/ui/ConfigureDialog.ui b/src/View/ui/ConfigureDialog.ui index 3caaab7f..5ff289d0 100644 --- a/src/View/ui/ConfigureDialog.ui +++ b/src/View/ui/ConfigureDialog.ui @@ -115,7 +115,7 @@ - false + true Backup @@ -134,13 +134,6 @@ - - - - Path - - - @@ -148,13 +141,6 @@ - - - - Max. archives - - - @@ -164,28 +150,16 @@ Enable + + true + false - - - - - - - - - - - - ressources/open.pngressources/open.png - - - - + @@ -196,6 +170,9 @@ 0 + + QDateTimeEdit::MinuteSection + HH:mm:ss @@ -211,16 +188,6 @@ - - - - 1 - - - 10 - - - diff --git a/src/config.py b/src/config.py index f15ae677..6c7eccfb 100644 --- a/src/config.py +++ b/src/config.py @@ -20,6 +20,8 @@ import os import pickle import logging +from platformdirs import user_cache_dir + from SQL import SQL from Model.Stricklers.Stricklers import Stricklers @@ -27,7 +29,7 @@ from Model.Stricklers.StricklersList import StricklersList from Solver.Solvers import solver_type_list -config_dir = "/.cache/pamhyr/" +config_dir = user_cache_dir("pamhyr") config_file = "config.sqlite3" logger = logging.getLogger() @@ -181,12 +183,12 @@ class Config(SQL): # Backup v = self.execute("SELECT value FROM data WHERE key='backup_enable'") self.backup_enable = v[0] == "True" - v = self.execute("SELECT value FROM data WHERE key='backup_path'") - self.backup_path = v[0] + # v = self.execute("SELECT value FROM data WHERE key='backup_path'") + # self.backup_path = v[0] v = self.execute("SELECT value FROM data WHERE key='backup_frequence'") self.backup_frequence = v[0] - v = self.execute("SELECT value FROM data WHERE key='backup_max'") - self.backup_max = int(v[0]) + # v = self.execute("SELECT value FROM data WHERE key='backup_max'") + # self.backup_max = int(v[0]) # Editor v = self.execute("SELECT value FROM data WHERE key='editor'") @@ -250,9 +252,9 @@ class Config(SQL): def _save(self): data = { "backup_enable": self.backup_enable, - "backup_path": self.backup_path, + # "backup_path": self.backup_path, "backup_frequence": self.backup_frequence, - "backup_max": self.backup_max, + # "backup_max": self.backup_max, "editor": self.editor, "lang": self.lang, "last_study": self.last_study, @@ -291,9 +293,9 @@ class Config(SQL): # Backup self.backup_enable = True - self.backup_path = "" + # self.backup_path = "" self.backup_frequence = "00:05:00" - self.backup_max = 10 + # self.backup_max = 10 # Editor self.editor = "editor @file" @@ -350,13 +352,13 @@ class Config(SQL): file = "" if os.name == 'posix': - ndir = os.path.expanduser('~') + config_dir + ndir = config_dir else: - ndir = os.path.expanduser('~') + config_dir + ndir = config_dir ndir = ndir.replace("/", "\\") os.makedirs(ndir, exist_ok=True) - file = ndir + config_file + file = os.path.join(ndir, config_file) return file