1   
  2   
  3   
  4   
  5   
  6   
  7   
  8   
  9   
 10   
 11   
 12   
 13   
 14   
 15   
 16   
 17   
 18   
 19   
 20   
 21   
 22   
 23  """Module containing a set of special GUI elements to be used in the relax wizards.""" 
 24   
 25   
 26  import wx 
 27  from wx.lib import scrolledpanel 
 28  import wx.lib.mixins.listctrl 
 29   
 30   
 31  from graphics import fetch_icon 
 32  from gui.filedialog import RelaxFileDialog 
 33  from gui.fonts import font 
 34  from gui.misc import add_border, open_file 
 35  from gui.string_conv import gui_to_list, gui_to_str, list_to_gui, str_to_gui 
 36  from lib.errors import RelaxError 
 37  from status import Status; status = Status() 
 38   
 39   
 41      """A single file element for the multiple file input GUI element.""" 
 42   
 43 -    def __init__(self, default='', parent=None, index=None, wildcard=wx.FileSelectorDefaultWildcardStr, style=wx.FD_DEFAULT_STYLE, padding=3, height_spacer=1, width_spacer=2, height_element=27, preview=True, can_be_none=False): 
  44          """Set up the file GUI element. 
 45   
 46          @keyword default:           The default value of the element. 
 47          @type default:              str 
 48          @keyword parent:            The parent GUI element. 
 49          @type parent:               wx.Panel instance 
 50          @keyword index:             The index of the file element, to display its sequence number in the GUI element. 
 51          @type index:                int 
 52          @keyword wildcard:          The file wildcard pattern.  For example for opening PDB files, this could be "PDB files (*.pdb)|*.pdb;*.PDB". 
 53          @type wildcard:             String 
 54          @keyword style:             The dialog style.  To open a single file, set to wx.FD_OPEN.  To open multiple files, set to wx.FD_OPEN|wx.FD_MULTIPLE.  To save a single file, set to wx.FD_SAVE.  To save multiple files, set to wx.FD_SAVE|wx.FD_MULTIPLE. 
 55          @type style:                long 
 56          @keyword padding:           Spacing to the left and right of the widgets. 
 57          @type padding:              int 
 58          @keyword height_spacer:     The amount of spacing to add below the field in pixels. 
 59          @type height_spacer:        int 
 60          @keyword width_spacer:      The amount of spacing to add horizontally between the TextCtrl and buttons in pixels. 
 61          @type width_spacer:         int 
 62          @keyword height_element:    The height in pixels of the GUI element. 
 63          @type height_element:       int 
 64          @keyword preview:           A flag which if true will allow the file to be previewed. 
 65          @type preview:              bool 
 66          @keyword can_be_none:       A flag which specifies if the element is allowed to have the None value. 
 67          @type can_be_none:          bool 
 68          """ 
 69   
 70           
 71          self.default = default 
 72          self.parent = parent 
 73          self.wildcard = wildcard 
 74          self.style = style 
 75          self.can_be_none = can_be_none 
 76   
 77           
 78          self.sizer = wx.BoxSizer(wx.VERTICAL) 
 79   
 80           
 81          sub_sizer = wx.BoxSizer(wx.HORIZONTAL) 
 82   
 83           
 84          sub_sizer.AddSpacer(padding) 
 85   
 86           
 87          desc = str_to_gui("%i:  " % (index+1)) 
 88          text = wx.StaticText(self.parent, -1, desc, style=wx.ALIGN_LEFT) 
 89          text.SetFont(font.normal_bold) 
 90          text.SetMinSize((35, -1)) 
 91          sub_sizer.Add(text, 0, wx.LEFT|wx.ALIGN_CENTER_VERTICAL|wx.ADJUST_MINSIZE, 0) 
 92   
 93           
 94          sub_sizer.AddSpacer(width_spacer) 
 95   
 96           
 97          self.field = wx.TextCtrl(self.parent, -1, self.default) 
 98          self.field.SetMinSize((-1, height_element)) 
 99          self.field.SetFont(font.normal) 
