mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Permit renaming on the tags pane to combine items (rename to same as existing item)
This commit is contained in:
parent
984bea5033
commit
e4ad4ceb71
@ -138,7 +138,8 @@ class TagsView(QTreeView): # {{{
|
|||||||
# the possibility of renaming that item
|
# the possibility of renaming that item
|
||||||
if tag_name and \
|
if tag_name and \
|
||||||
(key in ['authors', 'tags', 'series', 'publisher', 'search'] or \
|
(key in ['authors', 'tags', 'series', 'publisher', 'search'] or \
|
||||||
self.db.field_metadata[key]['is_custom']):
|
self.db.field_metadata[key]['is_custom'] and \
|
||||||
|
self.db.field_metadata[key]['datatype'] != 'rating'):
|
||||||
self.context_menu.addAction(_('Rename') + " '" + tag_name + "'",
|
self.context_menu.addAction(_('Rename') + " '" + tag_name + "'",
|
||||||
partial(self.context_menu_handler, action='edit_item',
|
partial(self.context_menu_handler, action='edit_item',
|
||||||
category=tag_item, index=index))
|
category=tag_item, index=index))
|
||||||
@ -359,12 +360,8 @@ class TagsModel(QAbstractItemModel): # {{{
|
|||||||
data = self.db.get_categories(sort_on_count=sort, icon_map=self.category_icon_map)
|
data = self.db.get_categories(sort_on_count=sort, icon_map=self.category_icon_map)
|
||||||
|
|
||||||
tb_categories = self.db.field_metadata
|
tb_categories = self.db.field_metadata
|
||||||
self.category_items = {}
|
|
||||||
for category in tb_categories:
|
for category in tb_categories:
|
||||||
if category in data: # They should always be there, but ...
|
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] = set([tag.name for tag in data[category]])
|
|
||||||
self.row_map.append(category)
|
self.row_map.append(category)
|
||||||
self.categories.append(tb_categories[category]['name'])
|
self.categories.append(tb_categories[category]['name'])
|
||||||
return data
|
return data
|
||||||
@ -412,15 +409,14 @@ class TagsModel(QAbstractItemModel): # {{{
|
|||||||
return False
|
return False
|
||||||
item = index.internalPointer()
|
item = index.internalPointer()
|
||||||
key = item.parent.category_key
|
key = item.parent.category_key
|
||||||
# make certain we know about the category
|
# make certain we know about the item's category
|
||||||
if key not in self.db.field_metadata:
|
if key not in self.db.field_metadata:
|
||||||
return
|
return
|
||||||
if val in self.category_items[key]:
|
|
||||||
error_dialog(self.tags_view, 'Duplicate item',
|
|
||||||
_('The name %s is already used.')%val).exec_()
|
|
||||||
return False
|
|
||||||
oldval = item.tag.name
|
|
||||||
if key == 'search':
|
if key == 'search':
|
||||||
|
if val in saved_searches.names():
|
||||||
|
error_dialog(self.tags_view, _('Duplicate search name'),
|
||||||
|
_('The saved search name %s is already used.')%val).exec_()
|
||||||
|
return False
|
||||||
saved_searches.rename(unicode(item.data(role).toString()), val)
|
saved_searches.rename(unicode(item.data(role).toString()), val)
|
||||||
self.tags_view.search_item_renamed.emit()
|
self.tags_view.search_item_renamed.emit()
|
||||||
else:
|
else:
|
||||||
@ -437,10 +433,7 @@ class TagsModel(QAbstractItemModel): # {{{
|
|||||||
label=self.db.field_metadata[key]['label'])
|
label=self.db.field_metadata[key]['label'])
|
||||||
self.tags_view.tag_item_renamed.emit()
|
self.tags_view.tag_item_renamed.emit()
|
||||||
item.tag.name = val
|
item.tag.name = val
|
||||||
self.dataChanged.emit(index, index)
|
self.refresh()
|
||||||
# replace the old value in the duplicate detection map with the new one
|
|
||||||
self.category_items[key].discard(oldval)
|
|
||||||
self.category_items[key].add(val)
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def headerData(self, *args):
|
def headerData(self, *args):
|
||||||
|
@ -183,15 +183,30 @@ class CustomColumns(object):
|
|||||||
ans = self.conn.get('SELECT id, value FROM %s'%table)
|
ans = self.conn.get('SELECT id, value FROM %s'%table)
|
||||||
return ans
|
return ans
|
||||||
|
|
||||||
def rename_custom_item(self, id, new_name, label=None, num=None):
|
def rename_custom_item(self, old_id, new_name, label=None, num=None):
|
||||||
if id:
|
if label is not None:
|
||||||
if label is not None:
|
data = self.custom_column_label_map[label]
|
||||||
data = self.custom_column_label_map[label]
|
if num is not None:
|
||||||
if num is not None:
|
data = self.custom_column_num_map[num]
|
||||||
data = self.custom_column_num_map[num]
|
table,lt = self.custom_table_names(data['num'])
|
||||||
table,lt = self.custom_table_names(data['num'])
|
# check if item exists
|
||||||
self.conn.execute('UPDATE %s SET value=? WHERE id=?'%table, (new_name, id))
|
new_id = self.conn.get(
|
||||||
self.conn.commit()
|
'SELECT id FROM %s WHERE value=?'%table, (new_name,), all=False)
|
||||||
|
if new_id is None:
|
||||||
|
self.conn.execute('UPDATE %s SET value=? WHERE id=?'%table, (new_name, old_id))
|
||||||
|
else:
|
||||||
|
# New id exists. If the column is_multiple, then process like
|
||||||
|
# tags, otherwise process like publishers (see database2)
|
||||||
|
if data['is_multiple']:
|
||||||
|
books = self.conn.get('''SELECT book from %s
|
||||||
|
WHERE value=?'''%lt, (old_id,))
|
||||||
|
for (book_id,) in books:
|
||||||
|
self.conn.execute('''DELETE FROM %s
|
||||||
|
WHERE book=? and value=?'''%lt, (book_id, new_id))
|
||||||
|
self.conn.execute('''UPDATE %s SET value=?
|
||||||
|
WHERE value=?'''%lt, (new_id, old_id,))
|
||||||
|
self.conn.execute('DELETE FROM %s WHERE id=?'%table, (old_id,))
|
||||||
|
self.conn.commit()
|
||||||
|
|
||||||
def delete_custom_item_using_id(self, id, label=None, num=None):
|
def delete_custom_item_using_id(self, id, label=None, num=None):
|
||||||
if id:
|
if id:
|
||||||
|
@ -999,16 +999,37 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
|||||||
return []
|
return []
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def rename_tag(self, id, new_name):
|
def rename_tag(self, old_id, new_name):
|
||||||
if id:
|
new_id = self.conn.get(
|
||||||
self.conn.execute('UPDATE tags SET name=? WHERE id=?', (new_name, id))
|
'''SELECT id from tags
|
||||||
self.conn.commit()
|
WHERE name=?''', (new_name,), all=False)
|
||||||
|
if new_id is None:
|
||||||
|
# easy case. Simply rename the tag
|
||||||
|
self.conn.execute('''UPDATE tags SET name=?
|
||||||
|
WHERE id=?''', (new_name, old_id))
|
||||||
|
else:
|
||||||
|
# It is possible that by renaming a tag, the tag will appear
|
||||||
|
# twice on a book. This will throw an integrity error, aborting
|
||||||
|
# all the changes. To get around this, we first delete any links
|
||||||
|
# to the new_id from books referencing the old_id, so that
|
||||||
|
# renaming old_id to new_id will be unique on the book
|
||||||
|
books = self.conn.get('''SELECT book from books_tags_link
|
||||||
|
WHERE tag=?''', (old_id,))
|
||||||
|
for (book_id,) in books:
|
||||||
|
self.conn.execute('''DELETE FROM books_tags_link
|
||||||
|
WHERE book=? and tag=?''', (book_id, new_id))
|
||||||
|
|
||||||
|
# Change the link table to point at the new tag
|
||||||
|
self.conn.execute('''UPDATE books_tags_link SET tag=?
|
||||||
|
WHERE tag=?''',(new_id, old_id,))
|
||||||
|
# Get rid of the no-longer used publisher
|
||||||
|
self.conn.execute('DELETE FROM tags WHERE id=?', (old_id,))
|
||||||
|
self.conn.commit()
|
||||||
|
|
||||||
def delete_tag_using_id(self, id):
|
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 books_tags_link WHERE tag=?', (id,))
|
self.conn.execute('DELETE FROM tags WHERE id=?', (id,))
|
||||||
self.conn.execute('DELETE FROM tags WHERE id=?', (id,))
|
self.conn.commit()
|
||||||
self.conn.commit()
|
|
||||||
|
|
||||||
def get_series_with_ids(self):
|
def get_series_with_ids(self):
|
||||||
result = self.conn.get('SELECT id,name FROM series')
|
result = self.conn.get('SELECT id,name FROM series')
|
||||||
@ -1016,19 +1037,42 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
|||||||
return []
|
return []
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def rename_series(self, id, new_name):
|
def rename_series(self, old_id, new_name):
|
||||||
if id:
|
new_id = self.conn.get(
|
||||||
self.conn.execute('UPDATE series SET name=? WHERE id=?', (new_name, id))
|
'''SELECT id from series
|
||||||
self.conn.commit()
|
WHERE name=?''', (new_name,), all=False)
|
||||||
|
if new_id is None:
|
||||||
|
self.conn.execute('UPDATE series SET name=? WHERE id=?',
|
||||||
|
(new_name, old_id))
|
||||||
|
else:
|
||||||
|
# New series exists. Must update the link, then assign a
|
||||||
|
# new series index to each of the books.
|
||||||
|
|
||||||
|
# Get the list of books where we must update the series index
|
||||||
|
books = self.conn.get('''SELECT book from books_series_link
|
||||||
|
WHERE series=?''', (old_id,))
|
||||||
|
# Get the next series index
|
||||||
|
index = self.get_next_series_num_for(new_name)
|
||||||
|
# Now update the link table
|
||||||
|
self.conn.execute('''UPDATE books_series_link
|
||||||
|
SET series=?
|
||||||
|
WHERE series=?''',(new_id, old_id,))
|
||||||
|
# Now set the indices
|
||||||
|
for (book_id,) in books:
|
||||||
|
self.conn.execute('''UPDATE books
|
||||||
|
SET series_index=?
|
||||||
|
WHERE id=?''',(index, book_id,))
|
||||||
|
index = index + 1
|
||||||
|
self.conn.commit()
|
||||||
|
|
||||||
|
|
||||||
def delete_series_using_id(self, id):
|
def delete_series_using_id(self, id):
|
||||||
if id:
|
books = self.conn.get('SELECT book from books_series_link WHERE series=?', (id,))
|
||||||
books = self.conn.get('SELECT book from books_series_link WHERE series=?', (id,))
|
self.conn.execute('DELETE FROM books_series_link WHERE series=?', (id,))
|
||||||
self.conn.execute('DELETE FROM books_series_link WHERE series=?', (id,))
|
self.conn.execute('DELETE FROM series WHERE id=?', (id,))
|
||||||
self.conn.execute('DELETE FROM series WHERE id=?', (id,))
|
self.conn.commit()
|
||||||
self.conn.commit()
|
for (book_id,) in books:
|
||||||
for (book_id,) in books:
|
self.conn.execute('UPDATE books SET series_index=1.0 WHERE id=?', (book_id,))
|
||||||
self.conn.execute('UPDATE books SET series_index=1.0 WHERE id=?', (book_id,))
|
|
||||||
|
|
||||||
def get_publishers_with_ids(self):
|
def get_publishers_with_ids(self):
|
||||||
result = self.conn.get('SELECT id,name FROM publishers')
|
result = self.conn.get('SELECT id,name FROM publishers')
|
||||||
@ -1036,43 +1080,103 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
|||||||
return []
|
return []
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def rename_publisher(self, id, new_name):
|
def rename_publisher(self, old_id, new_name):
|
||||||
if id:
|
new_id = self.conn.get(
|
||||||
self.conn.execute('UPDATE publishers SET name=? WHERE id=?', (new_name, id))
|
'''SELECT id from publishers
|
||||||
self.conn.commit()
|
WHERE name=?''', (new_name,), all=False)
|
||||||
|
if new_id is None:
|
||||||
|
# New name doesn't exist. Simply change the old name
|
||||||
|
self.conn.execute('UPDATE publishers SET name=? WHERE id=?', \
|
||||||
|
(new_name, old_id))
|
||||||
|
else:
|
||||||
|
# Change the link table to point at the new one
|
||||||
|
self.conn.execute('''UPDATE books_publishers_link
|
||||||
|
SET publisher=?
|
||||||
|
WHERE publisher=?''',(new_id, old_id,))
|
||||||
|
# Get rid of the no-longer used publisher
|
||||||
|
self.conn.execute('DELETE FROM publishers WHERE id=?', (old_id,))
|
||||||
|
self.conn.commit()
|
||||||
|
|
||||||
def delete_publisher_using_id(self, id):
|
def delete_publisher_using_id(self, old_id):
|
||||||
if id:
|
self.conn.execute('''DELETE FROM books_publishers_link
|
||||||
self.conn.execute('DELETE FROM books_publishers_link WHERE publisher=?', (id,))
|
WHERE publisher=?''', (old_id,))
|
||||||
self.conn.execute('DELETE FROM publishers WHERE id=?', (id,))
|
self.conn.execute('DELETE FROM publishers WHERE id=?', (old_id,))
|
||||||
self.conn.commit()
|
self.conn.commit()
|
||||||
|
|
||||||
# There is no editor for author, so we do not need get_authors_with_ids or
|
# There is no editor for author, so we do not need get_authors_with_ids or
|
||||||
# delete_author_using_id.
|
# delete_author_using_id.
|
||||||
def rename_author(self, id, new_name):
|
|
||||||
if id:
|
def rename_author(self, old_id, new_name):
|
||||||
# Make sure that any commas in new_name are changed to '|'!
|
# Make sure that any commas in new_name are changed to '|'!
|
||||||
new_name = new_name.replace(',', '|')
|
new_name = new_name.replace(',', '|')
|
||||||
self.conn.execute('UPDATE authors SET name=? WHERE id=?', (new_name, id))
|
|
||||||
self.conn.commit()
|
# Get the list of books we must fix up, one way or the other
|
||||||
# now must fix up the books
|
books = self.conn.get('SELECT book from books_authors_link WHERE author=?', (old_id,))
|
||||||
books = self.conn.get('SELECT book from books_authors_link WHERE author=?', (id,))
|
|
||||||
|
# check if the new author already exists
|
||||||
|
new_id = self.conn.get('SELECT id from authors WHERE name=?',
|
||||||
|
(new_name,), all=False)
|
||||||
|
if new_id is None:
|
||||||
|
# No name clash. Go ahead and update the author's name
|
||||||
|
self.conn.execute('UPDATE authors SET name=? WHERE id=?',
|
||||||
|
(new_name, old_id))
|
||||||
|
else:
|
||||||
|
# Author exists. To fix this, we must replace all the authors
|
||||||
|
# instead of replacing the one. Reason: db integrity checks can stop
|
||||||
|
# the rename process, which would leave everything half-done. We
|
||||||
|
# can't do it the same way as tags (delete and add) because author
|
||||||
|
# order is important.
|
||||||
for (book_id,) in books:
|
for (book_id,) in books:
|
||||||
# First, must refresh the cache to see the new authors
|
# Get the existing list of 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('''
|
authors = self.conn.get('''
|
||||||
SELECT authors.name
|
SELECT author from books_authors_link
|
||||||
FROM authors, books_authors_link as bl
|
WHERE book=?
|
||||||
WHERE bl.book = ? and bl.author = authors.id
|
ORDER BY id''',(book_id,))
|
||||||
''' , (book_id,))
|
|
||||||
# unpack the double-list structure
|
# unpack the double-list structure, replacing the old author
|
||||||
|
# with the new one while we are at it
|
||||||
for i,aut in enumerate(authors):
|
for i,aut in enumerate(authors):
|
||||||
authors[i] = aut[0]
|
authors[i] = aut[0] if aut[0] != old_id else new_id
|
||||||
ss = authors_to_sort_string(authors)
|
|
||||||
self.conn.execute('UPDATE books SET author_sort=? WHERE id=?', (ss, id))
|
# Delete the existing authors list
|
||||||
|
self.conn.execute('''DELETE FROM books_authors_link
|
||||||
|
WHERE book=?''',(book_id,))
|
||||||
|
# Change the authors to the new list
|
||||||
|
for aid in authors:
|
||||||
|
try:
|
||||||
|
self.conn.execute('''
|
||||||
|
INSERT INTO books_authors_link(book, author)
|
||||||
|
VALUES (?,?)''', (book_id, aid))
|
||||||
|
except IntegrityError:
|
||||||
|
# Sometimes books specify the same author twice in their
|
||||||
|
# metadata. Ignore it.
|
||||||
|
pass
|
||||||
|
# Now delete the old author from the DB
|
||||||
|
self.conn.execute('DELETE FROM authors WHERE id=?', (old_id,))
|
||||||
|
self.conn.commit()
|
||||||
|
# the authors are now changed, either by changing the author's name
|
||||||
|
# or replacing the author in the list. Now must fix up the books.
|
||||||
|
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, old_id))
|
||||||
|
self.conn.commit()
|
||||||
|
# the caller will do a general refresh, so we don't need to
|
||||||
|
# do one here
|
||||||
|
|
||||||
# end convenience methods
|
# end convenience methods
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user