Skip to content

Commit d1c5962

Browse files
committed
dendrogram: Fix public method naming
1 parent c843561 commit d1c5962

File tree

1 file changed

+112
-50
lines changed

1 file changed

+112
-50
lines changed

Orange/widgets/utils/dendrogram.py

Lines changed: 112 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ def boundingRect(self):
199199
self.__boundingRect = sh.boundingRect().adjusted(-pw, -pw, pw, pw)
200200
return self.__boundingRect
201201

202-
class SelectionItem(QGraphicsItemGroup):
202+
class _SelectionItem(QGraphicsItemGroup):
203203
def __init__(self, parent, path, unscaled_path, label=""):
204204
super().__init__(parent)
205205
self.path = QGraphicsPathItem(path, self)
@@ -243,13 +243,14 @@ def _update_label_pos(self):
243243

244244
#: Emitted when a user clicks on the cluster item.
245245
itemClicked = Signal(ClusterGraphicsItem)
246+
#: Signal emitted when the selection changes.
246247
selectionChanged = Signal()
248+
#: Signal emitted when the selection was changed by the user.
247249
selectionEdited = Signal()
248250

249251
def __init__(self, parent=None, root=None, orientation=Left,
250252
hoverHighlightEnabled=True, selectionMode=ExtendedSelection,
251253
**kwargs):
252-
253254
super().__init__(None, **kwargs)
254255
# Filter all events from children (`ClusterGraphicsItem`s)
255256
self.setFiltersChildEvents(True)
@@ -272,11 +273,46 @@ def __init__(self, parent=None, root=None, orientation=Left,
272273
self.__hoverHighlightEnabled = hoverHighlightEnabled
273274
self.__selectionMode = selectionMode
274275
self.setContentsMargins(0, 0, 0, 0)
275-
self.set_root(root)
276+
self.setRoot(root)
276277
if parent is not None:
277278
self.setParentItem(parent)
278279

280+
def setSelectionMode(self, mode):
281+
"""
282+
Set the selection mode.
283+
"""
284+
assert mode in [DendrogramWidget.NoSelection,
285+
DendrogramWidget.SingleSelection,
286+
DendrogramWidget.ExtendedSelection]
287+
288+
if self.__selectionMode != mode:
289+
self.__selectionMode = mode
290+
if self.__selectionMode == DendrogramWidget.NoSelection and \
291+
self._selection:
292+
self.setSelectedClusters([])
293+
elif self.__selectionMode == DendrogramWidget.SingleSelection and \
294+
len(self._selection) > 1:
295+
self.setSelectedClusters([self.selected_nodes()[-1]])
296+
297+
def selectionMode(self):
298+
"""
299+
Return the current selection mode.
300+
"""
301+
return self.__selectionMode
302+
303+
def setHoverHighlightEnabled(self, enabled):
304+
if self.__hoverHighlightEnabled != bool(enabled):
305+
self.__hoverHighlightEnabled = bool(enabled)
306+
if self._highlighted_item is not None:
307+
self._set_hover_item(None)
308+
309+
def isHoverHighlightEnabled(self):
310+
return self.__hoverHighlightEnabled
311+
279312
def clear(self):
313+
"""
314+
Clear the widget.
315+
"""
280316
scene = self.scene()
281317
if scene is not None:
282318
scene.removeItem(self._itemgroup)
@@ -299,10 +335,15 @@ def clear(self):
299335
self._cluster_parent = {}
300336
self.updateGeometry()
301337

302-
def set_root(self, root):
303-
"""Set the root cluster.
338+
def setRoot(self, root):
339+
# type: (Tree) -> None
340+
"""
341+
Set the root cluster tree node for display.
304342
305-
:param Tree root: Root tree.
343+
Parameters
344+
----------
345+
root : Tree
346+
The tree root node.
306347
"""
307348
self.clear()
308349
self._root = root
@@ -322,17 +363,30 @@ def set_root(self, root):
322363
self._relayout()
323364
self._rescale()
324365
self.updateGeometry()
366+
set_root = setRoot
325367

326-
def item(self, node):
327-
"""Return the DendrogramNode instance representing the cluster.
368+
def root(self):
369+
# type: () -> Tree
370+
"""
371+
Return the cluster tree root node.
328372
329-
:type cluster: :class:`Tree`
373+
Returns
374+
-------
375+
root : Tree
376+
"""
377+
return self._root
330378

379+
def item(self, node):
380+
# type: (Tree) -> DendrogramWidget.ClusterGraphicsItem
381+
"""
382+
Return the ClusterGraphicsItem instance representing the cluster `node`.
331383
"""
332384
return self._items.get(node)
333385

334-
def height_at(self, point):
335-
"""Return the cluster height at the point in widget local coordinates.
386+
def heightAt(self, point):
387+
# type: (QPointF) -> float
388+
"""
389+
Return the cluster height at the point in widget local coordinates.
336390
"""
337391
if not self._root:
338392
return 0
@@ -356,10 +410,12 @@ def height_at(self, point):
356410
if self.orientation in [self.Left, self.Bottom]:
357411
height = Fr(base) - Fr(height)
358412
return float(height)
413+
height_at = heightAt
359414

360-
def pos_at_height(self, height):
361-
"""Return a point in local coordinates for `height` (in cluster
362-
height scale).
415+
def posAtHeight(self, height):
416+
# type: (float) -> float
417+
"""
418+
Return a point in local coordinates for `height` (in cluster
363419
"""
364420
if not self._root:
365421
return QPointF()
@@ -374,6 +430,7 @@ def pos_at_height(self, height):
374430
else:
375431
p = QPointF(0, height)
376432
return self._transform.map(p)
433+
pos_at_height = posAtHeight
377434

378435
def _set_hover_item(self, item):
379436
"""Set the currently highlighted item."""
@@ -394,32 +451,34 @@ def branches(item):
394451
for it in postorder(item, branches):
395452
it.setPen(hpen)
396453

397-
def leaf_items(self):
454+
def leafItems(self):
398455
"""Iterate over the dendrogram leaf items (:class:`QGraphicsItem`).
399456
"""
400457
if self._root:
401458
return (self._items[leaf] for leaf in leaves(self._root))
402459
else:
403460
return iter(())
461+
leaf_items = leafItems
404462

405-
def leaf_anchors(self):
463+
def leafAnchors(self):
406464
"""Iterate over the dendrogram leaf anchor points (:class:`QPointF`).
407465
408466
The points are in the widget local coordinates.
409467
"""
410-
for item in self.leaf_items():
468+
for item in self.leafItems():
411469
anchor = QPointF(item.element.anchor)
412470
yield self.mapFromItem(item, anchor)
471+
leaf_anchors = leafAnchors
413472

414-
def selected_nodes(self):
415-
"""Return the selected clusters."""
473+
def selectedNodes(self):
474+
"""
475+
Return the selected cluster nodes.
476+
"""
416477
return [item.node for item in self._selection]
478+
selected_nodes = selectedNodes
417479

418-
def set_selected_items(self, items):
419-
"""Set the item selection.
420-
421-
:param items: List of `GraphicsItems`s to select.
422-
"""
480+
def setSelectedItems(self, items: List[ClusterGraphicsItem]):
481+
"""Set the item selection."""
423482
to_remove = set(self._selection) - set(items)
424483
to_add = set(items) - set(self._selection)
425484

@@ -431,27 +490,26 @@ def set_selected_items(self, items):
431490
if to_add or to_remove:
432491
self._re_enumerate_selections()
433492
self.selectionChanged.emit()
493+
set_selected_items = setSelectedItems
434494

435-
def set_selected_clusters(self, clusters):
495+
def setSelectedClusters(self, clusters: List[Tree]) -> None:
436496
"""Set the selected clusters.
437-
438-
:param Tree items: List of cluster nodes to select .
439497
"""
440-
self.set_selected_items(list(map(self.item, clusters)))
498+
self.setSelectedItems(list(map(self.item, clusters)))
499+
set_selected_clusters = setSelectedClusters
441500

442-
def is_selected(self, item):
501+
def isItemSelected(self, item: ClusterGraphicsItem) -> bool:
502+
"""Is `item` selected (is a root of a selection)."""
443503
return item in self._selection
444504

445-
def is_included(self, item):
505+
def isItemIncludedInSelection(self, item: ClusterGraphicsItem) -> bool:
506+
"""Is item included in any selection."""
446507
return self._selected_super_item(item) is not None
508+
is_included = isItemIncludedInSelection
447509

448-
def select_item(self, item, state):
449-
"""Set the `item`s selection state to `select_state`
450-
451-
:param item: QGraphicsItem.
452-
:param bool state: New selection state for item.
453-
454-
"""
510+
def setItemSelected(self, item, state):
511+
# type: (ClusterGraphicsItem, bool) -> None
512+
"""Set the `item`s selection state to `state`."""
455513
if state is False and item not in self._selection or \
456514
state is True and item in self._selection:
457515
return # State unchanged
@@ -482,6 +540,7 @@ def select_item(self, item, state):
482540

483541
self._re_enumerate_selections()
484542
self.selectionChanged.emit()
543+
select_item = setItemSelected
485544

486545
@staticmethod
487546
def _create_path(item, path):
@@ -493,7 +552,6 @@ def _create_path(item, path):
493552
ppath = path_outline(ppath, width=-8)
494553
return ppath
495554

496-
497555
@staticmethod
498556
def _create_label(i):
499557
return f"C{i + 1}"
@@ -505,7 +563,7 @@ def _add_selection(self, item):
505563
path = self._transform.map(outline)
506564
ppath = self._create_path(item, path)
507565
label = self._create_label(len(self._selection))
508-
selection_item = self.SelectionItem(self, ppath, outline, label)
566+
selection_item = self._SelectionItem(self, ppath, outline, label)
509567
selection_item.setPos(self.contentsRect().topLeft())
510568
self._selection[item] = selection_item
511569

@@ -697,7 +755,8 @@ def _rescale(self):
697755
self._selection_items = None
698756
self._update_selection_items()
699757

700-
def sizeHint(self, which, constraint=QSizeF()):
758+
def sizeHint(self, which: Qt.SizeHint, constraint=QSizeF()) -> QRectF:
759+
# reimplemented
701760
fm = QFontMetrics(self.font())
702761
spacing = fm.lineSpacing()
703762
mleft, mtop, mright, mbottom = self.getContentsMargins()
@@ -726,31 +785,31 @@ def sceneEventFilter(self, obj, event):
726785
elif event.type() == QEvent.GraphicsSceneMousePress and \
727786
event.button() == Qt.LeftButton:
728787

729-
is_selected = self.is_selected(obj)
788+
is_selected = self.isItemSelected(obj)
730789
is_included = self.is_included(obj)
731790
current_selection = list(self._selection)
732791

733792
if self.__selectionMode == DendrogramWidget.SingleSelection:
734793
if event.modifiers() & Qt.ControlModifier:
735-
self.set_selected_items(
794+
self.setSelectedItems(
736795
[obj] if not is_selected else [])
737796
elif event.modifiers() & Qt.AltModifier:
738-
self.set_selected_items([])
797+
self.setSelectedItems([])
739798
elif event.modifiers() & Qt.ShiftModifier:
740799
if not is_included:
741-
self.set_selected_items([obj])
800+
self.setSelectedItems([obj])
742801
elif current_selection != [obj]:
743-
self.set_selected_items([obj])
802+
self.setSelectedItems([obj])
744803
elif self.__selectionMode == DendrogramWidget.ExtendedSelection:
745804
if event.modifiers() & Qt.ControlModifier:
746-
self.select_item(obj, not is_selected)
805+
self.setItemSelected(obj, not is_selected)
747806
elif event.modifiers() & Qt.AltModifier:
748-
self.select_item(self._selected_super_item(obj), False)
807+
self.setItemSelected(self._selected_super_item(obj), False)
749808
elif event.modifiers() & Qt.ShiftModifier:
750809
if not is_included:
751-
self.select_item(obj, True)
810+
self.setItemSelected(obj, True)
752811
elif current_selection != [obj]:
753-
self.set_selected_items([obj])
812+
self.setSelectedItems([obj])
754813

755814
if current_selection != self._selection:
756815
self.selectionEdited.emit()
@@ -764,6 +823,7 @@ def sceneEventFilter(self, obj, event):
764823
return super().sceneEventFilter(obj, event)
765824

766825
def changeEvent(self, event):
826+
# reimplemented
767827
super().changeEvent(event)
768828

769829
if event.type() == QEvent.FontChange:
@@ -774,11 +834,13 @@ def changeEvent(self, event):
774834
self._rescale()
775835

776836
def resizeEvent(self, event):
837+
# reimplemented
777838
super().resizeEvent(event)
778839
self._rescale()
779840

780841
def mousePressEvent(self, event):
781-
QGraphicsWidget.mousePressEvent(self, event)
842+
# reimplemented
843+
super().mousePressEvent(event)
782844
# A mouse press on an empty widget part
783845
if event.modifiers() == Qt.NoModifier and self._selection:
784846
self.set_selected_clusters([])

0 commit comments

Comments
 (0)