feat(tags): add tag merging (#322)

* added merge tag context menu option, created modal, and created merge_tag logic

* forgot to close out the modal

* added ability to re-assign current tag

* ruff/mypy checks
This commit is contained in:
Brady LaTessa
2024-08-28 15:57:45 -04:00
committed by GitHub
parent 02c245504a
commit 205a362bda
3 changed files with 96 additions and 0 deletions

View File

@@ -1895,6 +1895,31 @@ class Library:
for t in self.tags:
self._map_tag_strings_to_tag_id(t)
def merge_tag(self, source_tag: Tag, target_tag: Tag) -> None:
source_tag_id: int = source_tag.id
target_tag_id: int = target_tag.id
if source_tag.name not in target_tag.aliases:
target_tag.aliases.append(source_tag.name)
for alias in source_tag.aliases:
if alias not in target_tag.aliases:
target_tag.aliases.append(alias)
for subtag_id in source_tag.subtag_ids:
if subtag_id not in target_tag.subtag_ids:
target_tag.subtag_ids.append(subtag_id)
for entry in self.entries:
for field in entry.fields:
if self.get_field_attr(field, "type") == "tag_box":
if source_tag_id in self.get_field_attr(field, "content"):
self.get_field_attr(field, "content").remove(source_tag_id)
if target_tag_id not in self.get_field_attr(field, "content"):
self.get_field_attr(field, "content").append(target_tag_id)
self.remove_tag(source_tag_id)
def get_tag_ref_count(self, tag_id: int) -> tuple[int, int]:
"""Returns an int tuple (entry_ref_count, subtag_ref_count) of Tag reference counts."""
entry_ref_count: int = 0

View File

@@ -0,0 +1,63 @@
from PySide6.QtWidgets import QDialog, QVBoxLayout, QLabel, QComboBox, QPushButton
from PySide6.QtCore import Qt
import logging
class MergeTagModal(QDialog):
def __init__(self, library, current_tag):
super().__init__()
self.lib = library
self.current_tag = current_tag
self.init_ui()
def init_ui(self):
layout = QVBoxLayout()
layout.addWidget(QLabel("Selected tag:"))
self.selected_tag_dropdown = QComboBox(self)
for tag in self.lib.tags:
self.selected_tag_dropdown.addItem(tag.display_name(self.lib), tag)
self.selected_tag_dropdown.setCurrentIndex(self.find_current_tag_index())
self.selected_tag_dropdown.currentIndexChanged.connect(self.update_current_tag)
layout.addWidget(self.selected_tag_dropdown)
arrow_label = QLabel("")
arrow_label.setAlignment(Qt.AlignCenter)
layout.addWidget(arrow_label)
layout.addWidget(QLabel("Select tag to merge with:"))
self.tag2_dropdown = QComboBox(self)
self.update_tag2_dropdown()
layout.addWidget(self.tag2_dropdown)
self.merge_button = QPushButton("Merge", self)
layout.addWidget(self.merge_button)
self.merge_button.clicked.connect(self.merge_tags)
self.setLayout(layout)
def find_current_tag_index(self):
for index in range(self.selected_tag_dropdown.count()):
if self.selected_tag_dropdown.itemData(index) == self.current_tag:
return index
return 0
def update_current_tag(self):
self.current_tag = self.selected_tag_dropdown.currentData()
self.update_tag2_dropdown()
def update_tag2_dropdown(self):
self.tag2_dropdown.clear()
for tag in self.lib.tags:
if tag.id != self.current_tag.id:
self.tag2_dropdown.addItem(tag.display_name(self.lib), tag)
def merge_tags(self):
target_tag = self.tag2_dropdown.currentData()
if target_tag and self.current_tag != target_tag:
self.lib.merge_tag(self.current_tag, target_tag)
self.accept()
else:
logging.error("MergeTagModal: Invalid tag selection.")
self.reject()

View File

@@ -15,6 +15,7 @@ from PySide6.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QPushButton
from src.core.library import Library, Tag
from src.core.palette import ColorType, get_tag_color
from src.qt.modals.merge_tag import MergeTagModal
ERROR = f"[ERROR]"
@@ -77,6 +78,10 @@ class TagWidget(QWidget):
add_to_search_action = QAction("Add to Search", self)
self.bg_button.addAction(add_to_search_action)
merge_tag_action = QAction("Merge Tag", self)
merge_tag_action.triggered.connect(self.show_merge_tag_modal)
self.bg_button.addAction(merge_tag_action)
self.inner_layout = QHBoxLayout()
self.inner_layout.setObjectName("innerLayout")
self.inner_layout.setContentsMargins(2, 2, 2, 2)
@@ -234,6 +239,9 @@ class TagWidget(QWidget):
# pass
# # self.bg.clicked.connect(lambda checked=False, filepath=filepath: open_file(filepath))
# # self.bg.clicked.connect(function)
def show_merge_tag_modal(self):
modal = MergeTagModal(self.lib, self.tag)
modal.exec_()
def enterEvent(self, event: QEnterEvent) -> None:
if self.has_remove: