@@ -354,11 +354,11 @@ def _setup(self):
354
354
text = _ ("Dock" ),
355
355
tip = _ ("Dock the pane" ),
356
356
icon = self .create_icon ('dock' ),
357
- triggered = self .close_window ,
357
+ triggered = self .dock_window ,
358
358
)
359
359
self .lock_unlock_action = self .create_action (
360
360
name = PluginMainWidgetActions .LockUnlockPosition ,
361
- text = _ ("Unlock position " ),
361
+ text = _ ("Move " ),
362
362
tip = _ ("Unlock to move pane to another position" ),
363
363
icon = self .create_icon ('drag_dock_widget' ),
364
364
triggered = self .lock_unlock_position ,
@@ -387,7 +387,7 @@ def _setup(self):
387
387
)
388
388
389
389
for item in [self .lock_unlock_action , self .undock_action ,
390
- self .close_action , self .dock_action ]:
390
+ self .dock_action , self .close_action ]:
391
391
self .add_item_to_menu (
392
392
item ,
393
393
self ._options_menu ,
@@ -416,7 +416,6 @@ def _update_actions(self):
416
416
"""
417
417
show_dock_actions = self .windowwidget is None
418
418
self .undock_action .setVisible (show_dock_actions )
419
- self .close_action .setVisible (show_dock_actions )
420
419
self .lock_unlock_action .setVisible (show_dock_actions )
421
420
self .dock_action .setVisible (not show_dock_actions )
422
421
@@ -442,13 +441,13 @@ def _on_title_bar_shown(self, visible):
442
441
Actions to perform when the title bar is shown/hidden.
443
442
"""
444
443
if visible :
445
- self .lock_unlock_action .setText (_ ('Lock position ' ))
444
+ self .lock_unlock_action .setText (_ ('Lock' ))
446
445
self .lock_unlock_action .setIcon (self .create_icon ('lock_open' ))
447
446
for method_name in ['setToolTip' , 'setStatusTip' ]:
448
447
method = getattr (self .lock_unlock_action , method_name )
449
448
method (_ ("Lock pane to the current position" ))
450
449
else :
451
- self .lock_unlock_action .setText (_ ('Unlock position ' ))
450
+ self .lock_unlock_action .setText (_ ('Move ' ))
452
451
self .lock_unlock_action .setIcon (
453
452
self .create_icon ('drag_dock_widget' ))
454
453
for method_name in ['setToolTip' , 'setStatusTip' ]:
@@ -703,21 +702,21 @@ def render_toolbars(self):
703
702
This action can only be performed once.
704
703
"""
705
704
# if not self._toolbars_already_rendered:
706
- self ._main_toolbar ._render ()
707
- self ._corner_toolbar ._render ()
705
+ self ._main_toolbar .render ()
706
+ self ._corner_toolbar .render ()
708
707
for __ , toolbar in self ._auxiliary_toolbars .items ():
709
- toolbar ._render ()
708
+ toolbar .render ()
710
709
711
710
# self._toolbars_already_rendered = True
712
711
713
- # ---- SpyderDockwidget handling
712
+ # ---- SpyderWindowWidget handling
714
713
# -------------------------------------------------------------------------
715
714
@Slot ()
716
715
def create_window (self ):
717
716
"""
718
- Create a QMainWindow instance containing this widget.
717
+ Create an undocked window containing this widget.
719
718
"""
720
- logger .debug ("Undocking plugin" )
719
+ logger .debug (f "Undocking plugin { self . _name } " )
721
720
722
721
# Widgets
723
722
self .windowwidget = window = SpyderWindowWidget (self )
@@ -756,21 +755,63 @@ def create_window(self):
756
755
window .show ()
757
756
758
757
@Slot ()
759
- def close_window (self , save_undocked = False ):
758
+ def dock_window (self ):
759
+ """Dock undocked window back to the main window."""
760
+ logger .debug (f"Docking window of plugin { self ._name } " )
761
+
762
+ # Reset undocked state
763
+ self .set_conf ('window_was_undocked_before_hiding' , False )
764
+
765
+ # This avoids trying to close the window twice: once when calling
766
+ # _close_window below and the other when Qt calls the closeEvent of
767
+ # windowwidget
768
+ self .windowwidget .blockSignals (True )
769
+
770
+ # Close window
771
+ self ._close_window (switch_to_plugin = True )
772
+
773
+ # Make plugin visible on main window
774
+ self .dockwidget .setVisible (True )
775
+ self .dockwidget .raise_ ()
776
+
777
+ @Slot ()
778
+ def close_window (self ):
760
779
"""
761
- Close QMainWindow instance that contains this widget.
780
+ Close undocked window when clicking on the close window button.
781
+
782
+ Notes
783
+ -----
784
+ * This can either dock or hide the window, depending on whether the
785
+ user hid the window before.
786
+ * The default behavior is to dock the window, so that new users can
787
+ experiment with the dock/undock functionality without surprises.
788
+ * If the user closes the window by clicking on the `Close` action in
789
+ the plugin's Options menu or by going to the `View > Panes` menu,
790
+ then we will hide it when they click on the close button again.
791
+ That gives users the ability to show/hide plugins without
792
+ docking/undocking them first.
793
+ """
794
+ if self .get_conf ('window_was_undocked_before_hiding' , default = False ):
795
+ self .close_dock ()
796
+ else :
797
+ self .dock_window ()
798
+
799
+ def _close_window (self , save_undocked = False , switch_to_plugin = True ):
800
+ """
801
+ Helper function to close the undocked window with different parameters.
762
802
763
803
Parameters
764
804
----------
765
805
save_undocked : bool, optional
766
806
True if the undocked state needs to be saved. The default is False.
807
+ switch_to_plugin : bool, optional
808
+ Whether to switch to the plugin after closing the window. The
809
+ default is True.
767
810
768
811
Returns
769
812
-------
770
813
None.
771
814
"""
772
- logger .debug ("Docking plugin back to the main window" )
773
-
774
815
if self .windowwidget is not None :
775
816
# Save window geometry to restore it when undocking the plugin
776
817
# again.
@@ -793,15 +834,20 @@ def close_window(self, save_undocked=False):
793
834
794
835
if self .dockwidget is not None :
795
836
self .sig_update_ancestor_requested .emit ()
796
- self .get_plugin ().switch_to_plugin ()
837
+ if switch_to_plugin :
838
+ # This is necessary to restore the main window layout when
839
+ # there's a maximized plugin on it when the user requests
840
+ # to dock back this plugin.
841
+ self .get_plugin ().switch_to_plugin ()
842
+
797
843
self .dockwidget .setWidget (self )
798
- self .dockwidget .setVisible (True )
799
- self .dockwidget .raise_ ()
800
844
self ._update_actions ()
801
845
else :
802
846
# Reset undocked state
803
847
self .set_conf ('undocked_on_window_close' , False )
804
848
849
+ # ---- SpyderDockwidget handling
850
+ # -------------------------------------------------------------------------
805
851
def change_visibility (self , enable , force_focus = None ):
806
852
"""Dock widget visibility has changed."""
807
853
if self .dockwidget is None :
@@ -853,15 +899,40 @@ def toggle_view(self, checked):
853
899
if not self .dockwidget :
854
900
return
855
901
856
- # Dock plugin if it's undocked before hiding it.
857
- if self .windowwidget is not None :
858
- self .close_window (save_undocked = True )
902
+ # To check if the plugin needs to be undocked at the end
903
+ undock = False
859
904
860
905
if checked :
861
906
self .dockwidget .show ()
862
907
self .dockwidget .raise_ ()
863
908
self .is_visible = True
909
+
910
+ # We need to undock the plugin if that was its state before
911
+ # toggling its visibility.
912
+ if (
913
+ # Don't run this while the window is being created to not
914
+ # affect setting up the layout at startup.
915
+ not self ._plugin .main .is_setting_up
916
+ and self .get_conf (
917
+ 'window_was_undocked_before_hiding' , default = False
918
+ )
919
+ ):
920
+ undock = True
864
921
else :
922
+ if self .windowwidget is not None :
923
+ logger .debug (f"Closing window of plugin { self ._name } " )
924
+
925
+ # This avoids trying to close the window twice: once when
926
+ # calling _close_window below and the other when Qt calls the
927
+ # closeEvent of windowwidget
928
+ self .windowwidget .blockSignals (True )
929
+
930
+ # Dock plugin if it's undocked before hiding it.
931
+ self ._close_window (switch_to_plugin = False )
932
+
933
+ # Save undocked state to restore it afterwards.
934
+ self .set_conf ('window_was_undocked_before_hiding' , True )
935
+
865
936
self .dockwidget .hide ()
866
937
self .is_visible = False
867
938
@@ -873,6 +944,15 @@ def toggle_view(self, checked):
873
944
874
945
self .sig_toggle_view_changed .emit (checked )
875
946
947
+ logger .debug (
948
+ f"Plugin { self ._name } is now { 'visible' if checked else 'hidden' } "
949
+ )
950
+
951
+ if undock :
952
+ # We undock the plugin at this point so that the View menu is
953
+ # updated correctly.
954
+ self .create_window ()
955
+
876
956
def create_dockwidget (self , mainwindow ):
877
957
"""
878
958
Add to parent QMainWindow as a dock widget.
@@ -897,7 +977,8 @@ def close_dock(self):
897
977
"""
898
978
Close the dockwidget.
899
979
"""
900
- self .toggle_view (False )
980
+ logger .debug (f"Hiding plugin { self ._name } " )
981
+ self .toggle_view_action .setChecked (False )
901
982
902
983
def lock_unlock_position (self ):
903
984
"""
@@ -926,7 +1007,7 @@ def set_maximized_state(self, state):
926
1007
# This is necessary for old API plugins interacting with new ones.
927
1008
self ._plugin ._ismaximized = state
928
1009
929
- # --- API: methods to define or override
1010
+ # ---- API: methods to define or override
930
1011
# ------------------------------------------------------------------------
931
1012
def get_title (self ):
932
1013
"""
0 commit comments