1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 """Main module for the relax graphical user interface."""
25
26
27 from os import F_OK, access, getcwd, sep
28 import platform
29 from re import search
30 import sys
31 from time import sleep
32 import webbrowser
33 import wx
34
35
36 from data_store import Relax_data_store; ds = Relax_data_store()
37 from data_store.gui import Gui
38 from graphics import IMAGE_PATH, fetch_icon
39 from gui.about import About_relax
40 from gui.analyses import Analysis_controller
41 from gui.spin_viewer.frame import Spin_view_window
42 from gui.controller import Controller
43 from gui.export_bmrb import Export_bmrb_window
44 from gui.filedialog import RelaxFileDialog
45 from gui.fonts import font
46 from gui.icons import relax_icons
47 from gui.interpreter import Interpreter
48 from gui.menu import Menu
49 from gui.message import error_message, Question
50 from gui.misc import bitmap_setup, gui_raise, open_file, protected_exec
51 from gui.pipe_editor import Pipe_editor
52 from gui.references import References
53 from gui.relax_prompt import Prompt
54 from gui.results_viewer import Results_viewer
55 from gui.components.free_file_format import Free_file_format_window
56 from gui.string_conv import gui_to_str
57 from gui.uf_objects import Uf_storage; uf_store = Uf_storage()
58 from info import Info_box
59 from lib.errors import RelaxNoPipeError
60 from lib.io import io_streams_restore
61 from pipe_control import state
62 from pipe_control.pipes import cdp_name
63 from pipe_control.reset import reset
64 from status import Status; status = Status()
65 from version import version
66
67
68 -class Main(wx.Frame):
69 """The main GUI class."""
70
71
72 min_width = 1000
73 min_height = 600
74
75 - def __init__(self, parent=None, id=-1, title=""):
76 """Initialise the main relax GUI frame."""
77
78
79 status.wx_info = {}
80 status.wx_info["version"] = wx.__version__.split('.')
81 status.wx_info["minor"] = "%s.%s" % (status.wx_info["version"][0], status.wx_info["version"][1])
82 status.wx_info["os"] = sys.platform
83 status.wx_info["build"] = None
84 if search('gtk2', wx.version()):
85 status.wx_info["build"] = 'gtk'
86 elif search('cocoa', wx.version()):
87 status.wx_info["build"] = 'cocoa'
88 elif search('mac-unicode', wx.version()):
89 status.wx_info["build"] = 'carbon'
90 status.wx_info["full"] = None
91 if status.wx_info["build"]:
92 status.wx_info["full"] = "%s-%s" % (status.wx_info["os"], status.wx_info["build"])
93
94
95 self.test_suite_flag = False
96
97
98 style = wx.DEFAULT_FRAME_STYLE
99 if not status.debug and status.wx_info["os"] != 'darwin':
100 style = style | wx.MAXIMIZE
101
102
103 super(Main, self).__init__(parent=parent, id=id, title=title, style=style)
104
105
106 if not status.debug and status.wx_info["os"] != 'darwin':
107 self.Maximize()
108
109
110 font.setup()
111
112
113 relax_icons.setup()
114 self.SetIcons(relax_icons)
115
116
117
118
119
120
121 self.launch_dir = getcwd()
122
123
124 self.Layout()
125 self.SetSize((self.min_width, self.min_height))
126 self.SetMinSize((self.min_width, self.min_height))
127 self.Centre()
128
129
130 self.analysis = Analysis_controller(self)
131
132
133 self.calc_threads = []
134
135
136 self.init_data()
137
138
139 self.menu = Menu(self)
140
141
142 self.build_toolbar()
143
144
145 self.controller = Controller(self)
146
147
148 self.SetTitle("relax " + version)
149
150
151 self.status_bar = self.CreateStatusBar(3, 0)
152 self.status_bar.SetStatusWidths([-4, -1, -2])
153 self.update_status_bar()
154
155
156 self.add_start_screen()
157
158
159 self.Bind(wx.EVT_CLOSE, self.exit_gui)
160
161
162 self.interpreter = Interpreter()
163
164
165 status.observers.pipe_alteration.register('status bar', self.update_status_bar, method_name='update_status_bar')
166 status.observers.result_file.register('gui', self.show_results_viewer_no_warn, method_name='show_results_viewer_no_warn')
167 status.observers.exec_lock.register('gui', self.enable, method_name='enab')
168
169
170 self.analysis.load_from_store()
171
172
173 - def about_relax(self, event=None):
174 """The about message for relax.
175
176 @keyword event: The wx event.
177 @type event: wx event
178 """
179
180
181 dialog = About_relax(None, -1)
182
183
184 if status.show_gui:
185 dialog.Show()
186
187
188 - def action_export_bmrb(self, event=None):
189 """Export the contents of the current data pipe for BMRB deposition.
190
191 @keyword event: The wx event.
192 @type event: wx event
193 """
194
195
196 if not cdp_name():
197 gui_raise(RelaxNoPipeError())
198 return
199
200
201 Export_bmrb_window(self)
202
203
204 - def action_state_save(self, event=None):
205 """Save the program state.
206
207 @keyword event: The wx event.
208 @type event: wx event
209 """
210
211
212 if not self.save_file:
213 self.action_state_save_as(event)
214 return
215
216
217 self.state_save()
218
219
220 - def action_state_save_as(self, event=None):
221 """Save the program state with file name selection.
222
223 @keyword event: The wx event.
224 @type event: wx event
225 """
226
227
228 dialog = RelaxFileDialog(parent=self, message='Select the relax save state file', defaultFile='state.bz2', wildcard='relax save file (*.bz2)|*.bz2', style=wx.FD_SAVE)
229
230
231 if status.show_gui and dialog.ShowModal() != wx.ID_OK:
232
233 return
234
235
236 file_name = dialog.get_file()
237
238
239 self.save_file = file_name
240
241
242 self.state_save()
243
244
246 """Create a start screen for the main window when no analyses exist."""
247
248
249 sizer = wx.BoxSizer(wx.VERTICAL)
250 self.SetSizer(sizer)
251
252
253 image = wx.StaticBitmap(self, -1, bitmap_setup(IMAGE_PATH+'ulysses_shadowless_400x168.png'))
254
255
256 sizer.AddStretchSpacer()
257 sizer.Add(image, 0, wx.ALIGN_CENTER_HORIZONTAL, 0)
258 sizer.AddStretchSpacer()
259
260
261 self.Layout()
262 self.Refresh()
263
264
266 """Create the toolbar."""
267
268
269 self.toolbar = self.CreateToolBar(wx.TB_HORIZONTAL|wx.TB_FLAT)
270
271
272 self.TB_FILE_NEW = wx.NewId()
273 self.toolbar.AddLabelTool(self.TB_FILE_NEW, "New analysis", wx.Bitmap(fetch_icon('oxygen.actions.document-new', "22x22"), wx.BITMAP_TYPE_ANY), shortHelp="New analysis")
274 self.Bind(wx.EVT_TOOL, self.analysis.menu_new, id=self.TB_FILE_NEW)
275
276
277 self.TB_FILE_CLOSE = wx.NewId()
278 self.toolbar.AddLabelTool(self.TB_FILE_CLOSE, "Close analysis", wx.Bitmap(fetch_icon('oxygen.actions.document-close', "22x22"), wx.BITMAP_TYPE_ANY), shortHelp="Close analysis")
279 self.Bind(wx.EVT_TOOL, self.analysis.menu_close, id=self.TB_FILE_CLOSE)
280
281
282 self.TB_FILE_CLOSE_ALL = wx.NewId()
283 self.toolbar.AddLabelTool(self.TB_FILE_CLOSE_ALL, "Close all analyses", wx.Bitmap(fetch_icon('oxygen.actions.dialog-close', "22x22"), wx.BITMAP_TYPE_ANY), shortHelp="Close all analyses")
284 self.Bind(wx.EVT_TOOL, self.analysis.menu_close_all, id=self.TB_FILE_CLOSE_ALL)
285
286
287 self.toolbar.AddSeparator()
288
289
290 self.TB_FILE_OPEN = wx.NewId()
291 self.toolbar.AddLabelTool(self.TB_FILE_OPEN, "Open relax state", wx.Bitmap(fetch_icon('oxygen.actions.document-open', "22x22"), wx.BITMAP_TYPE_ANY), shortHelp="Open relax state")
292 self.Bind(wx.EVT_TOOL, self.state_load, id=self.TB_FILE_OPEN)
293
294
295 self.TB_FILE_SAVE = wx.NewId()
296 self.toolbar.AddLabelTool(self.TB_FILE_SAVE, "Save relax state", wx.Bitmap(fetch_icon('oxygen.actions.document-save', "22x22"), wx.BITMAP_TYPE_ANY), shortHelp="Save relax state")
297 self.Bind(wx.EVT_TOOL, self.action_state_save, id=self.TB_FILE_SAVE)
298
299
300 self.TB_FILE_SAVE_AS = wx.NewId()
301 self.toolbar.AddLabelTool(self.TB_FILE_SAVE_AS, "Save as", wx.Bitmap(fetch_icon('oxygen.actions.document-save-as', "22x22"), wx.BITMAP_TYPE_ANY), shortHelp="Save as")
302 self.Bind(wx.EVT_TOOL, self.action_state_save_as, id=self.TB_FILE_SAVE_AS)
303
304
305 self.toolbar.AddSeparator()
306
307
308 self.TB_VIEW_CONTROLLER = wx.NewId()
309 self.toolbar.AddLabelTool(self.TB_VIEW_CONTROLLER, "Controller", wx.Bitmap(fetch_icon('oxygen.apps.preferences-system-performance', "22x22"), wx.BITMAP_TYPE_ANY), shortHelp="relax controller")
310 self.Bind(wx.EVT_TOOL, self.show_controller, id=self.TB_VIEW_CONTROLLER)
311
312
313 self.TB_VIEW_SPIN_VIEW = wx.NewId()
314 self.toolbar.AddLabelTool(self.TB_VIEW_SPIN_VIEW, "Spin viewer", wx.Bitmap(fetch_icon('relax.spin', "22x22"), wx.BITMAP_TYPE_ANY), shortHelp="Spin viewer window")
315 self.Bind(wx.EVT_TOOL, self.show_tree, id=self.TB_VIEW_SPIN_VIEW)
316
317
318 self.TB_VIEW_RESULTS = wx.NewId()
319 self.toolbar.AddLabelTool(self.TB_VIEW_RESULTS, "Results viewer", wx.Bitmap(fetch_icon('oxygen.actions.view-statistics', "22x22"), wx.BITMAP_TYPE_ANY), shortHelp="Results viewer window")
320 self.Bind(wx.EVT_TOOL, self.show_results_viewer, id=self.TB_VIEW_RESULTS)
321
322
323 self.TB_VIEW_PIPE_EDIT = wx.NewId()
324 self.toolbar.AddLabelTool(self.TB_VIEW_PIPE_EDIT, "Data pipe editor", wx.Bitmap(fetch_icon('relax.pipe', "22x22"), wx.BITMAP_TYPE_ANY), shortHelp="Data pipe editor")
325 self.Bind(wx.EVT_TOOL, self.show_pipe_editor, id=self.TB_VIEW_PIPE_EDIT)
326
327
328 self.TB_VIEW_PROMPT = wx.NewId()
329 self.toolbar.AddLabelTool(self.TB_VIEW_PROMPT, "relax prompt", wx.Bitmap(fetch_icon('oxygen.mimetypes.application-x-executable-script', "22x22"), wx.BITMAP_TYPE_ANY), shortHelp="The relax prompt GUI window")
330 self.Bind(wx.EVT_TOOL, self.show_prompt, id=self.TB_VIEW_PROMPT)
331
332
333 self.toolbar.Realize()
334
335
336 - def close_windows(self):
337 """Throw a warning to close all of the non-essential windows when execution is locked.
338
339 This is to speed up the calculations by avoiding window updates.
340 """
341
342
343 win_list = []
344
345
346 if hasattr(self, 'spin_viewer') and self.spin_viewer.IsShown():
347 win_list.append('The spin viewer window')
348
349
350 if hasattr(self, 'pipe_editor') and self.pipe_editor.IsShown():
351 win_list.append('The data pipe editor window')
352
353
354 if hasattr(self, 'results_viewer') and self.results_viewer.IsShown():
355 win_list.append('The results viewer window')
356
357
358 if not len(win_list):
359 return
360
361
362 text = "The following windows are currently open:\n\n"
363 for win in win_list:
364 text = "%s\t%s.\n" % (text, win)
365 text = text + "\nClosing these will significantly speed up the calculations."
366
367
368 dlg = wx.MessageDialog(self, text, caption="Close windows", style=wx.OK|wx.ICON_EXCLAMATION|wx.STAY_ON_TOP)
369 if status.show_gui:
370 dlg.ShowModal()
371
372
373 else:
374 sys.stderr.write(text)
375
376
378 """Write an email to the relax mailing-list using the standard mailing program.
379
380 @keyword event: The wx event.
381 @type event: wx event
382 """
383
384 webbrowser.open_new('mailto:relax-users@gna.org')
385
386
388 """Enable and disable certain parts of the main window with the execution lock."""
389
390
391 enable = False
392 if not status.exec_lock.locked():
393 enable = True
394
395
396 wx.CallAfter(self.toolbar.EnableTool, self.TB_FILE_NEW, enable)
397 wx.CallAfter(self.toolbar.EnableTool, self.TB_FILE_CLOSE, enable)
398 wx.CallAfter(self.toolbar.EnableTool, self.TB_FILE_CLOSE_ALL, enable)
399 wx.CallAfter(self.toolbar.EnableTool, self.TB_FILE_OPEN, enable)
400 wx.CallAfter(self.toolbar.EnableTool, self.TB_FILE_SAVE, enable)
401 wx.CallAfter(self.toolbar.EnableTool, self.TB_FILE_SAVE_AS, enable)
402
403
404 - def exit_gui(self, event=None):
405 """Catch the main window closure and perform the exit procedure.
406
407 @keyword event: The wx event.
408 @type event: wx event
409 """
410
411
412 doexit = wx.ID_YES
413 if status.show_gui and not ds.is_empty():
414 doexit = Question('Are you sure you would like to quit relax? All unsaved data will be lost.', title='Exit relax', default=True).ShowModal()
415
416
417 if doexit == wx.ID_YES:
418
419 io_streams_restore(verbosity=0)
420
421
422 info = Info_box()
423
424
425 if platform.uname()[0] in ['Windows', 'Microsoft']:
426 width = 80
427 else:
428 width = 100
429
430
431 if hasattr(self, 'taskbar_icon'):
432 self.taskbar_icon.Destroy()
433
434
435 self.interpreter.exit()
436
437
438 app = wx.GetApp()
439 app.ExitMainLoop()
440
441
442 - def init_data(self):
443 """Initialise the data used by the GUI interface."""
444
445
446 self.save_file = None
447
448
449 if not hasattr(ds, 'relax_gui'):
450 ds.relax_gui = Gui()
451
452
454 """Open the free file format settings window.
455
456 @keyword event: The wx event.
457 @type event: wx event
458 """
459
460
461 win = Free_file_format_window()
462
463
464 if status.show_gui:
465 win.Show()
466
467
468 - def references(self, event=None):
469 """Display the references relevant for relax.
470
471 @keyword event: The wx event.
472 @type event: wx event
473 """
474
475
476 self.references = References(self)
477 if status.show_gui:
478 self.references.Show()
479
480
481 - def relax_manual(self, event=None):
482 """Display the relax manual.
483
484 @keyword event: The wx event.
485 @type event: wx event
486 """
487
488
489 file = status.install_path + sep+"docs"+sep+"relax.pdf"
490
491
492 if not access(file, F_OK):
493 error_message("The relax manual '%s' cannot be found. Please compile using the scons program." % file)
494 return
495
496
497 open_file(file)
498
499
501 """Reset the GUI."""
502
503
504 windows = ['pipe_editor', 'relax_prompt', 'results_viewer', 'spin_viewer']
505 for window in windows:
506 if hasattr(self, window):
507
508 win_obj = getattr(self, window)
509
510
511 win_obj.Close()
512
513
514 wx.Yield()
515
516
517 self.controller.reset()
518
519
520 - def run_test_suite(self, event=None, categories=['system', 'unit', 'gui', 'verification']):
521 """Execute the full test suite.
522
523 @keyword event: The wx event.
524 @type event: wx event
525 @keyword categories: The list of test categories to run, for example ['system', 'unit', 'gui', 'verification'] for all tests.
526 @type categories: list of str
527 """
528
529
530 msg = "In running the test suite, relax will be reset and all data lost. Are you sure you would like to run the test suite?"
531 if Question(msg, parent=self, size=(400, 150), default=False).ShowModal() == wx.ID_NO:
532 return
533
534
535 self.test_suite_flag = True
536
537
538 wx.BeginBusyCursor()
539
540
541 orig_style = self.controller.GetWindowStyle()
542 self.controller.SetWindowStyle(orig_style | wx.STAY_ON_TOP)
543 self.controller.Refresh()
544
545
546 self.controller.MakeModal(True)
547
548
549 if hasattr(self, 'spin_viewer'):
550 self.spin_viewer.Close()
551 if hasattr(self, 'pipe_editor'):
552 self.pipe_editor.Close()
553 if hasattr(self, 'results_viewer'):
554 self.results_viewer.Close()
555 if hasattr(self, 'relax_prompt'):
556 self.relax_prompt.Close()
557
558
559 reset()
560
561
562 self.show_controller(event)
563
564
565 wx.GetApp().Yield(True)
566
567
568 status.show_gui = False
569
570
571 import test_suite.test_suite_runner
572 runner = test_suite.test_suite_runner.Test_suite_runner([], from_gui=True, categories=categories)
573 runner.run_all_tests()
574
575
576 status.show_gui = True
577
578
579 if wx.IsBusy():
580 wx.EndBusyCursor()
581
582
583 self.controller.SetWindowStyle(orig_style)
584 self.controller.MakeModal(False)
585 self.controller.Refresh()
586
587
588 self.test_suite_flag = False
589
590
591 wx.CallAfter(self.controller.main_gauge.SetValue, 100)
592
593
594 - def run_test_suite_gui(self, event=None):
595 """Execute the GUI tests.
596
597 @keyword event: The wx event.
598 @type event: wx event
599 """
600
601
602 self.run_test_suite(event, categories=['gui'])
603
604
605 - def run_test_suite_sys(self, event=None):
606 """Execute the system tests.
607
608 @keyword event: The wx event.
609 @type event: wx event
610 """
611
612
613 self.run_test_suite(event, categories=['system'])
614
615
616 - def run_test_suite_unit(self, event=None):
617 """Execute the unit tests.
618
619 @keyword event: The wx event.
620 @type event: wx event
621 """
622
623
624 self.run_test_suite(event, categories=['unit'])
625
626
627 - def run_test_suite_verification(self, event=None):
628 """Execute the verification tests.
629
630 @keyword event: The wx event.
631 @type event: wx event
632 """
633
634
635 self.run_test_suite(event, categories=['verification'])
636
637
638 - def show_controller(self, event=None):
639 """Display the relax controller window.
640
641 @keyword event: The wx event.
642 @type event: wx event
643 """
644
645
646 if self.controller.IsShown():
647 self.controller.Raise()
648 return
649
650
651 if status.show_gui:
652 self.controller.Show()
653
654
655 - def show_pipe_editor(self, event=None):
656 """Display the data pipe editor window.
657
658 @keyword event: The wx event.
659 @type event: wx event
660 """
661
662
663 if status.exec_lock.locked():
664 dlg = wx.MessageDialog(self, "Leaving the pipe editor window open will slow down the calculations.", caption="Warning", style=wx.OK|wx.ICON_EXCLAMATION|wx.STAY_ON_TOP)
665 if status.show_gui:
666 dlg.ShowModal()
667
668
669 if not hasattr(self, 'pipe_editor'):
670 self.pipe_editor = Pipe_editor(gui=self)
671
672
673 if self.pipe_editor.IsShown():
674 self.pipe_editor.Raise()
675 return
676
677
678 if status.show_gui and not self.pipe_editor.IsShown():
679 self.pipe_editor.Show()
680
681
682 self.pipe_editor.update_grid()
683 self.pipe_editor.activate()
684
685
686 self.pipe_editor.observer_setup(register=True)
687
688
689 - def show_prompt(self, event=None):
690 """Display the relax prompt window.
691
692 @keyword event: The wx event.
693 @type event: wx event
694 """
695
696
697 if not hasattr(self, 'relax_prompt'):
698 self.relax_prompt = Prompt(None, -1, "", parent=self)
699
700
701 if self.relax_prompt.IsShown():
702 self.relax_prompt.Raise()
703 return
704
705
706 if status.show_gui:
707 self.relax_prompt.Show()
708
709
710 - def show_results_viewer(self, event=None):
711 """Display the analysis results.
712
713 @keyword event: The wx event.
714 @type event: wx event
715 """
716
717
718 wx.CallAfter(self.show_results_viewer_safe, warn=True)
719
720
721 - def show_results_viewer_safe(self, warn=False):
722 """Display the analysis results in a thread safe wx.CallAfter call.
723
724 @keyword warn: A flag which if True will cause a message dialog to appear warning about keeping the window open with the execution lock.
725 @type warn: bool
726 """
727
728
729 if warn and status.exec_lock.locked():
730 dlg = wx.MessageDialog(self, "Leaving the results viewer window open will slow down the calculations.", caption="Warning", style=wx.OK|wx.ICON_EXCLAMATION|wx.STAY_ON_TOP)
731 if status.show_gui:
732 wx.CallAfter(dlg.ShowModal)
733
734
735 if not hasattr(self, 'results_viewer'):
736 self.results_viewer = Results_viewer(self)
737
738
739 if self.results_viewer.IsShown():
740 self.results_viewer.Raise()
741 return
742
743
744 if status.show_gui and not self.results_viewer.IsShown():
745 self.results_viewer.Show()
746
747
749 """Display the analysis results."""
750
751
752 wx.CallAfter(self.show_results_viewer_safe, warn=False)
753
754
755 - def show_tree(self, event=None):
756 """Display the molecule, residue, and spin tree window.
757
758 @keyword event: The wx event.
759 @type event: wx event
760 """
761
762
763 if status.exec_lock.locked():
764 dlg = wx.MessageDialog(self, "Leaving the spin viewer window open will slow down the calculations.", caption="Warning", style=wx.OK|wx.ICON_EXCLAMATION|wx.STAY_ON_TOP)
765 if status.show_gui:
766 dlg.ShowModal()
767
768
769 if not hasattr(self, 'spin_viewer'):
770 self.spin_viewer = Spin_view_window(None, -1, "", parent=self)
771
772
773 if self.spin_viewer.IsShown():
774 self.spin_viewer.Raise()
775 return
776
777
778 if status.show_gui and not self.spin_viewer.IsShown():
779 self.spin_viewer.Show()
780
781
782 - def state_load(self, event=None, file_name=None):
783 """Load the program state.
784
785 @keyword event: The wx event.
786 @type event: wx event
787 @keyword file_name: The name of the file to load (for dialogless operation).
788 @type file_name: str
789 """
790
791
792 if status.exec_lock.locked():
793 return
794
795
796 if not self.analysis.init_state or not ds.is_empty():
797
798 msg = "Loading a saved relax state file will cause all unsaved data to be lost. Are you sure you would to open a save file?"
799
800
801 if status.show_gui and Question(msg, default=True, size=(400, 150)).ShowModal() == wx.ID_NO:
802 return
803
804
805 if not file_name:
806 dialog = RelaxFileDialog(parent=self, message='Select the relax save state file', defaultFile='state.bz2', wildcard='relax save files (*.bz2;*.gz)|*.bz2;*.gz|All files (*)|*', style=wx.FD_OPEN)
807
808
809 if status.show_gui and dialog.ShowModal() != wx.ID_OK:
810
811 return
812
813
814 file_name = gui_to_str(dialog.get_file())
815
816
817 wx.Yield()
818
819
820 wx.BeginBusyCursor()
821 self.Freeze()
822
823
824 try:
825
826 self.analysis.delete_all()
827
828
829 reset()
830
831
832 self.save_file = file_name
833
834
835 if protected_exec(state.load_state, file_name, verbosity=0):
836
837 self.sync_ds(upload=False)
838
839
840 else:
841
842 reset()
843
844
845 self.init_data()
846
847
848 finally:
849 self.Thaw()
850
851
852 if wx.IsBusy():
853 wx.EndBusyCursor()
854
855
856 - def state_save(self):
857 """Save the program state."""
858
859
860 self.sync_ds(upload=True)
861
862
863 try:
864 wx.BeginBusyCursor()
865 state.save_state(self.save_file, verbosity=0, force=True)
866
867
868 sleep(1)
869
870
871 finally:
872 if wx.IsBusy():
873 wx.EndBusyCursor()
874
875
876 - def sync_ds(self, upload=False):
877 """Synchronise the GUI and the relax data store, both ways.
878
879 This method allows the GUI information to be uploaded into the relax data store, or for the information in the relax data store to be downloaded by the GUI.
880
881 @keyword upload: A flag which if True will cause the GUI to send data to the relax data store. If False, data will be downloaded from the relax data store to update the GUI.
882 @type upload: bool
883 """
884
885
886 for page in self.analysis.analysis_loop():
887
888 if hasattr(page, 'sync_ds'):
889 page.sync_ds(upload)
890
891
892 - def uf_call(self, event=None):
893 """Catch the user function call to properly specify the parent window.
894
895 @keyword event: The wx event.
896 @type event: wx event
897 """
898
899
900 uf_id = event.GetId()
901
902
903 name = uf_store.get_uf(uf_id)
904
905
906 uf_store[name](event=event, wx_parent=self)
907
908
910 """Update the status bar info."""
911
912
913 pipe = cdp_name()
914
915
916 if pipe == None:
917 pipe = ''
918
919
920 wx.CallAfter(self.status_bar.SetStatusText, "(C) 2001-2014 the relax development team", 0)
921 wx.CallAfter(self.status_bar.SetStatusText, "Current data pipe:", 1)
922 wx.CallAfter(self.status_bar.SetStatusText, pipe, 2)
923