From 031229132f2c00d0671df7540f1f18ed4de85d31 Mon Sep 17 00:00:00 2001 From: Travis Abendshien <46939827+CyanVoxel@users.noreply.github.com> Date: Tue, 7 Jan 2025 04:33:30 -0800 Subject: [PATCH] refactor(ui): move recent libraries list to file menu --- tagstudio/resources/translations/en.json | 2 + tagstudio/src/qt/ts_qt.py | 91 ++++++++++-- .../qt/widgets/preview/recent_libraries.py | 136 ------------------ 3 files changed, 82 insertions(+), 147 deletions(-) delete mode 100644 tagstudio/src/qt/widgets/preview/recent_libraries.py diff --git a/tagstudio/resources/translations/en.json b/tagstudio/resources/translations/en.json index e9247b71..c68e6576 100644 --- a/tagstudio/resources/translations/en.json +++ b/tagstudio/resources/translations/en.json @@ -158,6 +158,8 @@ "menu.file.close_library": "&Close Library", "menu.file.new_library": "New Library", "menu.file.open_create_library": "&Open/Create Library", + "menu.file.open_recent_library": "Open Recent", + "menu.file.clear_recent_libraries": "Clear Recent", "menu.file.open_library": "Open Library", "menu.file.refresh_directories": "&Refresh Directories", "menu.file.save_backup": "&Save Library Backup", diff --git a/tagstudio/src/qt/ts_qt.py b/tagstudio/src/qt/ts_qt.py index 98962715..204d5508 100644 --- a/tagstudio/src/qt/ts_qt.py +++ b/tagstudio/src/qt/ts_qt.py @@ -289,6 +289,27 @@ class QtDriver(DriverMixin, QObject): open_library_action.setToolTip("Ctrl+O") file_menu.addAction(open_library_action) + self.open_recent_library_menu = QMenu(menu_bar) + Translations.translate_qobject( + self.open_recent_library_menu, "menu.file.open_recent_library" + ) + # open_recent_library_menu.set + file_menu.addMenu(self.open_recent_library_menu) + self.update_recent_lib_menu() + + open_on_start_action = QAction(self) + Translations.translate_qobject(open_on_start_action, "settings.open_library_on_start") + open_on_start_action.setCheckable(True) + open_on_start_action.setChecked( + bool(self.settings.value(SettingItems.START_LOAD_LAST, defaultValue=True, type=bool)) + ) + open_on_start_action.triggered.connect( + lambda checked: self.settings.setValue(SettingItems.START_LOAD_LAST, checked) + ) + file_menu.addAction(open_on_start_action) + + file_menu.addSeparator() + save_library_backup_action = QAction(menu_bar) Translations.translate_qobject(save_library_backup_action, "menu.file.save_backup") save_library_backup_action.triggered.connect( @@ -329,17 +350,6 @@ class QtDriver(DriverMixin, QObject): file_menu.addAction(close_library_action) file_menu.addSeparator() - open_on_start_action = QAction(self) - Translations.translate_qobject(open_on_start_action, "settings.open_library_on_start") - open_on_start_action.setCheckable(True) - open_on_start_action.setChecked( - bool(self.settings.value(SettingItems.START_LOAD_LAST, defaultValue=True, type=bool)) - ) - open_on_start_action.triggered.connect( - lambda checked: self.settings.setValue(SettingItems.START_LOAD_LAST, checked) - ) - file_menu.addAction(open_on_start_action) - # Edit Menu ============================================================ new_tag_action = QAction(menu_bar) Translations.translate_qobject(new_tag_action, "menu.edit.new_tag") @@ -1264,6 +1274,65 @@ class QtDriver(DriverMixin, QObject): self.settings.endGroup() self.settings.sync() + self.update_recent_lib_menu() + + def update_recent_lib_menu(self): + """Updates the recent library menu from the latest values from the settings file.""" + actions: list[QAction] = [] + lib_items: dict[str, tuple[str, str]] = {} + + settings = self.settings + settings.beginGroup(SettingItems.LIBS_LIST) + for item_tstamp in settings.allKeys(): + val = str(settings.value(item_tstamp, type=str)) + cut_val = val + if len(val) > 45: + cut_val = f"{val[0:10]} ... {val[-10:]}" + lib_items[item_tstamp] = (val, cut_val) + + # Sort lib_items by the key + libs_sorted = sorted(lib_items.items(), key=lambda item: item[0], reverse=True) + settings.endGroup() + + # Create actions for each library + for library_key in libs_sorted: + path = Path(library_key[1][0]) + action = QAction(self.open_recent_library_menu) + action.setText(str(path)) + action.triggered.connect(lambda checked=False, p=path: self.open_library(p)) + actions.append(action) + + clear_recent_action = QAction(self.open_recent_library_menu) + Translations.translate_qobject(clear_recent_action, "menu.file.clear_recent_libraries") + clear_recent_action.triggered.connect(self.clear_recent_libs) + actions.append(clear_recent_action) + + # Clear previous actions + for action in self.open_recent_library_menu.actions(): + logger.info(action) + self.open_recent_library_menu.removeAction(action) + + # Add new actions + for action in actions: + logger.info(action.text()) + self.open_recent_library_menu.addAction(action) + + # Only enable add "clear recent" if there are still recent libraries. + if len(actions) > 1: + self.open_recent_library_menu.setDisabled(False) + self.open_recent_library_menu.addSeparator() + self.open_recent_library_menu.addAction(clear_recent_action) + else: + self.open_recent_library_menu.setDisabled(True) + + def clear_recent_libs(self): + """Clear the list of recent libraries from the settings file.""" + settings = self.settings + settings.beginGroup(SettingItems.LIBS_LIST) + self.settings.remove("") + self.settings.endGroup() + self.settings.sync() + self.update_recent_lib_menu() def open_library(self, path: Path) -> None: """Open a TagStudio library.""" diff --git a/tagstudio/src/qt/widgets/preview/recent_libraries.py b/tagstudio/src/qt/widgets/preview/recent_libraries.py deleted file mode 100644 index b2f80617..00000000 --- a/tagstudio/src/qt/widgets/preview/recent_libraries.py +++ /dev/null @@ -1,136 +0,0 @@ -# Copyright (C) 2025 Travis Abendshien (CyanVoxel). -# Licensed under the GPL-3.0 License. -# Created for TagStudio: https://github.com/CyanVoxel/TagStudio - -import typing - -import structlog -from PySide6.QtWidgets import ( - QWidget, -) -from src.core.library.alchemy.library import Library - -if typing.TYPE_CHECKING: - from src.qt.ts_qt import QtDriver - -logger = structlog.get_logger(__name__) - - -class RecentLibraries(QWidget): - """The Recent Libraries Widget.""" - - def __init__(self, library: Library, driver: "QtDriver"): - super().__init__() - - # # keep list of rendered libraries to avoid needless re-rendering - # self.render_libs: set = set() - # self.library = library - # self.driver = driver - # layout = QVBoxLayout() - - # settings = driver.settings - # settings.beginGroup(SettingItems.LIBS_LIST) - # lib_items: dict[str, tuple[str, str]] = {} - # for item_tstamp in settings.allKeys(): - # val = str(settings.value(item_tstamp, type=str)) - # cut_val = val - # if len(val) > 45: - # cut_val = f"{val[0:10]} ... {val[-10:]}" - # lib_items[item_tstamp] = (val, cut_val) - - # settings.endGroup() - - # new_keys = set(lib_items.keys()) - # if new_keys == self.render_libs: - # # no need to re-render - # return - - # # sort lib_items by the key - # libs_sorted = sorted(lib_items.items(), key=lambda item: item[0], reverse=True) - - # self.render_libs = new_keys - # self.setLayout(layout) - - # self._fill_libs_widget(libs_sorted, layout) - - # def _fill_libs_widget( - # self, - # libraries: list[tuple[str, tuple[str, str]]], - # layout: QVBoxLayout, - # ): - # def clear_layout(layout_item: QVBoxLayout): - # for i in reversed(range(layout_item.count())): - # child = layout_item.itemAt(i) - # if child.widget() is not None: - # child.widget().deleteLater() - # elif child.layout() is not None: - # clear_layout(child.layout()) # type: ignore - - -# # remove any potential previous items -# clear_layout(layout) - -# label = QLabel() -# Translations.translate_qobject(label, "generic.recent_libraries") -# label.setAlignment(Qt.AlignmentFlag.AlignCenter) - -# row_layout = QHBoxLayout() -# row_layout.addWidget(label) -# layout.addLayout(row_layout) - -# def set_button_style( -# btn: QPushButtonWrapper | QPushButton, extras: list[str] | None = None -# ): -# base_style = [ -# f"background-color:{Theme.COLOR_BG.value};", -# "border-radius:6px;", -# "text-align: left;", -# "padding-top: 3px;", -# "padding-left: 6px;", -# "padding-bottom: 4px;", -# ] - -# full_style_rows = base_style + (extras or []) - -# btn.setStyleSheet( -# "QPushButton{" -# f"{''.join(full_style_rows)}" -# "}" -# f"QPushButton::hover{{background-color:{Theme.COLOR_HOVER.value};}}" -# f"QPushButton::pressed{{background-color:{Theme.COLOR_PRESSED.value};}}" -# f"QPushButton::disabled{{background-color:{Theme.COLOR_FORBIDDEN_BG.value};}}" -# ) -# btn.setCursor(Qt.CursorShape.PointingHandCursor) - -# for item_key, (full_val, cut_val) in libraries: -# button = QPushButton(text=cut_val) -# button.setObjectName(f"path{item_key}") - -# lib = Path(full_val) -# if not lib.exists() or not (lib / TS_FOLDER_NAME).exists(): -# button.setDisabled(True) -# Translations.translate_with_setter(button.setToolTip, "library.missing") - -# def open_library_button_clicked(path): -# return lambda: self.driver.open_library(Path(path)) - -# button.clicked.connect(open_library_button_clicked(full_val)) -# set_button_style(button, ["padding-left: 6px;", "text-align: left;"]) -# button_remove = QPushButton("—") -# button_remove.setCursor(Qt.CursorShape.PointingHandCursor) -# button_remove.setFixedWidth(24) -# set_button_style(button_remove, ["font-weight:bold;", "text-align:center;"]) - -# def remove_recent_library_clicked(key: str): -# return lambda: ( -# self.driver.remove_recent_library(key), -# self.fill_libs_widget(self.libs_layout), -# ) - -# button_remove.clicked.connect(remove_recent_library_clicked(item_key)) - -# row_layout = QHBoxLayout() -# row_layout.addWidget(button) -# row_layout.addWidget(button_remove) - -# layout.addLayout(row_layout)