diff --git a/ArtNet/artnet_manager.py b/ArtNet/artnet_manager.py index a7efcbd..6dd1d9f 100644 --- a/ArtNet/artnet_manager.py +++ b/ArtNet/artnet_manager.py @@ -342,6 +342,7 @@ class ArtNetManager: len(image_db_result["title"]) > 0 else self.window.UNKNOWN_TITLE image_author = self.db_connection.get_authors_of_art_by_ID(image_db_result["ID"]) image_link = image_db_result["link"] + image_description = image_db_result["description"] art_ID = image_db_result["ID"] if image_author is None or len(image_author) == 0: image_author = [(self.all_images[self.curr_image_index].split(os.path.sep)[0], "(Not in Database)")] @@ -350,12 +351,13 @@ class ArtNetManager: image_author = [(s[0], "(Not in Database)")] image_title = s[-1] + " (Not in Database)" image_link = "(Unknown)" + image_description = None print("Displaying", self.all_images[self.curr_image_index]) self.window.display_image(image_title, image_author, os.path.join(self.config.data["file_root"], self.all_images[self.curr_image_index]), self.all_images[self.curr_image_index], - art_ID, image_link, file_name=s[-1]) + art_ID, image_link, file_name=s[-1], description=image_description) self.window.set_tag_list([self.db_connection.get_tag_by_ID(x)[0][1].strip() for x in self.db_connection.get_art_tags_by_ID(art_ID)]) self.window.data_changed = False diff --git a/ArtNet/db/db_adapter.py b/ArtNet/db/db_adapter.py index 2283319..f42a58b 100644 --- a/ArtNet/db/db_adapter.py +++ b/ArtNet/db/db_adapter.py @@ -47,7 +47,7 @@ class DBAdapter: return True - def save_image(self, ID: str, title: str, authors: list, path: str, tags: list, link: str, md5_hash: str): + def save_image(self, ID: str, title: str, authors: list, path: str, tags: list, link: str, md5_hash: str, desc: str): """ Updates or saves the given image data to the DB :param ID: @@ -57,28 +57,31 @@ class DBAdapter: :param tags: list of tag names List[str] :param link: :param md5_hash: md5 hash as a hex digest + :param desc: image description or None for empty :return: """ - print("Saving Image {0}:{1} authors: {2} path: {3} tags: {4} link: {5} hash:{6}" - .format(ID, title, authors, path, tags, link, md5_hash)) - d = {"title": title, "path": path, "id": ID, "link": link, "hash": md5_hash} + print("Saving Image {0}:{1} authors: {2} path: {3} tags: {4} link: {5} hash:{6} desc:{7}" + .format(ID, title, authors, path, tags, link, md5_hash, desc)) + d = {"title": title, "path": path, "id": ID, "link": link, "hash": md5_hash, "desc": desc} if self.get_art_by_path(path) is None: if ID is None: self.db_cursor.execute( - "INSERT INTO art (path, title, link, md5_hash) VALUES (%(path)s, %(title)s, %(link)s, %(hash)s)", + "INSERT INTO art (path, title, link, md5_hash, description) " + "VALUES (%(path)s, %(title)s, %(link)s, %(hash)s, %(desc)s)", d) ID = self.get_art_by_path(path)["ID"] d["id"] = ID elif self.get_tag_by_ID(ID) is None: self.db_cursor.execute( - "INSERT INTO art (path, title, link, md5_hash) VALUES (%(path)s, %(title)s, %(link)s, %(hash)s)", d) + "INSERT INTO art (path, title, link, md5_hash, description) " + "VALUES (%(path)s, %(title)s, %(link)s, %(hash)s, %(desc)s)", d) else: self.db_cursor.execute("UPDATE art SET path = %(path)s, title = %(title)s, link = %(link)s, " + - "md5_hash = %(hash)s WHERE id = %(id)s", d) + "md5_hash = %(hash)s, description = %(desc)s WHERE id = %(id)s", d) if ID is None: ID = self.get_art_by_path(path)["ID"] - assert(ID != None) + assert(ID != None) # was checked before, should never fail old_tags = [self.get_tag_by_ID(x)[0][1].strip() for x in self.get_art_tags_by_ID(ID)] for tag in tags: @@ -135,7 +138,6 @@ class DBAdapter: #self.db_cursor.execute("DELETE FROM art WHERE md5_hash = %(hash)s", {"hash": hash}) - def remove_artist_from_image(self, art_ID, presence_name, presence_domain): """ Removes the relationship between an artist and the image @@ -344,7 +346,7 @@ class DBAdapter: :return: """ d = {"hash": file_hash} - self.db_cursor.execute("SELECT id, path, title, link, md5_hash FROM art where md5_hash = %(hash)s", d) + self.db_cursor.execute("SELECT id, path, title, link, md5_hash, description FROM art where md5_hash = %(hash)s", d) result = self.db_cursor.fetchall() @@ -358,6 +360,7 @@ class DBAdapter: "title": result[2], "link": result[3], "md5_hash": result[4], + "description": result[5], } return image_data diff --git a/ArtNet/gui/dialogs/artist_modify_dialog/artist_modify_dialog.py b/ArtNet/gui/dialogs/artist_modify_dialog/artist_modify_dialog.py index ddc7de8..3ed320f 100644 --- a/ArtNet/gui/dialogs/artist_modify_dialog/artist_modify_dialog.py +++ b/ArtNet/gui/dialogs/artist_modify_dialog/artist_modify_dialog.py @@ -2,7 +2,7 @@ # Form implementation generated from reading ui file 'dialogs/artist_modify_dialog/artist_modify_dialog.ui' # -# Created by: PyQt5 UI code generator 5.15.0 +# Created by: PyQt5 UI code generator 5.15.6 # # WARNING: Any manual changes made to this file will be lost when pyuic5 is # run again. Do not edit this file unless you know what you are doing. @@ -79,8 +79,8 @@ class Ui_Artist_Mod_Dialog(object): self.verticalLayout.addWidget(self.buttonBox) self.retranslateUi(Artist_Mod_Dialog) - self.buttonBox.accepted.connect(Artist_Mod_Dialog.accept) - self.buttonBox.rejected.connect(Artist_Mod_Dialog.reject) + self.buttonBox.accepted.connect(Artist_Mod_Dialog.accept) # type: ignore + self.buttonBox.rejected.connect(Artist_Mod_Dialog.reject) # type: ignore QtCore.QMetaObject.connectSlotsByName(Artist_Mod_Dialog) def retranslateUi(self, Artist_Mod_Dialog): diff --git a/ArtNet/gui/dialogs/category_modify_dialog/category_modify_dialog.py b/ArtNet/gui/dialogs/category_modify_dialog/category_modify_dialog.py index 2bb7e8e..f6213dd 100644 --- a/ArtNet/gui/dialogs/category_modify_dialog/category_modify_dialog.py +++ b/ArtNet/gui/dialogs/category_modify_dialog/category_modify_dialog.py @@ -2,7 +2,7 @@ # Form implementation generated from reading ui file 'dialogs/category_modify_dialog/category_modify_dialog.ui' # -# Created by: PyQt5 UI code generator 5.15.0 +# Created by: PyQt5 UI code generator 5.15.6 # # WARNING: Any manual changes made to this file will be lost when pyuic5 is # run again. Do not edit this file unless you know what you are doing. @@ -71,8 +71,8 @@ class Ui_category_modify_dialog(object): self.verticalLayout.addWidget(self.buttonBox) self.retranslateUi(category_modify_dialog) - self.buttonBox.accepted.connect(category_modify_dialog.accept) - self.buttonBox.rejected.connect(category_modify_dialog.reject) + self.buttonBox.accepted.connect(category_modify_dialog.accept) # type: ignore + self.buttonBox.rejected.connect(category_modify_dialog.reject) # type: ignore QtCore.QMetaObject.connectSlotsByName(category_modify_dialog) def retranslateUi(self, category_modify_dialog): diff --git a/ArtNet/gui/dialogs/db_connection_dialog/db_connection_dialog.py b/ArtNet/gui/dialogs/db_connection_dialog/db_connection_dialog.py index 0e577ed..b57a715 100644 --- a/ArtNet/gui/dialogs/db_connection_dialog/db_connection_dialog.py +++ b/ArtNet/gui/dialogs/db_connection_dialog/db_connection_dialog.py @@ -2,7 +2,7 @@ # Form implementation generated from reading ui file 'dialogs/db_connection_dialog/db_connection_dialog.ui' # -# Created by: PyQt5 UI code generator 5.15.0 +# Created by: PyQt5 UI code generator 5.15.6 # # WARNING: Any manual changes made to this file will be lost when pyuic5 is # run again. Do not edit this file unless you know what you are doing. @@ -122,8 +122,8 @@ class Ui_DBConnection(object): self.verticalLayout.addWidget(self.buttonBox) self.retranslateUi(DBConnection) - self.buttonBox.accepted.connect(DBConnection.accept) - self.buttonBox.rejected.connect(DBConnection.reject) + self.buttonBox.accepted.connect(DBConnection.accept) # type: ignore + self.buttonBox.rejected.connect(DBConnection.reject) # type: ignore QtCore.QMetaObject.connectSlotsByName(DBConnection) def retranslateUi(self, DBConnection): diff --git a/ArtNet/gui/dialogs/presence_modify_dialog/presence_modify_dialog.py b/ArtNet/gui/dialogs/presence_modify_dialog/presence_modify_dialog.py index 460f460..9702a8a 100644 --- a/ArtNet/gui/dialogs/presence_modify_dialog/presence_modify_dialog.py +++ b/ArtNet/gui/dialogs/presence_modify_dialog/presence_modify_dialog.py @@ -2,7 +2,7 @@ # Form implementation generated from reading ui file 'dialogs/presence_modify_dialog/presence_modify_dialog.ui' # -# Created by: PyQt5 UI code generator 5.15.0 +# Created by: PyQt5 UI code generator 5.15.6 # # WARNING: Any manual changes made to this file will be lost when pyuic5 is # run again. Do not edit this file unless you know what you are doing. @@ -122,8 +122,8 @@ class Ui_PresenceModDialog(object): self.verticalLayout.addWidget(self.buttonBox) self.retranslateUi(PresenceModDialog) - self.buttonBox.accepted.connect(PresenceModDialog.accept) - self.buttonBox.rejected.connect(PresenceModDialog.reject) + self.buttonBox.accepted.connect(PresenceModDialog.accept) # type: ignore + self.buttonBox.rejected.connect(PresenceModDialog.reject) # type: ignore QtCore.QMetaObject.connectSlotsByName(PresenceModDialog) def retranslateUi(self, PresenceModDialog): diff --git a/ArtNet/gui/dialogs/presence_selection_dialog/presence_selection_dialog.py b/ArtNet/gui/dialogs/presence_selection_dialog/presence_selection_dialog.py index 7bf2683..061159f 100644 --- a/ArtNet/gui/dialogs/presence_selection_dialog/presence_selection_dialog.py +++ b/ArtNet/gui/dialogs/presence_selection_dialog/presence_selection_dialog.py @@ -2,7 +2,7 @@ # Form implementation generated from reading ui file 'dialogs/presence_selection_dialog/presence_selection_dialog.ui' # -# Created by: PyQt5 UI code generator 5.15.0 +# Created by: PyQt5 UI code generator 5.15.6 # # WARNING: Any manual changes made to this file will be lost when pyuic5 is # run again. Do not edit this file unless you know what you are doing. @@ -79,8 +79,8 @@ class Ui_presence_selection_dialog(object): self.verticalLayout.addWidget(self.buttonBox) self.retranslateUi(presence_selection_dialog) - self.buttonBox.accepted.connect(presence_selection_dialog.accept) - self.buttonBox.rejected.connect(presence_selection_dialog.reject) + self.buttonBox.accepted.connect(presence_selection_dialog.accept) # type: ignore + self.buttonBox.rejected.connect(presence_selection_dialog.reject) # type: ignore QtCore.QMetaObject.connectSlotsByName(presence_selection_dialog) def retranslateUi(self, presence_selection_dialog): diff --git a/ArtNet/gui/dialogs/tag_import_dialog/tag_import_dialog.py b/ArtNet/gui/dialogs/tag_import_dialog/tag_import_dialog.py index 6798c28..7d73cd1 100644 --- a/ArtNet/gui/dialogs/tag_import_dialog/tag_import_dialog.py +++ b/ArtNet/gui/dialogs/tag_import_dialog/tag_import_dialog.py @@ -2,7 +2,7 @@ # Form implementation generated from reading ui file 'dialogs/tag_import_dialog/tag_import_dialog.ui' # -# Created by: PyQt5 UI code generator 5.15.0 +# Created by: PyQt5 UI code generator 5.15.6 # # WARNING: Any manual changes made to this file will be lost when pyuic5 is # run again. Do not edit this file unless you know what you are doing. @@ -116,8 +116,8 @@ class Ui_Dialog(object): self.verticalLayout.addWidget(self.buttonBox) self.retranslateUi(Dialog) - self.buttonBox.accepted.connect(Dialog.accept) - self.buttonBox.rejected.connect(Dialog.reject) + self.buttonBox.accepted.connect(Dialog.accept) # type: ignore + self.buttonBox.rejected.connect(Dialog.reject) # type: ignore QtCore.QMetaObject.connectSlotsByName(Dialog) def retranslateUi(self, Dialog): diff --git a/ArtNet/gui/dialogs/tag_modify_dialog/tag_modify_dialog.py b/ArtNet/gui/dialogs/tag_modify_dialog/tag_modify_dialog.py index 53ad4e0..efc0e9b 100644 --- a/ArtNet/gui/dialogs/tag_modify_dialog/tag_modify_dialog.py +++ b/ArtNet/gui/dialogs/tag_modify_dialog/tag_modify_dialog.py @@ -2,7 +2,7 @@ # Form implementation generated from reading ui file 'dialogs/tag_modify_dialog/tag_modify_dialog.ui' # -# Created by: PyQt5 UI code generator 5.15.0 +# Created by: PyQt5 UI code generator 5.15.6 # # WARNING: Any manual changes made to this file will be lost when pyuic5 is # run again. Do not edit this file unless you know what you are doing. @@ -197,8 +197,8 @@ class Ui_TagModify(object): self.verticalLayout.addWidget(self.buttonBox) self.retranslateUi(TagModify) - self.buttonBox.accepted.connect(TagModify.accept) - self.buttonBox.rejected.connect(TagModify.reject) + self.buttonBox.accepted.connect(TagModify.accept) # type: ignore + self.buttonBox.rejected.connect(TagModify.reject) # type: ignore QtCore.QMetaObject.connectSlotsByName(TagModify) def retranslateUi(self, TagModify): diff --git a/ArtNet/gui/dialogs/tag_select_dialog/tag_selection_dialog.py b/ArtNet/gui/dialogs/tag_select_dialog/tag_selection_dialog.py index cd885a7..8d721d7 100644 --- a/ArtNet/gui/dialogs/tag_select_dialog/tag_selection_dialog.py +++ b/ArtNet/gui/dialogs/tag_select_dialog/tag_selection_dialog.py @@ -2,7 +2,7 @@ # Form implementation generated from reading ui file 'dialogs/tag_select_dialog/tag_selection_dialog.ui' # -# Created by: PyQt5 UI code generator 5.15.0 +# Created by: PyQt5 UI code generator 5.15.6 # # WARNING: Any manual changes made to this file will be lost when pyuic5 is # run again. Do not edit this file unless you know what you are doing. @@ -50,8 +50,8 @@ class Ui_TagSelection(object): self.verticalLayout_2.addWidget(self.buttonBox) self.retranslateUi(TagSelection) - self.buttonBox.accepted.connect(TagSelection.accept) - self.buttonBox.rejected.connect(TagSelection.reject) + self.buttonBox.accepted.connect(TagSelection.accept) # type: ignore + self.buttonBox.rejected.connect(TagSelection.reject) # type: ignore QtCore.QMetaObject.connectSlotsByName(TagSelection) def retranslateUi(self, TagSelection): diff --git a/ArtNet/gui/dockers/presence/presence_docker.py b/ArtNet/gui/dockers/presence/presence_docker.py index 2c56b3e..7cd6792 100644 --- a/ArtNet/gui/dockers/presence/presence_docker.py +++ b/ArtNet/gui/dockers/presence/presence_docker.py @@ -2,7 +2,7 @@ # Form implementation generated from reading ui file 'dockers/presence/presence_docker.ui' # -# Created by: PyQt5 UI code generator 5.15.0 +# Created by: PyQt5 UI code generator 5.15.6 # # WARNING: Any manual changes made to this file will be lost when pyuic5 is # run again. Do not edit this file unless you know what you are doing. diff --git a/ArtNet/gui/picture_importer.py b/ArtNet/gui/picture_importer.py index 3bc8f48..55c1ab7 100644 --- a/ArtNet/gui/picture_importer.py +++ b/ArtNet/gui/picture_importer.py @@ -2,7 +2,7 @@ # Form implementation generated from reading ui file 'picture_importer.ui' # -# Created by: PyQt5 UI code generator 5.15.0 +# Created by: PyQt5 UI code generator 5.15.6 # # WARNING: Any manual changes made to this file will be lost when pyuic5 is # run again. Do not edit this file unless you know what you are doing. @@ -14,7 +14,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") - MainWindow.resize(827, 777) + MainWindow.resize(1239, 824) self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setEnabled(True) self.centralwidget.setObjectName("centralwidget") @@ -135,15 +135,21 @@ class Ui_MainWindow(object): self.link_label.setAlignment(QtCore.Qt.AlignCenter) self.link_label.setObjectName("link_label") self.verticalLayout.addWidget(self.link_label) - self.label_5 = QtWidgets.QLabel(self.center_frame) - self.label_5.setObjectName("label_5") - self.verticalLayout.addWidget(self.label_5) + self.source_link_label = QtWidgets.QLabel(self.center_frame) + self.source_link_label.setObjectName("source_link_label") + self.verticalLayout.addWidget(self.source_link_label) self.link_line = QtWidgets.QLineEdit(self.center_frame) font = QtGui.QFont() font.setPointSize(7) self.link_line.setFont(font) self.link_line.setObjectName("link_line") self.verticalLayout.addWidget(self.link_line) + self.description_label = QtWidgets.QLabel(self.center_frame) + self.description_label.setObjectName("description_label") + self.verticalLayout.addWidget(self.description_label) + self.description_edit = QtWidgets.QTextEdit(self.center_frame) + self.description_edit.setObjectName("description_edit") + self.verticalLayout.addWidget(self.description_edit) self.horizontalLayout_2.addWidget(self.center_frame) self.right_layout = QtWidgets.QVBoxLayout() self.right_layout.setSizeConstraint(QtWidgets.QLayout.SetMinimumSize) @@ -263,7 +269,7 @@ class Ui_MainWindow(object): self.statusbar.setObjectName("statusbar") MainWindow.setStatusBar(self.statusbar) self.menuBar = QtWidgets.QMenuBar(MainWindow) - self.menuBar.setGeometry(QtCore.QRect(0, 0, 827, 19)) + self.menuBar.setGeometry(QtCore.QRect(0, 0, 1239, 30)) self.menuBar.setObjectName("menuBar") self.menuArtNet = QtWidgets.QMenu(self.menuBar) self.menuArtNet.setObjectName("menuArtNet") @@ -315,7 +321,8 @@ class Ui_MainWindow(object): self.image_author_label.setText(_translate("MainWindow", "author_name")) self.image_label.setText(_translate("MainWindow", "No Image")) self.link_label.setText(_translate("MainWindow", "Source_Link")) - self.label_5.setText(_translate("MainWindow", "Link:")) + self.source_link_label.setText(_translate("MainWindow", "Link:")) + self.description_label.setText(_translate("MainWindow", "Description:")) self.next_image_button.setText(_translate("MainWindow", ">")) self.label.setText(_translate("MainWindow", "Search Tags")) self.label_2.setText(_translate("MainWindow", "Selected Tags:")) diff --git a/ArtNet/gui/picture_importer.ui b/ArtNet/gui/picture_importer.ui index 22fbf14..7e7f3f3 100644 --- a/ArtNet/gui/picture_importer.ui +++ b/ArtNet/gui/picture_importer.ui @@ -6,8 +6,8 @@ 0 0 - 827 - 777 + 1239 + 824 @@ -216,7 +216,7 @@ - + Link: @@ -231,6 +231,16 @@ + + + + Description: + + + + + + @@ -483,8 +493,8 @@ 0 0 - 827 - 19 + 1239 + 30 diff --git a/ArtNet/gui/window.py b/ArtNet/gui/window.py index e18000a..9947156 100644 --- a/ArtNet/gui/window.py +++ b/ArtNet/gui/window.py @@ -81,11 +81,14 @@ class Window(QtWidgets.QMainWindow): 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.link_line.textChanged.connect(self.on_link_line_change) + self.ui.description_edit.textChanged.connect(self.on_description_change) self.ui.link_label.setText("No Source Available") self.ui.image_file_label.setTextInteractionFlags(Qt.TextSelectableByMouse) self.set_image_title_link() + self.ui.description_edit.setReadOnly(False) + self.on_tag_search_change() self.center() @@ -138,8 +141,13 @@ class Window(QtWidgets.QMainWindow): :return: """ new_title = self.curr_image_title + new_description = self.ui.description_edit.toPlainText().strip() if new_title == self.curr_file_name or len(new_title) == 0 or new_title == Window.UNKNOWN_TITLE: new_title = None + if new_description is None or len(new_description) == 0: + new_description = None + else: + new_description = new_description.strip() image_data = { "ID": self.curr_art_id, "title": new_title, @@ -147,7 +155,8 @@ class Window(QtWidgets.QMainWindow): "path": self.curr_art_path, "tags": self.curr_tags, "link": self.curr_link, - "md5_hash": self.__main.get_md5_of_image(self.curr_art_path) + "md5_hash": self.__main.get_md5_of_image(self.curr_art_path), + "description": new_description, } for presence in self.curr_presences: @@ -163,7 +172,7 @@ class Window(QtWidgets.QMainWindow): self.__main.db_connection.save_image(ID=image_data["ID"], title=image_data["title"], authors=image_data["authors"], path=image_data["path"], tags=image_data["tags"], link=image_data["link"], - md5_hash=image_data["md5_hash"]) + md5_hash=image_data["md5_hash"], desc=image_data["description"]) self.set_temporary_status_message("Saved {0} ({1}) to ArtNet DB!" .format(image_data["title"], image_data["ID"]), 5000) @@ -193,15 +202,6 @@ class Window(QtWidgets.QMainWindow): return self.__main.db_connection.save_presence(name=name, domain=domain, artist_ID=artist[0], link=link) - def remove_presence(self, name: str, domain: str): - """ - Remove the presence from the DB - :param name: - :param domain: - :return: - """ - self.__main.db_connection.remove_presence(name, domain) - def get_authors(self, presence_name: str, presence_domain: str) -> list: """ Query a search for the authors fitting the given strings @@ -449,6 +449,12 @@ class Window(QtWidgets.QMainWindow): item_model.itemChanged.connect(self.on_tag_search_item_changed) self.ui.search_result_list.setModel(item_model) + def set_description_text(self, text: str): + """ + Set the text for the description field + """ + self.ui.description_edit.setText(text) + def set_tag_list(self, tags: list, set_checked: bool = True, no_implication: bool = False): """ Set the tags in the tag list to this. @@ -508,7 +514,7 @@ class Window(QtWidgets.QMainWindow): self.data_changed = True def display_image(self, image_title: str, image_authors: list, full_path: str, relative_path: str, art_ID: int, - link: str, file_name: str): + link: str, file_name: str, description: str): """ Display an image in the central widget :param image_authors: @@ -587,9 +593,12 @@ class Window(QtWidgets.QMainWindow): self.update_window_title() self.ui.link_line.setText(link) self.ui.image_file_label.setText(file_name) + self.ui.description_edit.setText(description) self.set_image_title_link() self.set_image_id_spinbox() + self.data_changed = False # reset any triggered change detection + def update_window_title(self): """ Update the title of the window with the newest image title as given in text field @@ -1054,4 +1063,7 @@ class Window(QtWidgets.QMainWindow): def on_image_author_label_activated(self, link: str): print("Image author link activated!", link) - QDesktopServices.openUrl(QUrl(link)) \ No newline at end of file + QDesktopServices.openUrl(QUrl(link)) + + def on_description_change(self): + self.data_changed = True