From c9cf3066e895a1a3f4f23bebf13d9a7ae29307fe Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 6 Apr 2015 11:59:03 +0530 Subject: [PATCH] Edit Book: When dragging and dropping files to re-order them in the file browser, fix the final order being dependent on the order the files were selected in. Fixes #1440598 [Edit Book: Inverted order of files after drag and drop](https://bugs.launchpad.net/calibre/+bug/1440598) --- src/calibre/gui2/tweak_book/file_list.py | 48 ++++++++++++++++-------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/src/calibre/gui2/tweak_book/file_list.py b/src/calibre/gui2/tweak_book/file_list.py index 70c6dab384..5cd95187fe 100644 --- a/src/calibre/gui2/tweak_book/file_list.py +++ b/src/calibre/gui2/tweak_book/file_list.py @@ -155,6 +155,7 @@ class FileList(QTreeWidget): def __init__(self, parent=None): QTreeWidget.__init__(self, parent) + self.ordered_selected_indexes = False pi = plugins['progress_indicator'][0] if hasattr(pi, 'set_no_activate_on_click'): pi.set_no_activate_on_click(self) @@ -556,23 +557,38 @@ class FileList(QTreeWidget): b.setValue(b.minimum()) QTimer.singleShot(0, lambda : b.setValue(b.maximum())) + def __enter__(self): + self.ordered_selected_indexes = True + + def __exit__(self, *args): + self.ordered_selected_indexes = False + + def selectedIndexes(self): + ans = QTreeWidget.selectedIndexes(self) + if self.ordered_selected_indexes: + # The reverse is needed because Qt's implementation of dropEvent + # reverses the selectedIndexes when dropping. + ans = list(sorted(ans, key=lambda idx:idx.row(), reverse=True)) + return ans + def dropEvent(self, event): - text = self.categories['text'] - pre_drop_order = {text.child(i):i for i in xrange(text.childCount())} - super(FileList, self).dropEvent(event) - current_order = {text.child(i):i for i in xrange(text.childCount())} - if current_order != pre_drop_order: - order = [] - for child in (text.child(i) for i in xrange(text.childCount())): - name = unicode(child.data(0, NAME_ROLE) or '') - linear = bool(child.data(0, LINEAR_ROLE)) - order.append([name, linear]) - # Ensure that all non-linear items are at the end, any non-linear - # items not at the end will be made linear - for i, (name, linear) in tuple(enumerate(order)): - if not linear and i < len(order) - 1 and order[i+1][1]: - order[i][1] = True - self.reorder_spine.emit(order) + with self: + text = self.categories['text'] + pre_drop_order = {text.child(i):i for i in xrange(text.childCount())} + super(FileList, self).dropEvent(event) + current_order = {text.child(i):i for i in xrange(text.childCount())} + if current_order != pre_drop_order: + order = [] + for child in (text.child(i) for i in xrange(text.childCount())): + name = unicode(child.data(0, NAME_ROLE) or '') + linear = bool(child.data(0, LINEAR_ROLE)) + order.append([name, linear]) + # Ensure that all non-linear items are at the end, any non-linear + # items not at the end will be made linear + for i, (name, linear) in tuple(enumerate(order)): + if not linear and i < len(order) - 1 and order[i+1][1]: + order[i][1] = True + self.reorder_spine.emit(order) def item_double_clicked(self, item, column): category = unicode(item.data(0, CATEGORY_ROLE) or '')