From 6b1035b0f61b97d71e97d7a85aaf4503b13b1587 Mon Sep 17 00:00:00 2001 From: DrRetro Date: Fri, 26 Apr 2024 10:07:59 -0400 Subject: [PATCH 1/6] A simple TagDatabasePanel has been created based off TagSearchPanel. To access, go to Edit > Tag Database --- tagstudio/src/qt/ts_qt.py | 130 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) diff --git a/tagstudio/src/qt/ts_qt.py b/tagstudio/src/qt/ts_qt.py index 306fe857..612b7f20 100644 --- a/tagstudio/src/qt/ts_qt.py +++ b/tagstudio/src/qt/ts_qt.py @@ -1147,6 +1147,126 @@ class BuildTagPanel(PanelWidget): # self.search_field.setFocus() # self.parentWidget().hide() +class TagDatabasePanel(PanelWidget): + tag_chosen = Signal(int) + def __init__(self, library): + super().__init__() + self.lib: Library = library + # self.callback = callback + self.first_tag_id = -1 + self.tag_limit = 30 + # self.selected_tag: int = 0 + + self.setMinimumSize(300, 400) + self.root_layout = QVBoxLayout(self) + self.root_layout.setContentsMargins(6,0,6,0) + + self.search_field = QLineEdit() + self.search_field.setObjectName('searchField') + self.search_field.setMinimumSize(QSize(0, 32)) + self.search_field.setPlaceholderText('Search Tags') + self.search_field.textEdited.connect(lambda x=self.search_field.text(): self.update_tags(x)) + self.search_field.returnPressed.connect(lambda checked=False: self.on_return(self.search_field.text())) + + # self.content_container = QWidget() + # self.content_layout = QHBoxLayout(self.content_container) + + self.scroll_contents = QWidget() + self.scroll_layout = QVBoxLayout(self.scroll_contents) + self.scroll_layout.setContentsMargins(6,0,6,0) + self.scroll_layout.setAlignment(Qt.AlignmentFlag.AlignTop) + + self.scroll_area = QScrollArea() + # self.scroll_area.setStyleSheet('background: #000000;') + self.scroll_area.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOn) + # self.scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff) + self.scroll_area.setWidgetResizable(True) + self.scroll_area.setFrameShadow(QFrame.Shadow.Plain) + self.scroll_area.setFrameShape(QFrame.Shape.NoFrame) + # sa.setMaximumWidth(self.preview_size[0]) + self.scroll_area.setWidget(self.scroll_contents) + + # self.add_button = QPushButton() + # self.root_layout.addWidget(self.add_button) + # self.add_button.setText('Add Tag') + # # self.done_button.clicked.connect(lambda checked=False, x=1101: (callback(x), self.hide())) + # self.add_button.clicked.connect(lambda checked=False, x=1101: callback(x)) + # # self.setLayout(self.root_layout) + + self.root_layout.addWidget(self.search_field) + self.root_layout.addWidget(self.scroll_area) + self.update_tags('') + + # def reset(self): + # self.search_field.setText('') + # self.update_tags('') + # self.search_field.setFocus() + + def on_return(self, text:str): + if text and self.first_tag_id >= 0: + # callback(self.first_tag_id) + self.search_field.setText('') + self.update_tags('') + else: + self.search_field.setFocus() + self.parentWidget().hide() + + def update_tags(self, query:str): + # for c in self.scroll_layout.children(): + # c.widget().deleteLater() + while self.scroll_layout.itemAt(0): + # logging.info(f"I'm deleting { self.scroll_layout.itemAt(0).widget()}") + self.scroll_layout.takeAt(0).widget().deleteLater() + + if query: + first_id_set = False + for tag_id in self.lib.search_tags(query, include_cluster=True)[:self.tag_limit-1]: + if not first_id_set: + self.first_tag_id = tag_id + first_id_set = True + c = QWidget() + l = QHBoxLayout(c) + l.setContentsMargins(0,0,0,0) + l.setSpacing(3) + tw = TagWidget(self.lib, self.lib.get_tag(tag_id), True, False) + + l.addWidget(tw) + self.scroll_layout.addWidget(c) + else: + first_id_set = False + for tag in self.lib.tags: + if not first_id_set: + self.first_tag_id = tag.id + first_id_set = True + c = QWidget() + l = QHBoxLayout(c) + l.setContentsMargins(0,0,0,0) + l.setSpacing(3) + tw = TagWidget(self.lib, tag, True, False) + tw.on_edit.connect(lambda checked=False, t=tag: (self.edit_tag(t.id))) + l.addWidget(tw) + self.scroll_layout.addWidget(c) + + self.search_field.setFocus() + + def edit_tag(self, tag_id:int): + btp = BuildTagPanel(self.lib, tag_id) + # btp.on_edit.connect(lambda x: self.edit_tag_callback(x)) + self.edit_modal = PanelModal(btp, + self.lib.get_tag(tag_id).display_name(self.lib), + 'Edit Tag', + done_callback=(self.update_tags('')), + has_save=True) + # self.edit_modal.widget.update_display_name.connect(lambda t: self.edit_modal.title_widget.setText(t)) + panel: BuildTagPanel = self.edit_modal.widget + self.edit_modal.saved.connect(lambda: self.lib.update_tag(btp.build_tag())) + # panel.tag_updated.connect(lambda tag: self.lib.update_tag(tag)) + self.edit_modal.show() + # def enterEvent(self, event: QEnterEvent) -> None: + # self.search_field.setFocus() + # return super().enterEvent(event) + # self.focusOutEvent + class FunctionIterator(QObject): """Iterates over a yielding function and emits progress as the 'value' signal.\n\nThread-Safe Guaranteeā„¢""" @@ -3735,6 +3855,12 @@ class QtDriver(QObject): new_tag_action.triggered.connect(lambda: self.add_tag_action_callback()) edit_menu.addAction(new_tag_action) + edit_menu.addSeparator() + + tag_database_action = QAction('Tag Database', menu_bar) + tag_database_action.triggered.connect(lambda: self.show_tag_database()) + edit_menu.addAction(tag_database_action) + # Tools Menu =========================================================== fix_unlinked_entries_action = QAction('Fix &Unlinked Entries', menu_bar) fue_modal = FixUnlinkedEntriesModal(self.lib, self) @@ -3901,6 +4027,10 @@ class QtDriver(QObject): # panel.tag_updated.connect(lambda tag: self.lib.update_tag(tag)) self.modal.show() + def show_tag_database(self): + self.modal = PanelModal(TagDatabasePanel(self.lib),'Tag Database', 'Tag Database', has_save=False) + self.modal.show() + def add_new_files_callback(self): """Runs when user initiates adding new files to the Library.""" # # if self.lib.files_not_in_library: From f23ff1669eece3d92f04157e9906ccb96bddc728 Mon Sep 17 00:00:00 2001 From: DrRetro Date: Fri, 26 Apr 2024 10:50:19 -0400 Subject: [PATCH 2/6] Fixed Issue when Searching Tags, Editing Option was not Connected to Searched TagWidets --- tagstudio/src/qt/ts_qt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tagstudio/src/qt/ts_qt.py b/tagstudio/src/qt/ts_qt.py index 612b7f20..7d788c46 100644 --- a/tagstudio/src/qt/ts_qt.py +++ b/tagstudio/src/qt/ts_qt.py @@ -1229,7 +1229,7 @@ class TagDatabasePanel(PanelWidget): l.setContentsMargins(0,0,0,0) l.setSpacing(3) tw = TagWidget(self.lib, self.lib.get_tag(tag_id), True, False) - + tw.on_edit.connect(lambda checked=False, t=tag: (self.edit_tag(t.id))) l.addWidget(tw) self.scroll_layout.addWidget(c) else: From 5feb3a6d203a1d5e5b572fe88df3e937541e0e6b Mon Sep 17 00:00:00 2001 From: DrRetro Date: Fri, 26 Apr 2024 10:51:49 -0400 Subject: [PATCH 3/6] Fixed Issue with Previous Commit --- tagstudio/src/qt/ts_qt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tagstudio/src/qt/ts_qt.py b/tagstudio/src/qt/ts_qt.py index 7d788c46..6bedc6f0 100644 --- a/tagstudio/src/qt/ts_qt.py +++ b/tagstudio/src/qt/ts_qt.py @@ -1229,7 +1229,7 @@ class TagDatabasePanel(PanelWidget): l.setContentsMargins(0,0,0,0) l.setSpacing(3) tw = TagWidget(self.lib, self.lib.get_tag(tag_id), True, False) - tw.on_edit.connect(lambda checked=False, t=tag: (self.edit_tag(t.id))) + tw.on_edit.connect(lambda checked=False, t=self.lib.get_tag(tag_id): (self.edit_tag(t.id))) l.addWidget(tw) self.scroll_layout.addWidget(c) else: From 85ae16781796ad8d38907fb10ddebb05bebaf912 Mon Sep 17 00:00:00 2001 From: DrRetro Date: Fri, 26 Apr 2024 11:01:09 -0400 Subject: [PATCH 4/6] Fixed Issue with Tags in Database not refreshing after Tag was Edited. --- tagstudio/src/qt/ts_qt.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tagstudio/src/qt/ts_qt.py b/tagstudio/src/qt/ts_qt.py index 6bedc6f0..114fe1ed 100644 --- a/tagstudio/src/qt/ts_qt.py +++ b/tagstudio/src/qt/ts_qt.py @@ -1255,13 +1255,18 @@ class TagDatabasePanel(PanelWidget): self.edit_modal = PanelModal(btp, self.lib.get_tag(tag_id).display_name(self.lib), 'Edit Tag', - done_callback=(self.update_tags('')), + done_callback=(self.update_tags(self.search_field.text())), has_save=True) # self.edit_modal.widget.update_display_name.connect(lambda t: self.edit_modal.title_widget.setText(t)) panel: BuildTagPanel = self.edit_modal.widget - self.edit_modal.saved.connect(lambda: self.lib.update_tag(btp.build_tag())) + self.edit_modal.saved.connect(lambda: self.edit_tag_callback(btp)) # panel.tag_updated.connect(lambda tag: self.lib.update_tag(tag)) self.edit_modal.show() + + def edit_tag_callback(self, btp:BuildTagPanel): + self.lib.update_tag(btp.build_tag()) + self.update_tags(self.search_field.text()) + # def enterEvent(self, event: QEnterEvent) -> None: # self.search_field.setFocus() # return super().enterEvent(event) From 1f7a5d3cbb00ceb33aa7edcf87dee72c2c19ac1f Mon Sep 17 00:00:00 2001 From: Xarvex Date: Fri, 26 Apr 2024 14:46:13 -0500 Subject: [PATCH 5/6] Windows: fix files w/ spaces opening cmd rather than associated program --- tagstudio/src/qt/ts_qt.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tagstudio/src/qt/ts_qt.py b/tagstudio/src/qt/ts_qt.py index 306fe857..bda97854 100644 --- a/tagstudio/src/qt/ts_qt.py +++ b/tagstudio/src/qt/ts_qt.py @@ -68,7 +68,8 @@ QSettings.setPath(QSettings.IniFormat, QSettings.UserScope, os.getcwd()) def open_file(path: str): try: if sys.platform == "win32": - subprocess.Popen(["start", path], shell=True, close_fds=True, creationflags=subprocess.DETACHED_PROCESS) + # Windows needs special attention to handle spaces in the file + subprocess.Popen(["start", f'"{path.replace('"', '\"')}"'], shell=True, close_fds=True, creationflags=subprocess.DETACHED_PROCESS) else: if sys.platform == "darwin": command_name = "open" From 66fec731368895f41c640e22d56e58fef559e747 Mon Sep 17 00:00:00 2001 From: Xarvex Date: Fri, 26 Apr 2024 15:05:07 -0500 Subject: [PATCH 6/6] Correct usage of start command --- tagstudio/src/qt/ts_qt.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tagstudio/src/qt/ts_qt.py b/tagstudio/src/qt/ts_qt.py index bda97854..fbd05432 100644 --- a/tagstudio/src/qt/ts_qt.py +++ b/tagstudio/src/qt/ts_qt.py @@ -69,7 +69,8 @@ def open_file(path: str): try: if sys.platform == "win32": # Windows needs special attention to handle spaces in the file - subprocess.Popen(["start", f'"{path.replace('"', '\"')}"'], shell=True, close_fds=True, creationflags=subprocess.DETACHED_PROCESS) + # first parameter is for title, NOT filepath + subprocess.Popen(["start", "", os.path.normpath(path)], shell=True, close_fds=True, creationflags=subprocess.DETACHED_PROCESS) else: if sys.platform == "darwin": command_name = "open"