Skip to content

Add Tag Merging #322

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Aug 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions tagstudio/src/core/library.py
Original file line number Diff line number Diff line change
Expand Up @@ -1895,6 +1895,31 @@ def remove_tag(self, tag_id: int) -> None:
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
Expand Down
63 changes: 63 additions & 0 deletions tagstudio/src/qt/modals/merge_tag.py
Original file line number Diff line number Diff line change
@@ -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()
8 changes: 8 additions & 0 deletions tagstudio/src/qt/widgets/tag.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

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]"
Expand Down Expand Up @@ -77,6 +78,10 @@ def __init__(
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)
Expand Down Expand Up @@ -234,6 +239,9 @@ def __init__(
# 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:
Expand Down