Repository: biolab/orange3

Issue:
Edit Domain: enable reordering for discrete variables
<!--
This is an issue template. Please fill in the relevant details in the
sections below.

Wrap code and verbatim terminal window output into triple backticks, see:
https://help.github.com/articles/basic-writing-and-formatting-syntax/#quoting-code

If you're raising an issue about an add-on (e.g. installed via
Options > Add-ons), raise an issue on the relevant add-on's issue
tracker instead. See: https://github.com/biolab?q=orange3
-->

##### Orange version
<!-- From menu _Help→About→Version_ or code `Orange.version.full_version` -->
3.14.dev

##### Expected behavior
One can change the order of values of discrete variables in Edit Domain.


##### Actual behavior
No changing is possible.


##### Steps to reproduce the behavior
File - Iris - Edit Domain. Try to have iris virginica on top.


##### Additional info (worksheets, data, screenshots, ...)
When would this be useful? I have a variable with days of the week. Orange sorts them alphabetically, which means I will always see this: Friday, Monday, Saturday, Sunday, Thursday, Tuesday, Wednesday. Evidently, this is not what one would want. For visualizations it would be great to change the order in Edit Domain.



Discussion:

Resolving patch:
diff --git a/Orange/widgets/data/oweditdomain.py b/Orange/widgets/data/oweditdomain.py
--- a/Orange/widgets/data/oweditdomain.py
+++ b/Orange/widgets/data/oweditdomain.py
@@ -317,14 +317,55 @@ def setup_gui(self):
         self._setup_gui_labels()
 
     def _setup_gui_values(self):
+        vlayout = QVBoxLayout()
+        vlayout.setContentsMargins(0, 0, 0, 0)
+        vlayout.setSpacing(1)
+
         self.values_edit = QListView()
         self.values_edit.setEditTriggers(QTreeView.CurrentChanged)
         self.values_model = itemmodels.PyListModel(flags=Qt.ItemIsSelectable | \
                                         Qt.ItemIsEnabled | Qt.ItemIsEditable)
         self.values_edit.setModel(self.values_model)
 
+        self.values_edit.selectionModel().selectionChanged.connect(
+            self.on_value_selection_changed)
+
         self.values_model.dataChanged.connect(self.on_values_changed)
-        self.main_form.addRow("Values:", self.values_edit)
+
+        vlayout.addWidget(self.values_edit)
+        hlayout = QHBoxLayout()
+        hlayout.setContentsMargins(0, 0, 0, 0)
+        hlayout.setSpacing(1)
+        self.move_value_up = QAction(
+            unicodedata.lookup("UPWARDS ARROW"), self,
+            toolTip="Move up.",
+            triggered=self.move_up,
+            enabled=False,
+            shortcut=QKeySequence(QKeySequence.New))
+
+        self.move_value_down = QAction(
+            unicodedata.lookup("DOWNWARDS ARROW"), self,
+            toolTip="Move down.",
+            triggered=self.move_down,
+            enabled=False,
+            shortcut=QKeySequence(QKeySequence.Delete))
+
+        button_size = gui.toolButtonSizeHint()
+        button_size = QSize(button_size, button_size)
+
+        button = QToolButton(self)
+        button.setFixedSize(button_size)
+        button.setDefaultAction(self.move_value_up)
+        hlayout.addWidget(button)
+
+        button = QToolButton(self)
+        button.setFixedSize(button_size)
+        button.setDefaultAction(self.move_value_down)
+        hlayout.addWidget(button)
+        hlayout.addStretch(10)
+        vlayout.addLayout(hlayout)
+
+        self.main_form.addRow("Values:", vlayout)
 
     def set_data(self, var):
         """Set the variable to edit
@@ -361,10 +402,29 @@ def clear(self):
         VariableEditor.clear(self)
         self.values_model.clear()
 
+    def move_rows(self, rows, offset):
+        i = rows[0].row()
+        self.values_model[i], self.values_model[i+offset] = \
+            self.values_model[i+offset], self.values_model[i]
+        self.maybe_commit()
+
+    def move_up(self):
+        rows = self.values_edit.selectionModel().selectedRows()
+        self.move_rows(rows, -1)
+
+    def move_down(self):
+        rows = self.values_edit.selectionModel().selectedRows()
+        self.move_rows(rows, 1)
+
     @Slot()
     def on_values_changed(self):
         self.maybe_commit()
 
+    @Slot()
+    def on_value_selection_changed(self):
+        i = self.values_edit.selectionModel().selectedRows()[0].row()
+        self.move_value_up.setEnabled(i)
+        self.move_value_down.setEnabled(i != len(self.var.values)-1)
 
 class ContinuousVariableEditor(VariableEditor):
     # TODO: enable editing of number_of_decimals, scientific format ...


Test patch: