diff --git a/src/libprs500/gui2/dialogs/tag_editor.py b/src/libprs500/gui2/dialogs/tag_editor.py index 2a503b2222..55cf45f3b0 100644 --- a/src/libprs500/gui2/dialogs/tag_editor.py +++ b/src/libprs500/gui2/dialogs/tag_editor.py @@ -13,10 +13,11 @@ ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. from PyQt4.QtCore import SIGNAL, Qt -from PyQt4.QtGui import QDialog +from PyQt4.QtGui import QDialog, QMessageBox from libprs500.gui2.dialogs.tag_editor_ui import Ui_TagEditor from libprs500.gui2 import qstring_to_unicode +from libprs500.gui2 import question_dialog class TagEditor(QDialog, Ui_TagEditor): @@ -45,12 +46,34 @@ class TagEditor(QDialog, Ui_TagEditor): if tag not in tags: self.available_tags.addItem(tag) - self.connect(self.apply_button, SIGNAL('clicked()'), self.apply_tags) + self.connect(self.apply_button, SIGNAL('clicked()'), self.apply_tags) self.connect(self.unapply_button, SIGNAL('clicked()'), self.unapply_tags) self.connect(self.add_tag_button, SIGNAL('clicked()'), self.add_tag) - self.connect(self.add_tag_input, SIGNAL('returnPressed()'), self.add_tag) + self.connect(self.delete_button, SIGNAL('clicked()'), self.delete_tags) + self.connect(self.add_tag_input, SIGNAL('returnPressed()'), self.add_tag) self.connect(self.available_tags, SIGNAL('itemActivated(QListWidgetItem*)'), self.apply_tags) - self.connect(self.applied_tags, SIGNAL('itemActivated(QListWidgetItem*)'), self.unapply_tags) + self.connect(self.applied_tags, SIGNAL('itemActivated(QListWidgetItem*)'), self.unapply_tags) + + + def delete_tags(self, item=None): + confirms, deletes = [], [] + items = self.available_tags.selectedItems() if item is None else [item] + for item in items: + if self.db.is_tag_used(qstring_to_unicode(item.text())): + confirms.append(item) + else: + deletes.append(item) + if confirms: + ct = ', '.join([qstring_to_unicode(item.text()) for item in confirms]) + d = question_dialog(self, 'Are your sure?', + '

The following tags are used by one or more books. Are you certain you want to delete them?
'+ct) + if d.exec_() == QMessageBox.Yes: + deletes += confirms + + for item in deletes: + self.db.delete_tag(qstring_to_unicode(item.text())) + self.available_tags.takeItem(self.available_tags.row(item)) + def apply_tags(self, item=None): items = self.available_tags.selectedItems() if item is None else [item] diff --git a/src/libprs500/gui2/dialogs/tag_editor.ui b/src/libprs500/gui2/dialogs/tag_editor.ui index 7c09a70952..4f9953e1e7 100644 --- a/src/libprs500/gui2/dialogs/tag_editor.ui +++ b/src/libprs500/gui2/dialogs/tag_editor.ui @@ -17,35 +17,48 @@ - + - + - - - - - A&vailable tags - - - available_tags - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - + + + A&vailable tags + + + available_tags + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Delete tag from database. This will unapply the tag from all books and then remove it from the database. + + + ... + + + :/images/trash.svg + + @@ -62,136 +75,136 @@ + + + + - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - Apply tag to current book - - - ... - - - :/images/forward.svg - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - + + + Qt::Vertical + + + + 20 + 40 + + + - - - - - - - A&pplied tags - - - applied_tags - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - true - - - QAbstractItemView::MultiSelection - - - - + + + Apply tag to current book + + + ... + + + :/images/forward.svg + + - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - Unapply (remove) tag from current book - - - ... - - - :/images/list_remove.svg - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - + + + Qt::Vertical + + + + 20 + 40 + + + - + + + + + + + + A&pplied tags + + + applied_tags + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + true + + + QAbstractItemView::MultiSelection + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Unapply (remove) tag from current book + + + ... + + + :/images/list_remove.svg + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + @@ -251,7 +264,7 @@ - + Qt::Horizontal diff --git a/src/libprs500/library/database.py b/src/libprs500/library/database.py index 247f0e400e..816aa0d16e 100644 --- a/src/libprs500/library/database.py +++ b/src/libprs500/library/database.py @@ -377,7 +377,7 @@ class LibraryDatabase(object): BEFORE DELETE ON tags BEGIN SELECT CASE - WHEN (SELECT COUNT(id) FROM books_tags_link WHERE book=OLD.book) > 0 + WHEN (SELECT COUNT(id) FROM books_tags_link WHERE tag=OLD.book) > 0 THEN RAISE(ABORT, 'Foreign key violation: tag is still referenced') END; END; @@ -722,7 +722,23 @@ ALTER TABLE books ADD COLUMN isbn TEXT DEFAULT "" COLLATE NOCASE; ''') conn.execute('pragma user_version=5') conn.commit() - + + @staticmethod + def upgrade_version5(conn): + conn.executescript(\ + ''' + DROP TRIGGER fkc_delete_books_tags_link; + CREATE TRIGGER fkc_delete_books_tags_link + BEFORE DELETE ON tags + BEGIN + SELECT CASE + WHEN (SELECT COUNT(id) FROM books_tags_link WHERE tag=OLD.id) > 0 + THEN RAISE(ABORT, 'Foreign key violation: tag is still referenced') + END; + END; + ''') + conn.execute('pragma user_version=6') + conn.commit() def __del__(self): global _lock_file @@ -747,6 +763,8 @@ ALTER TABLE books ADD COLUMN isbn TEXT DEFAULT "" COLLATE NOCASE; LibraryDatabase.upgrade_version3(self.conn) if self.user_version == 4: # Upgrade to 5 LibraryDatabase.upgrade_version4(self.conn) + if self.user_version == 5: # Upgrade to 6 + LibraryDatabase.upgrade_version5(self.conn) def close(self): global _lock_file @@ -1049,6 +1067,24 @@ ALTER TABLE books ADD COLUMN isbn TEXT DEFAULT "" COLLATE NOCASE; self.conn.execute('INSERT INTO comments(book,text) VALUES (?,?)', (id, text)) self.conn.commit() + def is_tag_used(self, tag): + id = self.conn.execute('SELECT id FROM tags WHERE name=?', (tag,)).fetchone() + if not id: + return False + return bool(self.conn.execute('SELECT tag FROM books_tags_link WHERE tag=?',(id[0],)).fetchone()) + + def delete_tag(self, tag): + id = self.conn.execute('SELECT id FROM tags WHERE name=?', (tag,)).fetchone() + if id: + id = id[0] + self.conn.execute('DELETE FROM books_tags_link WHERE tag=?', (id,)) + self.conn.execute('DELETE FROM tags WHERE id=?', (id,)) + self.conn.commit() + + def delete_tags(self, tags): + for tag in tags: + self.delete_tag(tag) + def set_tags(self, id, tags, append=False): ''' @param tags: list of strings