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)
|
||||
|
||||
fname = fname + "." + str(self._old_save_id)
|
||||
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
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue