Skip to content

Commit

Permalink
Merge pull request #2994 from ales-erjavec/model-views-optimizations
Browse files Browse the repository at this point in the history
[ENH] Variable lists (with QListView) optimizations
  • Loading branch information
markotoplak authored Apr 13, 2018
2 parents f1d3c25 + 24e6ce0 commit 1f55179
Show file tree
Hide file tree
Showing 16 changed files with 55 additions and 34 deletions.
5 changes: 4 additions & 1 deletion Orange/widgets/data/owdiscretize.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,10 @@ def _intbox(widget, attr, callback):
)

# List view with all attributes
self.varview = QListView(selectionMode=QListView.ExtendedSelection)
self.varview = QListView(
selectionMode=QListView.ExtendedSelection,
uniformItemSizes=True,
)
self.varview.setItemDelegate(DiscDelegate())
self.varmodel = itemmodels.VariableListModel()
self.varview.setModel(self.varmodel)
Expand Down
3 changes: 2 additions & 1 deletion Orange/widgets/data/oweditdomain.py
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,8 @@ def __init__(self):

self.domain_model = itemmodels.VariableListModel()
self.domain_view = QListView(
selectionMode=QListView.SingleSelection
selectionMode=QListView.SingleSelection,
uniformItemSizes=True
)
self.domain_view.setModel(self.domain_model)
self.domain_view.selectionModel().selectionChanged.connect(
Expand Down
4 changes: 2 additions & 2 deletions Orange/widgets/data/owfeatureconstructor.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ def __init__(self, *args, **kwargs):

self.attrs_model = itemmodels.VariableListModel(
["Select Feature"], parent=self)
self.attributescb = QComboBox(
self.attributescb = gui.OrangeComboBox(
minimumContentsLength=16,
sizeAdjustPolicy=QComboBox.AdjustToMinimumContentsLengthWithIcon,
sizePolicy=QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
Expand All @@ -137,7 +137,7 @@ def __init__(self, *args, **kwargs):
[''],
[self.FUNCTIONS[func].__doc__ for func in sorted_funcs])

self.functionscb = QComboBox(
self.functionscb = gui.OrangeComboBox(
minimumContentsLength=16,
sizeAdjustPolicy=QComboBox.AdjustToMinimumContentsLengthWithIcon,
sizePolicy=QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum))
Expand Down
3 changes: 2 additions & 1 deletion Orange/widgets/data/owimpute.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,8 @@ def __init__(self):
main_layout.addWidget(box)

self.varview = QListView(
selectionMode=QListView.ExtendedSelection
selectionMode=QListView.ExtendedSelection,
uniformItemSizes=True
)
self.varview.setItemDelegate(DisplayFormatDelegate())
self.varmodel = itemmodels.VariableListModel()
Expand Down
6 changes: 4 additions & 2 deletions Orange/widgets/data/owmergedata.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,14 @@ def add_option(label, pre_label, between_label,
model[:] = [getattr(self, 'attr_{}_data'.format(merge_type))]
extra_model[:] = [getattr(self, 'attr_{}_extra'.format(merge_type))]
cb = gui.comboBox(box, self, 'attr_{}_data'.format(merge_type),
callback=self._invalidate, model=model)
contentsLength=12, callback=self._invalidate,
model=model)
cb.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed)
cb.setFixedWidth(190)
gui.widgetLabel(box, between_label)
cb = gui.comboBox(box, self, 'attr_{}_extra'.format(merge_type),
callback=self._invalidate, model=extra_model)
contentsLength=12, callback=self._invalidate,
model=extra_model)
cb.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed)
cb.setFixedWidth(190)
vbox.layout().addSpacing(6)
Expand Down
2 changes: 1 addition & 1 deletion Orange/widgets/data/owselectrows.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ def add_row(self, attr=None, condition_type=None, condition_value=None):
row = model.rowCount()
model.insertRow(row)

