1010from sscanss .__version import __version__ , Version
1111from sscanss .config import settings , DOCS_URL , UPDATE_URL , RELEASES_URL
1212from sscanss .themes import ThemeManager , path_for , IconEngine
13- from sscanss .app .dialogs import (ProgressDialog , ProjectDialog , Preferences , AlignmentErrorDialog , ScriptExportDialog ,
14- PathLengthPlotter , AboutDialog , CalibrationErrorDialog , InstrumentCoordinatesDialog ,
13+ from sscanss .app .dialogs import (ProgressDialog , ProjectWidget , Preferences , AlignmentErrorDialog , ScriptExportDialog ,
14+ PathLengthPlotter , AboutWidget , CalibrationErrorDialog , InstrumentCoordinatesDialog ,
1515 CurveEditor , VolumeLoader )
1616from sscanss .core .scene import Node , OpenGLRenderer , SceneManager
1717from sscanss .core .util import (Primitives , Directions , TransformType , PointType , MessageType , Attributes ,
@@ -37,6 +37,69 @@ def __call__(self):
3737 return self .view .presenter .openProject (self .filename )
3838
3939
40+ class OverlayContainer (QtWidgets .QWidget ):
41+ """A container that allow a widget to be overlaid over a background widget
42+
43+ :param background: background widget
44+ :type background: QWidget
45+ :param parent: instance of main window
46+ :type parent: MainWindow
47+ """
48+ def __init__ (self , background , parent ):
49+ super ().__init__ (parent )
50+
51+ self .widget = None
52+ self .main_layout = QtWidgets .QStackedLayout ()
53+ self .main_layout .setStackingMode (QtWidgets .QStackedLayout .StackingMode .StackAll )
54+ self .setLayout (self .main_layout )
55+
56+ self .main_layout .addWidget (background )
57+ overlay_widget = QtWidgets .QWidget ()
58+ overlay_widget .setObjectName ('overlay' )
59+ overlay_widget .setStyleSheet ('#overlay {background: transparent;}' )
60+
61+ layout = QtWidgets .QHBoxLayout ()
62+ self .overlay_layout = QtWidgets .QVBoxLayout ()
63+ layout .addStretch (1 )
64+ layout .addLayout (self .overlay_layout )
65+ layout .addStretch (1 )
66+ overlay_widget .setLayout (layout )
67+ self .main_layout .addWidget (overlay_widget )
68+
69+ def setOverlayWidget (self , widget ):
70+ """Sets and shows the overlay widget
71+
72+ :param widget: widget to overlay over background
73+ :type widget: QWidget
74+ """
75+ self .closeOverlayWidget ()
76+ self .widget = widget
77+ self .overlay_layout .addStretch (1 )
78+ self .overlay_layout .addWidget (widget )
79+ self .overlay_layout .addStretch (1 )
80+ self .main_layout .setCurrentIndex (1 )
81+
82+ widget .installEventFilter (self )
83+
84+ def eventFilter (self , _obj , event ):
85+ """Catch close event for overlay widget"""
86+ if event .type () == QtCore .QEvent .Type .Close :
87+ self .closeOverlayWidget ()
88+ return True
89+ return False
90+
91+ def closeOverlayWidget (self ):
92+ """Closes the overlay widget and show background"""
93+ if self .widget is None :
94+ return
95+
96+ self .main_layout .setCurrentIndex (0 )
97+ for i in reversed (range (self .overlay_layout .count ())):
98+ self .overlay_layout .takeAt (i )
99+ self .widget .hide ()
100+ self .widget = None
101+
102+
40103class MainWindow (QtWidgets .QMainWindow ):
41104 """Creates the main view for the sscanss app"""
42105 def __init__ (self ):
@@ -54,9 +117,11 @@ def __init__(self):
54117 self .themes = ThemeManager (self )
55118 self .themes .theme_changed .connect (self .setStyleSheet )
56119 self .themes .theme_changed .connect (self .updateImages )
120+
57121 self .gl_widget = OpenGLRenderer (self )
58122 self .gl_widget .custom_error_handler = self .sceneSizeErrorHandler
59- self .setCentralWidget (self .gl_widget )
123+ self .overlay = OverlayContainer (self .gl_widget , self )
124+ self .setCentralWidget (self .overlay )
60125
61126 self .docks = DockManager (self )
62127 self .scenes = SceneManager (self .presenter .model , self .gl_widget )
@@ -76,21 +141,21 @@ def __init__(self):
76141 self .setAttribute (QtCore .Qt .WidgetAttribute .WA_DeleteOnClose )
77142
78143 self .readSettings ()
79- self .updateMenus ()
144+ self .updateMenus (False )
80145
81146 def createActions (self ):
82147 """Creates the menu and toolbar actions """
83148 self .new_project_action = QtGui .QAction ('&New Project' , self )
84149 self .new_project_action .setStatusTip ('Create a new project' )
85150 self .new_project_action .setIcon (QtGui .QIcon (IconEngine ('file.png' )))
86151 self .new_project_action .setShortcut (QtGui .QKeySequence .StandardKey .New )
87- self .new_project_action .triggered .connect (lambda : self .presenter .confirmSave (self .showNewProjectDialog ))
152+ self .new_project_action .triggered .connect (lambda : self .presenter .confirmSave (self .showNewProjectWidget ))
88153
89154 self .open_project_action = QtGui .QAction ('&Open Project' , self )
90155 self .open_project_action .setStatusTip ('Open an existing project' )
91156 self .open_project_action .setIcon (QtGui .QIcon (IconEngine ('folder-open.png' )))
92157 self .open_project_action .setShortcut (QtGui .QKeySequence .StandardKey .Open )
93- self .open_project_action .triggered .connect (lambda : self .presenter .confirmSave (self .presenter .openProject () ))
158+ self .open_project_action .triggered .connect (lambda : self .presenter .confirmSave (self .presenter .openProject ))
94159
95160 self .save_project_action = QtGui .QAction ('&Save Project' , self )
96161 self .save_project_action .setStatusTip ('Save project' )
@@ -378,7 +443,7 @@ def createActions(self):
378443
379444 self .show_about_action = QtGui .QAction (f'&About { MAIN_WINDOW_TITLE } ' , self )
380445 self .show_about_action .setStatusTip (f'About { MAIN_WINDOW_TITLE } ' )
381- self .show_about_action .triggered .connect (self .showAboutDialog )
446+ self .show_about_action .triggered .connect (self .showAboutWidget )
382447
383448 # ToolBar Actions
384449 self .rotate_sample_action = QtGui .QAction ('Rotate Sample' , self )
@@ -422,10 +487,11 @@ def createActions(self):
422487 self .show_curve_editor_action .setIcon (QtGui .QIcon (IconEngine ('curve.png' )))
423488 self .show_curve_editor_action .triggered .connect (self .showCurveEditor )
424489
425- def showAboutDialog (self ):
490+ def showAboutWidget (self ):
426491 """Display the About Dialog"""
427- self .createNonModalDialog (AboutDialog )
428- self .non_modal_dialog .show ()
492+ self .closeNonModalDialog ()
493+ about_dialog = AboutWidget (self )
494+ self .overlay .setOverlayWidget (about_dialog )
429495
430496 def updateImages (self ):
431497 """Updates the images of the actions on the menu"""
@@ -579,10 +645,8 @@ def createMenus(self):
579645 help_menu .addAction (self .check_update_action )
580646 help_menu .addAction (self .show_about_action )
581647
582- def updateMenus (self ):
648+ def updateMenus (self , enable ):
583649 """Disables the menus when a project is not created and enables menus when a project is created"""
584- enable = self .presenter .model .project_data is not None
585-
586650 self .save_project_action .setEnabled (enable )
587651 self .save_as_action .setEnabled (enable )
588652 for action in self .export_menu .actions ():
@@ -706,6 +770,7 @@ def createStatusBar(self):
706770 sb .addPermanentWidget (self .size_label )
707771
708772 def createNonModalDialog (self , dialog_type ):
773+ self .overlay .closeOverlayWidget ()
709774 if not isinstance (self .non_modal_dialog , dialog_type ):
710775 self .closeNonModalDialog ()
711776 dialog = dialog_type (self )
@@ -716,6 +781,7 @@ def createNonModalDialog(self, dialog_type):
716781 def closeNonModalDialog (self ):
717782 if self .non_modal_dialog is not None :
718783 self .non_modal_dialog .close ()
784+ self .non_modal_dialog = None
719785
720786 def clearUndoStack (self ):
721787 """Clears the undo stack and ensures stack is cleaned even when stack is empty"""
@@ -859,11 +925,12 @@ def __createChangeCollimatorAction(self, name, active, detector):
859925
860926 return change_collimator_action
861927
862- def showNewProjectDialog (self ):
863- """Opens the new project dialog"""
864- self .createNonModalDialog (ProjectDialog )
865- self .non_modal_dialog .updateRecentProjects (self .recent_projects )
866- self .non_modal_dialog .show ()
928+ def showNewProjectWidget (self ):
929+ """Opens the new project widget"""
930+ self .closeNonModalDialog ()
931+ project_dialog = ProjectWidget (self )
932+ project_dialog .updateRecentProjects (self .recent_projects )
933+ self .overlay .setOverlayWidget (project_dialog )
867934
868935 def showPreferences (self , group = None ):
869936 """Opens the preferences dialog"""
0 commit comments