100          sub_sizer.Add(self.field, 1, wx.EXPAND|wx.ADJUST_MINSIZE|wx.ALIGN_CENTER_VERTICAL, 0) 
101   
102           
103          sub_sizer.AddSpacer(width_spacer) 
104   
105           
106          button = wx.BitmapButton(self.parent, -1, wx.Bitmap(fetch_icon('oxygen.actions.document-open', "16x16"), wx.BITMAP_TYPE_ANY)) 
107          button.SetMinSize((height_element, height_element)) 
108          button.SetToolTipString("Select the file.") 
109          sub_sizer.Add(button, 0, wx.ADJUST_MINSIZE|wx.ALIGN_CENTER_VERTICAL, 0) 
110          self.parent.Bind(wx.EVT_BUTTON, self.select_file, button) 
111   
112           
113          if preview: 
114               
115              sub_sizer.AddSpacer(width_spacer) 
116   
117               
118              button = wx.BitmapButton(self.parent, -1, wx.Bitmap(fetch_icon('oxygen.actions.document-preview', "16x16"), wx.BITMAP_TYPE_ANY)) 
119              button.SetMinSize((height_element, height_element)) 
120              button.SetToolTipString("Preview") 
121              sub_sizer.Add(button, 0, wx.ADJUST_MINSIZE|wx.ALIGN_CENTER_VERTICAL, 0) 
122              self.parent.Bind(wx.EVT_BUTTON, self.preview_file, button) 
123   
124           
125          sub_sizer.AddSpacer(padding) 
126   
127           
128          self.sizer.Add(sub_sizer, 1, wx.ALL|wx.EXPAND, 0) 
129   
130           
131          self.sizer.AddSpacer(height_spacer) 
 132   
133   
135          """Return the file name. 
136   
137          @return:    The file name. 
138          @rtype:     str 
139          """ 
140   
141           
142          return gui_to_str(self.field.GetValue()) 
 143   
144   
146          """Set up the list of file. 
147   
148          @param value:   The list of values to add to the list. 
149          @type value:    list of str or None 
150          """ 
151   
152           
153          self.field.SetValue(str_to_gui(value)) 
 154   
155   
157          """Preview a file. 
158   
159          @keyword event: The wx event. 
160          @type event:    wx event 
161          """ 
162   
163           
164          file = gui_to_str(self.field.GetValue()) 
165   
166           
167          if file == None: 
168              return 
169   
170           
171          open_file(file, force_text=True) 
 172   
173   
175          """Select a file. 
176   
177          @keyword event: The wx event. 
178          @type event:    wx event 
179          """ 
180   
181           
182          dialog = RelaxFileDialog(self.parent, field=self.field, message="File selection", defaultFile=self.default, wildcard=self.wildcard, style=self.style) 
183   
184           
185          if status.show_gui: 
186              dialog.select_event(event) 
  187   
