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