mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-08 18:54:09 -04:00
Allow the user to remove tags from the database from the tag editor
This commit is contained in:
parent
45d418f874
commit
5b276ee524
@ -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?',
|
||||
'<p>The following tags are used by one or more books. Are you certain you want to delete them?<br>'+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]
|
||||
|
@ -17,35 +17,48 @@
|
||||
</property>
|
||||
<layout class="QGridLayout" >
|
||||
<item row="0" column="0" >
|
||||
<layout class="QHBoxLayout" >
|
||||
<layout class="QVBoxLayout" >
|
||||
<item>
|
||||
<layout class="QVBoxLayout" >
|
||||
<layout class="QHBoxLayout" >
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<item>
|
||||
<widget class="QLabel" name="label" >
|
||||
<property name="text" >
|
||||
<string>A&vailable tags</string>
|
||||
</property>
|
||||
<property name="buddy" >
|
||||
<cstring>available_tags</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
<widget class="QLabel" name="label" >
|
||||
<property name="text" >
|
||||
<string>A&vailable tags</string>
|
||||
</property>
|
||||
<property name="buddy" >
|
||||
<cstring>available_tags</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<item>
|
||||
<widget class="QToolButton" name="delete_button" >
|
||||
<property name="toolTip" >
|
||||
<string>Delete tag from database. This will unapply the tag from all books and then remove it from the database.</string>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon" >
|
||||
<iconset resource="../images.qrc" >:/images/trash.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QListWidget" name="available_tags" >
|
||||
@ -62,136 +75,136 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="1" >
|
||||
<layout class="QVBoxLayout" >
|
||||
<item>
|
||||
<layout class="QVBoxLayout" >
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="apply_button" >
|
||||
<property name="toolTip" >
|
||||
<string>Apply tag to current book</string>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon" >
|
||||
<iconset resource="../images.qrc" >:/images/forward.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" >
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2" >
|
||||
<property name="text" >
|
||||
<string>A&pplied tags</string>
|
||||
</property>
|
||||
<property name="buddy" >
|
||||
<cstring>applied_tags</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QListWidget" name="applied_tags" >
|
||||
<property name="alternatingRowColors" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="selectionMode" >
|
||||
<enum>QAbstractItemView::MultiSelection</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
<widget class="QToolButton" name="apply_button" >
|
||||
<property name="toolTip" >
|
||||
<string>Apply tag to current book</string>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon" >
|
||||
<iconset resource="../images.qrc" >:/images/forward.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" >
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="unapply_button" >
|
||||
<property name="toolTip" >
|
||||
<string>Unapply (remove) tag from current book</string>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon" >
|
||||
<iconset resource="../images.qrc" >:/images/list_remove.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0" >
|
||||
<item row="0" column="2" >
|
||||
<layout class="QVBoxLayout" >
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2" >
|
||||
<property name="text" >
|
||||
<string>A&pplied tags</string>
|
||||
</property>
|
||||
<property name="buddy" >
|
||||
<cstring>applied_tags</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QListWidget" name="applied_tags" >
|
||||
<property name="alternatingRowColors" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="selectionMode" >
|
||||
<enum>QAbstractItemView::MultiSelection</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="3" >
|
||||
<layout class="QVBoxLayout" >
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="unapply_button" >
|
||||
<property name="toolTip" >
|
||||
<string>Unapply (remove) tag from current book</string>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon" >
|
||||
<iconset resource="../images.qrc" >:/images/list_remove.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="4" >
|
||||
<layout class="QHBoxLayout" >
|
||||
<item>
|
||||
<spacer>
|
||||
@ -251,7 +264,7 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="0" >
|
||||
<item row="2" column="0" colspan="4" >
|
||||
<widget class="QDialogButtonBox" name="buttonBox" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user