mirror of https://gitlab.com/pamhyr/pamhyr2
pamhyr: Add periodic backup.
parent
632cd2cd4c
commit
7f3cf46ee1
|
|
@ -104,9 +104,13 @@ class Study(SQLModel):
|
||||||
logger.error(e)
|
logger.error(e)
|
||||||
|
|
||||||
fname = fname + "." + str(self._old_save_id)
|
fname = fname + "." + str(self._old_save_id)
|
||||||
filename = os.path.join(fdir, "_PAMHYR_", "__old__", fname)
|
if os.path.exists(self.filename) and ".backup" not in self.filename:
|
||||||
shutil.copy(self.filename, filename)
|
filename = os.path.join(fdir, "_PAMHYR_", "__old__", fname)
|
||||||
self._old_save_id += 1
|
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
|
# Save
|
||||||
self.last_save_date = datetime.now()
|
self.last_save_date = datetime.now()
|
||||||
|
|
@ -128,6 +132,16 @@ class Study(SQLModel):
|
||||||
|
|
||||||
@filename.setter
|
@filename.setter
|
||||||
def filename(self, filename):
|
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._filename = str(filename)
|
||||||
self._init_db_file(filename, is_new=True)
|
self._init_db_file(filename, is_new=True)
|
||||||
self.status.modified()
|
self.status.modified()
|
||||||
|
|
|
||||||
|
|
@ -123,11 +123,11 @@ class ConfigureWindow(PamhyrDialog):
|
||||||
def setup_data(self):
|
def setup_data(self):
|
||||||
# Backup
|
# Backup
|
||||||
self.set_check_box("checkBox_backup", self._config.backup_enable)
|
self.set_check_box("checkBox_backup", self._config.backup_enable)
|
||||||
self.set_line_edit_text("lineEdit_backup_path",
|
# self.set_line_edit_text("lineEdit_backup_path",
|
||||||
self._config.backup_path)
|
# self._config.backup_path)
|
||||||
self.set_time_edit("timeEdit_backup_frequence",
|
self.set_time_edit("timeEdit_backup_frequence",
|
||||||
self._config.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
|
# Editor
|
||||||
self.set_line_edit_text("lineEdit_editor_cmd",
|
self.set_line_edit_text("lineEdit_editor_cmd",
|
||||||
|
|
@ -155,12 +155,12 @@ class ConfigureWindow(PamhyrDialog):
|
||||||
"pushButton_stricklers_del": self.del_stricklers,
|
"pushButton_stricklers_del": self.del_stricklers,
|
||||||
"pushButton_stricklers_sort": self.sort_stricklers,
|
"pushButton_stricklers_sort": self.sort_stricklers,
|
||||||
# Others
|
# Others
|
||||||
"pushButton_backup_path": lambda: self.file_dialog(
|
# "pushButton_backup_path": lambda: self.file_dialog(
|
||||||
select_file=False,
|
# select_file=False,
|
||||||
callback=lambda f: self.set_line_edit_text(
|
# callback=lambda f: self.set_line_edit_text(
|
||||||
"lineEdit_backup_path", f[0]
|
# "lineEdit_backup_path", f[0]
|
||||||
)
|
# )
|
||||||
),
|
# ),
|
||||||
}
|
}
|
||||||
|
|
||||||
for button in buttons:
|
for button in buttons:
|
||||||
|
|
@ -172,11 +172,12 @@ class ConfigureWindow(PamhyrDialog):
|
||||||
|
|
||||||
# Backup
|
# Backup
|
||||||
self._config.backup_enable = self.get_check_box("checkBox_backup")
|
self._config.backup_enable = self.get_check_box("checkBox_backup")
|
||||||
self._config.backup_path = self.get_line_edit_text(
|
# self._config.backup_path = self.get_line_edit_text(
|
||||||
"lineEdit_backup_path")
|
# "lineEdit_backup_path")
|
||||||
self._config.backup_frequence = self.get_time_edit(
|
self._config.backup_frequence = self.get_time_edit(
|
||||||
"timeEdit_backup_frequence")
|
"timeEdit_backup_frequence"
|
||||||
self._config.backup_max = self.get_spin_box("spinBox_backup_max")
|
)
|
||||||
|
# self._config.backup_max = self.get_spin_box("spinBox_backup_max")
|
||||||
|
|
||||||
# Stricklers
|
# Stricklers
|
||||||
self._config.stricklers = deepcopy(self._stricklers)
|
self._config.stricklers = deepcopy(self._stricklers)
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,9 @@ import sys
|
||||||
import logging
|
import logging
|
||||||
import subprocess
|
import subprocess
|
||||||
from queue import Queue
|
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 import QtGui
|
||||||
from PyQt5.QtGui import (
|
from PyQt5.QtGui import (
|
||||||
|
|
@ -365,6 +368,10 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
||||||
self.set_debug_lvl(debug=False)
|
self.set_debug_lvl(debug=False)
|
||||||
|
|
||||||
def setup_timer(self):
|
def setup_timer(self):
|
||||||
|
self.setup_timer_propagation()
|
||||||
|
self.setup_timer_backup()
|
||||||
|
|
||||||
|
def setup_timer_propagation(self):
|
||||||
self._init_propagation_keys()
|
self._init_propagation_keys()
|
||||||
|
|
||||||
self._propagation_timer = QTimer(self)
|
self._propagation_timer = QTimer(self)
|
||||||
|
|
@ -374,6 +381,32 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
||||||
self._do_propagate_update
|
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):
|
def _init_propagation_keys(self):
|
||||||
self._propagation_keys = Modules(0)
|
self._propagation_keys = Modules(0)
|
||||||
|
|
||||||
|
|
@ -523,11 +556,12 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
||||||
progress.setWindowModality(Qt.WindowModal)
|
progress.setWindowModality(Qt.WindowModal)
|
||||||
progress.setValue(0)
|
progress.setValue(0)
|
||||||
|
|
||||||
logger.info("Save...")
|
logger.info(f"Save ({self._study.filename})...")
|
||||||
self._study.save(
|
self._study.save(
|
||||||
progress=lambda: progress.setValue(progress.value() + 1)
|
progress=lambda: progress.setValue(progress.value() + 1)
|
||||||
)
|
)
|
||||||
logger.info("Done")
|
logger.info("Done")
|
||||||
|
self.conf.set_last_study(self._study.filename)
|
||||||
|
|
||||||
def save_as_study(self):
|
def save_as_study(self):
|
||||||
"""Save current study as new file
|
"""Save current study as new file
|
||||||
|
|
@ -569,11 +603,53 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
||||||
progress.setWindowModality(Qt.WindowModal)
|
progress.setWindowModality(Qt.WindowModal)
|
||||||
progress.setValue(0)
|
progress.setValue(0)
|
||||||
|
|
||||||
logger.info("Save...")
|
logger.info(f"Save ({self._study.filename})...")
|
||||||
self._study.save(
|
self._study.save(
|
||||||
progress=lambda: progress.setValue(progress.value() + 1)
|
progress=lambda: progress.setValue(progress.value() + 1)
|
||||||
)
|
)
|
||||||
logger.info("Done")
|
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 #
|
# MSG AND DIALOG #
|
||||||
|
|
|
||||||
|
|
@ -115,7 +115,7 @@
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="tab_backup">
|
<widget class="QWidget" name="tab_backup">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>false</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
<attribute name="title">
|
<attribute name="title">
|
||||||
<string>Backup</string>
|
<string>Backup</string>
|
||||||
|
|
@ -134,13 +134,6 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="label_8">
|
|
||||||
<property name="text">
|
|
||||||
<string>Path</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="label_9">
|
<widget class="QLabel" name="label_9">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
|
|
@ -148,13 +141,6 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="label_10">
|
|
||||||
<property name="text">
|
|
||||||
<string>Max. archives</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
|
@ -164,28 +150,16 @@
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Enable</string>
|
<string>Enable</string>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
<property name="tristate">
|
<property name="tristate">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
<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>
|
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QTimeEdit" name="timeEdit_backup_frequence">
|
<widget class="QTimeEdit" name="timeEdit_backup_frequence">
|
||||||
|
|
@ -196,6 +170,9 @@
|
||||||
<second>0</second>
|
<second>0</second>
|
||||||
</time>
|
</time>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="currentSection">
|
||||||
|
<enum>QDateTimeEdit::MinuteSection</enum>
|
||||||
|
</property>
|
||||||
<property name="displayFormat">
|
<property name="displayFormat">
|
||||||
<string>HH:mm:ss</string>
|
<string>HH:mm:ss</string>
|
||||||
</property>
|
</property>
|
||||||
|
|
@ -211,16 +188,6 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</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>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,8 @@ import os
|
||||||
import pickle
|
import pickle
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
from platformdirs import user_cache_dir
|
||||||
|
|
||||||
from SQL import SQL
|
from SQL import SQL
|
||||||
|
|
||||||
from Model.Stricklers.Stricklers import Stricklers
|
from Model.Stricklers.Stricklers import Stricklers
|
||||||
|
|
@ -27,7 +29,7 @@ from Model.Stricklers.StricklersList import StricklersList
|
||||||
|
|
||||||
from Solver.Solvers import solver_type_list
|
from Solver.Solvers import solver_type_list
|
||||||
|
|
||||||
config_dir = "/.cache/pamhyr/"
|
config_dir = user_cache_dir("pamhyr")
|
||||||
config_file = "config.sqlite3"
|
config_file = "config.sqlite3"
|
||||||
|
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger()
|
||||||
|
|
@ -181,12 +183,12 @@ class Config(SQL):
|
||||||
# Backup
|
# Backup
|
||||||
v = self.execute("SELECT value FROM data WHERE key='backup_enable'")
|
v = self.execute("SELECT value FROM data WHERE key='backup_enable'")
|
||||||
self.backup_enable = v[0] == "True"
|
self.backup_enable = v[0] == "True"
|
||||||
v = self.execute("SELECT value FROM data WHERE key='backup_path'")
|
# v = self.execute("SELECT value FROM data WHERE key='backup_path'")
|
||||||
self.backup_path = v[0]
|
# self.backup_path = v[0]
|
||||||
v = self.execute("SELECT value FROM data WHERE key='backup_frequence'")
|
v = self.execute("SELECT value FROM data WHERE key='backup_frequence'")
|
||||||
self.backup_frequence = v[0]
|
self.backup_frequence = v[0]
|
||||||
v = self.execute("SELECT value FROM data WHERE key='backup_max'")
|
# v = self.execute("SELECT value FROM data WHERE key='backup_max'")
|
||||||
self.backup_max = int(v[0])
|
# self.backup_max = int(v[0])
|
||||||
|
|
||||||
# Editor
|
# Editor
|
||||||
v = self.execute("SELECT value FROM data WHERE key='editor'")
|
v = self.execute("SELECT value FROM data WHERE key='editor'")
|
||||||
|
|
@ -250,9 +252,9 @@ class Config(SQL):
|
||||||
def _save(self):
|
def _save(self):
|
||||||
data = {
|
data = {
|
||||||
"backup_enable": self.backup_enable,
|
"backup_enable": self.backup_enable,
|
||||||
"backup_path": self.backup_path,
|
# "backup_path": self.backup_path,
|
||||||
"backup_frequence": self.backup_frequence,
|
"backup_frequence": self.backup_frequence,
|
||||||
"backup_max": self.backup_max,
|
# "backup_max": self.backup_max,
|
||||||
"editor": self.editor,
|
"editor": self.editor,
|
||||||
"lang": self.lang,
|
"lang": self.lang,
|
||||||
"last_study": self.last_study,
|
"last_study": self.last_study,
|
||||||
|
|
@ -291,9 +293,9 @@ class Config(SQL):
|
||||||
|
|
||||||
# Backup
|
# Backup
|
||||||
self.backup_enable = True
|
self.backup_enable = True
|
||||||
self.backup_path = ""
|
# self.backup_path = ""
|
||||||
self.backup_frequence = "00:05:00"
|
self.backup_frequence = "00:05:00"
|
||||||
self.backup_max = 10
|
# self.backup_max = 10
|
||||||
|
|
||||||
# Editor
|
# Editor
|
||||||
self.editor = "editor @file"
|
self.editor = "editor @file"
|
||||||
|
|
@ -350,13 +352,13 @@ class Config(SQL):
|
||||||
file = ""
|
file = ""
|
||||||
|
|
||||||
if os.name == 'posix':
|
if os.name == 'posix':
|
||||||
ndir = os.path.expanduser('~') + config_dir
|
ndir = config_dir
|
||||||
else:
|
else:
|
||||||
ndir = os.path.expanduser('~') + config_dir
|
ndir = config_dir
|
||||||
ndir = ndir.replace("/", "\\")
|
ndir = ndir.replace("/", "\\")
|
||||||
|
|
||||||
os.makedirs(ndir, exist_ok=True)
|
os.makedirs(ndir, exist_ok=True)
|
||||||
file = ndir + config_file
|
file = os.path.join(ndir, config_file)
|
||||||
|
|
||||||
return file
|
return file
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue