import logging import os.path from PyQt5 import QtWidgets from PyQt5.QtCore import Qt, QSize, QModelIndex from PyQt5.QtGui import QStandardItem, QStandardItemModel, QIcon from ArtNet.gui.dialogs.image_select_dialog.image_select_dialog import Ui_Dialog from ArtNet.db.db_adapter import DBAdapter from ArtNet.singleton_manager import SingletonManager class ImageSelectDialog(QtWidgets.QDialog): def __init__(self, db_connection, parent=None): super().__init__(parent) self.parent = parent self.__config = SingletonManager.get_manager().config.data self.__file_root = self.__config["file_root"] self.db_connection: DBAdapter = db_connection self.data: dict = None # data to be returned by this dialog to the parent self.__tag_search_result = list() self.__presence_search_result = list() self.__art_list_dict = dict() self.curr_selected_tags = list() self.curr_selected_presences = list() self.setWindowTitle("Select Art") self.ui = Ui_Dialog() self.ui.setupUi(self) self.ui.search_tag_line.textChanged.connect(self.on_tag_search_changed) self.ui.search_presence_name_line.textChanged.connect(self.on_presence_search_changed) self.ui.search_presence_domain_line.textChanged.connect(self.on_presence_search_changed) self.ui.art_selection_list.hide() self.ui.art_selection_list.doubleClicked.connect(self.on_art_doubleclicked) self.on_presence_search_changed("") self.on_tag_search_changed("") def set_tag_search_result_list(self, tags: list): """ Set the tag search result list given the tags from the search """ item_model = QStandardItemModel(self.ui.search_tag_list) self.__tag_search_result = tags for tag in tags: item = QStandardItem(tag) flags = Qt.ItemIsEnabled item.setData(Qt.Unchecked, Qt.CheckStateRole) flags |= Qt.ItemIsUserCheckable if self.curr_selected_tags is not None and tag in self.curr_selected_tags: # already selected, implied or aliased tags item.setCheckState(Qt.Checked) item.setFlags(flags) item_model.appendRow(item) item_model.itemChanged.connect(self.on_tag_search_item_changed) self.ui.search_tag_list.setModel(item_model) def refresh_selected_tags_list(self): """ Refreshes the selected tags list according to self.curr_selected_tags """ item_model = QStandardItemModel(self.ui.selected_tag_list) for tag in self.curr_selected_tags: item = QStandardItem(tag) flags = Qt.ItemIsEnabled item.setData(Qt.Unchecked, Qt.CheckStateRole) flags |= Qt.ItemIsUserCheckable item.setCheckState(Qt.Checked) item.setFlags(flags) item_model.appendRow(item) item_model.itemChanged.connect(self.on_tag_selected_item_changed) self.ui.selected_tag_list.setModel(item_model) self.refresh_image_selection() def refresh_selected_presences_list(self): """ Refreshes the selected presences list according to self.curr_selected_presences """ item_model = QStandardItemModel(self.ui.selected_presence_list) for name, domain in self.curr_selected_presences: item = QStandardItem(f"{name}:{domain}") flags = Qt.ItemIsEnabled item.setData(Qt.Unchecked, Qt.CheckStateRole) flags |= Qt.ItemIsUserCheckable item.setCheckState(Qt.Checked) item.setFlags(flags) item_model.appendRow(item) item_model.itemChanged.connect(self.on_presence_selected_item_changed) self.ui.selected_presence_list.setModel(item_model) self.refresh_image_selection() def refresh_image_selection(self): """ Refreshes the images available for selection by using self.curr_selected_presences and self.curr_selected_tags """ logging.debug(f"Refreshing info selection with tags {self.curr_selected_tags} " f"and presences {self.curr_selected_presences}") arts = self.db_connection.search_art(tags=self.curr_selected_tags, resolve_tags=True, presences=self.curr_selected_presences) #print("Result:", arts) self.ui.art_placeholder_label.hide() self.ui.art_selection_list.show() self.ui.art_selection_list.setViewMode(QtWidgets.QListView.IconMode) self.__art_list_dict = dict() item_model = QStandardItemModel(self.ui.art_selection_list) items = list() if len(arts) > 100: arts = arts[:100] for art in arts: art_data = self.db_connection.get_art_by_ID(art) full_path = os.path.join(self.__file_root, art_data["path"]) if not os.path.isfile(full_path): continue icon = QIcon() icon.addFile(full_path) flags = Qt.ItemIsEnabled item = QStandardItem( art_data["title"] if art_data["title"] is not None else os.path.basename(art_data["path"])) item.setData(icon, role=Qt.DecorationRole) item.setData(art_data["ID"], role=Qt.UserRole) # allows the item to be identified again presences = self.db_connection.get_authors_of_art_by_ID(art_data["ID"]) p = "" for presence in presences: p += f"{presence[0]}:{presence[1]}|" p = p[:-1] item.setData(f"{art_data['title']} \nby \n{p} \n\nDescription:\n{art_data['description']}", role=Qt.ToolTipRole) # tooltip for the item item.setFlags(flags) items.append(item) self.__art_list_dict[art_data["ID"]] = art_data #print("Adding to last row", items) item_model.appendColumn(items) self.ui.art_selection_list.setIconSize(QSize(150, 150)) self.ui.art_selection_list.setModel(item_model) def set_presence_search_result_list(self, presences: list): """ Set the presence search result list as given by presences. """ item_model = QStandardItemModel(self.ui.search_presence_list) self.__presence_search_result = presences for name, domain in presences: item = QStandardItem(f"{name}:{domain}") flags = Qt.ItemIsEnabled item.setData(Qt.Unchecked, Qt.CheckStateRole) flags |= Qt.ItemIsUserCheckable item.setFlags(flags) item_model.appendRow(item) item_model.itemChanged.connect(self.on_presence_search_item_changed) self.ui.search_presence_list.setModel(item_model) def on_art_doubleclicked(self, index: QModelIndex): art_id = index.model().itemData(index)[Qt.UserRole] print(f"Double-clicked: {self.__art_list_dict[art_id]}") self.data = self.__art_list_dict[art_id] self.done(QtWidgets.QDialog.Accepted) def on_tag_search_changed(self, v: str): result = self.db_connection.search_fuzzy_tag(v, all_if_empty=True) self.set_tag_search_result_list([r[0] for r in result]) def on_presence_search_changed(self, v: str): presence_name = self.ui.search_presence_name_line.text() presence_domain = self.ui.search_presence_domain_line.text() result = self.db_connection.search_fuzzy_presence(name=presence_name, domain=presence_domain, all_if_empty=True) presences = list() for name, domain in result: presences.append((name, domain)) self.set_presence_search_result_list(presences) def on_tag_search_item_changed(self, item: QStandardItem): logging.info(f"Tag search item {item.text()} has changed!") if item.checkState() == Qt.Checked: self.curr_selected_tags.append(item.text()) if item.checkState() == Qt.Unchecked: self.curr_selected_tags.remove(item.text()) self.refresh_selected_tags_list() def on_tag_selected_item_changed(self, item: QStandardItem): logging.info(f"Tag select item {item.text()} has changed!") self.curr_selected_tags.remove(item.text()) self.refresh_selected_tags_list() self.set_tag_search_result_list(self.__tag_search_result) def on_presence_search_item_changed(self, item: QStandardItem): logging.info(f"Presence search item {item.text()} has changed!") name, domain = item.text().split(":") if item.checkState() == Qt.Checked: self.curr_selected_presences.append((name, domain)) elif item.checkState() == Qt.Unchecked: self.curr_selected_presences.remove((name, domain)) self.refresh_selected_presences_list() def on_presence_selected_item_changed(self, item: QStandardItem): logging.info(f"Presence select item {item.text()} has changed!") name, domain = item.text().split(":") self.curr_selected_presences.remove((name, domain)) self.set_presence_search_result_list(self.__presence_search_result) self.refresh_selected_presences_list() def exec_(self) -> dict: if super(ImageSelectDialog, self).exec_() == QtWidgets.QDialog.Rejected: return None if self.data is None: self.done(QtWidgets.QDialog.Rejected) return self.data