diff --git a/core/gui/prioritize_dialog.py b/core/gui/prioritize_dialog.py index 70f6ddf4..24ad4367 100644 --- a/core/gui/prioritize_dialog.py +++ b/core/gui/prioritize_dialog.py @@ -18,6 +18,19 @@ class CriterionCategoryList(GUISelectableList): def _update_selection(self): self.dialog.select_category(self.dialog.categories[self.selected_index]) +class PrioritizationList(GUISelectableList): + def __init__(self, dialog): + self.dialog = dialog + GUISelectableList.__init__(self) + + def move_indexes(self, indexes, dest_index): + indexes.sort() + prilist = self.dialog.prioritizations + selected = [prilist[i] for i in indexes] + for i in reversed(indexes): + del prilist[i] + prilist[dest_index:dest_index] = selected + self[:] = [crit.display for crit in prilist] class PrioritizeDialog: def __init__(self, view, app): @@ -27,7 +40,7 @@ class PrioritizeDialog: self.criteria = [] self.criteria_list = GUISelectableList() self.prioritizations = [] - self.prioritization_list = GUISelectableList() + self.prioritization_list = PrioritizationList(self) #--- Private def _sort_key(self, dupe): diff --git a/core/tests/base.py b/core/tests/base.py index 593b173f..6489b995 100644 --- a/core/tests/base.py +++ b/core/tests/base.py @@ -101,3 +101,8 @@ class TestApp(TestAppBase): # maintainable. index = self.pdialog.category_list.index(name) self.pdialog.category_list.select(index) + + def add_pri_criterion(self, name, index): + self.select_pri_criterion("Kind") + self.pdialog.criteria_list.select([index]) + self.pdialog.add_selected() diff --git a/core/tests/prioritize_test.py b/core/tests/prioritize_test.py index 7ec84dee..18ebd5e2 100644 --- a/core/tests/prioritize_test.py +++ b/core/tests/prioritize_test.py @@ -98,3 +98,14 @@ def test_size_reprioritization(app): app.pdialog.add_selected() app.pdialog.perform_reprioritization() eq_(app.rtable[0].data[0], 'foo2.ext2') + +@with_app(app_normal_results) +def test_reorder_prioritizations(app): + app.add_pri_criterion("Kind", 0) # ext1 + app.add_pri_criterion("Kind", 1) # ext2 + app.pdialog.prioritization_list.move_indexes([1], 0) + expected = [ + "Kind (ext2)", + "Kind (ext1)", + ] + eq_(app.pdialog.prioritization_list[:], expected) diff --git a/qt/base/prioritize_dialog.py b/qt/base/prioritize_dialog.py index 580e3976..fd6bac85 100644 --- a/qt/base/prioritize_dialog.py +++ b/qt/base/prioritize_dialog.py @@ -6,14 +6,48 @@ # which should be included with this package. The terms are also available at # http://www.hardcoded.net/licenses/bsd_license -from PyQt4.QtCore import Qt +from PyQt4.QtCore import Qt, QMimeData, QByteArray from PyQt4.QtGui import (QDialog, QVBoxLayout, QHBoxLayout, QPushButton, QComboBox, QListView, - QDialogButtonBox) + QDialogButtonBox, QAbstractItemView) from hscommon.trans import tr from qtlib.selectable_list import ComboboxModel, ListviewModel from core.gui.prioritize_dialog import PrioritizeDialog as PrioritizeDialogModel +MIME_INDEXES = 'application/dupeguru.rowindexes' + +class PrioritizationList(ListviewModel): + def flags(self, index): + if not index.isValid(): + return Qt.ItemIsEnabled | Qt.ItemIsDropEnabled + return Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsDragEnabled + + #--- Drag & Drop + def dropMimeData(self, mimeData, action, row, column, parentIndex): + if not mimeData.hasFormat(MIME_INDEXES): + return False + # Since we only drop in between items, parentIndex must be invalid, and we use the row arg + # to know where the drop took place. + if parentIndex.isValid(): + return False + strMimeData = bytes(mimeData.data(MIME_INDEXES)).decode() + indexes = list(map(int, strMimeData.split(','))) + self.model.move_indexes(indexes, row) + return True + + def mimeData(self, indexes): + rows = {str(index.row()) for index in indexes} + data = ','.join(rows) + mimeData = QMimeData() + mimeData.setData(MIME_INDEXES, QByteArray(data.encode())) + return mimeData + + def mimeTypes(self): + return [MIME_INDEXES] + + def supportedDropActions(self): + return Qt.MoveAction + class PrioritizeDialog(QDialog): def __init__(self, parent, app): flags = Qt.CustomizeWindowHint | Qt.WindowTitleHint | Qt.WindowSystemMenuHint @@ -23,7 +57,7 @@ class PrioritizeDialog(QDialog): self.model = PrioritizeDialogModel(view=self, app=app) self.categoryList = ComboboxModel(model=self.model.category_list, view=self.categoryCombobox) self.criteriaList = ListviewModel(model=self.model.criteria_list, view=self.criteriaListView) - self.prioritizationList = ListviewModel(model=self.model.prioritization_list, view=self.prioritizationListView) + self.prioritizationList = PrioritizationList(model=self.model.prioritization_list, view=self.prioritizationListView) self.addCriteriaButton.clicked.connect(self.model.add_selected) self.buttonBox.accepted.connect(self.accept) @@ -38,6 +72,10 @@ class PrioritizeDialog(QDialog): self.criteriaListView = QListView() self.addCriteriaButton = QPushButton("-->") self.prioritizationListView = QListView() + self.prioritizationListView.setAcceptDrops(True) + self.prioritizationListView.setDragEnabled(True) + self.prioritizationListView.setDragDropMode(QAbstractItemView.InternalMove) + self.prioritizationListView.setSelectionBehavior(QAbstractItemView.SelectRows) self.buttonBox = QDialogButtonBox() self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel|QDialogButtonBox.Ok)