188   
189   
191      """Wizard GUI element for selecting files.""" 
192   
193 -    def __init__(self, name=None, default=None, parent=None, sizer=None, desc=None, message='File selection', wildcard=wx.FileSelectorDefaultWildcardStr, style=wx.FD_DEFAULT_STYLE, tooltip=None, divider=None, padding=0, spacer=None, height_element=27, preview=True, read_only=False): 
 194          """Build the file selection element. 
195   
196          @keyword name:              The name of the element to use in titles, etc. 
197          @type name:                 str 
198          @keyword default:           The default value of the element. 
199          @type default:              str 
200          @keyword parent:            The wizard GUI element. 
201          @type parent:               wx.Panel instance 
202          @keyword sizer:             The sizer to put the input field into. 
203          @type sizer:                wx.Sizer instance 
204          @keyword desc:              The text description. 
205          @type desc:                 str 
206          @keyword message:           The file selector prompt string. 
207          @type message:              String 
208          @keyword wildcard:          The file wildcard pattern.  For example for opening PDB files, this could be "PDB files (*.pdb)|*.pdb;*.PDB". 
209          @type wildcard:             String 
210          @keyword style:             The dialog style.  To open a single file, set to wx.FD_OPEN.  To open multiple files, set to wx.FD_OPEN|wx.FD_MULTIPLE.  To save a single file, set to wx.FD_SAVE.  To save multiple files, set to wx.FD_SAVE|wx.FD_MULTIPLE. 
211          @type style:                long 
212          @keyword tooltip:           The tooltip which appears on hovering over all the GUI elements. 
213          @type tooltip:              str 
214          @keyword divider:           The position of the divider. 
215          @type divider:              int 
216          @keyword padding:           Spacing to the left and right of the widgets. 
217          @type padding:              int 
218          @keyword spacer:            The amount of spacing to add below the field in pixels.  If None, a stretchable spacer will be used. 
219          @type spacer:               None or int 
220          @keyword height_element:    The height in pixels of the GUI element. 
221          @type height_element:       int 
222          @keyword preview:           A flag which if true will allow the file to be previewed. 
223          @type preview:              bool 
224          @keyword read_only:         A flag which if True means that the text of the element cannot be edited. 
225          @type read_only:            bool 
226          """ 
227   
228           
229          self.name = name 
230   
231           
232          if default == None: 
233              default = wx.EmptyString 
234   
235           
236          sub_sizer = wx.BoxSizer(wx.HORIZONTAL) 
237   
238           
239          sub_sizer.AddSpacer(padding) 
240   
241           
242          text = wx.StaticText(parent, -1, desc, style=wx.ALIGN_LEFT) 
243          text.SetFont(font.normal) 
244          sub_sizer.Add(text, 0, wx.LEFT|wx.ALIGN_CENTER_VERTICAL, 0) 
245   
246           
247          if not divider: 
248              raise RelaxError("The divider position has not been supplied.") 
249   
250           
251          x, y = text.GetSize() 
252          sub_sizer.AddSpacer((divider - x, 0)) 
253   
254           
255          self._field = wx.TextCtrl(parent, -1, default) 
256          self._field.SetMinSize((-1, height_element)) 
257          self._field.SetFont(font.normal) 
258          sub_sizer.Add(self._field, 1, wx.ADJUST_MINSIZE|wx.ALIGN_CENTER_VERTICAL, 0) 
259   
260           
261          obj = RelaxFileDialog(parent, field=self._field, message=message, defaultFile=default, wildcard=wildcard, style=style) 
262   
263           
264          sub_sizer.AddSpacer(5) 
265   
266           
267          button = wx.BitmapButton(parent, -1, wx.Bitmap(fetch_icon('oxygen.actions.document-open', "16x16"), wx.BITMAP_TYPE_ANY)) 
268          button.SetMinSize((height_element, height_element)) 
269          button.SetToolTipString("Select the file.") 
270          sub_sizer.Add(button, 0, wx.ADJUST_MINSIZE|wx.ALIGN_CENTER_VERTICAL, 0) 
271          parent.Bind(wx.EVT_BUTTON, obj.select_event, button) 
272   
273           
274          if preview: 
275               
276              sub_sizer.AddSpacer(5) 
277   
278               
279              button = wx.BitmapButton(parent, -1, wx.Bitmap(fetch_icon('oxygen.actions.document-preview', "16x16"), wx.BITMAP_TYPE_ANY)) 
280              button.SetMinSize((height_element, height_element)) 
281              button.SetToolTipString("Preview") 
282              sub_sizer.Add(button, 0, wx.ADJUST_MINSIZE|wx.ALIGN_CENTER_VERTICAL, 0) 
283              parent.Bind(wx.EVT_BUTTON, self.preview_file, button) 
284   
285           
286          sub_sizer.AddSpacer(padding) 
287   
288           
289          sizer.Add(sub_sizer, 1, wx.EXPAND|wx.ALL, 0) 
290   
291           
292          if spacer == None: 
293              sizer.AddStretchSpacer() 
294          else: 
295              sizer.AddSpacer(spacer) 
296   
297           
298          if tooltip: 
299              text.SetToolTipString(tooltip) 
300              self._field.SetToolTipString(tooltip) 
 301   
302   
304          """Special method for clearing or resetting the GUI element.""" 
305   
306           
307          self._field.Clear() 
 308   
