mirror of
https://github.com/TagStudioDev/TagStudio.git
synced 2026-02-02 08:09:13 +00:00
* feat(ui): add filename label under thumbnails * refactor(ui): organize menu items * feat: make thumbnail filenames toggleable * refactor variables, tweak spacing * fix(ui): only change cursor on thumb_button * revert changes to ../search_library/../ts_library.sqlite * fix: don't ever call .setHidden(False) on visible widgets * refactor: rename filename toggles to setters * fix: remove duplicate open_on_start_action
This commit is contained in:
committed by
GitHub
parent
24fa76ee30
commit
8387676d79
@@ -10,6 +10,7 @@ class SettingItems(str, enum.Enum):
|
||||
LAST_LIBRARY = "last_library"
|
||||
LIBS_LIST = "libs_list"
|
||||
WINDOW_SHOW_LIBS = "window_show_libs"
|
||||
SHOW_FILENAMES = "show_filenames"
|
||||
AUTOPLAY = "autoplay_videos"
|
||||
|
||||
|
||||
|
||||
@@ -25,15 +25,7 @@ import src.qt.resources_rc # noqa: F401
|
||||
import structlog
|
||||
from humanfriendly import format_timespan
|
||||
from PySide6 import QtCore
|
||||
from PySide6.QtCore import (
|
||||
QObject,
|
||||
QSettings,
|
||||
Qt,
|
||||
QThread,
|
||||
QThreadPool,
|
||||
QTimer,
|
||||
Signal,
|
||||
)
|
||||
from PySide6.QtCore import QObject, QSettings, Qt, QThread, QThreadPool, QTimer, Signal
|
||||
from PySide6.QtGui import (
|
||||
QAction,
|
||||
QColor,
|
||||
@@ -264,15 +256,12 @@ class QtDriver(DriverMixin, QObject):
|
||||
|
||||
file_menu = QMenu("&File", menu_bar)
|
||||
edit_menu = QMenu("&Edit", menu_bar)
|
||||
view_menu = QMenu("&View", menu_bar)
|
||||
tools_menu = QMenu("&Tools", menu_bar)
|
||||
macros_menu = QMenu("&Macros", menu_bar)
|
||||
window_menu = QMenu("&Window", menu_bar)
|
||||
help_menu = QMenu("&Help", menu_bar)
|
||||
|
||||
# File Menu ============================================================
|
||||
# file_menu.addAction(QAction('&New Library', menu_bar))
|
||||
# file_menu.addAction(QAction('&Open Library', menu_bar))
|
||||
|
||||
open_library_action = QAction("&Open/Create Library", menu_bar)
|
||||
open_library_action.triggered.connect(lambda: self.open_library_from_dialog())
|
||||
open_library_action.setShortcut(
|
||||
@@ -302,8 +291,6 @@ class QtDriver(DriverMixin, QObject):
|
||||
|
||||
file_menu.addSeparator()
|
||||
|
||||
# refresh_lib_action = QAction('&Refresh Directories', self.main_window)
|
||||
# refresh_lib_action.triggered.connect(lambda: self.lib.refresh_dir())
|
||||
add_new_files_action = QAction("&Refresh Directories", menu_bar)
|
||||
add_new_files_action.triggered.connect(
|
||||
lambda: self.callback_library_needed_check(self.add_new_files_callback)
|
||||
@@ -315,13 +302,23 @@ class QtDriver(DriverMixin, QObject):
|
||||
)
|
||||
)
|
||||
add_new_files_action.setStatusTip("Ctrl+R")
|
||||
# file_menu.addAction(refresh_lib_action)
|
||||
file_menu.addAction(add_new_files_action)
|
||||
file_menu.addSeparator()
|
||||
|
||||
close_library_action = QAction("&Close Library", menu_bar)
|
||||
close_library_action.triggered.connect(self.close_library)
|
||||
file_menu.addAction(close_library_action)
|
||||
file_menu.addSeparator()
|
||||
|
||||
open_on_start_action = QAction("Open Library on Start", self)
|
||||
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("New &Tag", menu_bar)
|
||||
@@ -364,15 +361,32 @@ class QtDriver(DriverMixin, QObject):
|
||||
tag_database_action.triggered.connect(lambda: self.show_tag_database())
|
||||
edit_menu.addAction(tag_database_action)
|
||||
|
||||
check_action = QAction("Open library on start", self)
|
||||
check_action.setCheckable(True)
|
||||
check_action.setChecked(
|
||||
bool(self.settings.value(SettingItems.START_LOAD_LAST, defaultValue=True, type=bool))
|
||||
# View Menu ============================================================
|
||||
show_libs_list_action = QAction("Show Recent Libraries", menu_bar)
|
||||
show_libs_list_action.setCheckable(True)
|
||||
show_libs_list_action.setChecked(
|
||||
bool(self.settings.value(SettingItems.WINDOW_SHOW_LIBS, defaultValue=True, type=bool))
|
||||
)
|
||||
check_action.triggered.connect(
|
||||
lambda checked: self.settings.setValue(SettingItems.START_LOAD_LAST, checked)
|
||||
show_libs_list_action.triggered.connect(
|
||||
lambda checked: (
|
||||
self.settings.setValue(SettingItems.WINDOW_SHOW_LIBS, checked),
|
||||
self.toggle_libs_list(checked),
|
||||
)
|
||||
)
|
||||
window_menu.addAction(check_action)
|
||||
view_menu.addAction(show_libs_list_action)
|
||||
|
||||
show_filenames_action = QAction("Show Filenames in Grid", menu_bar)
|
||||
show_filenames_action.setCheckable(True)
|
||||
show_filenames_action.setChecked(
|
||||
bool(self.settings.value(SettingItems.SHOW_FILENAMES, defaultValue=True, type=bool))
|
||||
)
|
||||
show_filenames_action.triggered.connect(
|
||||
lambda checked: (
|
||||
self.settings.setValue(SettingItems.SHOW_FILENAMES, checked),
|
||||
self.show_grid_filenames(checked),
|
||||
)
|
||||
)
|
||||
view_menu.addAction(show_filenames_action)
|
||||
|
||||
# Tools Menu ===========================================================
|
||||
def create_fix_unlinked_entries_modal():
|
||||
@@ -407,19 +421,6 @@ class QtDriver(DriverMixin, QObject):
|
||||
)
|
||||
macros_menu.addAction(self.autofill_action)
|
||||
|
||||
show_libs_list_action = QAction("Show Recent Libraries", menu_bar)
|
||||
show_libs_list_action.setCheckable(True)
|
||||
show_libs_list_action.setChecked(
|
||||
bool(self.settings.value(SettingItems.WINDOW_SHOW_LIBS, defaultValue=True, type=bool))
|
||||
)
|
||||
show_libs_list_action.triggered.connect(
|
||||
lambda checked: (
|
||||
self.settings.setValue(SettingItems.WINDOW_SHOW_LIBS, checked),
|
||||
self.toggle_libs_list(checked),
|
||||
)
|
||||
)
|
||||
window_menu.addAction(show_libs_list_action)
|
||||
|
||||
def create_folders_tags_modal():
|
||||
if not hasattr(self, "folders_modal"):
|
||||
self.folders_modal = FoldersToTagsModal(self.lib, self)
|
||||
@@ -429,7 +430,7 @@ class QtDriver(DriverMixin, QObject):
|
||||
folders_to_tags_action.triggered.connect(create_folders_tags_modal)
|
||||
macros_menu.addAction(folders_to_tags_action)
|
||||
|
||||
# Help Menu ==========================================================
|
||||
# Help Menu ============================================================
|
||||
self.repo_action = QAction("Visit GitHub Repository", menu_bar)
|
||||
self.repo_action.triggered.connect(
|
||||
lambda: webbrowser.open("https://github.com/TagStudioDev/TagStudio")
|
||||
@@ -439,9 +440,9 @@ class QtDriver(DriverMixin, QObject):
|
||||
|
||||
menu_bar.addMenu(file_menu)
|
||||
menu_bar.addMenu(edit_menu)
|
||||
menu_bar.addMenu(view_menu)
|
||||
menu_bar.addMenu(tools_menu)
|
||||
menu_bar.addMenu(macros_menu)
|
||||
menu_bar.addMenu(window_menu)
|
||||
menu_bar.addMenu(help_menu)
|
||||
|
||||
self.main_window.searchField.textChanged.connect(self.update_completions_list)
|
||||
@@ -551,6 +552,10 @@ class QtDriver(DriverMixin, QObject):
|
||||
self.preview_panel.libs_flow_container.hide()
|
||||
self.preview_panel.update()
|
||||
|
||||
def show_grid_filenames(self, value: bool):
|
||||
for thumb in self.item_thumbs:
|
||||
thumb.set_filename_visibility(value)
|
||||
|
||||
def callback_library_needed_check(self, func):
|
||||
"""Check if loaded library has valid path before executing the button function."""
|
||||
if self.lib.library_dir:
|
||||
@@ -833,9 +838,9 @@ class QtDriver(DriverMixin, QObject):
|
||||
it.thumb_button.setIcon(blank_icon)
|
||||
it.resize(self.thumb_size, self.thumb_size)
|
||||
it.thumb_size = (self.thumb_size, self.thumb_size)
|
||||
it.setMinimumSize(self.thumb_size, self.thumb_size)
|
||||
it.setMaximumSize(self.thumb_size, self.thumb_size)
|
||||
it.setFixedSize(self.thumb_size, self.thumb_size)
|
||||
it.thumb_button.thumb_size = (self.thumb_size, self.thumb_size)
|
||||
it.set_filename_visibility(it.show_filename_label)
|
||||
self.flow_container.layout().setSpacing(
|
||||
min(self.thumb_size // spacing_divisor, min_spacing)
|
||||
)
|
||||
@@ -883,7 +888,14 @@ class QtDriver(DriverMixin, QObject):
|
||||
# TODO - init after library is loaded, it can have different page_size
|
||||
for grid_idx in range(self.filter.page_size):
|
||||
item_thumb = ItemThumb(
|
||||
None, self.lib, self, (self.thumb_size, self.thumb_size), grid_idx
|
||||
None,
|
||||
self.lib,
|
||||
self,
|
||||
(self.thumb_size, self.thumb_size),
|
||||
grid_idx,
|
||||
bool(
|
||||
self.settings.value(SettingItems.SHOW_FILENAMES, defaultValue=True, type=bool)
|
||||
),
|
||||
)
|
||||
|
||||
layout.addWidget(item_thumb)
|
||||
|
||||
@@ -110,6 +110,8 @@ class ItemThumb(FlowWidget):
|
||||
"padding-left: 1px;"
|
||||
)
|
||||
|
||||
filename_style = "font-size:10px;"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
mode: ItemType,
|
||||
@@ -117,6 +119,7 @@ class ItemThumb(FlowWidget):
|
||||
driver: "QtDriver",
|
||||
thumb_size: tuple[int, int],
|
||||
grid_idx: int,
|
||||
show_filename_label: bool = False,
|
||||
):
|
||||
super().__init__()
|
||||
self.grid_idx = grid_idx
|
||||
@@ -125,10 +128,24 @@ class ItemThumb(FlowWidget):
|
||||
self.driver = driver
|
||||
self.item_id: int | None = None
|
||||
self.thumb_size: tuple[int, int] = thumb_size
|
||||
self.show_filename_label: bool = show_filename_label
|
||||
self.label_height = 12
|
||||
self.label_spacing = 4
|
||||
self.setMinimumSize(*thumb_size)
|
||||
self.setMaximumSize(*thumb_size)
|
||||
self.setMouseTracking(True)
|
||||
check_size = 24
|
||||
self.setFixedSize(
|
||||
thumb_size[0],
|
||||
thumb_size[1]
|
||||
+ ((self.label_height + self.label_spacing) if show_filename_label else 0),
|
||||
)
|
||||
|
||||
self.thumb_container = QWidget()
|
||||
self.base_layout = QVBoxLayout(self)
|
||||
self.base_layout.setContentsMargins(0, 0, 0, 0)
|
||||
self.base_layout.setSpacing(0)
|
||||
self.setLayout(self.base_layout)
|
||||
|
||||
# +----------+
|
||||
# | ARC FAV| Top Right: Favorite & Archived Badges
|
||||
@@ -136,6 +153,8 @@ class ItemThumb(FlowWidget):
|
||||
# | |
|
||||
# |EXT #| Lower Left: File Type, Tag Group Icon, or Collation Icon
|
||||
# +----------+ Lower Right: Collation Count, Video Length, or Word Count
|
||||
#
|
||||
# Filename Underneath: (Optional) Filename
|
||||
|
||||
# Thumbnail ============================================================
|
||||
|
||||
@@ -145,9 +164,9 @@ class ItemThumb(FlowWidget):
|
||||
# || ||
|
||||
# |*--------*|
|
||||
# +----------+
|
||||
self.base_layout = QVBoxLayout(self)
|
||||
self.base_layout.setObjectName("baseLayout")
|
||||
self.base_layout.setContentsMargins(0, 0, 0, 0)
|
||||
self.thumb_layout = QVBoxLayout(self.thumb_container)
|
||||
self.thumb_layout.setObjectName("baseLayout")
|
||||
self.thumb_layout.setContentsMargins(0, 0, 0, 0)
|
||||
|
||||
# +----------+
|
||||
# |[~~~~~~~~]|
|
||||
@@ -160,7 +179,7 @@ class ItemThumb(FlowWidget):
|
||||
self.top_layout.setContentsMargins(6, 6, 6, 6)
|
||||
self.top_container = QWidget()
|
||||
self.top_container.setLayout(self.top_layout)
|
||||
self.base_layout.addWidget(self.top_container)
|
||||
self.thumb_layout.addWidget(self.top_container)
|
||||
|
||||
# +----------+
|
||||
# |[~~~~~~~~]|
|
||||
@@ -168,7 +187,7 @@ class ItemThumb(FlowWidget):
|
||||
# | | |
|
||||
# | v |
|
||||
# +----------+
|
||||
self.base_layout.addStretch(2)
|
||||
self.thumb_layout.addStretch(2)
|
||||
|
||||
# +----------+
|
||||
# |[~~~~~~~~]|
|
||||
@@ -181,19 +200,20 @@ class ItemThumb(FlowWidget):
|
||||
self.bottom_layout.setContentsMargins(6, 6, 6, 6)
|
||||
self.bottom_container = QWidget()
|
||||
self.bottom_container.setLayout(self.bottom_layout)
|
||||
self.base_layout.addWidget(self.bottom_container)
|
||||
self.thumb_layout.addWidget(self.bottom_container)
|
||||
|
||||
self.thumb_button = ThumbButton(self, thumb_size)
|
||||
self.thumb_button = ThumbButton(self.thumb_container, thumb_size)
|
||||
self.renderer = ThumbRenderer()
|
||||
self.renderer.updated.connect(
|
||||
lambda ts, i, s, ext: (
|
||||
lambda ts, i, s, fn, ext: (
|
||||
self.update_thumb(ts, image=i),
|
||||
self.update_size(ts, size=s),
|
||||
self.set_filename_text(fn),
|
||||
self.set_extension(ext),
|
||||
)
|
||||
)
|
||||
self.thumb_button.setFlat(True)
|
||||
self.thumb_button.setLayout(self.base_layout)
|
||||
self.thumb_button.setLayout(self.thumb_layout)
|
||||
self.thumb_button.setContextMenuPolicy(Qt.ContextMenuPolicy.ActionsContextMenu)
|
||||
|
||||
self.opener = FileOpenerHelper("")
|
||||
@@ -285,6 +305,16 @@ class ItemThumb(FlowWidget):
|
||||
self.badges[badge_type] = badge
|
||||
self.cb_layout.addWidget(badge)
|
||||
|
||||
# Filename Label =======================================================
|
||||
self.file_label = QLabel(text="Filename")
|
||||
self.file_label.setStyleSheet(ItemThumb.filename_style)
|
||||
self.file_label.setMaximumHeight(self.label_height)
|
||||
if not show_filename_label:
|
||||
self.file_label.setHidden(True)
|
||||
|
||||
self.base_layout.addWidget(self.thumb_container)
|
||||
self.base_layout.addWidget(self.file_label)
|
||||
|
||||
self.set_mode(mode)
|
||||
|
||||
@property
|
||||
@@ -298,11 +328,11 @@ class ItemThumb(FlowWidget):
|
||||
def set_mode(self, mode: ItemType | None) -> None:
|
||||
if mode is None:
|
||||
self.setAttribute(Qt.WidgetAttribute.WA_TransparentForMouseEvents, on=True)
|
||||
self.unsetCursor()
|
||||
self.thumb_button.unsetCursor()
|
||||
self.thumb_button.setHidden(True)
|
||||
elif mode == ItemType.ENTRY and self.mode != ItemType.ENTRY:
|
||||
self.setAttribute(Qt.WidgetAttribute.WA_TransparentForMouseEvents, on=False)
|
||||
self.setCursor(Qt.CursorShape.PointingHandCursor)
|
||||
self.thumb_button.setCursor(Qt.CursorShape.PointingHandCursor)
|
||||
self.thumb_button.setHidden(False)
|
||||
self.cb_container.setHidden(False)
|
||||
# Count Badge depends on file extension (video length, word count)
|
||||
@@ -312,7 +342,7 @@ class ItemThumb(FlowWidget):
|
||||
self.ext_badge.setHidden(True)
|
||||
elif mode == ItemType.COLLATION and self.mode != ItemType.COLLATION:
|
||||
self.setAttribute(Qt.WidgetAttribute.WA_TransparentForMouseEvents, on=False)
|
||||
self.setCursor(Qt.CursorShape.PointingHandCursor)
|
||||
self.thumb_button.setCursor(Qt.CursorShape.PointingHandCursor)
|
||||
self.thumb_button.setHidden(False)
|
||||
self.cb_container.setHidden(True)
|
||||
self.ext_badge.setHidden(True)
|
||||
@@ -321,7 +351,7 @@ class ItemThumb(FlowWidget):
|
||||
self.item_type_badge.setHidden(False)
|
||||
elif mode == ItemType.TAG_GROUP and self.mode != ItemType.TAG_GROUP:
|
||||
self.setAttribute(Qt.WidgetAttribute.WA_TransparentForMouseEvents, on=False)
|
||||
self.setCursor(Qt.CursorShape.PointingHandCursor)
|
||||
self.thumb_button.setCursor(Qt.CursorShape.PointingHandCursor)
|
||||
self.thumb_button.setHidden(False)
|
||||
self.ext_badge.setHidden(True)
|
||||
self.count_badge.setHidden(False)
|
||||
@@ -366,14 +396,40 @@ class ItemThumb(FlowWidget):
|
||||
self.ext_badge.setHidden(True)
|
||||
self.count_badge.setHidden(True)
|
||||
|
||||
def set_filename_text(self, filename: Path | str | None):
|
||||
self.file_label.setText(str(filename))
|
||||
|
||||
def set_filename_visibility(self, set_visible: bool):
|
||||
"""Toggle the visibility of the filename label.
|
||||
|
||||
Args:
|
||||
set_visible (bool): Show the filename, true or false.
|
||||
"""
|
||||
if set_visible:
|
||||
if self.file_label.isHidden():
|
||||
self.file_label.setHidden(False)
|
||||
self.setFixedHeight(self.thumb_size[1] + self.label_height + self.label_spacing)
|
||||
else:
|
||||
self.file_label.setHidden(True)
|
||||
self.setFixedHeight(self.thumb_size[1])
|
||||
self.show_filename_label = set_visible
|
||||
|
||||
def update_thumb(self, timestamp: float, image: QPixmap | None = None):
|
||||
"""Update attributes of a thumbnail element."""
|
||||
if timestamp > ItemThumb.update_cutoff:
|
||||
self.thumb_button.setIcon(image if image else QPixmap())
|
||||
|
||||
def update_size(self, timestamp: float, size: QSize):
|
||||
"""Updates attributes of a thumbnail element."""
|
||||
if timestamp > ItemThumb.update_cutoff and self.thumb_button.iconSize != size:
|
||||
"""Updates attributes of a thumbnail element.
|
||||
|
||||
Args:
|
||||
timestamp (float | None): The UTC timestamp for when this call was
|
||||
originally dispatched. Used to skip outdated jobs.
|
||||
|
||||
size (QSize): The new thumbnail size to set.
|
||||
"""
|
||||
if timestamp > ItemThumb.update_cutoff:
|
||||
self.thumb_size = size.toTuple() # type: ignore
|
||||
self.thumb_button.setIconSize(size)
|
||||
self.thumb_button.setMinimumSize(size)
|
||||
self.thumb_button.setMaximumSize(size)
|
||||
|
||||
@@ -72,7 +72,7 @@ class ThumbRenderer(QObject):
|
||||
"""A class for rendering image and file thumbnails."""
|
||||
|
||||
rm: ResourceManager = ResourceManager()
|
||||
updated = Signal(float, QPixmap, QSize, str)
|
||||
updated = Signal(float, QPixmap, QSize, str, str)
|
||||
updated_ratio = Signal(float)
|
||||
|
||||
def __init__(self) -> None:
|
||||
@@ -1208,8 +1208,15 @@ class ThumbRenderer(QObject):
|
||||
math.ceil(adj_size / pixel_ratio),
|
||||
math.ceil(final.size[1] / pixel_ratio),
|
||||
),
|
||||
str(_filepath.name),
|
||||
_filepath.suffix.lower(),
|
||||
)
|
||||
|
||||
else:
|
||||
self.updated.emit(timestamp, QPixmap(), QSize(*base_size), _filepath.suffix.lower())
|
||||
self.updated.emit(
|
||||
timestamp,
|
||||
QPixmap(),
|
||||
QSize(*base_size),
|
||||
str(_filepath.name),
|
||||
_filepath.suffix.lower(),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user