Added description field to UI

Added a QTextEdit for art descriptions.
Also added the ability to save and load them from the database. Changing of the description field also triggers a unsaved changes prompt.
dev
Peery 2 years ago
parent 8905693dd9
commit 95498c061d

@ -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

@ -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

@ -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):

@ -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):

@ -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):

@ -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):

@ -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):

@ -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):

@ -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):

@ -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):

@ -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.

@ -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:"))

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>827</width>
<height>777</height>
<width>1239</width>
<height>824</height>
</rect>
</property>
<property name="windowTitle">
@ -216,7 +216,7 @@
</widget>
</item>
<item>
<widget class="QLabel" name="label_5">
<widget class="QLabel" name="source_link_label">
<property name="text">
<string>Link:</string>
</property>
@ -231,6 +231,16 @@
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="description_label">
<property name="text">
<string>Description:</string>
</property>
</widget>
</item>
<item>
<widget class="QTextEdit" name="description_edit"/>
</item>
</layout>
</widget>
</item>
@ -483,8 +493,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>827</width>
<height>19</height>
<width>1239</width>
<height>30</height>
</rect>
</property>
<widget class="QMenu" name="menuArtNet">

@ -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))
QDesktopServices.openUrl(QUrl(link))
def on_description_change(self):
self.data_changed = True

Loading…
Cancel
Save