diff --git a/src/calibre/gui2/dialogs/tag_list_editor.py b/src/calibre/gui2/dialogs/tag_list_editor.py index 3741226fc9..dc06a8897e 100644 --- a/src/calibre/gui2/dialogs/tag_list_editor.py +++ b/src/calibre/gui2/dialogs/tag_list_editor.py @@ -48,14 +48,14 @@ class TagListEditor(QDialog, Ui_TagListEditor): def finish_editing(self, item): if not item.text(): - error_dialog(self, 'Item is blank', - 'An item 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.')).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, 'Item already used', - 'The item %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,ign) = self.item_before_editing.data(Qt.UserRole).toInt() @@ -67,7 +67,8 @@ class TagListEditor(QDialog, Ui_TagListEditor): def _rename_tag(self, item): if item is None: - error_dialog(self, 'No item selected', 'You must select one item from the list of Available items.').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); @@ -76,7 +77,8 @@ class TagListEditor(QDialog, Ui_TagListEditor): def delete_tags(self, item=None): 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_() + 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?'), @@ -112,4 +114,3 @@ class TagListEditor(QDialog, Ui_TagListEditor): QDialog.reject(self) else: QDialog.accept(self) - diff --git a/src/calibre/gui2/tag_view.py b/src/calibre/gui2/tag_view.py index 8179188a87..6946f337d6 100644 --- a/src/calibre/gui2/tag_view.py +++ b/src/calibre/gui2/tag_view.py @@ -17,6 +17,7 @@ from calibre.gui2 import config, NONE from calibre.utils.config import prefs from calibre.library.field_metadata import TagsIcons from calibre.utils.search_query_parser import saved_searches +from calibre.gui2 import error_dialog class TagsView(QTreeView): # {{{ @@ -141,7 +142,7 @@ class TagsView(QTreeView): # {{{ self.context_menu = QMenu(self) # If the user right-clicked on a tag/series/publisher, then offer # the possibility of renaming that item - if tag_name and item.category_key in ['tags', 'series', 'publisher', 'search']: + if tag_name and item.category_key in ['authors', 'tags', 'series', 'publisher', 'search']: self.context_menu.addAction(_('Rename item') + " '" + tag_name + "'", partial(self.context_menu_handler, action='edit_item', category=tag_item, index=index)) @@ -381,8 +382,12 @@ class TagsModel(QAbstractItemModel): # {{{ data = self.db.get_categories(sort_on_count=sort, icon_map=self.category_icon_map) tb_categories = self.db.field_metadata + self.category_items = {} for category in tb_categories: if category in data: # They should always be there, but ... + # make a map of sets of names per category for duplicate + # checking when editing + self.category_items[category] = [tag.name for tag in data[category]] self.row_map.append(category) self.categories.append(tb_categories[category]['name']) @@ -425,23 +430,37 @@ class TagsModel(QAbstractItemModel): # {{{ if not index.isValid(): return NONE val = unicode(value.toString()) + if not val: + error_dialog(self.tags_view, _('Item is blank'), + _('An item cannot be set to nothing. Delete it instead.')).exec_() + return False + item = index.internalPointer() - if item.parent.category_key == 'series': + key = item.parent.category_key + if val in self.category_items[key]: + error_dialog(self.tags_view, 'Duplicate item', + _('The name %s is already used.')%val).exec_() + return False + if key == 'series': self.db.rename_series(item.tag.id, val) item.tag.name = val self.tags_view.tag_item_renamed.emit() - elif item.parent.category_key == 'publisher': + elif key == 'publisher': self.db.rename_publisher(item.tag.id, val) item.tag.name = val self.tags_view.tag_item_renamed.emit() - elif item.parent.category_key == 'tags': + elif key == 'tags': self.db.rename_tag(item.tag.id, val) item.tag.name = val self.tags_view.tag_item_renamed.emit() - elif item.parent.category_key == 'search': + elif key == 'search': saved_searches.rename(unicode(item.data(role).toString()), val) item.tag.name = val self.tags_view.search_item_renamed.emit() + elif key == 'authors': + self.db.rename_author(item.tag.id, val) + item.tag.name = val + self.tags_view.tag_item_renamed.emit() self.dataChanged.emit(index, index) return True diff --git a/src/calibre/library/database2.py b/src/calibre/library/database2.py index c01d6fd4d6..860859061c 100644 --- a/src/calibre/library/database2.py +++ b/src/calibre/library/database2.py @@ -993,8 +993,9 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns): return result def rename_tag(self, id, new_name): - self.conn.execute('UPDATE tags SET name=? WHERE id=?', (new_name, id)) - self.conn.commit() + if id: + self.conn.execute('UPDATE tags SET name=? WHERE id=?', (new_name, id)) + self.conn.commit() def delete_tag_using_id(self, id): if id: @@ -1009,8 +1010,9 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns): return result def rename_series(self, id, new_name): - self.conn.execute('UPDATE series SET name=? WHERE id=?', (new_name, id)) - self.conn.commit() + if id: + self.conn.execute('UPDATE series SET name=? WHERE id=?', (new_name, id)) + self.conn.commit() def delete_series_using_id(self, id): if id: @@ -1028,8 +1030,9 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns): return result def rename_publisher(self, id, new_name): - self.conn.execute('UPDATE publishers SET name=? WHERE id=?', (new_name, id)) - self.conn.commit() + if id: + self.conn.execute('UPDATE publishers SET name=? WHERE id=?', (new_name, id)) + self.conn.commit() def delete_publisher_using_id(self, id): if id: @@ -1037,6 +1040,31 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns): self.conn.execute('DELETE FROM publishers WHERE id=?', (id,)) self.conn.commit() + def rename_author(self, id, new_name): + if id: + # Make sure that any commas in new_name are changed to '|'! + new_name = new_name.replace(',', '|') + self.conn.execute('UPDATE authors SET name=? WHERE id=?', (new_name, id)) + self.conn.commit() + # now must fix up the books + books = self.conn.get('SELECT book from books_authors_link WHERE author=?', (id,)) + for (book_id,) in books: + # First, must refresh the cache to see the new authors + self.data.refresh_ids(self, [book_id]) + # now fix the filesystem paths + self.set_path(book_id, index_is_id=True) + # Next fix the author sort. Reset it to the default + authors = self.conn.get(''' + SELECT authors.name + FROM authors, books_authors_link as bl + WHERE bl.book = ? and bl.author = authors.id + ''' , (book_id,)) + # unpack the double-list structure + for i,aut in enumerate(authors): + authors[i] = aut[0] + ss = authors_to_sort_string(authors) + self.conn.execute('UPDATE books SET author_sort=? WHERE id=?', (ss, id)) + # end convenience methods def get_tags(self, id):