309   
311          """Special method for returning the value of the GUI element. 
312   
313          @return:    The string value. 
314          @rtype:     list of str 
315          """ 
316   
317           
318          return gui_to_str(self._field.GetValue()) 
 319   
320   
322          """Special method for setting the value of the GUI element. 
323   
324          @param value:   The value to set. 
325          @type value:    str 
326          """ 
327   
328           
329          self._field.SetValue(str_to_gui(value)) 
 330   
331   
333          """Preview a file. 
334   
335          @keyword event: The wx event. 
336          @type event:    wx event 
337          """ 
338   
339           
340          file = gui_to_str(self._field.GetValue()) 
341   
342           
343          if file == None: 
344              return 
345   
346           
347          open_file(file, force_text=True) 
  348   
349   
350   
352      """Wizard GUI element for selecting files.""" 
353   
354 -    def __init__(self, name=None, default=None, parent=None, sizer=None, desc=None, message='File selection', wildcard=wx.FileSelectorDefaultWildcardStr, style=wx.FD_DEFAULT_STYLE, tooltip=None, divider=None, padding=0, spacer=None, height_element=27, preview=True, read_only=False, can_be_none=False): 
 355          """Build the file selection element. 
356   
357          @keyword name:              The name of the element to use in titles, etc. 
358          @type name:                 str 
359          @keyword default:           The default value of the element. 
360          @type default:              str 
361          @keyword parent:            The wizard GUI element. 
362          @type parent:               wx.Panel instance 
363          @keyword sizer:             The sizer to put the input field into. 
364          @type sizer:                wx.Sizer instance 
365          @keyword desc:              The text description. 
366          @type desc:                 str 
367          @keyword message:           The file selector prompt string. 
368          @type message:              String 
369          @keyword wildcard:          The file wildcard pattern.  For example for opening PDB files, this could be "PDB files (*.pdb)|*.pdb;*.PDB". 
370          @type wildcard:             String 
371          @keyword style:             The dialog style.  To open a single file, set to wx.FD_OPEN.  To open multiple files, set to wx.FD_OPEN|wx.FD_MULTIPLE.  To save a single file, set to wx.FD_SAVE.  To save multiple files, set to wx.FD_SAVE|wx.FD_MULTIPLE. 
372          @type style:                long 
373          @keyword tooltip:           The tooltip which appears on hovering over all the GUI elements. 
374          @type tooltip:              str 
375          @keyword divider:           The position of the divider. 
376          @type divider:              int 
377          @keyword padding:           Spacing to the left and right of the widgets. 
378          @type padding:              int 
379          @keyword spacer:            The amount of spacing to add below the field in pixels.  If None, a stretchable spacer will be used. 
380          @type spacer:               None or int 
381          @keyword height_element:    The height in pixels of the GUI element. 
382          @type height_element:       int 
383          @keyword preview:           A flag which if true will allow the file to be previewed. 
384          @type preview:              bool 
385          @keyword read_only:         A flag which if True means that the text of the element cannot be edited. 
386          @type read_only:            bool 
387          @keyword can_be_none:       A flag which specifies if the element is allowed to have the None value. 
388          @type can_be_none:          bool 
389          """ 
390   
391           
392          self.name = name 
393          self.parent = parent 
394          self.can_be_none = can_be_none 
395   
396           
397          if default == None: 
398              default = wx.EmptyString 
399   
400           
401          sub_sizer = wx.BoxSizer(wx.HORIZONTAL) 
402   
403           
404          sub_sizer.AddSpacer(padding) 
405   
406           
407          text = wx.StaticText(parent, -1, desc, style=wx.ALIGN_LEFT) 
408          text.SetFont(font.normal) 
409          sub_sizer.Add(text, 0, wx.LEFT|wx.ALIGN_CENTER_VERTICAL, 0) 
410   
411           
412          if not divider: 
413              raise RelaxError("The divider position has not been supplied.") 
414   
415           
416          x, y = text.GetSize() 
417          sub_sizer.AddSpacer((divider - x, 0)) 
418   
419           
420          self._field = wx.TextCtrl(parent, -1, default) 
421          self._field.SetMinSize((-1, height_element)) 
422          self._field.SetFont(font.normal) 
423          sub_sizer.Add(self._field, 1, wx.ADJUST_MINSIZE|wx.ALIGN_CENTER_VERTICAL, 0) 
424   
425           
426          obj = RelaxFileDialog(parent, field=self._field, message=message, defaultFile=default, wildcard=wildcard, style=style) 
427   
428           
429          sub_sizer.AddSpacer(5) 
430   
431           
432          button = wx.BitmapButton(parent, -1, wx.Bitmap(fetch_icon('oxygen.actions.document-open', "16x16"), wx.BITMAP_TYPE_ANY)) 
433          button.SetMinSize((height_element, height_element)) 
434          button.SetToolTipString("Choose the file(s).") 
435          sub_sizer.Add(button, 0, wx.ADJUST_MINSIZE|wx.ALIGN_CENTER_VERTICAL, 0) 
436          parent.Bind(wx.EVT_BUTTON, self.open_dialog, button) 
437   
438           
439          sub_sizer.AddSpacer(padding) 
440   
441           
442          sizer.Add(sub_sizer, 1, wx.EXPAND|wx.ALL, 0) 
443   
444           
445          if spacer == None: 
446              sizer.AddStretchSpacer() 
447          else: 
448              sizer.AddSpacer(spacer) 
449   
450           
451          if tooltip: 
452              text.SetToolTipString(tooltip) 
453              self._field.SetToolTipString(tooltip) 
 454   
