Commit 7f3cf46e authored by Pierre-Antoine Rouby's avatar Pierre-Antoine Rouby
Browse files

pamhyr: Add periodic backup.

Showing with 131 additions and 71 deletions
+131 -71
......@@ -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()
......
......@@ -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)
......
......@@ -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 #
......
......@@ -115,7 +115,7 @@
</widget>
<widget class="QWidget" name="tab_backup">
<property name="enabled">
<bool>false</bool>
<bool>true</bool>
</property>
<attribute name="title">
<string>Backup</string>
......@@ -134,13 +134,6 @@
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_8">
<property name="text">
<string>Path</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_9">
<property name="text">
......@@ -148,13 +141,6 @@
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_10">
<property name="text">
<string>Max. archives</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
......@@ -164,28 +150,16 @@
<property name="text">
<string>Enable</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="tristate">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLineEdit" name="lineEdit_backup_path"/>
</item>
<item>
<widget class="QPushButton" name="pushButton_backup_path">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset>
<normaloff>ressources/open.png</normaloff>ressources/open.png</iconset>
</property>
</widget>
</item>
</layout>
<layout class="QHBoxLayout" name="horizontalLayout_3"/>
</item>
<item>
<widget class="QTimeEdit" name="timeEdit_backup_frequence">
......@@ -196,6 +170,9 @@
<second>0</second>
</time>
</property>
<property name="currentSection">
<enum>QDateTimeEdit::MinuteSection</enum>
</property>
<property name="displayFormat">
<string>HH:mm:ss</string>
</property>
......@@ -211,16 +188,6 @@
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinBox_backup_max">
<property name="minimum">
<number>1</number>
</property>
<property name="value">
<number>10</number>
</property>
</widget>
</item>
</layout>
</item>
</layout>
......
......@@ -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
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment