@@ -100,6 +100,12 @@ class MainWindow(QMainWindow):
100100
101101 _is_open = False
102102
103+ #: The keyboard shortcuts of the default layout
104+ default_shortcuts = []
105+
106+ #: The current keyboard shortcuts
107+ current_shortcuts = []
108+
103109 @property
104110 def logger (self ):
105111 """The logger of this instance"""
@@ -129,7 +135,7 @@ def __init__(self, show=True):
129135 QMainWindow .AnimatedDocks | QMainWindow .AllowNestedDocks |
130136 QMainWindow .AllowTabbedDocks )
131137 #: Inprocess console
132- self .console = ConsoleWidget (parent = self )
138+ self .console = ConsoleWidget (self )
133139 self .project_actions = {}
134140
135141 self .config_pages = []
@@ -147,7 +153,7 @@ def __init__(self, show=True):
147153 self .new_plot_action .setStatusTip (
148154 'Use an existing dataset (or open a new one) to create one or '
149155 'more plots' )
150- self .new_plot_action . setShortcut ( QKeySequence .New )
156+ self .register_shortcut ( self . new_plot_action , QKeySequence .New )
151157 self .new_plot_action .triggered .connect (lambda : self .new_plots (True ))
152158 self .file_menu .addAction (self .new_plot_action )
153159
@@ -157,14 +163,16 @@ def __init__(self, show=True):
157163 self .file_menu .addMenu (self .open_project_menu )
158164
159165 self .open_mp_action = QAction ('New main project' , self )
160- self .open_mp_action . setShortcut ( QKeySequence .Open )
166+ self .register_shortcut ( self . open_mp_action , QKeySequence .Open )
161167 self .open_mp_action .setStatusTip ('Open a new main project' )
162168 self .open_mp_action .triggered .connect (self .open_mp )
163169 self .open_project_menu .addAction (self .open_mp_action )
164170
165171 self .open_sp_action = QAction ('Add to current' , self )
166- self .open_sp_action .setShortcut (QKeySequence (
167- 'Ctrl+Shift+O' , QKeySequence .NativeText ))
172+
173+ self .register_shortcut (
174+ self .open_sp_action , QKeySequence (
175+ 'Ctrl+Shift+O' , QKeySequence .NativeText ))
168176 self .open_sp_action .setStatusTip (
169177 'Load a project as a sub project and add it to the current main '
170178 'project' )
@@ -173,36 +181,37 @@ def __init__(self, show=True):
173181
174182 # ----------------------- Save project --------------------------------
175183
176- self .save_project_menu = QMenu ('Save project ' , parent = self )
184+ self .save_project_menu = QMenu ('Save' , parent = self )
177185 self .file_menu .addMenu (self .save_project_menu )
178186
179- self .save_mp_action = QAction ('All ' , self )
187+ self .save_mp_action = QAction ('Full psyplot project ' , self )
180188 self .save_mp_action .setStatusTip (
181189 'Save the entire project into a pickle file' )
182- self .save_mp_action . setShortcut ( QKeySequence .Save )
190+ self .register_shortcut ( self . save_mp_action , QKeySequence .Save )
183191 self .save_mp_action .triggered .connect (self .save_mp )
184192 self .save_project_menu .addAction (self .save_mp_action )
185193
186- self .save_sp_action = QAction ('Selected' , self )
194+ self .save_sp_action = QAction ('Selected psyplot project ' , self )
187195 self .save_sp_action .setStatusTip (
188196 'Save the selected sub project into a pickle file' )
189197 self .save_sp_action .triggered .connect (self .save_sp )
190198 self .save_project_menu .addAction (self .save_sp_action )
191199
192200 # ------------------------ Save project as ----------------------------
193201
194- self .save_project_as_menu = QMenu ('Save project as' , parent = self )
202+ self .save_project_as_menu = QMenu ('Save as' , parent = self )
195203 self .file_menu .addMenu (self .save_project_as_menu )
196204
197- self .save_mp_as_action = QAction ('All ' , self )
205+ self .save_mp_as_action = QAction ('Full psyplot project ' , self )
198206 self .save_mp_as_action .setStatusTip (
199207 'Save the entire project into a pickle file' )
200- self .save_mp_as_action .setShortcut (QKeySequence .SaveAs )
208+ self .register_shortcut (self .save_mp_as_action ,
209+ QKeySequence .SaveAs )
201210 self .save_mp_as_action .triggered .connect (
202211 partial (self .save_mp , new_fname = True ))
203212 self .save_project_as_menu .addAction (self .save_mp_as_action )
204213
205- self .save_sp_as_action = QAction ('Selected' , self )
214+ self .save_sp_as_action = QAction ('Selected psyplot project ' , self )
206215 self .save_sp_as_action .setStatusTip (
207216 'Save the selected sub project into a pickle file' )
208217 self .save_sp_as_action .triggered .connect (
@@ -214,13 +223,13 @@ def __init__(self, show=True):
214223 self .pack_project_menu = QMenu ('Zip project files' , parent = self )
215224 self .file_menu .addMenu (self .pack_project_menu )
216225
217- self .pack_mp_action = QAction ('All ' , self )
226+ self .pack_mp_action = QAction ('Full psyplot project ' , self )
218227 self .pack_mp_action .setStatusTip (
219228 'Pack all the data of the main project into one folder' )
220229 self .pack_mp_action .triggered .connect (partial (self .save_mp , pack = True ))
221230 self .pack_project_menu .addAction (self .pack_mp_action )
222231
223- self .pack_sp_action = QAction ('Selected' , self )
232+ self .pack_sp_action = QAction ('Selected psyplot project ' , self )
224233 self .pack_sp_action .setStatusTip (
225234 'Pack all the data of the current sub project into one folder' )
226235 self .pack_sp_action .triggered .connect (partial (self .save_sp , pack = True ))
@@ -231,19 +240,21 @@ def __init__(self, show=True):
231240 self .export_project_menu = QMenu ('Export figures' , parent = self )
232241 self .file_menu .addMenu (self .export_project_menu )
233242
234- self .export_mp_action = QAction ('All ' , self )
243+ self .export_mp_action = QAction ('Full psyplot project ' , self )
235244 self .export_mp_action .setStatusTip (
236245 'Pack all the data of the main project into one folder' )
237246 self .export_mp_action .triggered .connect (self .export_mp )
238- self .export_mp_action .setShortcut (QKeySequence (
239- 'Ctrl+E' , QKeySequence .NativeText ))
247+ self .register_shortcut (
248+ self .export_mp_action , QKeySequence (
249+ 'Ctrl+E' , QKeySequence .NativeText ))
240250 self .export_project_menu .addAction (self .export_mp_action )
241251
242- self .export_sp_action = QAction ('Selected' , self )
252+ self .export_sp_action = QAction ('Selected psyplot project ' , self )
243253 self .export_sp_action .setStatusTip (
244254 'Pack all the data of the current sub project into one folder' )
245- self .export_sp_action .setShortcut (QKeySequence (
246- 'Ctrl+Shift+E' , QKeySequence .NativeText ))
255+ self .register_shortcut (
256+ self .export_sp_action , QKeySequence (
257+ 'Ctrl+Shift+E' , QKeySequence .NativeText ))
247258 self .export_sp_action .triggered .connect (self .export_sp )
248259 self .export_project_menu .addAction (self .export_sp_action )
249260
@@ -254,21 +265,23 @@ def __init__(self, show=True):
254265 self .close_project_menu = QMenu ('Close project' , parent = self )
255266 self .file_menu .addMenu (self .close_project_menu )
256267
257- self .close_mp_action = QAction ('Main project' , self )
258- self .close_mp_action .setShortcut (QKeySequence (
259- 'Ctrl+Shift+W' , QKeySequence .NativeText ))
268+ self .close_mp_action = QAction ('Full psyplot project' , self )
269+ self .register_shortcut (
270+ self .close_mp_action , QKeySequence (
271+ 'Ctrl+Shift+W' , QKeySequence .NativeText ))
260272 self .close_mp_action .setStatusTip (
261273 'Close the main project and delete all data and plots out of '
262274 'memory' )
263275 self .close_mp_action .triggered .connect (
264276 lambda : psy .close (psy .gcp (True ).num ))
265277 self .close_project_menu .addAction (self .close_mp_action )
266278
267- self .close_sp_action = QAction ('Only selected ' , self )
279+ self .close_sp_action = QAction ('Selected psyplot project ' , self )
268280 self .close_sp_action .setStatusTip (
269281 'Close the selected arrays project and delete all data and plots '
270282 'out of memory' )
271- self .close_sp_action .setShortcut (QKeySequence .Close )
283+ self .register_shortcut (self .close_sp_action ,
284+ QKeySequence .Close )
272285 self .close_sp_action .triggered .connect (
273286 lambda : psy .gcp ().close (True , True ))
274287 self .close_project_menu .addAction (self .close_sp_action )
@@ -280,7 +293,8 @@ def __init__(self, show=True):
280293 self .quit_action .triggered .connect (self .close )
281294 self .quit_action .triggered .connect (
282295 QtCore .QCoreApplication .instance ().quit )
283- self .quit_action .setShortcut (QKeySequence .Quit )
296+ self .register_shortcut (
297+ self .quit_action , QKeySequence .Quit )
284298 self .file_menu .addAction (self .quit_action )
285299
286300 self .menuBar ().addMenu (self .file_menu )
@@ -305,7 +319,8 @@ def __init__(self, show=True):
305319
306320 self .help_action = QAction ('Preferences' , self )
307321 self .help_action .triggered .connect (lambda : self .edit_preferences (True ))
308- self .help_action .setShortcut (QKeySequence .Preferences )
322+ self .register_shortcut (self .help_action ,
323+ QKeySequence .Preferences )
309324 self .help_menu .addAction (self .help_action )
310325
311326 # ---------------------------- About ----------------------------------
@@ -505,6 +520,13 @@ def setup_default_layout(self):
505520 if w .hidden :
506521 w .hide_plugin ()
507522
523+ action2shortcut = defaultdict (list )
524+ for s , a in self .default_shortcuts :
525+ action2shortcut [a ].append (s )
526+
527+ for a , s in action2shortcut .items ():
528+ self .register_shortcut (a , s )
529+
508530 def _save_project (self , p , new_fname = False , * args , ** kwargs ):
509531 if new_fname or 'project_file' not in p .attrs :
510532 fname = QFileDialog .getSaveFileName (
@@ -863,6 +885,29 @@ def run(cls, fnames=[], project=None, engine=None, plot_method=None,
863885 psyplot .with_gui = True
864886 return mainwindow
865887
888+ def register_shortcut (self , action , shortcut ,
889+ context = Qt .ApplicationShortcut ):
890+ """Register an action for a shortcut"""
891+ shortcuts = psy .safe_list (shortcut )
892+ for j , shortcut in enumerate (shortcuts ):
893+ found = False
894+ for i , (s , a ) in enumerate (self .current_shortcuts ):
895+ if s == shortcut :
896+ new_shortcuts = [
897+ sc for sc in self .current_shortcuts [i ][1 ].shortcuts ()
898+ if sc != s ]
899+ a .setShortcut (QKeySequence ())
900+ if new_shortcuts :
901+ a .setShortcuts (new_shortcuts )
902+ self .current_shortcuts [i ][1 ] = action
903+ found = True
904+ break
905+ if not found :
906+ self .default_shortcuts .append ([shortcut , action ])
907+ self .current_shortcuts .append ([shortcut , action ])
908+ action .setShortcuts (shortcuts )
909+ action .setShortcutContext (context )
910+
866911 @classmethod
867912 @docstrings .dedent
868913 def run_app (cls , * args , ** kwargs ):
0 commit comments