455   
457          """Special method for clearing or resetting the GUI element.""" 
458   
459           
460          self._field.Clear() 
 461   
462   
510   
511   
513          """Special method for setting the value of the GUI element. 
514   
515          @param value:   The value to set. 
516          @type value:    str 
517          """ 
518   
519           
520          if isinstance(value, list) and len(value) == 1: 
521              value = value[0] 
522   
523           
524          self._field.SetValue(list_to_gui(value)) 
 525   
526   
528          """Open a special dialog for inputting a list of text values. 
529   
530          @param event:   The wx event. 
531          @type event:    wx event 
532          """ 
533   
534           
535          self.selection_win_show() 
536   
537           
538          self.selection_win_data() 
539   
540           
541          del self.sel_win 
 542   
543   
545          """Preview a file. 
546   
547          @keyword event: The wx event. 
548          @type event:    wx event 
549          """ 
550   
551           
552          file = gui_to_str(self._field.GetValue()) 
553   
554           
555          if file == None: 
556              return 
557   
558           
559          open_file(file, force_text=True) 
 560   
561   
563          """Extract the data from the file list selection window.""" 
564   
565           
566          value = self.sel_win.GetValue() 
567   
568           
569          if not len(value): 
570              self.Clear() 
571   
572           
573          else: 
574              self.SetValue(value) 
 575   
576   
 590   
591   
592   
594      """The file list selection window.""" 
595   
596       
597      SIZE = (800, 600) 
598   
599       
600      BORDER = 10 
601   
602       
603      SIZE_BUTTON = (150, 33) 
604   
605 -    def __init__(self, parent=None, name='', spacing=10): 
 606          """Set up the file list selection window. 
607   
608          @keyword parent:    The parent GUI element. 
609          @type parent:       wx.Window instance or None 
610          @keyword name:      The name of the window. 
611          @type name:         str 
612          @keyword spacing:   The spacing between elements in pixels. 
613          @type spacing:      int 
614          """ 
615   
616           
617          self.name = name 
618          self.spacing = spacing 
619   
620           
621          title = "Multiple %s selection." % name 
622   
623           
624          wx.Dialog.__init__(self, parent, id=-1, title=title) 
625   
626           
627          self.width = self.SIZE[0] - 2*self.BORDER 
628   
629           
630          self.SetSize(self.SIZE) 
631          self.Centre() 
632          self.SetFont(font.normal) 
633   
634           
635          main_sizer = wx.BoxSizer(wx.VERTICAL) 
636   
637           
638          self.SetSizer(main_sizer) 
639   
640           
641          sizer = add_border(main_sizer, border=self.BORDER, packing=wx.VERTICAL) 
642   
643           
644          self.add_file_list(sizer) 
645   
646           
647          sizer.AddSpacer(self.BORDER) 
648   
649           
650          self.add_buttons(sizer) 
651   
652           
653          self.elements = [] 
654          self.add_element() 
 655   