attr_combo = QComboBox(
attr_combo = gui.OrangeComboBox(
minimumContentsLength=12,
sizeAdjustPolicy=QComboBox.AdjustToMinimumContentsLengthWithIcon)
attr_combo.row = row
Expand Down
4 changes: 2 additions & 2 deletions Orange/widgets/data/owtranspose.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ def __init__(self):
alphabetical=True)
self.feature_combo = gui.comboBox(
gui.indentedBox(box, gui.checkButtonOffsetHint(button)), self,
"feature_names_column", callback=self._feature_combo_changed,
model=self.feature_model)
"feature_names_column", contentsLength=12,
callback=self._feature_combo_changed, model=self.feature_model)

self.apply_button = gui.auto_commit(
self.controlArea, self, "auto_apply", "&Apply",
Expand Down
20 changes: 16 additions & 4 deletions Orange/widgets/gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -1090,6 +1090,7 @@ def listView(widget, master, value=None, model=None, box=None, callback=None,
CallFrontListView(view),
CallBackListView(model, view, master, value))
misc.setdefault('addSpace', True)
misc.setdefault('uniformItemSizes', True)
miscellanea(view, bg, widget, **misc)
return view

Expand Down Expand Up @@ -1497,11 +1498,18 @@ def valueSlider(widget, master, value, box=None, label=None,
class OrangeComboBox(QtWidgets.QComboBox):
"""
A QComboBox subclass extended to support bounded contents width hint.
Prefer to use this class in place of plain QComboBox when the used
model will possibly contain many items.
"""
def __init__(self, parent=None, maximumContentsLength=-1, **kwargs):
# Forward-declared for sizeHint()
self.__maximumContentsLength = maximumContentsLength
super().__init__(parent, **kwargs)
view = self.view()
# optimization for displaying large models
if isinstance(view, QListView):
view.setUniformItemSizes(True)

def setMaximumContentsLength(self, length):
"""
Expand All @@ -1513,11 +1521,11 @@ def setMaximumContentsLength(self, length):
.. note::
This property does not affect the widget's `maximumSize`.
The widget can still grow depending in it's sizePolicy.
The widget can still grow depending on its `sizePolicy`.
Parameters
----------
lenght : int
length : int
Maximum contents length hint.
"""
if self.__maximumContentsLength != length:
Expand Down Expand Up @@ -2493,6 +2501,7 @@ def action(self, values):

selection = QItemSelection()
for value in values:
index = None
if not isinstance(value, int):
if isinstance(value, Variable):
search_role = TableVariable
Expand All @@ -2501,9 +2510,12 @@ def action(self, values):
value = str(value)
for i in range(model.rowCount()):
if model.data(model.index(i), search_role) == value:
value = i
index = i
break
selection.select(model.index(value), model.index(value))
else:
index = value
if index is not None:
selection.select(model.index(index), model.index(index))
sel_model.select(selection, sel_model.ClearAndSelect)


Expand Down
5 changes: 4 additions & 1 deletion Orange/widgets/unsupervised/owcorrespondence.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,10 @@ def __init__(self):

box = gui.vBox(self.controlArea, "Variables")
self.varlist = itemmodels.VariableListModel()
self.varview = view = QListView(selectionMode=QListView.MultiSelection)
self.varview = view = QListView(
selectionMode=QListView.MultiSelection,
uniformItemSizes=True
)
view.setModel(self.varlist)
view.selectionModel().selectionChanged.connect(self._var_changed)

Expand Down
10 changes: 1 addition & 9 deletions Orange/widgets/utils/itemmodels.py
Original file line number Diff line number Diff line change
Expand Up @@ -536,22 +536,14 @@ def wrap(self, lst):
self._other_data = [_store() for _ in lst]
self.endResetModel()


# noinspection PyMethodOverriding
def index(self, row, column=0, parent=QModelIndex()):
if self._is_index_valid(row) and column == 0:
return QAbstractListModel.createIndex(self, row, column, parent)
else:
return QModelIndex()

def headerData(self, section, orientation, role=Qt.DisplayRole):
if role == Qt.DisplayRole:
return str(section)


# noinspection PyMethodOverriding
def rowCount(self, parent=QModelIndex()):
return 0 if parent.isValid() else len(self)
return 0 if parent.isValid() else len(self._list)

def columnCount(self, parent=QModelIndex()):
return 0 if parent.isValid() else 1
Expand Down
1 change: 1 addition & 0 deletions Orange/widgets/utils/listfilter.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ def __init__(self, parent=None, acceptedType=Orange.data.Variable):
self.setDragDropMode(self.DragDrop)
self.setDefaultDropAction(Qt.MoveAction)
self.setDragDropOverwriteMode(False)
self.setUniformItemSizes(True)
self.viewport().setAcceptDrops(True)

#: type | Tuple[type]
Expand Down
4 changes: 3 additions & 1 deletion Orange/widgets/visualize/owdistributions.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,9 @@ def __init__(self):
self.groupvarmodel = []

self.varview = QListView(
selectionMode=QListView.SingleSelection)
selectionMode=QListView.SingleSelection,
uniformItemSizes=True,
)
self.varview.setSizePolicy(
QSizePolicy.Minimum, QSizePolicy.Expanding)
self.varview.setModel(self.varmodel)
Expand Down
6 changes: 3 additions & 3 deletions Orange/widgets/visualize/owheatmap.py
Original file line number Diff line number Diff line change
Expand Up @@ -541,9 +541,9 @@ def __init__(self):

annotbox = gui.vBox(box, "Row Annotations", addSpace=False)
annotbox.setFlat(True)
self.annotations_cb = gui.comboBox(annotbox, self, "annotation_index",
items=self.annotation_vars,
callback=self.update_annotations)
self.annotations_cb = gui.comboBox(
annotbox, self, "annotation_index", contentsLength=12,
items=self.annotation_vars, callback=self.update_annotations)

posbox = gui.vBox(box, "Column Labels Position", addSpace=False)
posbox.setFlat(True)
Expand Down
3 changes: 2 additions & 1 deletion Orange/widgets/visualize/owscatterplot.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@ def __init__(self):

common_options = dict(
labelWidth=50, orientation=Qt.Horizontal, sendSelectedValue=True,
valueType=str)
valueType=str, contentsLength=14
)
box = gui.vBox(self.controlArea, "Axis Data")
dmod = DomainModel
self.xy_model = DomainModel(dmod.MIXED, valid_types=dmod.PRIMITIVE)
Expand Down
8 changes: 5 additions & 3 deletions Orange/widgets/visualize/owsilhouetteplot.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,9 @@ def __init__(self):

