Skip to content

Instantly share code, notes, and snippets.

@hongwen000
Created April 14, 2023 12:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hongwen000/497ca355641542f82c96d861e16152dd to your computer and use it in GitHub Desktop.
Save hongwen000/497ca355641542f82c96d861e16152dd to your computer and use it in GitHub Desktop.
PyQt配置备份程序
from PyQt6.QtCore import QAbstractListModel, Qt, QModelIndex, pyqtSlot
from PyQt6.QtGui import QGuiApplication
from PyQt6.QtQml import QQmlApplicationEngine
import os
import shutil
from typing import Optional
import shutil
import os
import time
class ConfigModel:
def __init__(self, name: str, base_dir: str, files: list[str]):
self.name = name
self.dir_base = base_dir
self.files = files
class ConfigBackupWorker():
def __init__(self, model: ConfigModel, base_dir: str) -> None:
self.model = model
self.base_dir = base_dir
def backupConfig(self) -> None:
# create base backup dir if not exists
backup_dir = os.path.join(self.base_dir, self.model.name + "_backup")
os.makedirs(backup_dir, exist_ok=True)
for file in self.model.files:
soruce = os.path.join(self.model.dir_base, file)
soruce = os.path.expanduser(path=soruce)
target = os.path.join(backup_dir, file)
if not os.path.exists(soruce):
continue
# 创建target_file的父目录
target_parent_dir = os.path.dirname(target)
os.makedirs(target_parent_dir, exist_ok=True)
if os.path.isdir(soruce):
shutil.copytree(soruce, target)
else:
shutil.copy2(soruce, target)
def restoreConfig(self) -> None:
backup_dir = os.path.join(self.base_dir, self.model.name + "_backup")
for file in self.model.files:
rsource = os.path.join(backup_dir, file)
rtarget = os.path.join(self.model.dir_base, file)
rtarget = os.path.expanduser(path=rtarget)
# 创建被还原文件的父目录
os.makedirs(os.path.dirname(rtarget), exist_ok=True)
# 备份旧文件
tsp = time.strftime("%Y_%m_%d", time.localtime(time.time()))
if os.path.exists(rtarget):
rbackup = rtarget + "_old_" + tsp
os.rename(rtarget, rbackup)
if os.path.isdir(rsource):
shutil.copytree(rsource, rtarget)
else:
shutil.copy2(rsource, rtarget)
class ConfigModelList(QAbstractListModel):
def __init__(self, configs: Optional[list[ConfigModel]] = None, parent: Optional[QAbstractListModel] =None):
super().__init__(parent)
self.configs = configs or []
def rowCount(self, parent=QModelIndex()):
return len(self.configs)
def data(self, index, role=Qt.ItemDataRole.DisplayRole):
if not index.isValid() or not 0 <= index.row() < self.rowCount():
return None
config = self.configs[index.row()]
if role == Qt.ItemDataRole.DisplayRole:
return config.name
return None
def roleNames(self):
return {Qt.ItemDataRole.DisplayRole: b"name"}
@pyqtSlot(int)
def backupConfig(self, row_index: int):
if row_index >= self.rowCount():
return
config = self.configs[row_index]
worker = ConfigBackupWorker(config, os.path.join(os.getcwd(), "backup"))
worker.backupConfig()
@pyqtSlot(int)
def restoreConfig(self, row_index: int):
if row_index >= self.rowCount():
return
config = self.configs[row_index]
worker = ConfigBackupWorker(config, os.path.join(os.getcwd(), "backup"))
worker.restoreConfig()
import yaml
import sys
if __name__ == '__main__':
app = QGuiApplication(sys.argv)
engine = QQmlApplicationEngine()
# Read config from backup_restore.yaml
configs = []
with open("backup_restore.yaml", 'r') as file:
data = yaml.safe_load(file)
for item in data['configures']:
name = item['name']
base_dir = item['base_dir']
files = item['files']
for f in files:
full_path = os.path.join(base_dir, f)
abs_path = os.path.expanduser(full_path)
model = ConfigModel(name, base_dir, files)
configs.append(model)
configmodelList = ConfigModelList()
configmodelList.configs = configs
engine.rootContext().setContextProperty("configModelList", configmodelList)
engine.quit.connect(app.quit)
engine.load("configbackup.qml")
sys.exit(app.exec())
configures:
-
name: neovim
base_dir: ~\AppData\Local\nvim\
files:
- init.vim
-
name: ideavim
base_dir: ~\
files:
- .ideavimrc
import QtQuick 2.15
import QtQuick.Controls 2.15
ApplicationWindow {
width: 500
height: 500
title: "Config Backup"
visible: true
id: root
Column {
width: parent.width
height: parent.height
spacing: 10
ListView {
id: configListView
width: parent.width
height: parent.height - 100
model: configModelList
spacing: 10
delegate: Rectangle {
width: parent.width
height: 50
color: ListView.isCurrentItem?"gray":"white"
Text {
text: name
}
MouseArea {
anchors.fill: parent
onClicked: configListView.currentIndex = index //实现item切换
}
}
Component.onCompleted: {
console.info(configModelList);
}
}
Row {
spacing: 10
width: parent.width
height: 50
Button {
text: "Backup"
onClicked: {
console.debug(configListView.currentIndex);
configModelList.backupConfig(configListView.currentIndex)
}
}
Button {
text: "Restore"
onClicked: {
configModelList.restoreConfig(configListView.currentIndex)
}
}
}
}
Component {
id: scheduleItem
Rectangle {
width: parent.width
height: 50
color: "red"
Text {
text: "test"
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment