Changed Source Link editing; Added Collection UI

Replaced the link LineEdit with a tool button and a dialog to make room for another label that displays selected collections.
dev
Peery 3 years ago
parent 2bb9b06a8f
commit 8a30dc2cb9

@ -75,6 +75,8 @@ class ArtNetManager:
self.import_window = ImporterWindow(self) self.import_window = ImporterWindow(self)
self.browse_window = BrowseWindow(self) self.browse_window = BrowseWindow(self)
self.curr_active_window = self.import_window
if len(self.config.data["file_root"]) == 0 or not os.path.isdir( if len(self.config.data["file_root"]) == 0 or not os.path.isdir(
self.config.data["file_root"]): # no file_root given by config or invalid self.config.data["file_root"]): # no file_root given by config or invalid
logging.info("Querying for new file root due to lack of valid one ...") logging.info("Querying for new file root due to lack of valid one ...")
@ -92,10 +94,9 @@ class ArtNetManager:
if len(self.all_images) == 0: if len(self.all_images) == 0:
raise FileNotFoundError("No files or folders were in artnet root!") raise FileNotFoundError("No files or folders were in artnet root!")
self.curr_image_index = 0 self.curr_image_index = 0
self.curr_active_window = self.import_window
self.refresh_shown_image() self.refresh_shown_image()
self.import_window.show() self.curr_active_window.show()
status = self.__app.exec_() status = self.__app.exec_()
logging.info(f"Shutting client down with status: {status}") logging.info(f"Shutting client down with status: {status}")
@ -106,6 +107,7 @@ class ArtNetManager:
if displayed_image_index is not None: if displayed_image_index is not None:
self.curr_image_index = displayed_image_index self.curr_image_index = displayed_image_index
self.refresh_shown_image() self.refresh_shown_image()
if self.curr_active_window is not None:
self.curr_active_window.hide() self.curr_active_window.hide()
self.browse_window.show() self.browse_window.show()
@ -116,6 +118,7 @@ class ArtNetManager:
if displayed_image_index is not None: if displayed_image_index is not None:
self.curr_image_index = displayed_image_index self.curr_image_index = displayed_image_index
self.refresh_shown_image() self.refresh_shown_image()
if self.curr_active_window is not None:
self.curr_active_window.hide() self.curr_active_window.hide()
self.import_window.show() self.import_window.show()

@ -1,12 +1,17 @@
import logging import logging
from PyQt5.QtCore import Qt
from ArtNet.gui.windows.browser.picture_browser import Ui_MainWindow from ArtNet.gui.windows.browser.picture_browser import Ui_MainWindow
from ArtNet.gui.windows.artnet_mainwindow import ArtnetMainWindow from ArtNet.gui.windows.artnet_mainwindow import ArtnetMainWindow
from ArtNet.gui.dialogs.image_info_dialog.image_dialog import ArtInfoDialog
class BrowseWindow(ArtnetMainWindow): class BrowseWindow(ArtnetMainWindow):
UNKNOWN_TITLE = "-Title Unknown-" UNKNOWN_TITLE = "-Title Unknown-"
UNKNOWN_PRESENCE = "(Not in Database)"
def __init__(self, main): def __init__(self, main):
super().__init__(main) super().__init__(main)
@ -14,14 +19,114 @@ class BrowseWindow(ArtnetMainWindow):
self.ui = Ui_MainWindow() self.ui = Ui_MainWindow()
self.ui.setupUi(self) self.ui.setupUi(self)
self.__showing_search_param_frame: bool = True
self.__showing_detail_frame: bool = True
self.curr_art_id: int = None
self.curr_image_title: str = None
self.curr_link: str = None
self.curr_art_path: str = None
self.curr_file_name: str = None
self.curr_presences: list = list()
self.curr_tags: list = list()
self.curr_imply_tags: list = list()
self.curr_tag_aliases: list = list()
# callbacks
# action
self.ui.actionArtNet_Importer.triggered.connect(self.on_importer_clicked) self.ui.actionArtNet_Importer.triggered.connect(self.on_importer_clicked)
# buttons
self.ui.toggle_search_frame_button.clicked.connect(self.on_toggle_search_frame_clicked)
self.ui.toggle_detail_frame_button.clicked.connect(self.on_toggle_detail_frame_clicked)
self.ui.image_info_button.clicked.connect(self.on_image_info_clicked)
def display_image(self, image_title: str, image_authors: list, full_path: str, relative_path: str, art_ID: int, def display_image(self, image_title: str, image_authors: list, full_path: str, relative_path: str, art_ID: int,
link: str, file_name: str, description: str): link: str, file_name: str, description: str):
""" """
Display the described image in the GraphicsView Display the described image in the GraphicsView
""" """
logging.debug(f"Asked browser to display image ID:\"{art_ID}\", title:\"{image_title}\", path:\"{full_path}\"")
self.set_presences(image_authors)
def set_tag_list(self, tags: list, set_checked: bool = True, no_implication: bool = False):
pass # TODO to implement
def set_presences(self, presences: list):
"""
Set the presences for this window
"""
if len(presences) > 1:
for name, domain in presences:
if domain == BrowseWindow.UNKNOWN_PRESENCE:
presences.remove((name, domain))
elif len(presences) == 0:
presences = [(self.curr_art_path.split("/")[0], BrowseWindow.UNKNOWN_PRESENCE)]
self.curr_presences = presences
self.data_changed = True
def convert_presences_to_text(self, presences: list) -> str:
"""
Prepares the presence variable to be printed as a label.
"""
s = ""
for name, domain in presences:
full_data = self.get_presence(name, domain)
if full_data is None:
link = ""
else:
name, domain, _, link = full_data[0]
text = name + ":" + domain
if link is None or len(link) == 0: # no link, then just do plain text
hyperlink = text
else:
hyperlink = "<a href=\"{0}\">{1}</a>".format(link, text)
s += hyperlink
s += "|"
s = s[:-1]
return s
# callback methods
def on_importer_clicked(self): def on_importer_clicked(self):
logging.debug("Clicked on open ArtNet importer!") logging.debug("Clicked on open ArtNet importer!")
self.main.switch_to_importer() self.main.switch_to_importer()
def on_toggle_search_frame_clicked(self):
logging.debug("Clicked on button to toggle the search frame!")
if self.__showing_search_param_frame:
logging.debug("Hiding search param frame")
self.ui.search_param_frame.hide()
self.__showing_search_param_frame = False
self.ui.toggle_search_frame_button.setArrowType(Qt.RightArrow)
else:
logging.debug("Showing search param frame")
self.ui.search_param_frame.show()
self.__showing_search_param_frame = True
self.ui.toggle_search_frame_button.setArrowType(Qt.LeftArrow)
def on_toggle_detail_frame_clicked(self):
logging.debug("Clicked on button to toggle the detail frame!")
if self.__showing_detail_frame:
logging.debug("Hiding detail frame")
self.ui.bottom_frame.hide()
self.__showing_detail_frame = False
self.ui.toggle_detail_frame_button.setArrowType(Qt.DownArrow)
else:
logging.debug("Showing detail frame")
self.ui.bottom_frame.show()
self.__showing_detail_frame = True
self.ui.toggle_detail_frame_button.setArrowType(Qt.UpArrow)
def on_image_info_clicked(self):
logging.debug("Clicked on button to show image info!")
if self.main.curr_image_index is not None:
dialog = ArtInfoDialog(self)
#dialog.set_image_info() # TODO see image_info_dialog/
dialog.exec_()
else:
pass

@ -0,0 +1,25 @@
from PyQt5 import QtWidgets
from PyQt5.QtGui import QStandardItemModel, QStandardItem
from ArtNet.gui.dialogs.image_info_dialog.image_info_dialog import Ui_Dialog
class ArtInfoDialog(QtWidgets.QDialog):
"""
Dialog popup to display more detailed information about a given Art Entry
"""
def __init__(self, parent=None):
super().__init__(parent)
self.ui = Ui_Dialog()
self.ui.setupUi(self)
def set_image_info(self, image_title: str, presences: str, path: str, artists: str, collections: str, source: str):
"""
Set the image info of this dialog.
"""
self.ui.table_view
self.ui.table_view.setModel()

@ -0,0 +1,23 @@
from PyQt5 import QtWidgets
from ArtNet.gui.dialogs.link_input_dialog.link_input_dialog import Ui_Dialog
class LinkInputDialog(QtWidgets.QDialog):
def __init__(self, parent=None, link: str = None):
super().__init__(parent)
self.ui = Ui_Dialog()
self.ui.setupUi(self)
if link is not None:
self.ui.link_line.setText(link)
def get_link_text(self) -> str:
return self.ui.link_line.text()
def exec_(self) -> str:
if super(LinkInputDialog, self).exec_() == QtWidgets.QDialog.Rejected:
return None
return self.get_link_text()

@ -16,14 +16,15 @@ from ArtNet.gui.dialogs.tag_select_dialog.tag_select_dialog import TagSelectDial
from ArtNet.gui.dockers.presence.presence_dock import PresenceDocker from ArtNet.gui.dockers.presence.presence_dock import PresenceDocker
from ArtNet.gui.dialogs.category_modify_dialog.category_mod_dialog import CategoryModDialog from ArtNet.gui.dialogs.category_modify_dialog.category_mod_dialog import CategoryModDialog
from ArtNet.gui.dialogs.tag_import_dialog.tag_imp_dialog import TagImportDialog from ArtNet.gui.dialogs.tag_import_dialog.tag_imp_dialog import TagImportDialog
from ArtNet.gui.dialogs.link_input_dialog.link_dialog import LinkInputDialog
from ArtNet.web.link_generator import LinkGenerator from ArtNet.web.link_generator import LinkGenerator
class ImporterWindow(ArtnetMainWindow): class ImporterWindow(ArtnetMainWindow):
UNKNOWN_TITLE = "-Title Unknown-" UNKNOWN_TITLE = "-Title Unknown-"
UNKNOWN_PRESENCE = "(Not in Database)" UNKNOWN_PRESENCE = "(Not in Database)"
UNKNOWN_LINK = "No Source Available"
def __init__(self, main): def __init__(self, main):
super().__init__(main) super().__init__(main)
@ -72,7 +73,9 @@ class ImporterWindow(ArtnetMainWindow):
self.ui.import_button.clicked.connect(self.on_import_tags_clicked) self.ui.import_button.clicked.connect(self.on_import_tags_clicked)
self.ui.prev_unknown_image_button.clicked.connect(self.on_prev_unknown_image_clicked) self.ui.prev_unknown_image_button.clicked.connect(self.on_prev_unknown_image_clicked)
self.ui.next_unknown_image_button.clicked.connect(self.on_next_unknown_image_clicked) self.ui.next_unknown_image_button.clicked.connect(self.on_next_unknown_image_clicked)
self.ui.collections_button.clicked.connect(self.on_collection_button_clicked)
self.ui.delete_button.clicked.connect(self.on_delete_image_clicked) self.ui.delete_button.clicked.connect(self.on_delete_image_clicked)
self.ui.link_button.clicked.connect(self.on_source_link_button_clicked)
self.ui.link_label.linkActivated.connect(self.on_link_label_activated) self.ui.link_label.linkActivated.connect(self.on_link_label_activated)
self.ui.image_author_label.linkActivated.connect(self.on_image_author_label_activated) self.ui.image_author_label.linkActivated.connect(self.on_image_author_label_activated)
@ -81,12 +84,10 @@ class ImporterWindow(ArtnetMainWindow):
self.ui.tag_search_bar.textChanged.connect(self.on_tag_search_change) self.ui.tag_search_bar.textChanged.connect(self.on_tag_search_change)
self.ui.image_title_line.textChanged.connect(self.on_image_title_change) self.ui.image_title_line.textChanged.connect(self.on_image_title_change)
self.ui.link_line.textChanged.connect(self.on_link_line_change)
self.ui.description_edit.textChanged.connect(self.on_description_change) self.ui.description_edit.textChanged.connect(self.on_description_change)
self.ui.link_label.setText("No Source Available") self.ui.link_label.setText(ImporterWindow.UNKNOWN_LINK)
self.ui.image_file_label.setTextInteractionFlags(Qt.TextSelectableByMouse) self.ui.image_file_label.setTextInteractionFlags(Qt.TextSelectableByMouse)
self.set_image_title_link()
self.ui.description_edit.setReadOnly(False) self.ui.description_edit.setReadOnly(False)
@ -320,14 +321,14 @@ class ImporterWindow(ArtnetMainWindow):
return self.main.db_connection.search_fuzzy_categories(search) return self.main.db_connection.search_fuzzy_categories(search)
def get_image_link_from_line(self) -> str: def get_image_link_from_label(self) -> str:
""" """
Gets the image link from the QLineEdit if it is a valid link. Gets the image link from the label if it is a valid link.
Otherwise an empty string Otherwise an empty string
:return: :return:
""" """
return self.ui.link_line.text() return self.ui.link_label.text()
def set_presence_label_text(self, presences: list): def set_presence_label_text(self, presences: list):
""" """
@ -335,7 +336,6 @@ class ImporterWindow(ArtnetMainWindow):
:param presences: :param presences:
:return: :return:
""" """
links = []
s = "" s = ""
for name, domain in presences: for name, domain in presences:
full_data = self.get_presence(name, domain) full_data = self.get_presence(name, domain)
@ -355,24 +355,24 @@ class ImporterWindow(ArtnetMainWindow):
s = s[:-1] s = s[:-1]
self.ui.image_author_label.setText(s) self.ui.image_author_label.setText(s)
def set_image_title_link(self) -> str: def set_image_title_link(self, link: str) -> str:
""" """
Sets the Image title to a link if there is link data given for this image. Sets the Image title to a link if there is link data given for this image.
:return: :return: Returns the result that has been set to see if a successful link was constructed
""" """
self.ui.link_label.setText("No Source Available") self.ui.link_label.setText(ImporterWindow.UNKNOWN_LINK)
link = self.ui.link_line.text()
if validators.url(link): if validators.url(link):
self.curr_link = link self.curr_link = link
self.data_changed = True self.data_changed = True
hyperlink = "<a href=\"{0}\">{1}</a>".format(link, "Source") hyperlink = "<a href=\"{0}\">{1}</a>".format(link, "Source")
self.ui.link_label.setText(hyperlink) self.ui.link_label.setText(hyperlink)
self.ui.link_label.setToolTip(link)
return link return link
elif len(link) == 0: elif len(link) == 0:
return "" return ""
else: else:
self.ui.link_label.setText("No Source Available") self.ui.link_label.setText(ImporterWindow.UNKNOWN_LINK)
self.set_temporary_status_message("Invalid link \"{0}\" detected!".format(link), 5000) self.set_temporary_status_message("Invalid link \"{0}\" detected!".format(link), 5000)
return "" return ""
@ -421,11 +421,11 @@ class ImporterWindow(ArtnetMainWindow):
item = QStandardItem(tag) item = QStandardItem(tag)
flags = Qt.ItemIsEnabled flags = Qt.ItemIsEnabled
if tag not in self.curr_imply_tags+self.curr_tag_aliases and tag not in self.curr_tags: if tag not in self.curr_imply_tags + self.curr_tag_aliases and tag not in self.curr_tags:
# new tag and not implied yet # new tag and not implied yet
item.setData(Qt.Unchecked, Qt.CheckStateRole) item.setData(Qt.Unchecked, Qt.CheckStateRole)
flags |= Qt.ItemIsUserCheckable flags |= Qt.ItemIsUserCheckable
if self.curr_tags is not None and tag in (self.curr_tags+self.curr_imply_tags+self.curr_tag_aliases): if self.curr_tags is not None and tag in (self.curr_tags + self.curr_imply_tags + self.curr_tag_aliases):
# already selected, implied or aliased tags # already selected, implied or aliased tags
item.setCheckState(Qt.Checked) item.setCheckState(Qt.Checked)
item.setFlags(flags) item.setFlags(flags)
@ -472,7 +472,7 @@ class ImporterWindow(ArtnetMainWindow):
self.set_implied_list(implied_tags) self.set_implied_list(implied_tags)
self.curr_tag_aliases = list() self.curr_tag_aliases = list()
for tag in tags+implied_tags: for tag in tags + implied_tags:
self.curr_tag_aliases += self.main.db_connection.get_tag_aliases_by_name(tag) self.curr_tag_aliases += self.main.db_connection.get_tag_aliases_by_name(tag)
self.data_changed = True self.data_changed = True
@ -520,7 +520,7 @@ class ImporterWindow(ArtnetMainWindow):
file_ending = relative_path.split(".")[-1] file_ending = relative_path.split(".")[-1]
if self.__showing_video: # remove old video from image layout if self.__showing_video: # remove old video from image layout
#self.ui.image_frame.layout().removeWidget(self.__video) # self.ui.image_frame.layout().removeWidget(self.__video)
self.__video.hide() self.__video.hide()
self.ui.image_label.show() self.ui.image_label.show()
if self.__showing_text: # remove text are from image layout if self.__showing_text: # remove text are from image layout
@ -576,10 +576,9 @@ class ImporterWindow(ArtnetMainWindow):
self.ui.image_label.setAlignment(Qt.AlignCenter) self.ui.image_label.setAlignment(Qt.AlignCenter)
self.ui.image_title_line.setText(image_title) self.ui.image_title_line.setText(image_title)
self.update_window_title() self.update_window_title()
self.ui.link_line.setText(link)
self.ui.image_file_label.setText(file_name) self.ui.image_file_label.setText(file_name)
self.ui.description_edit.setText(description) self.ui.description_edit.setText(description)
self.set_image_title_link() self.set_image_title_link(link)
self.set_image_id_spinbox() self.set_image_id_spinbox()
self.data_changed = False # reset any triggered change detection self.data_changed = False # reset any triggered change detection
@ -591,7 +590,7 @@ class ImporterWindow(ArtnetMainWindow):
""" """
image_title = self.ui.image_title_line.text() image_title = self.ui.image_title_line.text()
self.setWindowTitle(self.main_title + " - " + image_title self.setWindowTitle(self.main_title + " - " + image_title
+ f" ({round(self.main.known_image_amount/len(self.main.all_images), 5)}%)") + f" ({round(self.main.known_image_amount / len(self.main.all_images), 5)}%)")
def set_image_id_spinbox(self): def set_image_id_spinbox(self):
""" """
@ -599,7 +598,7 @@ class ImporterWindow(ArtnetMainWindow):
:return: :return:
""" """
self.ui.imageNumberSpinBox.setMinimum(0) self.ui.imageNumberSpinBox.setMinimum(0)
self.ui.imageNumberSpinBox.setMaximum(len(self.main.all_images)-1) self.ui.imageNumberSpinBox.setMaximum(len(self.main.all_images) - 1)
self.ui.imageNumberSpinBox.setValue(self.main.curr_image_index) self.ui.imageNumberSpinBox.setValue(self.main.curr_image_index)
def __image_resize(self): def __image_resize(self):
@ -613,7 +612,7 @@ class ImporterWindow(ArtnetMainWindow):
size = QSize(min(rect.width(), rect.height()), min(rect.width(), rect.height())) size = QSize(min(rect.width(), rect.height()), min(rect.width(), rect.height()))
if type(self.__pixmap) != QMovie: # using QVideoWidget? if type(self.__pixmap) != QMovie: # using QVideoWidget?
pass pass
#self.__player.setScaledSize(size) # self.__player.setScaledSize(size)
else: else:
self.__pixmap.setScaledSize(size) self.__pixmap.setScaledSize(size)
return return
@ -688,19 +687,19 @@ class ImporterWindow(ArtnetMainWindow):
def on_save_clicked(self): def on_save_clicked(self):
logging.info("Clicked Save!") logging.info("Clicked Save!")
self.set_image_title_link()
self.save_changes() self.save_changes()
def on_import_tags_clicked(self): def on_import_tags_clicked(self):
logging.info("Clicked Import!") logging.info("Clicked Import!")
dialog = TagImportDialog(self) dialog = TagImportDialog(self)
if len(self.get_image_link_from_line()) == 0 or self.get_image_link_from_line() == '(Unknown)': if len(self.get_image_link_from_label()) == 0 \
or self.get_image_link_from_label() == ImporterWindow.UNKNOWN_LINK:
url = LinkGenerator.get_instance().construct_link(self.curr_file_name, url = LinkGenerator.get_instance().construct_link(self.curr_file_name,
LinkGenerator.get_instance() LinkGenerator.get_instance()
.predict_domain(self.curr_file_name)) .predict_domain(self.curr_file_name))
self.ui.link_line.setText(url) # Update no link to the predicted link self.set_image_title_link(url) # Update no link to the predicted link
else: else:
url = self.get_image_link_from_line() url = self.get_image_link_from_label()
r = self.main.scrape_tags(self.curr_file_name, url=url, r = self.main.scrape_tags(self.curr_file_name, url=url,
art_ID=self.curr_art_id) art_ID=self.curr_art_id)
@ -713,8 +712,7 @@ class ImporterWindow(ArtnetMainWindow):
msg.exec_() msg.exec_()
return return
self.ui.link_line.setText(url) self.set_image_title_link(url)
self.set_image_title_link()
tags, artists = r tags, artists = r
i = 0 i = 0
@ -788,12 +786,12 @@ class ImporterWindow(ArtnetMainWindow):
self.presence_docker = PresenceDocker(self) self.presence_docker = PresenceDocker(self)
self.ui.presence_docker_layout.addWidget(self.presence_docker) self.ui.presence_docker_layout.addWidget(self.presence_docker)
self.presence_docker.set_selected_presences_list(self.get_current_presences()) self.presence_docker.set_selected_presences_list(self.get_current_presences())
self.ui.presence_docker_button.setText(">") self.ui.presence_docker_button.setArrowType(Qt.RightArrow)
self.presence_docker_open = True self.presence_docker_open = True
else: else:
logging.info("Closed presence docker!") logging.info("Closed presence docker!")
self.presence_docker.setParent(None) self.presence_docker.setParent(None)
self.ui.presence_docker_button.setText("<") self.ui.presence_docker_button.setArrowType(Qt.LeftArrow)
self.presence_docker.destroy() self.presence_docker.destroy()
self.presence_docker = None self.presence_docker = None
@ -926,7 +924,8 @@ class ImporterWindow(ArtnetMainWindow):
self.main.db_connection.edit_tag(tag_id=tag["ID"], self.main.db_connection.edit_tag(tag_id=tag["ID"],
name=tag_data["name"], description=tag_data["description"], name=tag_data["name"], description=tag_data["description"],
aliases=tag_data["aliases"], implications=tag_data["implications"], aliases=tag_data["aliases"], implications=tag_data["implications"],
category_id=self.main.db_connection.get_category_by_name(tag_data["category"])[0]) category_id=self.main.db_connection.get_category_by_name(tag_data["category"])[
0])
self.on_tag_search_change() self.on_tag_search_change()
def on_tag_search_item_changed(self, item: QStandardItem): def on_tag_search_item_changed(self, item: QStandardItem):
@ -976,9 +975,6 @@ class ImporterWindow(ArtnetMainWindow):
self.main.db_connection.remove_category(data["name"]) self.main.db_connection.remove_category(data["name"])
def on_link_line_change(self):
self.data_changed = True
def on_prev_unknown_image_clicked(self): def on_prev_unknown_image_clicked(self):
unknown_image_index = self.main.get_prev_unknown_image() unknown_image_index = self.main.get_prev_unknown_image()
logging.info("Previous unknown image clicked!") logging.info("Previous unknown image clicked!")
@ -1057,3 +1053,22 @@ class ImporterWindow(ArtnetMainWindow):
def on_browser_clicked(self): def on_browser_clicked(self):
logging.debug("Clicked on open ArtNet browser!") logging.debug("Clicked on open ArtNet browser!")
self.main.switch_to_browser() self.main.switch_to_browser()
def on_source_link_button_clicked(self):
logging.debug("Clicked on link button!")
dialog = LinkInputDialog(self, self.curr_link)
link = dialog.exec_()
if link is None: # dialog was cancelled
logging.debug("Cancelled link dialog.")
return
logging.info(f"Setting source link to \"{link}\"")
self.set_image_title_link(link)
def on_collection_button_clicked(self):
logging.debug("Clicked on collection button!")
QtWidgets.QMessageBox.information(self, "Not Implemented", "This feature has not been implemented yet!")
# TODO open dialog with collection selection and buttons for edit, creation and deletion
# TODO allow editing of the rank string
# TODO make collection inspectable (a list of all entries with their rank string would suffice)

Loading…
Cancel
Save