v0.9.13
This commit is contained in:
236
widgets.py
236
widgets.py
@@ -12,6 +12,7 @@ including:
|
||||
import os
|
||||
import glob
|
||||
import shutil
|
||||
import json
|
||||
import lmdb
|
||||
from datetime import datetime
|
||||
from collections import deque
|
||||
@@ -20,11 +21,11 @@ from PySide6.QtWidgets import (
|
||||
QApplication, QWidget, QVBoxLayout, QHBoxLayout, QLineEdit, QPushButton,
|
||||
QMessageBox, QSizePolicy, QInputDialog, QTableWidget, QTableWidgetItem,
|
||||
QMenu, QHeaderView, QAbstractItemView, QTreeView, QLabel, QTextEdit,
|
||||
QComboBox, QCompleter, QToolBar
|
||||
QComboBox, QCompleter, QToolBar, QDialog
|
||||
)
|
||||
from PySide6.QtGui import (
|
||||
QIcon, QStandardItemModel, QStandardItem, QColor, QPainter, QPen,
|
||||
QPalette, QAction,
|
||||
QPalette, QAction, QKeySequence
|
||||
)
|
||||
from PySide6.QtCore import (
|
||||
Signal, QSortFilterProxyModel, Slot, QStringListModel, Qt
|
||||
@@ -33,7 +34,7 @@ from PySide6.QtCore import (
|
||||
from metadatamanager import XattrManager
|
||||
from constants import (
|
||||
LAYOUTS_DIR, RATING_XATTR_NAME, XATTR_COMMENT_NAME, XATTR_NAME, UITexts,
|
||||
FACES_MENU_MAX_ITEMS_DEFAULT, APP_CONFIG
|
||||
FACES_MENU_MAX_ITEMS_DEFAULT, APP_CONFIG, FAVORITES_PATH
|
||||
)
|
||||
|
||||
|
||||
@@ -513,7 +514,7 @@ class TagEditWidget(QWidget):
|
||||
self.refresh_ui()
|
||||
self.tags_updated.emit(updated_files_tags)
|
||||
except Exception as e:
|
||||
QMessageBox.critical(self, "Error", str(e))
|
||||
QMessageBox.critical(self, UITexts.ERROR, str(e))
|
||||
finally:
|
||||
QApplication.restoreOverrideCursor()
|
||||
|
||||
@@ -898,6 +899,233 @@ class HistoryWidget(QWidget):
|
||||
self.refresh_list()
|
||||
|
||||
|
||||
class FavoritesWidget(QWidget):
|
||||
"""A widget for managing favorite search queries."""
|
||||
favorites_changed = Signal()
|
||||
|
||||
def __init__(self, main_win):
|
||||
super().__init__()
|
||||
self.main_win = main_win
|
||||
layout = QVBoxLayout(self)
|
||||
|
||||
self.search_bar = QLineEdit()
|
||||
self.search_bar.setPlaceholderText(UITexts.FAVORITES_SEARCH_PLACEHOLDER)
|
||||
self.search_bar.setClearButtonEnabled(True)
|
||||
self.search_bar.textChanged.connect(self.filter_favorites)
|
||||
layout.addWidget(self.search_bar)
|
||||
|
||||
self.table = QTableWidget()
|
||||
self.table.setColumnCount(3)
|
||||
self.table.setHorizontalHeaderLabels(UITexts.FAVORITES_TABLE_HEADER)
|
||||
self.table.horizontalHeader().setSectionResizeMode(QHeaderView.Interactive)
|
||||
self.table.horizontalHeader().setStretchLastSection(True)
|
||||
self.table.setSelectionBehavior(QAbstractItemView.SelectRows)
|
||||
self.table.setSelectionMode(QAbstractItemView.SingleSelection)
|
||||
self.table.setEditTriggers(QAbstractItemView.NoEditTriggers)
|
||||
self.table.verticalHeader().setVisible(False)
|
||||
self.table.doubleClicked.connect(self.load_selected)
|
||||
layout.addWidget(self.table)
|
||||
|
||||
toolbar = QToolBar()
|
||||
layout.addWidget(toolbar)
|
||||
|
||||
load_action = QAction(QIcon.fromTheme("system-run"), UITexts.LOAD, self)
|
||||
load_action.triggered.connect(self.load_selected)
|
||||
toolbar.addAction(load_action)
|
||||
|
||||
add_action = QAction(QIcon.fromTheme("list-add"), UITexts.CREATE, self)
|
||||
add_action.setToolTip(UITexts.ADD_FAVORITE_TOOLTIP)
|
||||
add_action.triggered.connect(self.add_favorite)
|
||||
toolbar.addAction(add_action)
|
||||
|
||||
edit_action = QAction(QIcon.fromTheme("edit-rename"), UITexts.RENAME, self)
|
||||
edit_action.triggered.connect(self.edit_comment)
|
||||
toolbar.addAction(edit_action)
|
||||
|
||||
shortcut_action = QAction(
|
||||
QIcon.fromTheme("preferences-desktop-keyboard-shortcuts"),
|
||||
UITexts.SHORTCUTS_KEY, self)
|
||||
shortcut_action.triggered.connect(self.edit_shortcut)
|
||||
toolbar.addAction(shortcut_action)
|
||||
|
||||
delete_action = QAction(QIcon.fromTheme("edit-delete"), UITexts.DELETE, self)
|
||||
delete_action.triggered.connect(self.delete_favorite)
|
||||
toolbar.addAction(delete_action)
|
||||
|
||||
toolbar.addSeparator()
|
||||
|
||||
up_action = QAction(QIcon.fromTheme("go-up"), UITexts.MOVE_UP, self)
|
||||
up_action.triggered.connect(self.move_up)
|
||||
toolbar.addAction(up_action)
|
||||
|
||||
down_action = QAction(QIcon.fromTheme("go-down"), UITexts.MOVE_DOWN, self)
|
||||
down_action.triggered.connect(self.move_down)
|
||||
toolbar.addAction(down_action)
|
||||
|
||||
self.refresh_list()
|
||||
|
||||
def resizeEvent(self, event):
|
||||
width = self.table.viewport().width()
|
||||
self.table.setColumnWidth(0, int(width * 0.60))
|
||||
self.table.setColumnWidth(2, int(width * 0.15))
|
||||
super().resizeEvent(event)
|
||||
|
||||
def refresh_list(self):
|
||||
self.table.setRowCount(0)
|
||||
if not os.path.exists(FAVORITES_PATH):
|
||||
return
|
||||
|
||||
try:
|
||||
with open(FAVORITES_PATH, 'r', encoding='utf-8') as f:
|
||||
favorites = json.load(f)
|
||||
except (json.JSONDecodeError, OSError):
|
||||
favorites = []
|
||||
|
||||
self.table.setRowCount(len(favorites))
|
||||
for i, fav in enumerate(favorites):
|
||||
query = fav.get('query', '')
|
||||
comment = fav.get('comment', '')
|
||||
shortcut = fav.get('shortcut', '')
|
||||
self.table.setItem(i, 0, QTableWidgetItem(comment))
|
||||
self.table.setItem(i, 1, QTableWidgetItem(query))
|
||||
self.table.setItem(i, 2, QTableWidgetItem(shortcut))
|
||||
|
||||
def filter_favorites(self, text):
|
||||
search_text = text.lower()
|
||||
for row in range(self.table.rowCount()):
|
||||
item = self.table.item(row, 0)
|
||||
if item:
|
||||
self.table.setRowHidden(row, search_text not in item.text().lower())
|
||||
|
||||
def save_favorites(self):
|
||||
favorites = []
|
||||
for i in range(self.table.rowCount()):
|
||||
item_comment = self.table.item(i, 0)
|
||||
item_query = self.table.item(i, 1)
|
||||
item_shortcut = self.table.item(i, 2)
|
||||
comment = item_comment.text() if item_comment else ""
|
||||
query = item_query.text() if item_query else ""
|
||||
shortcut = item_shortcut.text() if item_shortcut else ""
|
||||
favorites.append({'query': query, 'comment': comment, 'shortcut': shortcut})
|
||||
|
||||
try:
|
||||
with open(FAVORITES_PATH, 'w', encoding='utf-8') as f:
|
||||
json.dump(favorites, f, indent=4)
|
||||
self.favorites_changed.emit()
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
def load_selected(self):
|
||||
row = self.table.currentRow()
|
||||
if row >= 0:
|
||||
query = self.table.item(row, 1).text()
|
||||
self.main_win.process_term(query)
|
||||
|
||||
def add_favorite(self):
|
||||
query = self.main_win.search_input.currentText().strip()
|
||||
if not query:
|
||||
return
|
||||
|
||||
row = self.table.rowCount()
|
||||
self.table.insertRow(row)
|
||||
self.table.setItem(row, 0, QTableWidgetItem(""))
|
||||
self.table.setItem(row, 1, QTableWidgetItem(query))
|
||||
self.table.setItem(row, 2, QTableWidgetItem(""))
|
||||
self.table.setCurrentCell(row, 0)
|
||||
self.save_favorites()
|
||||
|
||||
def edit_comment(self):
|
||||
row = self.table.currentRow()
|
||||
if row < 0:
|
||||
return
|
||||
comment_item = self.table.item(row, 0)
|
||||
query = self.table.item(row, 1).text()
|
||||
old_comment = comment_item.text() if comment_item else ""
|
||||
|
||||
new_comment, ok = QInputDialog.getText(
|
||||
self, UITexts.EDIT_COMMENT_TITLE,
|
||||
UITexts.EDIT_COMMENT_TEXT.format(query),
|
||||
QLineEdit.Normal, old_comment)
|
||||
|
||||
if ok:
|
||||
self.table.item(row, 0).setText(new_comment)
|
||||
self.save_favorites()
|
||||
|
||||
def edit_shortcut(self):
|
||||
row = self.table.currentRow()
|
||||
if row < 0:
|
||||
return
|
||||
query = self.table.item(row, 1).text()
|
||||
current_sc = self.table.item(row, 2).text()
|
||||
|
||||
dialog = QDialog(self)
|
||||
dialog.setWindowTitle(UITexts.EDIT_SHORTCUT_TITLE)
|
||||
dlg_layout = QVBoxLayout(dialog)
|
||||
dlg_layout.addWidget(QLabel(UITexts.EDIT_SHORTCUT_TEXT.format(query)))
|
||||
|
||||
from PySide6.QtWidgets import QKeySequenceEdit, QDialogButtonBox
|
||||
key_edit = QKeySequenceEdit(QKeySequence(current_sc))
|
||||
dlg_layout.addWidget(key_edit)
|
||||
|
||||
buttons = QDialogButtonBox(
|
||||
QDialogButtonBox.Ok | QDialogButtonBox.Cancel | QDialogButtonBox.Reset)
|
||||
buttons.accepted.connect(dialog.accept)
|
||||
buttons.rejected.connect(dialog.reject)
|
||||
buttons.button(QDialogButtonBox.Reset).clicked.connect(
|
||||
lambda: key_edit.setKeySequence(QKeySequence()))
|
||||
dlg_layout.addWidget(buttons)
|
||||
|
||||
if dialog.exec() == QDialog.Accepted:
|
||||
new_sequence = key_edit.keySequence()
|
||||
new_sc_str = new_sequence.toString(QKeySequence.NativeText)
|
||||
if not new_sequence.isEmpty():
|
||||
new_key_combo = new_sequence[0]
|
||||
new_key = new_key_combo.key()
|
||||
new_mods = new_key_combo.keyboardModifiers()
|
||||
|
||||
conflict_desc = self.main_win.shortcut_controller.check_conflict(
|
||||
new_key, new_mods)
|
||||
if conflict_desc and new_sc_str != current_sc:
|
||||
res = QMessageBox.question(self, UITexts.SHORTCUT_CONFLICT_TITLE,
|
||||
UITexts.SHORTCUT_CONFLICT_TEXT.format(
|
||||
new_sc_str, conflict_desc) +
|
||||
"\n\n" +
|
||||
UITexts.SHORTCUT_OVERRIDE_QUESTION,
|
||||
QMessageBox.Yes | QMessageBox.No)
|
||||
if res == QMessageBox.No:
|
||||
return
|
||||
|
||||
self.table.item(row, 2).setText(new_sc_str)
|
||||
self.save_favorites()
|
||||
|
||||
def delete_favorite(self):
|
||||
row = self.table.currentRow()
|
||||
if row >= 0:
|
||||
self.table.removeRow(row)
|
||||
self.save_favorites()
|
||||
|
||||
def move_up(self):
|
||||
row = self.table.currentRow()
|
||||
if row > 0:
|
||||
self._swap_rows(row, row - 1)
|
||||
self.table.setCurrentCell(row - 1, 0)
|
||||
self.save_favorites()
|
||||
|
||||
def move_down(self):
|
||||
row = self.table.currentRow()
|
||||
if row >= 0 and row < self.table.rowCount() - 1:
|
||||
self._swap_rows(row, row + 1)
|
||||
self.table.setCurrentCell(row + 1, 0)
|
||||
self.save_favorites()
|
||||
|
||||
def _swap_rows(self, row1, row2):
|
||||
for col in range(self.table.columnCount()):
|
||||
item1 = self.table.takeItem(row1, col)
|
||||
item2 = self.table.takeItem(row2, col)
|
||||
self.table.setItem(row1, col, item2)
|
||||
self.table.setItem(row2, col, item1)
|
||||
|
||||
|
||||
class RatingStar(QLabel):
|
||||
"""An individual star label for the rating widget."""
|
||||
# Emits the star index (1-5)
|
||||
|
||||
Reference in New Issue
Block a user