box = gui.vBox(self.controlArea, "Cluster Label")
self.cluster_var_cb = gui.comboBox(
box, self, "cluster_var_idx", addSpace=4,
callback=self._invalidate_scores)
box, self, "cluster_var_idx", contentsLength=14, addSpace=4,
callback=self._invalidate_scores
)
gui.checkBox(
box, self, "group_by_cluster", "Group by cluster",
callback=self._replot)
Expand All @@ -128,7 +129,8 @@ def __init__(self):
callback=self._update_bar_size, addSpace=6)
gui.widgetLabel(box, "Annotations:")
self.annotation_cb = gui.comboBox(
box, self, "annotation_var_idx", callback=self._update_annotations)
box, self, "annotation_var_idx", contentsLength=14,
callback=self._update_annotations)
self.annotation_var_model = itemmodels.VariableListModel(parent=self)
self.annotation_var_model[:] = ["None"]
self.annotation_cb.setModel(self.annotation_var_model)
Expand Down
5 changes: 3 additions & 2 deletions Orange/widgets/visualize/owvenndiagram.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,10 @@ def __init__(self):
addSpace=False)
box.setFlat(True)
model = itemmodels.VariableListModel(parent=self)
cb = QComboBox(
cb = gui.OrangeComboBox(
minimumContentsLength=12,
sizeAdjustPolicy=QComboBox.AdjustToMinimumContentsLengthWithIcon)
sizeAdjustPolicy=QComboBox.AdjustToMinimumContentsLengthWithIcon
)
cb.setModel(model)
cb.activated[int].connect(self._on_inputAttrActivated)
box.setEnabled(False)
Expand Down

0 comments on commit 1f55179

Please sign in to comment.