dev: 添加配置文件
This commit is contained in:
73
lib/config_utils.py
Normal file
73
lib/config_utils.py
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
# coding: utf8
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import json
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
def path_not_exist(path: str | Path) -> bool:
|
||||||
|
"""
|
||||||
|
判断目标路径是否存在
|
||||||
|
如果参数为空或者 None,亦认为不存在
|
||||||
|
|
||||||
|
:param path: 目标路径
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
if isinstance(path, str):
|
||||||
|
return len(path) == 0 or not Path(path).exists()
|
||||||
|
elif isinstance(path, Path):
|
||||||
|
return not path.exists()
|
||||||
|
else:
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def get_data_dir() -> str:
|
||||||
|
plat = sys.platform
|
||||||
|
if plat == "win32":
|
||||||
|
data_dir = os.path.expandvars("%appdata%")
|
||||||
|
elif plat == "darwin":
|
||||||
|
data_dir = os.path.expanduser("~/Library/Application Support")
|
||||||
|
else:
|
||||||
|
raise OSError("Unsupported platform")
|
||||||
|
return data_dir
|
||||||
|
|
||||||
|
|
||||||
|
def get_app_dir(org_name: str, app_name: str) -> Path:
|
||||||
|
data_dir = get_data_dir()
|
||||||
|
app_dir = Path(data_dir, org_name, app_name)
|
||||||
|
if not app_dir.exists():
|
||||||
|
app_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
return app_dir
|
||||||
|
|
||||||
|
|
||||||
|
def get_config_path(org_name: str, app_name: str) -> Path:
|
||||||
|
data_dir = get_app_dir(org_name, app_name)
|
||||||
|
return Path(data_dir, "config.json")
|
||||||
|
|
||||||
|
|
||||||
|
def read_config(org_name: str, app_name: str) -> dict:
|
||||||
|
config_path = get_config_path(org_name, app_name)
|
||||||
|
if not config_path.exists():
|
||||||
|
config = {
|
||||||
|
"table_name": "entries",
|
||||||
|
"button_min_width": 120,
|
||||||
|
"last_db_path": "",
|
||||||
|
"loaded_memory": {}
|
||||||
|
}
|
||||||
|
config_path.write_text(json.dumps(config, ensure_ascii=False, indent=4), encoding="utf-8")
|
||||||
|
return config
|
||||||
|
else:
|
||||||
|
return json.loads(config_path.read_text(encoding="utf-8"))
|
||||||
|
|
||||||
|
|
||||||
|
def write_config(config: dict, org_name: str, app_name: str):
|
||||||
|
config_path = get_config_path(org_name, app_name)
|
||||||
|
config_path.write_text(json.dumps(config, ensure_ascii=False, indent=4), encoding="utf-8")
|
||||||
|
|
||||||
|
|
||||||
|
def get_default_db_path(config: dict, org_name: str, app_name: str) -> str:
|
||||||
|
if path_not_exist(config["last_db_path"]):
|
||||||
|
app_dir = get_app_dir(org_name, app_name)
|
||||||
|
return str(app_dir / f"default.db")
|
||||||
|
return config["last_db_path"]
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
# coding: utf8
|
|
||||||
|
|
||||||
table_name = "entries"
|
|
||||||
button_min_width = 120
|
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
# coding: utf8
|
# coding: utf8
|
||||||
from os import PathLike
|
from os import PathLike
|
||||||
from pykeepass import PyKeePass
|
from pykeepass import PyKeePass
|
||||||
from .Sqlite3Helper import Sqlite3Worker, BlobType, Column
|
from lib.db_columns_def import all_columns
|
||||||
from .global_config import table_name
|
from .Sqlite3Helper import Sqlite3Worker, BlobType
|
||||||
|
|
||||||
|
|
||||||
def trim_str(value):
|
def trim_str(value):
|
||||||
@@ -28,7 +28,7 @@ def blob_fy(value: str) -> BlobType:
|
|||||||
|
|
||||||
|
|
||||||
def read_kps_to_db(kps_file: str | PathLike[str], password: str,
|
def read_kps_to_db(kps_file: str | PathLike[str], password: str,
|
||||||
columns: list[Column], sqh: Sqlite3Worker) -> PyKeePass:
|
table_name: str, sqh: Sqlite3Worker) -> PyKeePass:
|
||||||
kp = PyKeePass(kps_file, password=password)
|
kp = PyKeePass(kps_file, password=password)
|
||||||
|
|
||||||
values = []
|
values = []
|
||||||
@@ -44,5 +44,5 @@ def read_kps_to_db(kps_file: str | PathLike[str], password: str,
|
|||||||
blob_fy("::".join([kps_file] + entry.path[:-1])),
|
blob_fy("::".join([kps_file] + entry.path[:-1])),
|
||||||
])
|
])
|
||||||
|
|
||||||
sqh.insert_into(table_name, columns, values)
|
sqh.insert_into(table_name, all_columns[1:], values)
|
||||||
return kp
|
return kp
|
||||||
|
|||||||
9
main.py
9
main.py
@@ -3,9 +3,13 @@ import sys
|
|||||||
|
|
||||||
from PySide6.QtWidgets import QApplication
|
from PySide6.QtWidgets import QApplication
|
||||||
|
|
||||||
|
from lib.config_utils import get_default_db_path, read_config
|
||||||
from src.mw_kps_unifier import KpsUnifier
|
from src.mw_kps_unifier import KpsUnifier
|
||||||
import src.rc_kps_unifier
|
import src.rc_kps_unifier
|
||||||
|
|
||||||
|
__version__ = '0.1.0'
|
||||||
|
__version_info__ = tuple(map(int, __version__.split('.')))
|
||||||
|
|
||||||
ORG_NAME = "JnPrograms"
|
ORG_NAME = "JnPrograms"
|
||||||
APP_NAME = "KpsUnifier"
|
APP_NAME = "KpsUnifier"
|
||||||
|
|
||||||
@@ -15,7 +19,10 @@ def main():
|
|||||||
app.setOrganizationName(ORG_NAME)
|
app.setOrganizationName(ORG_NAME)
|
||||||
app.setApplicationName(APP_NAME)
|
app.setApplicationName(APP_NAME)
|
||||||
|
|
||||||
win = KpsUnifier()
|
config = read_config(ORG_NAME, APP_NAME)
|
||||||
|
db_path = get_default_db_path(config, ORG_NAME, APP_NAME)
|
||||||
|
|
||||||
|
win = KpsUnifier(db_path, config)
|
||||||
win.show()
|
win.show()
|
||||||
return app.exec()
|
return app.exec()
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
# coding: utf8
|
# coding: utf8
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
from pathlib import Path
|
|
||||||
from PySide6 import QtWidgets, QtCore, QtGui
|
from PySide6 import QtWidgets, QtCore, QtGui
|
||||||
|
|
||||||
from .page_load import PageLoad
|
from .page_load import PageLoad
|
||||||
@@ -9,28 +6,11 @@ from .page_query import PageQuery
|
|||||||
from .cmbx_styles import StyleComboBox
|
from .cmbx_styles import StyleComboBox
|
||||||
from lib.Sqlite3Helper import Sqlite3Worker
|
from lib.Sqlite3Helper import Sqlite3Worker
|
||||||
from lib.db_columns_def import all_columns
|
from lib.db_columns_def import all_columns
|
||||||
from lib.global_config import table_name
|
from lib.config_utils import write_config
|
||||||
|
|
||||||
|
|
||||||
def get_default_db_path() -> str:
|
|
||||||
plat = sys.platform
|
|
||||||
if plat == "win32":
|
|
||||||
data_dir = os.path.expandvars("%appdata%")
|
|
||||||
elif plat == "darwin":
|
|
||||||
data_dir = os.path.expanduser("~/Library/Application Support")
|
|
||||||
else:
|
|
||||||
raise OSError("Unsupported platform")
|
|
||||||
app_dir = Path(data_dir,
|
|
||||||
QtWidgets.QApplication.organizationName(),
|
|
||||||
QtWidgets.QApplication.applicationName())
|
|
||||||
if not app_dir.exists():
|
|
||||||
app_dir.mkdir(parents=True, exist_ok=True)
|
|
||||||
|
|
||||||
return str(app_dir / f"default.db")
|
|
||||||
|
|
||||||
|
|
||||||
class UiKpsUnifier(object):
|
class UiKpsUnifier(object):
|
||||||
def __init__(self, default_db_path: str, sqh: Sqlite3Worker, window: QtWidgets.QMainWindow):
|
def __init__(self, default_db_path: str, config: dict, sqh: Sqlite3Worker, window: QtWidgets.QMainWindow):
|
||||||
window.setWindowTitle('KeePassXC 多合一')
|
window.setWindowTitle('KeePassXC 多合一')
|
||||||
self.cw = QtWidgets.QWidget(window)
|
self.cw = QtWidgets.QWidget(window)
|
||||||
self.vly_m = QtWidgets.QVBoxLayout()
|
self.vly_m = QtWidgets.QVBoxLayout()
|
||||||
@@ -61,9 +41,9 @@ class UiKpsUnifier(object):
|
|||||||
self.sw_m = QtWidgets.QStackedWidget(self.cw)
|
self.sw_m = QtWidgets.QStackedWidget(self.cw)
|
||||||
self.vly_m.addWidget(self.sw_m)
|
self.vly_m.addWidget(self.sw_m)
|
||||||
|
|
||||||
self.page_load = PageLoad(sqh, self.cw)
|
self.page_load = PageLoad(sqh, config, self.cw)
|
||||||
self.sw_m.addWidget(self.page_load)
|
self.sw_m.addWidget(self.page_load)
|
||||||
self.page_query = PageQuery(sqh, self.cw)
|
self.page_query = PageQuery(sqh, config, self.cw)
|
||||||
self.sw_m.addWidget(self.page_query)
|
self.sw_m.addWidget(self.page_query)
|
||||||
|
|
||||||
def update_sqh(self, sqh: Sqlite3Worker):
|
def update_sqh(self, sqh: Sqlite3Worker):
|
||||||
@@ -72,24 +52,31 @@ class UiKpsUnifier(object):
|
|||||||
|
|
||||||
|
|
||||||
class KpsUnifier(QtWidgets.QMainWindow):
|
class KpsUnifier(QtWidgets.QMainWindow):
|
||||||
def __init__(self, parent=None):
|
def __init__(self, db_path: str, config: dict, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.db_path = get_default_db_path()
|
self.db_path = db_path
|
||||||
|
self.config = config
|
||||||
self.sqh = self.init_db()
|
self.sqh = self.init_db()
|
||||||
|
|
||||||
self.ui = UiKpsUnifier(self.db_path, self.sqh, self)
|
self.ui = UiKpsUnifier(self.db_path, self.config, self.sqh, self)
|
||||||
|
|
||||||
self.ui.act_new.triggered.connect(self.on_act_new_triggered)
|
self.ui.act_new.triggered.connect(self.on_act_new_triggered)
|
||||||
self.ui.act_open.triggered.connect(self.on_act_open_triggered)
|
self.ui.act_open.triggered.connect(self.on_act_open_triggered)
|
||||||
self.ui.act_load.triggered.connect(self.on_act_load_triggered)
|
self.ui.act_load.triggered.connect(self.on_act_load_triggered)
|
||||||
self.ui.act_query.triggered.connect(self.on_act_query_triggered)
|
self.ui.act_query.triggered.connect(self.on_act_query_triggered)
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
self.config["last_db_path"] = self.db_path
|
||||||
|
write_config(self.config,
|
||||||
|
QtWidgets.QApplication.organizationName(),
|
||||||
|
QtWidgets.QApplication.applicationName())
|
||||||
|
|
||||||
def sizeHint(self):
|
def sizeHint(self):
|
||||||
return QtCore.QSize(860, 640)
|
return QtCore.QSize(860, 640)
|
||||||
|
|
||||||
def init_db(self) -> Sqlite3Worker:
|
def init_db(self) -> Sqlite3Worker:
|
||||||
sqh = Sqlite3Worker(self.db_path)
|
sqh = Sqlite3Worker(self.db_path)
|
||||||
sqh.create_table(table_name, all_columns, if_not_exists=True)
|
sqh.create_table(self.config["table_name"], all_columns, if_not_exists=True)
|
||||||
return sqh
|
return sqh
|
||||||
|
|
||||||
def update_db(self, filename: str):
|
def update_db(self, filename: str):
|
||||||
|
|||||||
@@ -4,15 +4,14 @@ from pykeepass.exceptions import CredentialsError
|
|||||||
|
|
||||||
from .gbx_kps_login import GbxKpsLogin
|
from .gbx_kps_login import GbxKpsLogin
|
||||||
from lib.Sqlite3Helper import Sqlite3Worker
|
from lib.Sqlite3Helper import Sqlite3Worker
|
||||||
from lib.db_columns_def import all_columns
|
|
||||||
from lib.kps_operations import read_kps_to_db
|
from lib.kps_operations import read_kps_to_db
|
||||||
from lib.global_config import button_min_width
|
|
||||||
|
|
||||||
|
|
||||||
class WgLoadKps(QtWidgets.QWidget):
|
class WgLoadKps(QtWidgets.QWidget):
|
||||||
def __init__(self, sqh: Sqlite3Worker, parent=None):
|
def __init__(self, sqh: Sqlite3Worker, config: dict, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.sqh = sqh
|
self.sqh = sqh
|
||||||
|
self.config = config
|
||||||
self.kps_wgs: list[GbxKpsLogin] = []
|
self.kps_wgs: list[GbxKpsLogin] = []
|
||||||
|
|
||||||
self.vly_m = QtWidgets.QVBoxLayout()
|
self.vly_m = QtWidgets.QVBoxLayout()
|
||||||
@@ -36,7 +35,7 @@ class WgLoadKps(QtWidgets.QWidget):
|
|||||||
try:
|
try:
|
||||||
read_kps_to_db(kps_file=item.lne_path.text(),
|
read_kps_to_db(kps_file=item.lne_path.text(),
|
||||||
password=item.lne_password.text(),
|
password=item.lne_password.text(),
|
||||||
columns=all_columns[1:],
|
table_name=self.config["table_name"],
|
||||||
sqh=self.sqh)
|
sqh=self.sqh)
|
||||||
except CredentialsError:
|
except CredentialsError:
|
||||||
QtWidgets.QMessageBox.critical(self, "密码错误",
|
QtWidgets.QMessageBox.critical(self, "密码错误",
|
||||||
@@ -52,7 +51,7 @@ class WgLoadKps(QtWidgets.QWidget):
|
|||||||
|
|
||||||
|
|
||||||
class PageLoad(QtWidgets.QWidget):
|
class PageLoad(QtWidgets.QWidget):
|
||||||
def __init__(self, sqh: Sqlite3Worker, parent=None):
|
def __init__(self, sqh: Sqlite3Worker, config: dict, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.hly_m = QtWidgets.QHBoxLayout()
|
self.hly_m = QtWidgets.QHBoxLayout()
|
||||||
self.setLayout(self.hly_m)
|
self.setLayout(self.hly_m)
|
||||||
@@ -60,10 +59,10 @@ class PageLoad(QtWidgets.QWidget):
|
|||||||
self.hly_m.addLayout(self.vly_left)
|
self.hly_m.addLayout(self.vly_left)
|
||||||
|
|
||||||
self.pbn_add = QtWidgets.QPushButton("添加", self)
|
self.pbn_add = QtWidgets.QPushButton("添加", self)
|
||||||
self.pbn_add.setMinimumWidth(button_min_width)
|
self.pbn_add.setMinimumWidth(config["button_min_width"])
|
||||||
self.vly_left.addWidget(self.pbn_add)
|
self.vly_left.addWidget(self.pbn_add)
|
||||||
self.pbn_load_all = QtWidgets.QPushButton("加载全部", self)
|
self.pbn_load_all = QtWidgets.QPushButton("加载全部", self)
|
||||||
self.pbn_load_all.setMinimumWidth(button_min_width)
|
self.pbn_load_all.setMinimumWidth(config["button_min_width"])
|
||||||
self.pbn_load_all.setDisabled(True)
|
self.pbn_load_all.setDisabled(True)
|
||||||
self.vly_left.addWidget(self.pbn_load_all)
|
self.vly_left.addWidget(self.pbn_load_all)
|
||||||
self.vly_left.addStretch(1)
|
self.vly_left.addStretch(1)
|
||||||
@@ -71,7 +70,7 @@ class PageLoad(QtWidgets.QWidget):
|
|||||||
self.sa_m = QtWidgets.QScrollArea(self)
|
self.sa_m = QtWidgets.QScrollArea(self)
|
||||||
self.sa_m.setWidgetResizable(True)
|
self.sa_m.setWidgetResizable(True)
|
||||||
self.hly_m.addWidget(self.sa_m)
|
self.hly_m.addWidget(self.sa_m)
|
||||||
self.wg_sa = WgLoadKps(sqh, self.sa_m)
|
self.wg_sa = WgLoadKps(sqh, config, self.sa_m)
|
||||||
self.sa_m.setWidget(self.wg_sa)
|
self.sa_m.setWidget(self.wg_sa)
|
||||||
|
|
||||||
self.pbn_add.clicked.connect(self.on_pbn_add_clicked)
|
self.pbn_add.clicked.connect(self.on_pbn_add_clicked)
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
# coding: utf8
|
# coding: utf8
|
||||||
import json
|
import json
|
||||||
|
|
||||||
from PySide6 import QtWidgets, QtCore, QtGui
|
from PySide6 import QtWidgets, QtCore
|
||||||
from lib.Sqlite3Helper import Sqlite3Worker, Operand, Expression
|
from lib.Sqlite3Helper import Sqlite3Worker, Expression
|
||||||
from lib.db_columns_def import query_columns
|
from lib.db_columns_def import query_columns
|
||||||
from lib.global_config import button_min_width, table_name
|
|
||||||
|
|
||||||
|
|
||||||
class QueryTableModel(QtCore.QAbstractTableModel):
|
class QueryTableModel(QtCore.QAbstractTableModel):
|
||||||
@@ -34,9 +33,10 @@ class QueryTableModel(QtCore.QAbstractTableModel):
|
|||||||
|
|
||||||
|
|
||||||
class PageQuery(QtWidgets.QWidget):
|
class PageQuery(QtWidgets.QWidget):
|
||||||
def __init__(self, sqh: Sqlite3Worker, parent=None):
|
def __init__(self, sqh: Sqlite3Worker, config: dict, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.sqh = sqh
|
self.sqh = sqh
|
||||||
|
self.config = config
|
||||||
|
|
||||||
self.hly_m = QtWidgets.QHBoxLayout()
|
self.hly_m = QtWidgets.QHBoxLayout()
|
||||||
self.setLayout(self.hly_m)
|
self.setLayout(self.hly_m)
|
||||||
@@ -53,13 +53,13 @@ class PageQuery(QtWidgets.QWidget):
|
|||||||
self.sa_left.setWidget(self.sa_wg)
|
self.sa_left.setWidget(self.sa_wg)
|
||||||
|
|
||||||
self.pbn_all = QtWidgets.QPushButton("全部", self.sa_wg)
|
self.pbn_all = QtWidgets.QPushButton("全部", self.sa_wg)
|
||||||
self.pbn_all.setMinimumWidth(button_min_width)
|
self.pbn_all.setMinimumWidth(config["button_min_width"])
|
||||||
self.vly_sa_wg.addWidget(self.pbn_all)
|
self.vly_sa_wg.addWidget(self.pbn_all)
|
||||||
|
|
||||||
self.vly_sa_wg.addStretch(1)
|
self.vly_sa_wg.addStretch(1)
|
||||||
|
|
||||||
self.pbn_read_filters = QtWidgets.QPushButton("更多过滤", self)
|
self.pbn_read_filters = QtWidgets.QPushButton("更多过滤", self)
|
||||||
self.pbn_read_filters.setMinimumWidth(button_min_width)
|
self.pbn_read_filters.setMinimumWidth(config["button_min_width"])
|
||||||
self.vly_sa_wg.addWidget(self.pbn_read_filters)
|
self.vly_sa_wg.addWidget(self.pbn_read_filters)
|
||||||
|
|
||||||
self.trv_m = QtWidgets.QTreeView(self)
|
self.trv_m = QtWidgets.QTreeView(self)
|
||||||
@@ -91,7 +91,7 @@ class PageQuery(QtWidgets.QWidget):
|
|||||||
|
|
||||||
def set_filter_button(self, fil: dict):
|
def set_filter_button(self, fil: dict):
|
||||||
pbn_fil = PushButtonWithData(fil, self.sa_wg, fil["name"])
|
pbn_fil = PushButtonWithData(fil, self.sa_wg, fil["name"])
|
||||||
pbn_fil.setMinimumWidth(button_min_width)
|
pbn_fil.setMinimumWidth(self.config["button_min_width"])
|
||||||
self.vly_sa_wg.insertWidget(self.vly_sa_wg.count() - 2, pbn_fil)
|
self.vly_sa_wg.insertWidget(self.vly_sa_wg.count() - 2, pbn_fil)
|
||||||
pbn_fil.clicked_with_data.connect(self.on_custom_filters_clicked_with_data)
|
pbn_fil.clicked_with_data.connect(self.on_custom_filters_clicked_with_data)
|
||||||
|
|
||||||
@@ -107,7 +107,8 @@ class PageQuery(QtWidgets.QWidget):
|
|||||||
self.set_filter_button(fil)
|
self.set_filter_button(fil)
|
||||||
|
|
||||||
def on_custom_filters_clicked_with_data(self, data: dict):
|
def on_custom_filters_clicked_with_data(self, data: dict):
|
||||||
_, results = self.sqh.select(table_name, query_columns, where=Expression(data["where"]))
|
_, results = self.sqh.select(self.config["table_name"], query_columns,
|
||||||
|
where=Expression(data["where"]))
|
||||||
model = QueryTableModel(results, self)
|
model = QueryTableModel(results, self)
|
||||||
self.trv_m.setModel(model)
|
self.trv_m.setModel(model)
|
||||||
|
|
||||||
@@ -115,7 +116,7 @@ class PageQuery(QtWidgets.QWidget):
|
|||||||
self.sqh = sqh
|
self.sqh = sqh
|
||||||
|
|
||||||
def on_pbn_all_clicked(self):
|
def on_pbn_all_clicked(self):
|
||||||
_, results = self.sqh.select(table_name, query_columns)
|
_, results = self.sqh.select(self.config["table_name"], query_columns)
|
||||||
model = QueryTableModel(results, self)
|
model = QueryTableModel(results, self)
|
||||||
self.trv_m.setModel(model)
|
self.trv_m.setModel(model)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user