From 06dab197548e28facf2114cd82ba589c51fe3399 Mon Sep 17 00:00:00 2001 From: Ales Erjavec Date: Mon, 27 Nov 2017 11:27:24 +0100 Subject: [PATCH 1/4] owhierarchicalclustering: Fix size constraints --- .../unsupervised/owhierarchicalclustering.py | 37 ++++++++++--------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/Orange/widgets/unsupervised/owhierarchicalclustering.py b/Orange/widgets/unsupervised/owhierarchicalclustering.py index c071a0c0bfc..3bc904cb18c 100644 --- a/Orange/widgets/unsupervised/owhierarchicalclustering.py +++ b/Orange/widgets/unsupervised/owhierarchicalclustering.py @@ -674,11 +674,11 @@ def sizeHint(self, which, constraint=QSizeF()): if self._root and which == Qt.PreferredSize: nleaves = len([node for node in self._items.keys() if not node.branches]) - + base = max(10, min(spacing * 16, 250)) if self.orientation in [self.Left, self.Right]: - return QSizeF(250, spacing * nleaves + mleft + mright) + return QSizeF(base, spacing * nleaves + mleft + mright) else: - return QSizeF(spacing * nleaves + mtop + mbottom, 250) + return QSizeF(spacing * nleaves + mtop + mbottom, base) elif which == Qt.MinimumSize: return QSizeF(mleft + mright + 10, mtop + mbottom + 10) @@ -976,7 +976,7 @@ def axis_view(orientation): self.dendrogram.selectionEdited.connect(self._selection_edited) self.labels = GraphicsSimpleTextList() - self.labels.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) + self.labels.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Preferred) self.labels.setAlignment(Qt.AlignLeft) self.labels.setMaximumWidth(200) self.labels.layout().setSpacing(0) @@ -1255,9 +1255,12 @@ def sizeHint(self): def eventFilter(self, obj, event): if obj is self.view.viewport() and event.type() == QEvent.Resize: width = self.view.viewport().width() - 2 - self._main_graphics.setMaximumWidth(width) - self._main_graphics.setMinimumWidth(width) - self._main_graphics.layout().activate() + # layout with new width constraint + self.__layout_main_graphics(width=width) + elif obj is self._main_graphics and \ + event.type() == QEvent.LayoutRequest: + # layout preserving the width (vertical re layout) + self.__layout_main_graphics() elif event.type() == QEvent.MouseButtonPress and \ (obj is self.top_axis_view.viewport() or obj is self.bottom_axis_view.viewport()): @@ -1268,10 +1271,6 @@ def eventFilter(self, obj, event): self.top_axis.line.setValue(cut.x()) # update the line visibility, output, ... self._selection_method_changed() - elif obj is self._main_graphics and \ - event.type() == QEvent.LayoutRequest: - self.__update_size_constraints() - return super().eventFilter(obj, event) def onDeleteWidget(self): @@ -1399,12 +1398,15 @@ def __zoom_reset(self): self.zoom_factor = 0 self.__zoom_factor_changed() - def __update_size_constraints(self): - size = self._main_graphics.size() - preferred = self._main_graphics.sizeHint( - Qt.PreferredSize, constraint=QSizeF(size.width(), -1)) - self._main_graphics.resize(QSizeF(size.width(), preferred.height())) - self._main_graphics.layout().activate() + def __layout_main_graphics(self, width=-1): + if width < 0: + # Preserve current width. + width = self._main_graphics.size().width() + preferred = self._main_graphics.effectiveSizeHint( + Qt.PreferredSize, constraint=QSizeF(width, -1)) + self._main_graphics.resize(QSizeF(width, preferred.height())) + mw = self._main_graphics.minimumWidth() + 4 + self.view.setMinimumWidth(mw + self.view.verticalScrollBar().width()) def __zoom_factor_changed(self): font = self.scene.font() @@ -1412,7 +1414,6 @@ def __zoom_factor_changed(self): font = qfont_scaled(font, factor) self.labels.setFont(font) self.dendrogram.setFont(font) - self.__update_size_constraints() def send_report(self): annot = self.label_cb.currentText() From 6dcae323a63b6cf36c4da8537b7c93be7c49cd8c Mon Sep 17 00:00:00 2001 From: Ales Erjavec Date: Mon, 27 Nov 2017 11:51:35 +0100 Subject: [PATCH 2/4] owhierarchicalclustering: Fix font scale (zoom) initialization --- .../unsupervised/owhierarchicalclustering.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Orange/widgets/unsupervised/owhierarchicalclustering.py b/Orange/widgets/unsupervised/owhierarchicalclustering.py index 3bc904cb18c..fd4a5605aa8 100644 --- a/Orange/widgets/unsupervised/owhierarchicalclustering.py +++ b/Orange/widgets/unsupervised/owhierarchicalclustering.py @@ -885,7 +885,7 @@ def __init__(self): self.zoom_slider = gui.hSlider( self.controlArea, self, "zoom_factor", box="Zoom", minValue=-6, maxValue=3, step=1, ticks=True, createLabel=False, - callback=self.__zoom_factor_changed) + callback=self.__update_font_scale) zoom_in = QAction( "Zoom in", self, shortcut=QKeySequence.ZoomIn, @@ -1003,6 +1003,7 @@ def axis_view(orientation): self.top_axis.line.valueChanged.connect(self._axis_slider_changed) self.dendrogram.geometryChanged.connect(self._dendrogram_geom_changed) self._set_cut_line_visible(self.selection_method == 1) + self.__update_font_scale() @Inputs.distances def set_distances(self, matrix): @@ -1384,7 +1385,7 @@ def clip(minval, maxval, val): self.zoom_factor = clip(self.zoom_slider.minimum(), self.zoom_slider.maximum(), self.zoom_factor + 1) - self.__zoom_factor_changed() + self.__update_font_scale() def __zoom_out(self): def clip(minval, maxval, val): @@ -1392,11 +1393,11 @@ def clip(minval, maxval, val): self.zoom_factor = clip(self.zoom_slider.minimum(), self.zoom_slider.maximum(), self.zoom_factor - 1) - self.__zoom_factor_changed() + self.__update_font_scale() def __zoom_reset(self): self.zoom_factor = 0 - self.__zoom_factor_changed() + self.__update_font_scale() def __layout_main_graphics(self, width=-1): if width < 0: @@ -1408,12 +1409,11 @@ def __layout_main_graphics(self, width=-1): mw = self._main_graphics.minimumWidth() + 4 self.view.setMinimumWidth(mw + self.view.verticalScrollBar().width()) - def __zoom_factor_changed(self): + def __update_font_scale(self): font = self.scene.font() factor = (1.25 ** self.zoom_factor) font = qfont_scaled(font, factor) - self.labels.setFont(font) - self.dendrogram.setFont(font) + self._main_graphics.setFont(font) def send_report(self): annot = self.label_cb.currentText() From fc47ddf37527070b67723e8ff35f22cbee4825fe Mon Sep 17 00:00:00 2001 From: Ales Erjavec Date: Mon, 27 Nov 2017 12:41:31 +0100 Subject: [PATCH 3/4] owhierarchicalclustering: Fix slider updates Set range before the value so the old range does not clip the new value --- Orange/widgets/unsupervised/owhierarchicalclustering.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Orange/widgets/unsupervised/owhierarchicalclustering.py b/Orange/widgets/unsupervised/owhierarchicalclustering.py index fd4a5605aa8..9a8b405dd07 100644 --- a/Orange/widgets/unsupervised/owhierarchicalclustering.py +++ b/Orange/widgets/unsupervised/owhierarchicalclustering.py @@ -1319,16 +1319,16 @@ def _dendrogram_slider_changed(self, value): def _set_slider_value(self, value, span): with blocked(self.cut_line): - self.cut_line.setValue(value) self.cut_line.setRange(0, span) + self.cut_line.setValue(value) with blocked(self.top_axis.line): - self.top_axis.line.setValue(value) self.top_axis.line.setRange(0, span) + self.top_axis.line.setValue(value) with blocked(self.bottom_axis.line): - self.bottom_axis.line.setValue(value) self.bottom_axis.line.setRange(0, span) + self.bottom_axis.line.setValue(value) def set_cutoff_height(self, height): self.cutoff_height = height From 8946e9afbe9a556ac874937ab5f75cd718b76bc3 Mon Sep 17 00:00:00 2001 From: Ales Erjavec Date: Fri, 8 Dec 2017 17:22:15 +0100 Subject: [PATCH 4/4] owhierarchicalclustering: Account for transient scroll bars et --- .../widgets/unsupervised/owhierarchicalclustering.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Orange/widgets/unsupervised/owhierarchicalclustering.py b/Orange/widgets/unsupervised/owhierarchicalclustering.py index 9a8b405dd07..3024a070212 100644 --- a/Orange/widgets/unsupervised/owhierarchicalclustering.py +++ b/Orange/widgets/unsupervised/owhierarchicalclustering.py @@ -1255,7 +1255,15 @@ def sizeHint(self): def eventFilter(self, obj, event): if obj is self.view.viewport() and event.type() == QEvent.Resize: - width = self.view.viewport().width() - 2 + # NOTE: not using viewport.width(), due to 'transient' scroll bars + # (macOS). Viewport covers the whole view, but QGraphicsView still + # scrolls left, right with scroll bar extent (other + # QAbstractScrollArea widgets behave as expected). + w_frame = self.view.frameWidth() + margin = self.view.viewportMargins() + w_scroll = self.view.verticalScrollBar().width() + width = (self.view.width() - w_frame * 2 - + margin.left() - margin.right() - w_scroll) # layout with new width constraint self.__layout_main_graphics(width=width) elif obj is self._main_graphics and \