"Fossies" - the Fresh Open Source Software Archive

Member "relax-5.0.0/gui/input_elements/file.py" (2 Dec 2019, 31573 Bytes) of package /linux/privat/relax-5.0.0.src.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. For more information about "file.py" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 4.1.3_vs_5.0.0.

    1 ###############################################################################
    2 #                                                                             #
    3 # Copyright (C) 2012,2014,2016,2019 Edward d'Auvergne                         #
    4 #                                                                             #
    5 # This file is part of the program relax (http://www.nmr-relax.com).          #
    6 #                                                                             #
    7 # This program is free software: you can redistribute it and/or modify        #
    8 # it under the terms of the GNU General Public License as published by        #
    9 # the Free Software Foundation, either version 3 of the License, or           #
   10 # (at your option) any later version.                                         #
   11 #                                                                             #
   12 # This program is distributed in the hope that it will be useful,             #
   13 # but WITHOUT ANY WARRANTY; without even the implied warranty of              #
   14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               #
   15 # GNU General Public License for more details.                                #
   16 #                                                                             #
   17 # You should have received a copy of the GNU General Public License           #
   18 # along with this program.  If not, see <http://www.gnu.org/licenses/>.       #
   19 #                                                                             #
   20 ###############################################################################
   21 
   22 # Module docstring.
   23 """Module containing a set of special GUI elements to be used in the relax wizards."""
   24 
   25 # Python module imports.
   26 import wx
   27 from wx.lib import scrolledpanel
   28 import wx.lib.mixins.listctrl
   29 
   30 # relax module imports.
   31 import dep_check
   32 from graphics import fetch_icon
   33 from gui.filedialog import RelaxFileDialog
   34 from gui.fonts import font
   35 from gui.misc import add_border, open_file
   36 from gui.string_conv import gui_to_list, gui_to_str, list_to_gui, str_to_gui
   37 from lib.errors import RelaxError
   38 from status import Status; status = Status()
   39 
   40 
   41 class File_element:
   42     """A single file element for the multiple file input GUI element."""
   43 
   44     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):
   45         """Set up the file GUI element.
   46 
   47         @keyword default:           The default value of the element.
   48         @type default:              str
   49         @keyword parent:            The parent GUI element.
   50         @type parent:               wx.Panel instance
   51         @keyword index:             The index of the file element, to display its sequence number in the GUI element.
   52         @type index:                int
   53         @keyword wildcard:          The file wildcard pattern.  For example for opening PDB files, this could be "PDB files (*.pdb)|*.pdb;*.PDB".
   54         @type wildcard:             String
   55         @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.
   56         @type style:                long
   57         @keyword padding:           Spacing to the left and right of the widgets.
   58         @type padding:              int
   59         @keyword height_spacer:     The amount of spacing to add below the field in pixels.
   60         @type height_spacer:        int
   61         @keyword width_spacer:      The amount of spacing to add horizontally between the TextCtrl and buttons in pixels.
   62         @type width_spacer:         int
   63         @keyword height_element:    The height in pixels of the GUI element.
   64         @type height_element:       int
   65         @keyword preview:           A flag which if true will allow the file to be previewed.
   66         @type preview:              bool
   67         @keyword can_be_none:       A flag which specifies if the element is allowed to have the None value.
   68         @type can_be_none:          bool
   69         """
   70 
   71         # Store the arguments.
   72         self.default = default
   73         self.parent = parent
   74         self.wildcard = wildcard
   75         self.style = style
   76         self.can_be_none = can_be_none
   77 
   78         # A vertical sizer for the two elements of the file selection GUI elements and a spacer element.
   79         self.sizer = wx.BoxSizer(wx.VERTICAL)
   80 
   81         # Create a sizer for the elements.
   82         sub_sizer = wx.BoxSizer(wx.HORIZONTAL)
   83 
   84         # Left padding.
   85         sub_sizer.AddSpacer(padding)
   86 
   87         # The file index.
   88         desc = str_to_gui("%i:  " % (index+1))
   89         text = wx.StaticText(self.parent, -1, desc, style=wx.ALIGN_LEFT)
   90         text.SetFont(font.normal_bold)
   91         text.SetMinSize((35, -1))
   92         sub_sizer.Add(text, 0, wx.LEFT|wx.ALIGN_CENTER_VERTICAL|wx.ADJUST_MINSIZE, 0)
   93 
   94         # A little spacing.
   95         sub_sizer.AddSpacer(width_spacer)
   96 
   97         # The input field.
   98         self.field = wx.TextCtrl(self.parent, -1, self.default)
   99         self.field.SetMinSize((-1, height_element))
  100         self.field.SetFont(font.normal)
  101         sub_sizer.Add(self.field, 1, wx.EXPAND|wx.ADJUST_MINSIZE|wx.ALIGN_CENTER_VERTICAL, 0)
  102 
  103         # A little spacing.
  104         sub_sizer.AddSpacer(width_spacer)
  105 
  106         # The file selection button.
  107         button = wx.BitmapButton(self.parent, -1, wx.Bitmap(fetch_icon('oxygen.actions.document-open', "16x16"), wx.BITMAP_TYPE_ANY))
  108         button.SetMinSize((height_element, height_element))
  109         button.SetToolTip(wx.ToolTip("Select the file."))
  110         sub_sizer.Add(button, 0, wx.ADJUST_MINSIZE|wx.ALIGN_CENTER_VERTICAL, 0)
  111         self.parent.Bind(wx.EVT_BUTTON, self.select_file, button)
  112 
  113         # File preview.
  114         if preview:
  115             # A little spacing.
  116             sub_sizer.AddSpacer(width_spacer)
  117 
  118             # The preview button.
  119             button = wx.BitmapButton(self.parent, -1, wx.Bitmap(fetch_icon('oxygen.actions.document-preview', "16x16"), wx.BITMAP_TYPE_ANY))
  120             button.SetMinSize((height_element, height_element))
  121             button.SetToolTip(wx.ToolTip("Preview"))
  122             sub_sizer.Add(button, 0, wx.ADJUST_MINSIZE|wx.ALIGN_CENTER_VERTICAL, 0)
  123             self.parent.Bind(wx.EVT_BUTTON, self.preview_file, button)
  124 
  125         # Right padding.
  126         sub_sizer.AddSpacer(padding)
  127 
  128         # Add the sizer to the main sizer.
  129         self.sizer.Add(sub_sizer, 1, wx.ALL|wx.EXPAND, 0)
  130 
  131         # Add spacing.
  132         self.sizer.AddSpacer(height_spacer)
  133 
  134 
  135     def GetValue(self):
  136         """Return the file name.
  137 
  138         @return:    The file name.
  139         @rtype:     str
  140         """
  141 
  142         # Return the current value.
  143         return gui_to_str(self.field.GetValue())
  144 
  145 
  146     def SetValue(self, value):
  147         """Set up the list of file.
  148 
  149         @param value:   The list of values to add to the list.
  150         @type value:    list of str or None
  151         """
  152 
  153         # Set the value.
  154         self.field.SetValue(str_to_gui(value))
  155 
  156 
  157     def preview_file(self, event=None):
  158         """Preview a file.
  159 
  160         @keyword event: The wx event.
  161         @type event:    wx event
  162         """
  163 
  164         # The file name.
  165         file = gui_to_str(self.field.GetValue())
  166 
  167         # No file, so do nothing.
  168         if file == None:
  169             return
  170 
  171         # Open the file as text.
  172         open_file(file, force_text=True)
  173 
  174 
  175     def select_file(self, event=None):
  176         """Select a file.
  177 
  178         @keyword event: The wx event.
  179         @type event:    wx event
  180         """
  181 
  182         # The file selection object (initialised in this function and not __init__() so that the working directory is more logical).
  183         dialog = RelaxFileDialog(self.parent, field=self.field, message="File selection", defaultFile=self.default, wildcard=self.wildcard, style=self.style)
  184 
  185         # Show the dialog and catch if no file has been selected.
  186         if status.show_gui:
  187             dialog.select_event(event)
  188 
  189 
  190 
  191 class Selector_file:
  192     """Wizard GUI element for selecting files."""
  193 
  194     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):
  195         """Build the file selection element.
  196 
  197         @keyword name:              The name of the element to use in titles, etc.
  198         @type name:                 str
  199         @keyword default:           The default value of the element.
  200         @type default:              str
  201         @keyword parent:            The wizard GUI element.
  202         @type parent:               wx.Panel instance
  203         @keyword sizer:             The sizer to put the input field into.
  204         @type sizer:                wx.Sizer instance
  205         @keyword desc:              The text description.
  206         @type desc:                 str
  207         @keyword message:           The file selector prompt string.
  208         @type message:              String
  209         @keyword wildcard:          The file wildcard pattern.  For example for opening PDB files, this could be "PDB files (*.pdb)|*.pdb;*.PDB".
  210         @type wildcard:             String
  211         @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.
  212         @type style:                long
  213         @keyword tooltip:           The tooltip which appears on hovering over all the GUI elements.
  214         @type tooltip:              str
  215         @keyword divider:           The position of the divider.
  216         @type divider:              int
  217         @keyword padding:           Spacing to the left and right of the widgets.
  218         @type padding:              int
  219         @keyword spacer:            The amount of spacing to add below the field in pixels.  If None, a stretchable spacer will be used.
  220         @type spacer:               None or int
  221         @keyword height_element:    The height in pixels of the GUI element.
  222         @type height_element:       int
  223         @keyword preview:           A flag which if true will allow the file to be previewed.
  224         @type preview:              bool
  225         @keyword read_only:         A flag which if True means that the text of the element cannot be edited.
  226         @type read_only:            bool
  227         """
  228 
  229         # Store the args.
  230         self.name = name
  231 
  232         # Argument translation.
  233         if default == None:
  234             default = wx.EmptyString
  235 
  236         # Init.
  237         sub_sizer = wx.BoxSizer(wx.HORIZONTAL)
  238 
  239         # Left padding.
  240         sub_sizer.AddSpacer(padding)
  241 
  242         # The description.
  243         text = wx.StaticText(parent, -1, desc, style=wx.ALIGN_LEFT)
  244         text.SetFont(font.normal)
  245         sub_sizer.Add(text, 0, wx.LEFT|wx.ALIGN_CENTER_VERTICAL, 0)
  246 
  247         # The divider.
  248         if not divider:
  249             raise RelaxError("The divider position has not been supplied.")
  250 
  251         # Spacing.
  252         x, y = text.GetSize()
  253         if dep_check.wx_classic:
  254             sub_sizer.AddSpacer((divider - x, 0))
  255         else:
  256             sub_sizer.AddSpacer(divider - x)
  257 
  258         # The input field.
  259         self._field = wx.TextCtrl(parent, -1, default)
  260         self._field.SetMinSize((-1, height_element))
  261         self._field.SetFont(font.normal)
  262         sub_sizer.Add(self._field, 1, wx.ADJUST_MINSIZE|wx.ALIGN_CENTER_VERTICAL, 0)
  263 
  264         # The file selection object.
  265         obj = RelaxFileDialog(parent, field=self._field, message=message, defaultFile=default, wildcard=wildcard, style=style)
  266 
  267         # A little spacing.
  268         sub_sizer.AddSpacer(5)
  269 
  270         # The file selection button.
  271         button = wx.BitmapButton(parent, -1, wx.Bitmap(fetch_icon('oxygen.actions.document-open', "16x16"), wx.BITMAP_TYPE_ANY))
  272         button.SetMinSize((height_element, height_element))
  273         button.SetToolTip(wx.ToolTip("Select the file."))
  274         sub_sizer.Add(button, 0, wx.ADJUST_MINSIZE|wx.ALIGN_CENTER_VERTICAL, 0)
  275         parent.Bind(wx.EVT_BUTTON, obj.select_event, button)
  276 
  277         # File preview.
  278         if preview:
  279             # A little spacing.
  280             sub_sizer.AddSpacer(5)
  281 
  282             # The preview button.
  283             button = wx.BitmapButton(parent, -1, wx.Bitmap(fetch_icon('oxygen.actions.document-preview', "16x16"), wx.BITMAP_TYPE_ANY))
  284             button.SetMinSize((height_element, height_element))
  285             button.SetToolTip(wx.ToolTip("Preview"))
  286             sub_sizer.Add(button, 0, wx.ADJUST_MINSIZE|wx.ALIGN_CENTER_VERTICAL, 0)
  287             parent.Bind(wx.EVT_BUTTON, self.preview_file, button)
  288 
  289         # Right padding.
  290         sub_sizer.AddSpacer(padding)
  291 
  292         # Add to the main sizer (followed by stretchable spacing).
  293         sizer.Add(sub_sizer, 1, wx.EXPAND|wx.ALL, 0)
  294 
  295         # Spacing below the widget.
  296         if spacer == None:
  297             sizer.AddStretchSpacer()
  298         else:
  299             sizer.AddSpacer(spacer)
  300 
  301         # Tooltip.
  302         if tooltip:
  303             text.SetToolTip(wx.ToolTip(tooltip))
  304             self._field.SetToolTip(wx.ToolTip(tooltip))
  305 
  306 
  307     def Clear(self):
  308         """Special method for clearing or resetting the GUI element."""
  309 
  310         # Clear the value from the TextCtrl.
  311         self._field.Clear()
  312 
  313 
  314     def GetValue(self):
  315         """Special method for returning the value of the GUI element.
  316 
  317         @return:    The string value.
  318         @rtype:     list of str
  319         """
  320 
  321         # Convert and return the value from a TextCtrl.
  322         return gui_to_str(self._field.GetValue())
  323 
  324 
  325     def SetValue(self, value):
  326         """Special method for setting the value of the GUI element.
  327 
  328         @param value:   The value to set.
  329         @type value:    str
  330         """
  331 
  332         # Convert and set the value for a TextCtrl.
  333         self._field.SetValue(str_to_gui(value))
  334 
  335 
  336     def preview_file(self, event=None):
  337         """Preview a file.
  338 
  339         @keyword event: The wx event.
  340         @type event:    wx event
  341         """
  342 
  343         # The file name.
  344         file = gui_to_str(self._field.GetValue())
  345 
  346         # No file, so do nothing.
  347         if file == None:
  348             return
  349 
  350         # Open the file as text.
  351         open_file(file, force_text=True)
  352 
  353 
  354 
  355 class Selector_file_multiple:
  356     """Wizard GUI element for selecting files."""
  357 
  358     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):
  359         """Build the file selection element.
  360 
  361         @keyword name:              The name of the element to use in titles, etc.
  362         @type name:                 str
  363         @keyword default:           The default value of the element.
  364         @type default:              str
  365         @keyword parent:            The wizard GUI element.
  366         @type parent:               wx.Panel instance
  367         @keyword sizer:             The sizer to put the input field into.
  368         @type sizer:                wx.Sizer instance
  369         @keyword desc:              The text description.
  370         @type desc:                 str
  371         @keyword message:           The file selector prompt string.
  372         @type message:              String
  373         @keyword wildcard:          The file wildcard pattern.  For example for opening PDB files, this could be "PDB files (*.pdb)|*.pdb;*.PDB".
  374         @type wildcard:             String
  375         @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.
  376         @type style:                long
  377         @keyword tooltip:           The tooltip which appears on hovering over all the GUI elements.
  378         @type tooltip:              str
  379         @keyword divider:           The position of the divider.
  380         @type divider:              int
  381         @keyword padding:           Spacing to the left and right of the widgets.
  382         @type padding:              int
  383         @keyword spacer:            The amount of spacing to add below the field in pixels.  If None, a stretchable spacer will be used.
  384         @type spacer:               None or int
  385         @keyword height_element:    The height in pixels of the GUI element.
  386         @type height_element:       int
  387         @keyword preview:           A flag which if true will allow the file to be previewed.
  388         @type preview:              bool
  389         @keyword read_only:         A flag which if True means that the text of the element cannot be edited.
  390         @type read_only:            bool
  391         @keyword can_be_none:       A flag which specifies if the element is allowed to have the None value.
  392         @type can_be_none:          bool
  393         """
  394 
  395         # Store the args.
  396         self.name = name
  397         self.parent = parent
  398         self.can_be_none = can_be_none
  399 
  400         # Argument translation.
  401         if default == None:
  402             default = wx.EmptyString
  403 
  404         # Init.
  405         sub_sizer = wx.BoxSizer(wx.HORIZONTAL)
  406 
  407         # Left padding.
  408         sub_sizer.AddSpacer(padding)
  409 
  410         # The description.
  411         text = wx.StaticText(parent, -1, desc, style=wx.ALIGN_LEFT)
  412         text.SetFont(font.normal)
  413         sub_sizer.Add(text, 0, wx.LEFT|wx.ALIGN_CENTER_VERTICAL, 0)
  414 
  415         # The divider.
  416         if not divider:
  417             raise RelaxError("The divider position has not been supplied.")
  418 
  419         # Spacing.
  420         x, y = text.GetSize()
  421         if dep_check.wx_classic:
  422             sub_sizer.AddSpacer((divider - x, 0))
  423         else:
  424             sub_sizer.AddSpacer(divider - x)
  425 
  426         # The input field.
  427         self._field = wx.TextCtrl(parent, -1, default)
  428         self._field.SetMinSize((-1, height_element))
  429         self._field.SetFont(font.normal)
  430         sub_sizer.Add(self._field, 1, wx.ADJUST_MINSIZE|wx.ALIGN_CENTER_VERTICAL, 0)
  431 
  432         # The file selection object.
  433         obj = RelaxFileDialog(parent, field=self._field, message=message, defaultFile=default, wildcard=wildcard, style=style)
  434 
  435         # A little spacing.
  436         sub_sizer.AddSpacer(5)
  437 
  438         # The edit button.
  439         button = wx.BitmapButton(parent, -1, wx.Bitmap(fetch_icon('oxygen.actions.document-open', "16x16"), wx.BITMAP_TYPE_ANY))
  440         button.SetMinSize((height_element, height_element))
  441         button.SetToolTip(wx.ToolTip("Choose the file(s)."))
  442         sub_sizer.Add(button, 0, wx.ADJUST_MINSIZE|wx.ALIGN_CENTER_VERTICAL, 0)
  443         parent.Bind(wx.EVT_BUTTON, self.open_dialog, button)
  444 
  445         # Right padding.
  446         sub_sizer.AddSpacer(padding)
  447 
  448         # Add to the main sizer (followed by stretchable spacing).
  449         sizer.Add(sub_sizer, 1, wx.EXPAND|wx.ALL, 0)
  450 
  451         # Spacing below the widget.
  452         if spacer == None:
  453             sizer.AddStretchSpacer()
  454         else:
  455             sizer.AddSpacer(spacer)
  456 
  457         # Tooltip.
  458         if tooltip:
  459             text.SetToolTip(wx.ToolTip(tooltip))
  460             self._field.SetToolTip(wx.ToolTip(tooltip))
  461 
  462 
  463     def Clear(self):
  464         """Special method for clearing or resetting the GUI element."""
  465 
  466         # Clear the value from the TextCtrl.
  467         self._field.Clear()
  468 
  469 
  470     def GetValue(self):
  471         """Special method for returning the value of the GUI element.
  472 
  473         @return:    The string value.
  474         @rtype:     list of str
  475         """
  476 
  477         # The value.
  478         value = self._field.GetValue()
  479 
  480         # Handle single values.
  481         value_set = False
  482         try:
  483             # Convert.
  484             value = gui_to_str(value)
  485 
  486             # Check that the conversion was successful.
  487             if value == None and self.can_be_none:
  488                 value_set = True
  489             else:
  490                 if value[0] != '[':
  491                     value_set = True
  492         except:
  493             pass
  494 
  495         # Convert to a list, handling bad user behaviour.
  496         if not value_set:
  497             try:
  498                 value = gui_to_list(value)
  499 
  500             # Set the value to None or an empty sequence.
  501             except:
  502                 if self.can_be_none:
  503                     value = None
  504                 else:
  505                     value = []
  506 
  507         # Convert sequences to single values as needed.
  508         if isinstance(value, list) and len(value) == 1:
  509             value = value[0]
  510 
  511         # Handle empty list and tuple values.
  512         if len(value) == 0:
  513             return None
  514 
  515         # Return the value.
  516         return value
  517 
  518 
  519     def SetValue(self, value):
  520         """Special method for setting the value of the GUI element.
  521 
  522         @param value:   The value to set.
  523         @type value:    str
  524         """
  525 
  526         # Handle single values.
  527         if isinstance(value, list) and len(value) == 1:
  528             value = value[0]
  529 
  530         # Convert and set the value.
  531         self._field.SetValue(list_to_gui(value))
  532 
  533 
  534     def open_dialog(self, event):
  535         """Open a special dialog for inputting a list of text values.
  536 
  537         @param event:   The wx event.
  538         @type event:    wx event
  539         """
  540 
  541         # Show the window.
  542         self.selection_win_show()
  543 
  544         # Extract the data from the selection window once closed.
  545         self.selection_win_data()
  546 
  547         # Destroy the window.
  548         del self.sel_win
  549 
  550 
  551     def preview_file(self, event=None):
  552         """Preview a file.
  553 
  554         @keyword event: The wx event.
  555         @type event:    wx event
  556         """
  557 
  558         # The file name.
  559         file = gui_to_str(self._field.GetValue())
  560 
  561         # No file, so do nothing.
  562         if file == None:
  563             return
  564 
  565         # Open the file as text.
  566         open_file(file, force_text=True)
  567 
  568 
  569     def selection_win_data(self):
  570         """Extract the data from the file list selection window."""
  571 
  572         # Get the value.
  573         value = self.sel_win.GetValue()
  574 
  575         # No sequence data.
  576         if not len(value):
  577             self.Clear()
  578 
  579         # Set the values.
  580         else:
  581             self.SetValue(value)
  582 
  583 
  584     def selection_win_show(self):
  585         """Show the file list selection window."""
  586 
  587         # Initialise the model selection window.
  588         self.sel_win = Selector_file_window(parent=self.parent, name=self.name)
  589 
  590         # Set the model selector window selections.
  591         self.sel_win.SetValue(self.GetValue())
  592 
  593         # Show the model selector window.
  594         if status.show_gui:
  595             self.sel_win.ShowModal()
  596             self.sel_win.Close()
  597 
  598 
  599 
  600 class Selector_file_window(wx.Dialog):
  601     """The file list selection window."""
  602 
  603     # The window size.
  604     SIZE = (800, 600)
  605 
  606     # A border.
  607     BORDER = 10
  608 
  609     # Sizes.
  610     SIZE_BUTTON = (150, 33)
  611 
  612     def __init__(self, parent=None, name='', spacing=10):
  613         """Set up the file list selection window.
  614 
  615         @keyword parent:    The parent GUI element.
  616         @type parent:       wx.Window instance or None
  617         @keyword name:      The name of the window.
  618         @type name:         str
  619         @keyword spacing:   The spacing between elements in pixels.
  620         @type spacing:      int
  621         """
  622 
  623         # Store the args.
  624         self.name = name
  625         self.spacing = spacing
  626 
  627         # The title of the dialog.
  628         title = "Multiple %s selection." % name
  629 
  630         # Set up the dialog.
  631         wx.Dialog.__init__(self, parent, id=-1, title=title)
  632 
  633         # Initialise some values
  634         self.width = self.SIZE[0] - 2*self.BORDER
  635 
  636         # Set the frame properties.
  637         self.SetSize(self.SIZE)
  638         if not dep_check.wx_classic and status.show_gui:
  639             self.Centre()
  640         self.SetFont(font.normal)
  641 
  642         # The main box sizer.
  643         main_sizer = wx.BoxSizer(wx.VERTICAL)
  644 
  645         # Pack the sizer into the frame.
  646         self.SetSizer(main_sizer)
  647 
  648         # Build the central sizer, with borders.
  649         sizer = add_border(main_sizer, border=self.BORDER, packing=wx.VERTICAL)
  650 
  651         # Add the file list element.
  652         self.add_file_list(sizer)
  653 
  654         # Some spacing.
  655         sizer.AddSpacer(self.BORDER)
  656 
  657         # Add the bottom buttons.
  658         self.add_buttons(sizer)
  659 
  660         # Initialise the list of file selection elements to a single element.
  661         self.elements = []
  662         self.add_element()
  663 
  664 
  665     def GetValue(self):
  666         """Return the file names as a list.
  667 
  668         @return:    The list of file names.
  669         @rtype:     list of str
  670         """
  671 
  672         # Init.
  673         values = []
  674 
  675         # Loop over the entries.
  676         for i in range(len(self.elements)):
  677             values.append(self.elements[i].GetValue())
  678 
  679         # Return the file name list.
  680         return values
  681 
  682 
  683     def SetValue(self, values):
  684         """Set up the list of file names.
  685 
  686         @param values:  The list of file names to add.
  687         @type values:   list of str or None
  688         """
  689 
  690         # No value.
  691         if values == None:
  692             return
  693 
  694         # Single values.
  695         if isinstance(values, str):
  696             values = [values]
  697 
  698         # Reset the elements. 
  699         self.delete_all()
  700 
  701         # Loop over the file paths, creating the elements.
  702         for i in range(len(values)):
  703             # The first element already exists.
  704             if i == 0:
  705                 self.elements[0].SetValue(values[i])
  706 
  707             # Otherwise create a new element.
  708             else:
  709                 self.add_element(path=values[i])
  710 
  711 
  712     def add_buttons(self, sizer):
  713         """Add the buttons to the sizer.
  714 
  715         @param sizer:   A sizer object.
  716         @type sizer:    wx.Sizer instance
  717         """
  718 
  719         # Create a horizontal layout for the buttons.
  720         button_sizer = wx.BoxSizer(wx.HORIZONTAL)
  721         sizer.Add(button_sizer, 0, wx.ALIGN_CENTER|wx.ALL, 0)
  722 
  723         # The add button.
  724         button = wx.lib.buttons.ThemedGenBitmapTextButton(self, -1, None, "  Add")
  725         button.SetBitmapLabel(wx.Bitmap(fetch_icon('oxygen.actions.list-add-relax-blue', "22x22"), wx.BITMAP_TYPE_ANY))
  726         button.SetFont(font.normal)
  727         button.SetToolTip(wx.ToolTip("Add a file selection item to the list."))
  728         button.SetMinSize(self.SIZE_BUTTON)
  729         button_sizer.Add(button, 0, wx.ADJUST_MINSIZE, 0)
  730         self.Bind(wx.EVT_BUTTON, self.add_element, button)
  731 
  732         # Spacer.
  733         button_sizer.AddSpacer(20)
  734 
  735         # The delete button.
  736         button = wx.lib.buttons.ThemedGenBitmapTextButton(self, -1, None, "  Delete")
  737         button.SetBitmapLabel(wx.Bitmap(fetch_icon('oxygen.actions.list-remove', "22x22"), wx.BITMAP_TYPE_ANY))
  738         button.SetFont(font.normal)
  739         button.SetToolTip(wx.ToolTip("Delete the last file selection item."))
  740         button.SetMinSize(self.SIZE_BUTTON)
  741         button_sizer.Add(button, 0, wx.ADJUST_MINSIZE, 0)
  742         self.Bind(wx.EVT_BUTTON, self.delete, button)
  743 
  744         # Spacer.
  745         button_sizer.AddSpacer(20)
  746 
  747         # The delete all button.
  748         button = wx.lib.buttons.ThemedGenBitmapTextButton(self, -1, None, "  Delete all")
  749         button.SetBitmapLabel(wx.Bitmap(fetch_icon('oxygen.actions.edit-delete', "22x22"), wx.BITMAP_TYPE_ANY))
  750         button.SetFont(font.normal)
  751         button.SetToolTip(wx.ToolTip("Delete all items."))
  752         button.SetMinSize(self.SIZE_BUTTON)
  753         button_sizer.Add(button, 0, wx.ADJUST_MINSIZE, 0)
  754         self.Bind(wx.EVT_BUTTON, self.delete_all, button)
  755 
  756         # Spacer.
  757         button_sizer.AddSpacer(20)
  758 
  759         # The Ok button.
  760         button = wx.lib.buttons.ThemedGenBitmapTextButton(self, -1, None, "  Ok")
  761         button.SetBitmapLabel(wx.Bitmap(fetch_icon('oxygen.actions.dialog-ok', "22x22"), wx.BITMAP_TYPE_ANY))
  762         button.SetFont(font.normal)
  763         button.SetMinSize(self.SIZE_BUTTON)
  764         button_sizer.Add(button, 0, wx.ADJUST_MINSIZE, 0)
  765         self.Bind(wx.EVT_BUTTON, self.close, button)
  766 
  767 
  768     def add_element(self, event=None, path=None):
  769         """Add a new file selection element to the list.
  770 
  771         @keyword event:     The wx event.
  772         @type event:        wx event
  773         @keyword path:      The file path to set the element value to.
  774         @type path:         str or None
  775         """
  776 
  777         # Initialise the element.
  778         element = File_element(parent=self.panel, index=len(self.elements))
  779 
  780         # Set its value.
  781         if path != None:
  782             element.SetValue(path)
  783 
  784         # Add the element's sizer to the main element sizer.
  785         self.element_sizer.Add(element.sizer, 0, wx.ALL|wx.EXPAND, 0)
  786 
  787         # Store the element.
  788         self.elements.append(element)
  789 
  790         # Reinitialise the scrolling for the panel, just in case the number of elements is bigger than the window.
  791         self.panel.SetupScrolling(scroll_x=False, scroll_y=True)
  792 
  793         # Redraw.
  794         self.panel.Layout()
  795 
  796 
  797     def add_file_list(self, sizer):
  798         """Initialise the control.
  799 
  800         @param sizer:       A sizer object.
  801         @type sizer:        wx.Sizer instance
  802         """
  803 
  804         # Create a scrolled panel.
  805         self.panel = scrolledpanel.ScrolledPanel(self, -1, name="file list")
  806 
  807         # A sizer for the panel.
  808         panel_sizer = wx.BoxSizer(wx.VERTICAL)
  809 
  810         # Set the title.
  811         title = "File list"
  812         text = wx.StaticText(self.panel, -1, title, style=wx.TE_MULTILINE)
  813         text.SetFont(font.subtitle)
  814         panel_sizer.Add(text, 0, wx.ALIGN_LEFT, 0)
  815         panel_sizer.AddSpacer(self.spacing)
  816 
  817         # Create a sizer for the file selection elements.
  818         self.element_sizer = wx.BoxSizer(wx.VERTICAL)
  819         panel_sizer.Add(self.element_sizer, 1, wx.ALL|wx.EXPAND, 0)
  820 
  821         # Set up and add the panel to the sizer.
  822         self.panel.SetSizer(panel_sizer)
  823         self.panel.SetAutoLayout(1)
  824         self.panel.SetupScrolling(scroll_x=False, scroll_y=True)
  825         sizer.Add(self.panel, 1, wx.ALL|wx.EXPAND, 0)
  826 
  827 
  828     def close(self, event):
  829         """Close the window.
  830 
  831         @param event:   The wx event.
  832         @type event:    wx event
  833         """
  834 
  835         # Close the window.
  836         self.Close()
  837 
  838 
  839     def delete(self, event=None):
  840         """Remove the last file selection item from the list.
  841 
  842         @keyword event: The wx event.
  843         @type event:    wx event
  844         """
  845 
  846         # Destroy the last subsizer.
  847         self.elements[-1].sizer.Clear(True)
  848         self.element_sizer.Remove(self.elements[-1].sizer)
  849 
  850         # Destroy the Python structures.
  851         self.elements.pop()
  852 
  853         # If the list is empty, start again with a single blank element.
  854         if not len(self.elements):
  855             self.add_element()
  856 
  857         # Redraw.
  858         self.panel.Layout()
  859 
  860 
  861     def delete_all(self, event=None):
  862         """Remove all file selection items from the list.
  863 
  864         @keyword event: The wx event.
  865         @type event:    wx event
  866         """
  867 
  868         # Destroy the subsizer.
  869         for i in range(len(self.elements)):
  870             self.elements[i].sizer.Clear(True)
  871             self.element_sizer.Remove(self.elements[i].sizer)
  872 
  873         # Destroy all Python structures.
  874         del self.elements
  875 
  876         # Reset the elements, starting again with a single blank element.
  877         self.elements = []
  878         self.add_element()
  879 
  880         # Redraw.
  881         self.panel.Layout()