dev: 支持标记状态
This commit is contained in:
@@ -12,6 +12,7 @@ columns_d = {
|
|||||||
"uuid": Column("uuid", DataType.TEXT, nullable=False),
|
"uuid": Column("uuid", DataType.TEXT, nullable=False),
|
||||||
"filepath": Column("filepath", DataType.BLOB, nullable=False),
|
"filepath": Column("filepath", DataType.BLOB, nullable=False),
|
||||||
"path": Column("path", DataType.BLOB),
|
"path": Column("path", DataType.BLOB),
|
||||||
|
"status": Column("status", DataType.TEXT), # 只有三种状态:keep, transfer, delete
|
||||||
}
|
}
|
||||||
|
|
||||||
all_columns = [
|
all_columns = [
|
||||||
@@ -25,13 +26,19 @@ all_columns = [
|
|||||||
columns_d["uuid"],
|
columns_d["uuid"],
|
||||||
columns_d["filepath"],
|
columns_d["filepath"],
|
||||||
columns_d["path"],
|
columns_d["path"],
|
||||||
|
columns_d["status"],
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# 插入数据时使用的列
|
||||||
|
insert_columns = all_columns[1:-1]
|
||||||
|
|
||||||
|
# 查询数据时使用的列
|
||||||
query_columns = [
|
query_columns = [
|
||||||
columns_d["entry_id"],
|
columns_d["entry_id"],
|
||||||
columns_d["title"],
|
columns_d["title"],
|
||||||
columns_d["username"],
|
columns_d["username"],
|
||||||
columns_d["url"],
|
columns_d["url"],
|
||||||
|
columns_d["status"],
|
||||||
]
|
]
|
||||||
|
|
||||||
# 从数据库中读取 UUID 和 文件路径分析相似度
|
# 从数据库中读取 UUID 和 文件路径分析相似度
|
||||||
@@ -41,5 +48,5 @@ sim_columns = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
filepath_col = columns_d["filepath"]
|
filepath_col = columns_d["filepath"]
|
||||||
|
|
||||||
entry_id_col = columns_d["entry_id"]
|
entry_id_col = columns_d["entry_id"]
|
||||||
|
status_col = columns_d["status"]
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# coding: utf8
|
# coding: utf8
|
||||||
from os import PathLike
|
from os import PathLike
|
||||||
from pykeepass import PyKeePass
|
from pykeepass import PyKeePass
|
||||||
from lib.db_columns_def import all_columns
|
from lib.db_columns_def import insert_columns
|
||||||
from .Sqlite3Helper import Sqlite3Worker, BlobType
|
from .Sqlite3Helper import Sqlite3Worker, BlobType
|
||||||
|
|
||||||
|
|
||||||
@@ -46,5 +46,5 @@ def read_kps_to_db(kps_file: str | PathLike[str], password: str,
|
|||||||
blob_fy("::".join(entry.path[:-1])),
|
blob_fy("::".join(entry.path[:-1])),
|
||||||
])
|
])
|
||||||
|
|
||||||
sqh.insert_into(table_name, all_columns[1:], values)
|
sqh.insert_into(table_name, insert_columns, values)
|
||||||
return kp
|
return kp
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
# coding: utf8
|
# coding: utf8
|
||||||
import json
|
import json
|
||||||
from PySide6 import QtWidgets, QtCore
|
from PySide6 import QtWidgets, QtCore, QtGui
|
||||||
|
|
||||||
from .da_entry_info import DaEntryInfo
|
from .da_entry_info import DaEntryInfo
|
||||||
from lib.Sqlite3Helper import Sqlite3Worker, Expression
|
from lib.Sqlite3Helper import Sqlite3Worker, Expression, Operand
|
||||||
from lib.db_columns_def import query_columns
|
from lib.db_columns_def import query_columns, status_col, entry_id_col
|
||||||
|
|
||||||
|
|
||||||
class QueryTableModel(QtCore.QAbstractTableModel):
|
class QueryTableModel(QtCore.QAbstractTableModel):
|
||||||
@@ -14,6 +14,25 @@ class QueryTableModel(QtCore.QAbstractTableModel):
|
|||||||
self.query_results = query_results
|
self.query_results = query_results
|
||||||
self.headers = ["序号", "标题", "用户名", "URL"]
|
self.headers = ["序号", "标题", "用户名", "URL"]
|
||||||
|
|
||||||
|
self.light_status_colors = {
|
||||||
|
"keep": QtGui.QBrush(QtGui.QColor("lightgreen")),
|
||||||
|
"transfer": QtGui.QBrush(QtGui.QColor("moccasin")),
|
||||||
|
"delete": QtGui.QBrush(QtGui.QColor("pink")),
|
||||||
|
"none": QtGui.QBrush(QtCore.Qt.GlobalColor.transparent)
|
||||||
|
}
|
||||||
|
self.dark_status_colors = {
|
||||||
|
"keep": QtGui.QBrush(QtGui.QColor("green")),
|
||||||
|
"transfer": QtGui.QBrush(QtGui.QColor("orange")),
|
||||||
|
"delete": QtGui.QBrush(QtGui.QColor("orangered")),
|
||||||
|
"none": QtGui.QBrush(QtCore.Qt.GlobalColor.transparent)
|
||||||
|
}
|
||||||
|
if QtWidgets.QApplication.style().name() == "windowsvista":
|
||||||
|
self.status_colors = self.light_status_colors
|
||||||
|
elif QtWidgets.QApplication.styleHints().colorScheme() == QtCore.Qt.ColorScheme.Dark:
|
||||||
|
self.status_colors = self.dark_status_colors
|
||||||
|
else:
|
||||||
|
self.status_colors = self.light_status_colors
|
||||||
|
|
||||||
def rowCount(self, parent: QtCore.QModelIndex = ...):
|
def rowCount(self, parent: QtCore.QModelIndex = ...):
|
||||||
return len(self.query_results)
|
return len(self.query_results)
|
||||||
|
|
||||||
@@ -26,6 +45,14 @@ class QueryTableModel(QtCore.QAbstractTableModel):
|
|||||||
if isinstance(item, bytes):
|
if isinstance(item, bytes):
|
||||||
return item.decode("utf-8")
|
return item.decode("utf-8")
|
||||||
return item
|
return item
|
||||||
|
if role == QtCore.Qt.ItemDataRole.BackgroundRole:
|
||||||
|
status = self.query_results[index.row()][-1] # 最后一列是状态
|
||||||
|
if status is None:
|
||||||
|
status = "none"
|
||||||
|
return self.status_colors[status]
|
||||||
|
if role == QtCore.Qt.ItemDataRole.TextAlignmentRole:
|
||||||
|
if index.column() == 0:
|
||||||
|
return QtCore.Qt.AlignmentFlag.AlignRight | QtCore.Qt.AlignmentFlag.AlignVCenter
|
||||||
|
|
||||||
def headerData(self, section: int, orientation: QtCore.Qt.Orientation, role: int = ...):
|
def headerData(self, section: int, orientation: QtCore.Qt.Orientation, role: int = ...):
|
||||||
if orientation == QtCore.Qt.Orientation.Horizontal:
|
if orientation == QtCore.Qt.Orientation.Horizontal:
|
||||||
@@ -39,6 +66,19 @@ class PageQuery(QtWidgets.QWidget):
|
|||||||
self.sqh = sqh
|
self.sqh = sqh
|
||||||
self.config = config
|
self.config = config
|
||||||
|
|
||||||
|
# 右键菜单
|
||||||
|
self.menu_ctx = QtWidgets.QMenu(self)
|
||||||
|
self.act_keep = ActionWithStr("keep", "保留", self)
|
||||||
|
self.act_transfer = ActionWithStr("transfer", "转移", self)
|
||||||
|
self.act_delete = ActionWithStr("delete", "删除", self)
|
||||||
|
self.menu_ctx.addActions([self.act_keep, self.act_transfer, self.act_delete])
|
||||||
|
|
||||||
|
self.act_keep.triggered_with_str.connect(self.on_act_mark_triggered_with_str)
|
||||||
|
self.act_transfer.triggered_with_str.connect(self.on_act_mark_triggered_with_str)
|
||||||
|
self.act_delete.triggered_with_str.connect(self.on_act_mark_triggered_with_str)
|
||||||
|
|
||||||
|
# 主布局
|
||||||
|
|
||||||
self.hly_m = QtWidgets.QHBoxLayout()
|
self.hly_m = QtWidgets.QHBoxLayout()
|
||||||
self.setLayout(self.hly_m)
|
self.setLayout(self.hly_m)
|
||||||
|
|
||||||
@@ -64,12 +104,15 @@ class PageQuery(QtWidgets.QWidget):
|
|||||||
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)
|
||||||
|
self.trv_m.setSelectionMode(QtWidgets.QTreeView.SelectionMode.ExtendedSelection)
|
||||||
|
self.trv_m.setContextMenuPolicy(QtCore.Qt.ContextMenuPolicy.CustomContextMenu)
|
||||||
# self.trv_m.setSortingEnabled(True)
|
# self.trv_m.setSortingEnabled(True)
|
||||||
self.hly_m.addWidget(self.trv_m)
|
self.hly_m.addWidget(self.trv_m)
|
||||||
|
|
||||||
self.pbn_all.clicked.connect(self.on_pbn_all_clicked)
|
self.pbn_all.clicked.connect(self.on_pbn_all_clicked)
|
||||||
self.pbn_read_filters.clicked.connect(self.on_pbn_read_filters_clicked)
|
self.pbn_read_filters.clicked.connect(self.on_pbn_read_filters_clicked)
|
||||||
self.trv_m.doubleClicked.connect(self.on_trv_m_double_clicked)
|
self.trv_m.doubleClicked.connect(self.on_trv_m_double_clicked)
|
||||||
|
self.trv_m.customContextMenuRequested.connect(self.on_trv_m_custom_context_menu_requested)
|
||||||
|
|
||||||
self.set_default_filters()
|
self.set_default_filters()
|
||||||
|
|
||||||
@@ -123,13 +166,23 @@ class PageQuery(QtWidgets.QWidget):
|
|||||||
self.trv_m.setModel(model)
|
self.trv_m.setModel(model)
|
||||||
|
|
||||||
def on_trv_m_double_clicked(self, index: QtCore.QModelIndex):
|
def on_trv_m_double_clicked(self, index: QtCore.QModelIndex):
|
||||||
model = index.model()
|
entry_id = index.siblingAtColumn(0).data(QtCore.Qt.ItemDataRole.DisplayRole)
|
||||||
row = index.row()
|
|
||||||
entry_id_index = model.index(row, 0)
|
|
||||||
entry_id = entry_id_index.data(QtCore.Qt.ItemDataRole.DisplayRole)
|
|
||||||
da_entry_info = DaEntryInfo(entry_id, self.config, self.sqh, self)
|
da_entry_info = DaEntryInfo(entry_id, self.config, self.sqh, self)
|
||||||
da_entry_info.exec()
|
da_entry_info.exec()
|
||||||
|
|
||||||
|
def on_trv_m_custom_context_menu_requested(self, pos: QtCore.QPoint):
|
||||||
|
self.menu_ctx.exec(self.trv_m.viewport().mapToGlobal(pos))
|
||||||
|
|
||||||
|
def on_act_mark_triggered_with_str(self, info: str):
|
||||||
|
indexes = self.trv_m.selectedIndexes()
|
||||||
|
entry_ids = [
|
||||||
|
index.data(QtCore.Qt.ItemDataRole.DisplayRole)
|
||||||
|
for index in indexes if index.column() == 0
|
||||||
|
]
|
||||||
|
|
||||||
|
self.sqh.update(self.config["table_name"], [(status_col, info)],
|
||||||
|
where=Operand(entry_id_col).in_(entry_ids))
|
||||||
|
|
||||||
|
|
||||||
class PushButtonWithData(QtWidgets.QPushButton):
|
class PushButtonWithData(QtWidgets.QPushButton):
|
||||||
|
|
||||||
@@ -142,3 +195,16 @@ class PushButtonWithData(QtWidgets.QPushButton):
|
|||||||
|
|
||||||
def on_self_clicked(self):
|
def on_self_clicked(self):
|
||||||
self.clicked_with_data.emit(self.data)
|
self.clicked_with_data.emit(self.data)
|
||||||
|
|
||||||
|
|
||||||
|
class ActionWithStr(QtGui.QAction):
|
||||||
|
|
||||||
|
triggered_with_str = QtCore.Signal(str)
|
||||||
|
|
||||||
|
def __init__(self, info: str, title: str, parent: QtWidgets.QWidget = None):
|
||||||
|
super().__init__(title, parent)
|
||||||
|
self.info = info
|
||||||
|
self.triggered.connect(self.on_self_triggered)
|
||||||
|
|
||||||
|
def on_self_triggered(self):
|
||||||
|
self.triggered_with_str.emit(self.info)
|
||||||
|
|||||||
Reference in New Issue
Block a user