diff --git a/src/calibre/gui2/actions/edit_metadata.py b/src/calibre/gui2/actions/edit_metadata.py index 559ea4a6f7..725bf35993 100644 --- a/src/calibre/gui2/actions/edit_metadata.py +++ b/src/calibre/gui2/actions/edit_metadata.py @@ -8,7 +8,7 @@ __docformat__ = 'restructuredtext en' import os from functools import partial -from PyQt4.Qt import Qt, QMenu +from PyQt4.Qt import Qt, QMenu, QModelIndex from calibre.gui2 import error_dialog, config from calibre.gui2.dialogs.metadata_single import MetadataSingleDialog @@ -126,20 +126,35 @@ class EditMetadataAction(InterfaceAction): if bulk or (bulk is None and len(rows) > 1): return self.edit_bulk_metadata(checked) - def accepted(id): - self.gui.library_view.model().refresh_ids([id]) + row_list = [r.row() for r in rows] + current_row = 0 + changed = set([]) + db = self.gui.library_view.model().db - for row in rows: - self.gui.iactions['View'].metadata_view_id = self.gui.library_view.model().db.id(row.row()) - d = MetadataSingleDialog(self.gui, row.row(), - self.gui.library_view.model().db, - accepted_callback=accepted, - cancel_all=rows.index(row) < len(rows)-1) - d.view_format.connect(self.gui.iactions['View'].metadata_view_format) - d.exec_() - if d.cancel_all: + if len(row_list) == 1: + cr = row_list[0] + row_list = \ + list(range(self.gui.library_view.model().rowCount(QModelIndex()))) + current_row = row_list.index(cr) + + while True: + prev = next_ = None + if current_row > 0: + prev = db.title(row_list[current_row-1]) + if current_row < len(row_list) - 1: + next_ = db.title(row_list[current_row+1]) + + d = MetadataSingleDialog(self.gui, row_list[current_row], db, + prev=prev, next_=next_) + if d.exec_() != d.Accepted: break - if rows: + changed.add(d.id) + if d.row_delta == 0: + break + current_row += d.row_delta + + if changed: + self.gui.library_view.model().refresh_ids(list(changed)) current = self.gui.library_view.currentIndex() m = self.gui.library_view.model() if self.gui.cover_flow: diff --git a/src/calibre/gui2/dialogs/metadata_single.py b/src/calibre/gui2/dialogs/metadata_single.py index b57ff318ad..2c08252266 100644 --- a/src/calibre/gui2/dialogs/metadata_single.py +++ b/src/calibre/gui2/dialogs/metadata_single.py @@ -7,9 +7,11 @@ add/remove formats ''' import os, re, time, traceback, textwrap +from functools import partial from PyQt4.Qt import SIGNAL, QObject, Qt, QTimer, QThread, QDate, \ - QPixmap, QListWidgetItem, QDialog, pyqtSignal, QMessageBox + QPixmap, QListWidgetItem, QDialog, pyqtSignal, QMessageBox, QIcon, \ + QPushButton from calibre.gui2 import error_dialog, file_icon_provider, dynamic, \ choose_files, choose_images, ResizableDialog, \ @@ -429,11 +431,8 @@ class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog): # }}} - def do_cancel_all(self): - self.cancel_all = True - self.reject() - - def __init__(self, window, row, db, accepted_callback=None, cancel_all=False): + def __init__(self, window, row, db, prev=None, + next_=None): ResizableDialog.__init__(self, window) self.bc_box.layout().setAlignment(self.cover, Qt.AlignCenter|Qt.AlignHCenter) self.cancel_all = False @@ -445,16 +444,27 @@ class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog): _(' The red color indicates that the current ' 'author sort does not match the current author')) - if cancel_all: - self.__abort_button = self.button_box.addButton(self.button_box.Abort) - self.__abort_button.setToolTip(_('Abort the editing of all remaining books')) - self.connect(self.__abort_button, SIGNAL('clicked()'), - self.do_cancel_all) + self.row_delta = 0 + if prev: + self.prev_button = QPushButton(QIcon(I('back.png')), _('Previous'), + self) + self.button_box.addButton(self.prev_button, self.button_box.ActionRole) + tip = _('Edit the metadata of %s')%prev + self.prev_button.setToolTip(tip) + self.prev_button.clicked.connect(partial(self.next_triggered, + -1)) + if next_: + self.next_button = QPushButton(QIcon(I('forward.png')), _('Next'), + self) + self.button_box.addButton(self.next_button, self.button_box.ActionRole) + tip = _('Edit the metadata of %s')%next_ + self.next_button.setToolTip(tip) + self.next_button.clicked.connect(partial(self.next_triggered, 1)) + self.splitter.setStretchFactor(100, 1) self.read_state() self.db = db self.pi = ProgressIndicator(self) - self.accepted_callback = accepted_callback self.id = db.id(row) self.row = row self.cover_data = None @@ -801,6 +811,10 @@ class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog): unicode(self.tags.text()).split(',')], notify=notify, commit=commit) + def next_triggered(self, row_delta, *args): + self.row_delta = row_delta + self.accept() + def accept(self): cf = getattr(self, 'cover_fetcher', None) if cf is not None and hasattr(cf, 'terminate'): @@ -862,8 +876,6 @@ class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog): raise self.save_state() QDialog.accept(self) - if callable(self.accepted_callback): - self.accepted_callback(self.id) def reject(self, *args): cf = getattr(self, 'cover_fetcher', None)