diff --git a/src/calibre/gui2/dialogs/tag_list_editor.py b/src/calibre/gui2/dialogs/tag_list_editor.py
index bccd0deee9..7ee616fe1b 100644
--- a/src/calibre/gui2/dialogs/tag_list_editor.py
+++ b/src/calibre/gui2/dialogs/tag_list_editor.py
@@ -6,12 +6,11 @@ from PyQt4.QtGui import QDialog, QListWidgetItem
from calibre.gui2.dialogs.tag_list_editor_ui import Ui_TagListEditor
from calibre.gui2 import question_dialog, error_dialog
+from calibre.ebooks.metadata import title_sort
+
class TagListEditor(QDialog, Ui_TagListEditor):
- def tag_cmp(self, x, y):
- return cmp(x.lower(), y.lower())
-
- def __init__(self, window, db, tag_to_match):
+ def __init__(self, window, db, tag_to_match, category):
QDialog.__init__(self, window)
Ui_TagListEditor.__init__(self)
self.setupUi(self)
@@ -20,9 +19,20 @@ class TagListEditor(QDialog, Ui_TagListEditor):
self.to_delete = []
self.db = db
self.all_tags = {}
- for k,v in db.get_tags_with_ids():
+ self.category = category
+ if category == 'tags':
+ result = db.get_tags_with_ids()
+ compare = (lambda x,y:cmp(x.lower(), y.lower()))
+ elif category == 'series':
+ result = db.get_series_with_ids()
+ compare = (lambda x,y:cmp(title_sort(x).lower(), title_sort(y).lower()))
+ elif category == 'publishers':
+ result = db.get_publishers_with_ids()
+ compare = (lambda x,y:cmp(x.lower(), y.lower()))
+
+ for k,v in result:
self.all_tags[v] = k
- for tag in sorted(self.all_tags.keys(), cmp=self.tag_cmp):
+ for tag in sorted(self.all_tags.keys(), cmp=compare):
item = QListWidgetItem(tag)
item.setData(Qt.UserRole, self.all_tags[tag])
self.available_tags.addItem(item)
@@ -38,17 +48,17 @@ class TagListEditor(QDialog, Ui_TagListEditor):
def finish_editing(self, item):
if not item.text():
- error_dialog(self, 'Tag is blank',
- 'A tag cannot be set to nothing. Delete it instead.'%(item.text())).exec_()
+ error_dialog(self, 'Item is blank',
+ 'An item cannot be set to nothing. Delete it instead.'%(item.text())).exec_()
item.setText(self.item_before_editing.text())
return
if item.text() != self.item_before_editing.text():
if item.text() in self.all_tags.keys() or item.text() in self.to_rename.keys():
- error_dialog(self, 'Tag already used',
- 'The tag %s is already used.'%(item.text())).exec_()
+ error_dialog(self, 'Item already used',
+ 'The item %s is already used.'%(item.text())).exec_()
item.setText(self.item_before_editing.text())
return
- (id,_) = self.item_before_editing.data(Qt.UserRole).toInt()
+ (id,ign) = self.item_before_editing.data(Qt.UserRole).toInt()
self.to_rename[item.text()] = id
def rename_tag(self):
@@ -57,39 +67,49 @@ class TagListEditor(QDialog, Ui_TagListEditor):
def _rename_tag(self, item):
if item is None:
- error_dialog(self, 'No tag selected', 'You must select one tag from the list of Available tags.').exec_()
+ error_dialog(self, 'No item selected', 'You must select one item from the list of Available items.').exec_()
return
self.item_before_editing = item.clone()
item.setFlags (item.flags() | Qt.ItemIsEditable);
self.available_tags.editItem(item)
def delete_tags(self, item=None):
- confirms, deletes = [], []
- items = self.available_tags.selectedItems() if item is None else [item]
- if not items:
- error_dialog(self, 'No tags selected', 'You must select at least one tag from the list of Available tags.').exec_()
+ deletes = self.available_tags.selectedItems() if item is None else [item]
+ if not deletes:
+ error_dialog(self, 'No items selected', 'You must select at least one items from the list.').exec_()
+ return
+ ct = ', '.join([unicode(item.text()) for item in deletes])
+ if not question_dialog(self, _('Are your sure?'),
+ '
'+_('Are you certain you want to delete the following items?')+'
'+ct):
return
- for item in items:
- if self.db.is_tag_used(unicode(item.text())):
- confirms.append(item)
- else:
- deletes.append(item)
- if confirms:
- ct = ', '.join([unicode(item.text()) for item in confirms])
- if 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):
- deletes += confirms
for item in deletes:
- (id,_) = item.data(Qt.UserRole).toInt()
+ (id,ign) = item.data(Qt.UserRole).toInt()
self.to_delete.append(id)
self.available_tags.takeItem(self.available_tags.row(item))
def accept(self):
- for text in self.to_rename:
- self.db.rename_tag(id=self.to_rename[text], new_name=unicode(text))
- for item in self.to_delete:
- self.db.delete_tag_using_id(item)
- QDialog.accept(self)
+ rename_func = None
+ if self.category == 'tags':
+ rename_func = self.db.rename_tag
+ delete_func = self.db.delete_tag_using_id
+ elif self.category == 'series':
+ rename_func = self.db.rename_series
+ delete_func = self.db.delete_series_using_id
+ elif self.category == 'publishers':
+ rename_func = self.db.rename_publisher
+ delete_func = self.db.delete_publisher_using_id
+
+ work_done = False
+ if rename_func:
+ for text in self.to_rename:
+ work_done = True
+ rename_func(id=self.to_rename[text], new_name=unicode(text))
+ for item in self.to_delete:
+ work_done = True
+ delete_func(item)
+ if not work_done:
+ QDialog.reject(self)
+ else:
+ QDialog.accept(self)
diff --git a/src/calibre/gui2/dialogs/tag_list_editor.ui b/src/calibre/gui2/dialogs/tag_list_editor.ui
index 383dc875ac..4f57af745b 100644
--- a/src/calibre/gui2/dialogs/tag_list_editor.ui
+++ b/src/calibre/gui2/dialogs/tag_list_editor.ui
@@ -11,7 +11,7 @@
- Tag Editor
+ Category Editor
@@ -25,7 +25,7 @@
-
- Tags in use
+ Items in use
available_tags
@@ -54,7 +54,7 @@
-
- Delete tag from database. This will unapply the tag from all books and then remove it from the database.
+ Delete item from database. This will unapply the item from all books and then remove it from the database.
...
@@ -74,7 +74,7 @@
-
- Rename the tag everywhere it is used.
+ Rename the item in every book where it is used.
...
diff --git a/src/calibre/gui2/tag_view.py b/src/calibre/gui2/tag_view.py
index 11db157ed4..fd232bb750 100644
--- a/src/calibre/gui2/tag_view.py
+++ b/src/calibre/gui2/tag_view.py
@@ -24,7 +24,7 @@ class TagsView(QTreeView): # {{{
restriction_set = pyqtSignal(object)
tags_marked = pyqtSignal(object, object)
user_category_edit = pyqtSignal(object)
- tag_list_edit = pyqtSignal(object)
+ tag_list_edit = pyqtSignal(object, object)
saved_search_edit = pyqtSignal(object)
def __init__(self, *args):
@@ -91,7 +91,13 @@ class TagsView(QTreeView): # {{{
return
try:
if action == 'manage_tags':
- self.tag_list_edit.emit(category)
+ self.tag_list_edit.emit(category, 'tags')
+ return
+ if action == 'manage_series':
+ self.tag_list_edit.emit(category, 'series')
+ return
+ if action == 'manage_publishers':
+ self.tag_list_edit.emit(category, 'publishers')
return
if action == 'manage_categories':
self.user_category_edit.emit(category)
@@ -136,10 +142,24 @@ class TagsView(QTreeView): # {{{
partial(self.context_menu_handler, action='defaults'))
self.context_menu.addSeparator()
- self.context_menu.addAction(_('Manage Tags'),
+ if category == _('Tags'):
+ self.context_menu.addAction(_('Manage Tags'),
partial(self.context_menu_handler, action='manage_tags',
category=tag_name))
+ elif category == _('Searches'):
+ self.context_menu.addAction(_('Manage Saved Searches'),
+ partial(self.context_menu_handler, action='manage_searches',
+ category=tag_name))
+ elif category == _('Publishers'):
+ self.context_menu.addAction(_('Manage Publishers'),
+ partial(self.context_menu_handler, action='manage_publishers',
+ category=tag_name))
+ elif category == _('Series'):
+ self.context_menu.addAction(_('Manage Series'),
+ partial(self.context_menu_handler, action='manage_series',
+ category=tag_name))
+ self.context_menu.addSeparator()
if category in prefs['user_categories'].keys():
self.context_menu.addAction(_('Manage User Categories'),
partial(self.context_menu_handler, action='manage_categories',
@@ -149,10 +169,6 @@ class TagsView(QTreeView): # {{{
partial(self.context_menu_handler, action='manage_categories',
category=None))
- self.context_menu.addAction(_('Manage Saved Searches'),
- partial(self.context_menu_handler, action='manage_searches',
- category=tag_name))
-
self.context_menu.popup(self.mapToGlobal(point))
return True
diff --git a/src/calibre/gui2/ui.py b/src/calibre/gui2/ui.py
index 773f44acd2..63172fc7a5 100644
--- a/src/calibre/gui2/ui.py
+++ b/src/calibre/gui2/ui.py
@@ -660,13 +660,16 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
self.tags_view.set_new_model()
self.tags_view.recount()
- def do_tags_list_edit(self, tag):
- d = TagListEditor(self, self.library_view.model().db, tag)
+ def do_tags_list_edit(self, tag, category):
+ d = TagListEditor(self, self.library_view.model().db, tag, category)
d.exec_()
if d.result() == d.Accepted:
+ # Clean up everything, as information could have changed for many books.
+ self.library_view.model().refresh()
self.tags_view.set_new_model()
self.tags_view.recount()
- self.library_view.model().refresh()
+ self.saved_search.clear_to_help()
+ self.search.clear_to_help()
def do_saved_search_edit(self, search):
d = SavedSearchEditor(self, search)
diff --git a/src/calibre/library/database2.py b/src/calibre/library/database2.py
index f76ae9c77a..c01d6fd4d6 100644
--- a/src/calibre/library/database2.py
+++ b/src/calibre/library/database2.py
@@ -731,8 +731,8 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
icon=icon, tooltip = tooltip)
for r in data if item_not_zero_func(r)]
if category == 'series':
- categories[category].sort(cmp=lambda x,y:cmp(title_sort(x.name),
- title_sort(y.name)))
+ categories[category].sort(cmp=lambda x,y:cmp(title_sort(x.name).lower(),
+ title_sort(y.name).lower()))
# We delayed computing the standard formats category because it does not
# use a view, but is computed dynamically
@@ -985,7 +985,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
if notify:
self.notify('metadata', [id])
- # Convenience method for tags_list_editor
+ # Convenience methods for tags_list_editor
def get_tags_with_ids(self):
result = self.conn.get('SELECT id,name FROM tags')
if not result:
@@ -996,6 +996,49 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
self.conn.execute('UPDATE tags SET name=? WHERE id=?', (new_name, id))
self.conn.commit()
+ def delete_tag_using_id(self, id):
+ if id:
+ self.conn.execute('DELETE FROM books_tags_link WHERE tag=?', (id,))
+ self.conn.execute('DELETE FROM tags WHERE id=?', (id,))
+ self.conn.commit()
+
+ def get_series_with_ids(self):
+ result = self.conn.get('SELECT id,name FROM series')
+ if not result:
+ return []
+ return result
+
+ def rename_series(self, id, new_name):
+ self.conn.execute('UPDATE series SET name=? WHERE id=?', (new_name, id))
+ self.conn.commit()
+
+ def delete_series_using_id(self, id):
+ if id:
+ books = self.conn.get('SELECT book from books_series_link WHERE series=?', (id,))
+ for (book_id,) in books:
+ self.conn.execute('UPDATE books SET series_index=1.0 WHERE id=?', (book_id,))
+ self.conn.execute('DELETE FROM books_series_link WHERE series=?', (id,))
+ self.conn.execute('DELETE FROM series WHERE id=?', (id,))
+ self.conn.commit()
+
+ def get_publishers_with_ids(self):
+ result = self.conn.get('SELECT id,name FROM publishers')
+ if not result:
+ return []
+ return result
+
+ def rename_publisher(self, id, new_name):
+ self.conn.execute('UPDATE publishers SET name=? WHERE id=?', (new_name, id))
+ self.conn.commit()
+
+ def delete_publisher_using_id(self, id):
+ if id:
+ self.conn.execute('DELETE FROM books_publishers_link WHERE publisher=?', (id,))
+ self.conn.execute('DELETE FROM publishers WHERE id=?', (id,))
+ self.conn.commit()
+
+ # end convenience methods
+
def get_tags(self, id):
result = self.conn.get(
'SELECT name FROM tags WHERE id IN (SELECT tag FROM books_tags_link WHERE book=?)',
@@ -1080,12 +1123,6 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
self.conn.execute('DELETE FROM tags WHERE id=?', (id,))
self.conn.commit()
- def delete_tag_using_id(self, id):
- if id:
- self.conn.execute('DELETE FROM books_tags_link WHERE tag=?', (id,))
- self.conn.execute('DELETE FROM tags WHERE id=?', (id,))
- self.conn.commit()
-
def set_series(self, id, series, notify=True):
self.conn.execute('DELETE FROM books_series_link WHERE book=?',(id,))
self.conn.execute('DELETE FROM series WHERE (SELECT COUNT(id) FROM books_series_link WHERE series=series.id) < 1')