99from AnyQt .QtWidgets import (
1010 QWidget , QDialog , QVBoxLayout , QSizePolicy , QApplication , QStyle ,
1111 QShortcut , QSplitter , QSplitterHandle , QPushButton , QStatusBar ,
12- QProgressBar , QAction
12+ QProgressBar , QAction , QWIDGETSIZE_MAX
1313)
1414from AnyQt .QtCore import (
15- Qt , QByteArray , QDataStream , QBuffer , QSettings , QUrl , pyqtSignal as Signal
15+ Qt , QRect , QMargins , QByteArray , QDataStream , QBuffer , QSettings ,
16+ QUrl , pyqtSignal as Signal
1617)
1718from AnyQt .QtGui import QIcon , QKeySequence , QDesktopServices
1819
@@ -235,12 +236,13 @@ def __new__(cls, *args, captionTitle=None, **kwargs):
235236 self .controlArea .setFocus (Qt .ActiveWindowFocusReason )
236237
237238 if self .__splitter is not None :
238- self .__splitter .controlAreaVisibilityChanged .connect (
239- self .storeControlAreaVisibility )
239+ self .__splitter .handleClicked .connect (
240+ self .__toggleControlArea
241+ )
240242 sc = QShortcut (
241243 QKeySequence (Qt .ControlModifier | Qt .ShiftModifier | Qt .Key_D ),
242- self )
243- sc .activated .connect (self .__splitter . flip )
244+ self , autoRepeat = False )
245+ sc .activated .connect (self .__toggleControlArea )
244246 return self
245247
246248 # pylint: disable=super-init-not-called
@@ -268,8 +270,7 @@ def get_flags(cls):
268270 else Qt .Dialog | Qt .MSWindowsFixedSizeDialogHint )
269271
270272 class _Splitter (QSplitter ):
271- controlAreaVisibilityChanged = Signal (int )
272-
273+ handleClicked = Signal ()
273274 def _adjusted_size (self , size_method ):
274275 size = size_method (super ())()
275276 height = max ((size_method (self .widget (i ))().height ()
@@ -289,26 +290,11 @@ def createHandle(self):
289290 return self ._Handle (
290291 self .orientation (), self , cursor = Qt .PointingHandCursor )
291292
292- def flip (self ):
293- if self .count () == 1 : # Prevent hiding control area by shortcut
294- return
295- self .setControlAreaVisible (not self .controlAreaVisible ())
296-
297- def setControlAreaVisible (self , visible ):
298- if self .controlAreaVisible () == visible :
299- return
300- self .setSizes ([int (visible ), 100000 ])
301- self .controlAreaVisibilityChanged .emit (visible )
302- self .updateGeometry ()
303-
304- def controlAreaVisible (self ):
305- return bool (self .sizes ()[0 ])
306-
307293 class _Handle (QSplitterHandle ):
308294 def mouseReleaseEvent (self , event ):
309295 """Resize on left button"""
310296 if event .button () == Qt .LeftButton :
311- self .splitter ().flip ()
297+ self .splitter ().handleClicked . emit ()
312298 super ().mouseReleaseEvent (event )
313299
314300 def mouseMoveEvent (self , event ):
@@ -458,6 +444,71 @@ def _(val):
458444 margins .setBottom (sb .sizeHint ().height ())
459445 self .setContentsMargins (margins )
460446
447+ def __toggleControlArea (self ):
448+ if self .__splitter is None or self .__splitter .count () < 2 :
449+ return
450+ self .__setControlAreaVisible (not self .__splitter .sizes ()[0 ])
451+
452+ def __setControlAreaVisible (self , visible ):
453+ # type: (bool) -> None
454+ if self .__splitter is None or self .__splitter .count () < 2 :
455+ return
456+ self .controlAreaVisible = visible
457+ splitter = self .__splitter # type: QSplitter
458+ w = splitter .widget (0 )
459+ # Set minimum width to 1 (overrides minimumSizeHint) when control area
460+ # is not visible to allow the main area to shrink further. Reset the
461+ # minimum width with a 0 if control area is visible.
462+ w .setMinimumWidth (int (not visible ))
463+
464+ sizes = splitter .sizes ()
465+ current_size = sizes [0 ]
466+ if bool (current_size ) == visible :
467+ return
468+
469+ current_width = w .width ()
470+ geom = self .geometry ()
471+ frame = self .frameGeometry ()
472+ framemargins = QMargins (
473+ frame .left () - geom .left (),
474+ frame .top () - geom .top (),
475+ frame .right () - geom .right (),
476+ frame .bottom () - geom .bottom ()
477+ )
478+ splitter .setSizes ([int (visible ), QWIDGETSIZE_MAX ])
479+ if not self .isWindow () or \
480+ self .windowState () not in [Qt .WindowNoState , Qt .WindowActive ]:
481+ # not a window or not in state where we can move move/resize
482+ return
483+
484+ # force immediate resize recalculation
485+ splitter .refresh ()
486+ self .layout ().invalidate ()
487+ self .layout ().activate ()
488+
489+ if visible :
490+ # move left and expand by the exposing widget's width
491+ diffx = - w .width ()
492+ diffw = w .width ()
493+ else :
494+ # move right and shrink by the collapsing width
495+ diffx = current_width
496+ diffw = - current_width
497+ newgeom = QRect (
498+ geom .x () + diffx , geom .y (), geom .width () + diffw , geom .height ()
499+ )
500+ # bound/move by available geometry
501+ bounds = QApplication .desktop ().availableGeometry (self )
502+ bounds = bounds .adjusted (
503+ framemargins .left (), framemargins .top (),
504+ - framemargins .right (), - framemargins .bottom ()
505+ )
506+ newsize = newgeom .size ().boundedTo (bounds .size ())
507+ newgeom = QRect (newgeom .topLeft (), newsize )
508+ newgeom .moveLeft (max (newgeom .left (), bounds .left ()))
509+ newgeom .moveRight (min (newgeom .right (), bounds .right ()))
510+ self .setGeometry (newgeom )
511+
461512 def save_graph (self ):
462513 """Save the graph with the name given in class attribute `graph_name`.
463514
@@ -476,15 +527,6 @@ def copy_to_clipboard(self):
476527 return
477528 ClipboardFormat .write_image (None , graph_obj )
478529
479- def storeControlAreaVisibility (self , visible ):
480- self .controlAreaVisible = visible
481-
482- # Set minimum width to 1 (overrides minimumSizeHint) when control area
483- # is not visible to allow the main area to shrink further. Reset the minimum
484- # width with a 0 if control area is visible.
485- self .__splitter .widget (0 ).setMinimumWidth (int (not visible ))
486- self .updateGeometry ()
487-
488530 def __restoreWidgetGeometry (self , geometry ):
489531 # type: (bytes) -> bool
490532 def _fullscreen_to_maximized (geometry ):
@@ -583,7 +625,7 @@ def showEvent(self, event):
583625 if self .save_position and not self .__was_restored :
584626 # Restore saved geometry on (first) show
585627 if self .__splitter is not None :
586- self .__splitter . setControlAreaVisible (self .controlAreaVisible )
628+ self .__setControlAreaVisible (self .controlAreaVisible )
587629 if self .savedWidgetGeometry is not None :
588630 self .__restoreWidgetGeometry (bytes (self .savedWidgetGeometry ))
589631 self .__was_restored = True
@@ -830,7 +872,7 @@ def restoreGeometryAndLayoutState(self, state):
830872 has_spliter = splitter_state & 0x2
831873 splitter_state = splitter_state & 0x1
832874 if has_spliter and self .__splitter is not None :
833- self .__splitter . setControlAreaVisible (bool (splitter_state ))
875+ self .__setControlAreaVisible (bool (splitter_state ))
834876 geometry = QByteArray ()
835877 stream >> geometry
836878 if stream .status () == QDataStream .Ok :
0 commit comments