mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -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.,
|
## with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
from PyQt4.QtCore import SIGNAL, Qt
|
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.dialogs.tag_editor_ui import Ui_TagEditor
|
||||||
from libprs500.gui2 import qstring_to_unicode
|
from libprs500.gui2 import qstring_to_unicode
|
||||||
|
from libprs500.gui2 import question_dialog
|
||||||
|
|
||||||
class TagEditor(QDialog, Ui_TagEditor):
|
class TagEditor(QDialog, Ui_TagEditor):
|
||||||
|
|
||||||
@ -45,12 +46,34 @@ class TagEditor(QDialog, Ui_TagEditor):
|
|||||||
if tag not in tags:
|
if tag not in tags:
|
||||||
self.available_tags.addItem(tag)
|
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.unapply_button, SIGNAL('clicked()'), self.unapply_tags)
|
||||||
self.connect(self.add_tag_button, SIGNAL('clicked()'), self.add_tag)
|
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.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):
|
def apply_tags(self, item=None):
|
||||||
items = self.available_tags.selectedItems() if item is None else [item]
|
items = self.available_tags.selectedItems() if item is None else [item]
|
||||||
|
@ -17,35 +17,48 @@
|
|||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" >
|
<layout class="QGridLayout" >
|
||||||
<item row="0" column="0" >
|
<item row="0" column="0" >
|
||||||
<layout class="QHBoxLayout" >
|
<layout class="QVBoxLayout" >
|
||||||
<item>
|
<item>
|
||||||
<layout class="QVBoxLayout" >
|
<layout class="QHBoxLayout" >
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" >
|
<widget class="QLabel" name="label" >
|
||||||
<item>
|
<property name="text" >
|
||||||
<widget class="QLabel" name="label" >
|
<string>A&vailable tags</string>
|
||||||
<property name="text" >
|
</property>
|
||||||
<string>A&vailable tags</string>
|
<property name="buddy" >
|
||||||
</property>
|
<cstring>available_tags</cstring>
|
||||||
<property name="buddy" >
|
</property>
|
||||||
<cstring>available_tags</cstring>
|
</widget>
|
||||||
</property>
|
</item>
|
||||||
</widget>
|
<item>
|
||||||
</item>
|
<spacer>
|
||||||
<item>
|
<property name="orientation" >
|
||||||
<spacer>
|
<enum>Qt::Horizontal</enum>
|
||||||
<property name="orientation" >
|
</property>
|
||||||
<enum>Qt::Horizontal</enum>
|
<property name="sizeHint" >
|
||||||
</property>
|
<size>
|
||||||
<property name="sizeHint" >
|
<width>40</width>
|
||||||
<size>
|
<height>20</height>
|
||||||
<width>40</width>
|
</size>
|
||||||
<height>20</height>
|
</property>
|
||||||
</size>
|
</spacer>
|
||||||
</property>
|
</item>
|
||||||
</spacer>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
<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>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QListWidget" name="available_tags" >
|
<widget class="QListWidget" name="available_tags" >
|
||||||
@ -62,136 +75,136 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1" >
|
||||||
|
<layout class="QVBoxLayout" >
|
||||||
<item>
|
<item>
|
||||||
<layout class="QVBoxLayout" >
|
<spacer>
|
||||||
<item>
|
<property name="orientation" >
|
||||||
<spacer>
|
<enum>Qt::Vertical</enum>
|
||||||
<property name="orientation" >
|
</property>
|
||||||
<enum>Qt::Vertical</enum>
|
<property name="sizeHint" >
|
||||||
</property>
|
<size>
|
||||||
<property name="sizeHint" >
|
<width>20</width>
|
||||||
<size>
|
<height>40</height>
|
||||||
<width>20</width>
|
</size>
|
||||||
<height>40</height>
|
</property>
|
||||||
</size>
|
</spacer>
|
||||||
</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>
|
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QVBoxLayout" >
|
<widget class="QToolButton" name="apply_button" >
|
||||||
<item>
|
<property name="toolTip" >
|
||||||
<layout class="QHBoxLayout" >
|
<string>Apply tag to current book</string>
|
||||||
<item>
|
</property>
|
||||||
<widget class="QLabel" name="label_2" >
|
<property name="text" >
|
||||||
<property name="text" >
|
<string>...</string>
|
||||||
<string>A&pplied tags</string>
|
</property>
|
||||||
</property>
|
<property name="icon" >
|
||||||
<property name="buddy" >
|
<iconset resource="../images.qrc" >:/images/forward.svg</iconset>
|
||||||
<cstring>applied_tags</cstring>
|
</property>
|
||||||
</property>
|
</widget>
|
||||||
</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>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QVBoxLayout" >
|
<spacer>
|
||||||
<item>
|
<property name="orientation" >
|
||||||
<spacer>
|
<enum>Qt::Vertical</enum>
|
||||||
<property name="orientation" >
|
</property>
|
||||||
<enum>Qt::Vertical</enum>
|
<property name="sizeHint" >
|
||||||
</property>
|
<size>
|
||||||
<property name="sizeHint" >
|
<width>20</width>
|
||||||
<size>
|
<height>40</height>
|
||||||
<width>20</width>
|
</size>
|
||||||
<height>40</height>
|
</property>
|
||||||
</size>
|
</spacer>
|
||||||
</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>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</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" >
|
<layout class="QHBoxLayout" >
|
||||||
<item>
|
<item>
|
||||||
<spacer>
|
<spacer>
|
||||||
@ -251,7 +264,7 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="0" >
|
<item row="2" column="0" colspan="4" >
|
||||||
<widget class="QDialogButtonBox" name="buttonBox" >
|
<widget class="QDialogButtonBox" name="buttonBox" >
|
||||||
<property name="orientation" >
|
<property name="orientation" >
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
|
@ -377,7 +377,7 @@ class LibraryDatabase(object):
|
|||||||
BEFORE DELETE ON tags
|
BEFORE DELETE ON tags
|
||||||
BEGIN
|
BEGIN
|
||||||
SELECT CASE
|
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')
|
THEN RAISE(ABORT, 'Foreign key violation: tag is still referenced')
|
||||||
END;
|
END;
|
||||||
END;
|
END;
|
||||||
@ -722,7 +722,23 @@ ALTER TABLE books ADD COLUMN isbn TEXT DEFAULT "" COLLATE NOCASE;
|
|||||||
''')
|
''')
|
||||||
conn.execute('pragma user_version=5')
|
conn.execute('pragma user_version=5')
|
||||||
conn.commit()
|
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):
|
def __del__(self):
|
||||||
global _lock_file
|
global _lock_file
|
||||||
@ -747,6 +763,8 @@ ALTER TABLE books ADD COLUMN isbn TEXT DEFAULT "" COLLATE NOCASE;
|
|||||||
LibraryDatabase.upgrade_version3(self.conn)
|
LibraryDatabase.upgrade_version3(self.conn)
|
||||||
if self.user_version == 4: # Upgrade to 5
|
if self.user_version == 4: # Upgrade to 5
|
||||||
LibraryDatabase.upgrade_version4(self.conn)
|
LibraryDatabase.upgrade_version4(self.conn)
|
||||||
|
if self.user_version == 5: # Upgrade to 6
|
||||||
|
LibraryDatabase.upgrade_version5(self.conn)
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
global _lock_file
|
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.execute('INSERT INTO comments(book,text) VALUES (?,?)', (id, text))
|
||||||
self.conn.commit()
|
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):
|
def set_tags(self, id, tags, append=False):
|
||||||
'''
|
'''
|
||||||
@param tags: list of strings
|
@param tags: list of strings
|
||||||
|
Loading…
x
Reference in New Issue
Block a user