diff --git a/src/calibre/gui2/dialogs/edit_authors_dialog.py b/src/calibre/gui2/dialogs/edit_authors_dialog.py
index 43c7faad24..edddeee05b 100644
--- a/src/calibre/gui2/dialogs/edit_authors_dialog.py
+++ b/src/calibre/gui2/dialogs/edit_authors_dialog.py
@@ -47,10 +47,11 @@ class EditColumnDelegate(QItemDelegate):
class EditAuthorsDialog(QDialog, Ui_EditAuthorsDialog):
- def __init__(self, parent, db, id_to_select, select_sort, select_link):
+ def __init__(self, parent, db, id_to_select, select_sort, select_link, find_aut_func):
QDialog.__init__(self, parent)
Ui_EditAuthorsDialog.__init__(self)
self.setupUi(self)
+
# Remove help icon on title bar
icon = self.windowIcon()
self.setWindowFlags(self.windowFlags()&(~Qt.WindowContextHelpButtonHint))
@@ -68,49 +69,15 @@ class EditAuthorsDialog(QDialog, Ui_EditAuthorsDialog):
self.buttonBox.button(QDialogButtonBox.Ok).setText(_('&OK'))
self.buttonBox.button(QDialogButtonBox.Cancel).setText(_('&Cancel'))
self.buttonBox.accepted.connect(self.accepted)
+ self.apply_vl_checkbox.stateChanged.connect(self.use_vl_changed)
- # Set up the column headings
+ # Set up the heading for sorting
self.table.setSelectionMode(QAbstractItemView.SingleSelection)
- self.table.setColumnCount(3)
self.down_arrow_icon = QIcon(I('arrow-down.png'))
self.up_arrow_icon = QIcon(I('arrow-up.png'))
self.blank_icon = QIcon(I('blank.png'))
- self.auth_col = QTableWidgetItem(_('Author'))
- self.table.setHorizontalHeaderItem(0, self.auth_col)
- self.auth_col.setIcon(self.blank_icon)
- self.aus_col = QTableWidgetItem(_('Author sort'))
- self.table.setHorizontalHeaderItem(1, self.aus_col)
- self.aus_col.setIcon(self.up_arrow_icon)
- self.aul_col = QTableWidgetItem(_('Link'))
- self.table.setHorizontalHeaderItem(2, self.aul_col)
- self.aus_col.setIcon(self.blank_icon)
-
- # Add the data
- self.authors = {}
- auts = db.get_authors_with_ids()
- self.table.setRowCount(len(auts))
- select_item = None
- completion_data = []
- for row, (_id, author, sort, link) in enumerate(auts):
- author = author.replace('|', ',')
- self.authors[_id] = (author, sort, link)
- completion_data.append(author)
- aut = tableItem(author)
- aut.setData(Qt.UserRole, _id)
- sort = tableItem(sort)
- link = tableItem(link)
- self.table.setItem(row, 0, aut)
- self.table.setItem(row, 1, sort)
- self.table.setItem(row, 2, link)
- if id_to_select in (_id, author):
- if select_sort:
- select_item = sort
- elif select_link:
- select_item = link
- else:
- select_item = aut
- self.table.setItemDelegate(EditColumnDelegate(completion_data))
+ self.find_aut_func = find_aut_func
self.table.resizeColumnsToContents()
if self.table.columnWidth(2) < 200:
self.table.setColumnWidth(2, 200)
@@ -118,28 +85,14 @@ class EditAuthorsDialog(QDialog, Ui_EditAuthorsDialog):
# set up the cellChanged signal only after the table is filled
self.table.cellChanged.connect(self.cell_changed)
- # set up sort buttons
- self.sort_by_author.setCheckable(True)
- self.sort_by_author.setChecked(False)
- self.sort_by_author.clicked.connect(self.do_sort_by_author)
- self.author_order = 1
-
- self.sort_by_author_sort.clicked.connect(self.do_sort_by_author_sort)
- self.sort_by_author_sort.setCheckable(True)
- self.sort_by_author_sort.setChecked(True)
- self.author_sort_order = 1
-
self.recalc_author_sort.clicked.connect(self.do_recalc_author_sort)
self.auth_sort_to_author.clicked.connect(self.do_auth_sort_to_author)
- # Position on the desired item
- if select_item is not None:
- self.table.setCurrentItem(select_item)
- self.table.editItem(select_item)
- self.start_find_pos = select_item.row() * 2 + select_item.column()
- else:
- self.table.setCurrentCell(0, 0)
- self.start_find_pos = -1
+ # Capture clicks on the horizontal header to sort the table columns
+ hh = self.table.horizontalHeader()
+ hh.setSectionsClickable(True)
+ hh.sectionClicked.connect(self.header_clicked)
+ hh.sectionResized.connect(self.table_column_resized)
# set up the search box
self.find_box.initialize('manage_authors_search')
@@ -165,7 +118,101 @@ class EditAuthorsDialog(QDialog, Ui_EditAuthorsDialog):
self.table.setContextMenuPolicy(Qt.CustomContextMenu)
self.table.customContextMenuRequested.connect(self.show_context_menu)
- self.do_sort_by_author_sort()
+
+ # Fetch the data
+ self.authors = {}
+ self.original_authors = {}
+ auts = db.new_api.author_data()
+ self.completion_data = []
+ for id_, v in auts.items():
+ name = v['name']
+ name = name.replace('|', ',')
+ self.completion_data.append(name)
+ self.authors[id_] = {'name': name, 'sort': v['sort'], 'link': v['link']}
+ self.original_authors[id_] = {'name': name, 'sort': v['sort'],
+ 'link': v['link']}
+
+ self.edited_icon = QIcon(I('edit_input.png'))
+ self.down_arrow_icon = QIcon(I('arrow-down.png'))
+ self.up_arrow_icon = QIcon(I('arrow-up.png'))
+ self.blank_icon = QIcon(I('blank.png'))
+ self.last_sorted_by = 'sort'
+ self.author_order = 1
+ self.author_sort_order = 0
+ self.link_order = 1
+ self.show_table(id_to_select, select_sort, select_link)
+
+ def use_vl_changed(self, x):
+ self.show_table(None, None, None)
+
+ def show_table(self, id_to_select, select_sort, select_link):
+ auts_to_show = [t[0] for t in
+ self.find_aut_func(use_virtual_library = self.apply_vl_checkbox.isChecked())]
+ self.table.blockSignals(True)
+ self.table.clear()
+ self.table.setColumnCount(3)
+ self.auth_col = QTableWidgetItem(_('Author'))
+ self.table.setHorizontalHeaderItem(0, self.auth_col)
+ self.aus_col = QTableWidgetItem(_('Author sort'))
+ self.table.setHorizontalHeaderItem(1, self.aus_col)
+ self.aul_col = QTableWidgetItem(_('Link'))
+ self.table.setHorizontalHeaderItem(2, self.aul_col)
+
+ self.table.setRowCount(len(auts_to_show))
+ select_item = None
+ row = 0
+ for id_, v in self.authors.items():
+ if id_ not in auts_to_show:
+ continue
+ name, sort, link = (v['name'], v['sort'], v['link'])
+ orig = self.original_authors[id_]
+ name = name.replace('|', ',')
+
+ name_item = tableItem(name)
+ name_item.setData(Qt.UserRole, id_)
+ if name != orig['name']:
+ name_item.setIcon(self.edited_icon)
+ sort_item = tableItem(sort)
+ if sort != orig['sort']:
+ sort_item.setIcon(self.edited_icon)
+ link_item = tableItem(link)
+ if link != orig['link']:
+ link_item.setIcon(self.edited_icon)
+ self.table.setItem(row, 0, name_item)
+ self.table.setItem(row, 1, sort_item)
+ self.table.setItem(row, 2, link_item)
+
+ if id_to_select and id_to_select in (id_, name):
+ print('id', id_to_select)
+ if select_sort:
+ select_item = sort_item
+ elif select_link:
+ select_item = link_item
+ else:
+ select_item = name_item
+ row += 1
+
+ self.table.setItemDelegate(EditColumnDelegate(self.completion_data))
+
+ if self.last_sorted_by == 'sort':
+ self.author_sort_order = 1 if self.author_sort_order == 0 else 0
+ self.do_sort_by_author_sort()
+ elif self.last_sorted_by == 'author':
+ self.author_order = 1 if self.author_order == 0 else 0
+ self.do_sort_by_author()
+ else:
+ self.link_order = 1 if self.link_order == 0 else 0
+ self.do_sort_by_link()
+
+ # Position on the desired item
+ if select_item is not None:
+ self.table.setCurrentItem(select_item)
+ self.table.editItem(select_item)
+ self.start_find_pos = select_item.row() * 2 + select_item.column()
+ else:
+ self.table.setCurrentCell(0, 0)
+ self.start_find_pos = -1
+ self.table.blockSignals(False)
def save_state(self):
self.table_column_widths = []
@@ -174,6 +221,11 @@ class EditAuthorsDialog(QDialog, Ui_EditAuthorsDialog):
gprefs['manage_authors_table_widths'] = self.table_column_widths
gprefs['manage_authors_dialog_geometry'] = bytearray(self.saveGeometry())
+ def table_column_resized(self, col, old, new):
+ self.table_column_widths = []
+ for c in range(0, self.table.columnCount()):
+ self.table_column_widths.append(self.table.columnWidth(c))
+
def resizeEvent(self, *args):
QDialog.resizeEvent(self, *args)
if self.table_column_widths is not None:
@@ -216,7 +268,7 @@ class EditAuthorsDialog(QDialog, Ui_EditAuthorsDialog):
ca.triggered.connect(self.copy_au_to_aus)
m.addSeparator()
ca = m.addAction(_("Show books by author in book list"))
- ca.triggered.connect(self.search)
+ ca.triggered.connect(self.search_in_book_list)
else:
ca = m.addAction(_('Copy to author'))
ca.triggered.connect(self.copy_aus_to_au)
@@ -224,7 +276,7 @@ class EditAuthorsDialog(QDialog, Ui_EditAuthorsDialog):
m.addMenu(case_menu)
m.exec_(self.table.mapToGlobal(point))
- def search(self):
+ def search_in_book_list(self):
from calibre.gui2.ui import get_gui
row = self.context_item.row()
get_gui().search.set_search_string(self.table.item(row, 0).text())
@@ -294,35 +346,48 @@ class EditAuthorsDialog(QDialog, Ui_EditAuthorsDialog):
self.not_found_label.setVisible(True)
self.not_found_label_timer.start(1500)
+ def header_clicked(self, idx):
+ if idx == 0:
+ self.do_sort_by_author()
+ elif idx == 1:
+ self.do_sort_by_author_sort()
+ else:
+ self.do_sort_by_link()
+
def do_sort_by_author(self):
+ self.last_sorted_by = 'author'
self.author_order = 1 if self.author_order == 0 else 0
self.table.sortByColumn(0, self.author_order)
- self.sort_by_author.setChecked(True)
- self.sort_by_author_sort.setChecked(False)
self.auth_col.setIcon(self.down_arrow_icon if self.author_order
else self.up_arrow_icon)
self.aus_col.setIcon(self.blank_icon)
+ self.aul_col.setIcon(self.blank_icon)
def do_sort_by_author_sort(self):
+ self.last_sorted_by = 'sort'
self.author_sort_order = 1 if self.author_sort_order == 0 else 0
self.table.sortByColumn(1, self.author_sort_order)
- self.sort_by_author.setChecked(False)
- self.sort_by_author_sort.setChecked(True)
self.aus_col.setIcon(self.down_arrow_icon if self.author_sort_order
else self.up_arrow_icon)
self.auth_col.setIcon(self.blank_icon)
+ self.aul_col.setIcon(self.blank_icon)
+
+ def do_sort_by_link(self):
+ self.last_sorted_by = 'link'
+ self.link_order = 1 if self.link_order == 0 else 0
+ self.table.sortByColumn(2, self.link_order)
+ self.aul_col.setIcon(self.down_arrow_icon if self.link_order
+ else self.up_arrow_icon)
+ self.auth_col.setIcon(self.blank_icon)
+ self.aus_col.setIcon(self.blank_icon)
def accepted(self):
self.save_state()
self.result = []
- for row in range(0,self.table.rowCount()):
- id = int(self.table.item(row, 0).data(Qt.UserRole))
- aut = unicode_type(self.table.item(row, 0).text()).strip()
- sort = unicode_type(self.table.item(row, 1).text()).strip()
- link = unicode_type(self.table.item(row, 2).text()).strip()
- orig_aut,orig_sort,orig_link = self.authors[id]
- if orig_aut != aut or orig_sort != sort or orig_link != link:
- self.result.append((id, orig_aut, aut, sort, link))
+ for id_, v in self.authors.items():
+ orig = self.original_authors[id_]
+ if orig != v:
+ self.result.append((id_, orig['name'], v['name'], v['sort'], v['link']))
def do_recalc_author_sort(self):
self.table.cellChanged.disconnect()
@@ -347,8 +412,10 @@ class EditAuthorsDialog(QDialog, Ui_EditAuthorsDialog):
self.table.cellChanged.connect(self.cell_changed)
def cell_changed(self, row, col):
+ id_ = int(self.table.item(row, 0).data(Qt.UserRole))
if col == 0:
item = self.table.item(row, 0)
+ item.setIcon(self.edited_icon)
aut = unicode_type(item.text()).strip()
aut_list = string_to_authors(aut)
if len(aut_list) != 1:
@@ -356,10 +423,18 @@ class EditAuthorsDialog(QDialog, Ui_EditAuthorsDialog):
_('You cannot change an author to multiple authors.')).exec_()
aut = ' % '.join(aut_list)
self.table.item(row, 0).setText(aut)
+ self.authors[id_]['name'] = aut
c = self.table.item(row, 1)
- c.setText(author_to_author_sort(aut))
+ txt = author_to_author_sort(aut)
+ c.setText(txt)
+ self.authors[id_]['sort'] = txt
item = c
else:
item = self.table.item(row, col)
+ item.setIcon(self.edited_icon)
+ if col == 1:
+ self.authors[id_]['sort'] = item.text()
+ else:
+ self.authors[id_]['link'] = item.text()
self.table.setCurrentItem(item)
self.table.scrollToItem(item)
diff --git a/src/calibre/gui2/dialogs/edit_authors_dialog.ui b/src/calibre/gui2/dialogs/edit_authors_dialog.ui
index e0f08d1b6a..8268c551ec 100644
--- a/src/calibre/gui2/dialogs/edit_authors_dialog.ui
+++ b/src/calibre/gui2/dialogs/edit_authors_dialog.ui
@@ -62,6 +62,18 @@
+ -
+
+
+ <p>Show authors only if they appear in the
+ current Virtual library. Edits already done may be hidden but will
+ not be forgotten.</p>
+
+
+ &Show only available items in current Virtual library
+
+
+
-
@@ -79,20 +91,6 @@
-
-
-
-
-
- Sort by &author
-
-
-
- -
-
-
- Sort by author &sort
-
-
-
-
diff --git a/src/calibre/gui2/dialogs/tag_list_editor.ui b/src/calibre/gui2/dialogs/tag_list_editor.ui
index f9235dc69e..bd2e157ae8 100644
--- a/src/calibre/gui2/dialogs/tag_list_editor.ui
+++ b/src/calibre/gui2/dialogs/tag_list_editor.ui
@@ -65,9 +65,9 @@
-
- <p>Show items in the Available items box only if they appear in the
- current Virtual library. Applied items not in the Virtual library will be marked
- "not on any book".</p>
+ <p>Show items only if they appear in the
+ current Virtual library. Edits already done may be hidden but will
+ not be forgotten.</p>
&Show only available items in current Virtual library
diff --git a/src/calibre/gui2/tag_browser/ui.py b/src/calibre/gui2/tag_browser/ui.py
index b67f643ac6..0bbd848679 100644
--- a/src/calibre/gui2/tag_browser/ui.py
+++ b/src/calibre/gui2/tag_browser/ui.py
@@ -231,6 +231,15 @@ class TagBrowserMixin(object): # {{{
self.tags_view.recount()
self.user_categories_edited()
+ def get_book_ids(self, use_virtual_library, db, category):
+ book_ids = None if not use_virtual_library else self.tags_view.model().get_book_ids_to_use()
+ data = db.new_api.get_categories(book_ids=book_ids)
+ if category in data:
+ result = [(t.id, t.original_name, t.count) for t in data[category] if t.count > 0]
+ else:
+ result = None
+ return result
+
def do_tags_list_edit(self, tag, category):
'''
Open the 'manage_X' dialog where X == category. If tag is not None, the
@@ -238,23 +247,15 @@ class TagBrowserMixin(object): # {{{
'''
db = self.current_db
-
- def get_book_ids(use_virtual_library):
- book_ids = None if not use_virtual_library else self.tags_view.model().get_book_ids_to_use()
- data = db.new_api.get_categories(book_ids=book_ids)
- if category in data:
- result = [(t.id, t.original_name, t.count) for t in data[category] if t.count > 0]
- else:
- result = None
- return result
-
if category == 'series':
key = lambda x:sort_key(title_sort(x))
else:
key = sort_key
d = TagListEditor(self, cat_name=db.field_metadata[category]['name'],
- tag_to_match=tag, get_book_ids=get_book_ids, sorter=key)
+ tag_to_match=tag,
+ get_book_ids=partial(self.get_book_ids, db=db, category=category),
+ sorter=key)
d.exec_()
if d.result() == d.Accepted:
to_rename = d.to_rename # dict of old id to new name
@@ -361,7 +362,8 @@ class TagBrowserMixin(object): # {{{
'''
db = self.library_view.model().db
- editor = EditAuthorsDialog(parent, db, id_, select_sort, select_link)
+ editor = EditAuthorsDialog(parent, db, id_, select_sort, select_link,
+ partial(self.get_book_ids, db=db, category='authors'))
if editor.exec_() == editor.Accepted:
# Save and restore the current selections. Note that some changes
# will cause sort orders to change, so don't bother with attempting