656   
658          """Return the file names as a list. 
659   
660          @return:    The list of file names. 
661          @rtype:     list of str 
662          """ 
663   
664           
665          values = [] 
666   
667           
668          for i in range(len(self.elements)): 
669              values.append(self.elements[i].GetValue()) 
670   
671           
672          return values 
 673   
674   
676          """Set up the list of file names. 
677   
678          @param values:  The list of file names to add. 
679          @type values:   list of str or None 
680          """ 
681   
682           
683          if values == None: 
684              return 
685   
686           
687          if isinstance(values, str): 
688              values = [values] 
689   
690           
691          self.delete_all() 
692   
693           
694          for i in range(len(values)): 
695               
696              if i == 0: 
697                  self.elements[0].SetValue(values[i]) 
698   
699               
700              else: 
701                  self.add_element(path=values[i]) 
 702   
703   
758   
759   
761          """Add a new file selection element to the list. 
762   
763          @keyword event:     The wx event. 
764          @type event:        wx event 
765          @keyword path:      The file path to set the element value to. 
766          @type path:         str or None 
767          """ 
768   
769           
770          element = File_element(parent=self.panel, index=len(self.elements)) 
771   
772           
773          if path != None: 
774              element.SetValue(path) 
775   
776           
777          self.element_sizer.Add(element.sizer, 0, wx.ALL|wx.EXPAND, 0) 
778   
779           
780          self.elements.append(element) 
781   
782           
783          self.panel.SetupScrolling(scroll_x=False, scroll_y=True) 
784   
785           
786          self.panel.Layout() 
 787   
788   
790          """Initialise the control. 
791   
792          @param sizer:       A sizer object. 
793          @type sizer:        wx.Sizer instance 
794          """ 
795   
796           
797          self.panel = scrolledpanel.ScrolledPanel(self, -1, name="file list") 
798   
799           
800          panel_sizer = wx.BoxSizer(wx.VERTICAL) 
801   
802           
803          title = "File list" 
804          text = wx.StaticText(self.panel, -1, title, style=wx.TE_MULTILINE) 
805          text.SetFont(font.subtitle) 
806          panel_sizer.Add(text, 0, wx.ALIGN_LEFT, 0) 
807          panel_sizer.AddSpacer(self.spacing) 
808   
809           
810          self.element_sizer = wx.BoxSizer(wx.VERTICAL) 
811          panel_sizer.Add(self.element_sizer, 1, wx.ALL|wx.EXPAND, 0) 
812   
813           
814          self.panel.SetSizer(panel_sizer) 
815          self.panel.SetAutoLayout(1) 
816          self.panel.SetupScrolling(scroll_x=False, scroll_y=True) 
817          sizer.Add(self.panel, 1, wx.ALL|wx.EXPAND, 0) 
 818   
819   
821          """Close the window. 
822   
823          @param event:   The wx event. 
824          @type event:    wx event 
825          """ 
826   
827           
828          self.Close() 
 829   
830   
831 -    def delete(self, event=None): 
 832          """Remove the last file selection item from the list. 
833   
834          @keyword event: The wx event. 
835          @type event:    wx event 
836          """ 
837   
838           
839          self.elements[-1].sizer.DeleteWindows() 
840          self.element_sizer.Remove(self.elements[-1].sizer) 
841   
842           
843          self.elements.pop() 
844   
845           
846          if not len(self.elements): 
847              self.add_element() 
848   
849           
850          self.panel.Layout() 
 851   
852   
854          """Remove all file selection items from the list. 
855   
856          @keyword event: The wx event. 
857          @type event:    wx event 
858          """ 
859   
860           
861          for i in range(len(self.elements)): 
862              self.elements[i].sizer.DeleteWindows() 
863              self.element_sizer.Remove(self.elements[i].sizer) 
864   
865           
866          del self.elements 
867   
868           
869          self.elements = [] 
870          self.add_element() 
871   
872           
873          self.panel.Layout() 
  874