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