"Fossies" - the Fresh Open Source Software Archive

Member "relax-5.0.0/gui/misc.py" (2 Dec 2019, 11763 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 "misc.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) 2009-2010 Michael Bieri                                       #
    4 # Copyright (C) 2009-2012 Edward d'Auvergne                                   #
    5 #                                                                             #
    6 # This file is part of the program relax (http://www.nmr-relax.com).          #
    7 #                                                                             #
    8 # This program is free software: you can redistribute it and/or modify        #
    9 # it under the terms of the GNU General Public License as published by        #
   10 # the Free Software Foundation, either version 3 of the License, or           #
   11 # (at your option) any later version.                                         #
   12 #                                                                             #
   13 # This program is distributed in the hope that it will be useful,             #
   14 # but WITHOUT ANY WARRANTY; without even the implied warranty of              #
   15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               #
   16 # GNU General Public License for more details.                                #
   17 #                                                                             #
   18 # You should have received a copy of the GNU General Public License           #
   19 # along with this program.  If not, see <http://www.gnu.org/licenses/>.       #
   20 #                                                                             #
   21 ###############################################################################
   22 
   23 # Module docstring.
   24 """Miscellaneous functions used throughout the GUI."""
   25 
   26 # Python module imports.
   27 from copy import deepcopy
   28 import os
   29 import platform
   30 import sys
   31 from textwrap import wrap
   32 import wx
   33 
   34 # relax module imports.
   35 from gui.errors import gui_raise
   36 from lib.errors import AllRelaxErrors
   37 from status import Status; status = Status()
   38 
   39 
   40 def add_border(box, border=0, packing=wx.VERTICAL, debug=False):
   41     """Create the main part of the frame, returning the central sizer.
   42 
   43     @param box:         The box sizer element to pack the borders into.
   44     @type box:          wx.BoxSizer instance
   45     @keyword border:    The size of the border in pixels.
   46     @type border:       int
   47     @keyword packing:   Specify if the central sizer should be vertically or horizontally packed.
   48     @type packing:      wx.VERTICAL or wx.HORIZONTAL
   49     @keyword debug:     A flag which if true will make colourful borders.
   50     @type debug:        bool
   51     @return:            The central sizer.
   52     @rtype:             wx.BoxSizer instance
   53     """
   54 
   55     # The orientation of the sub sizer.
   56     orient = box.GetOrientation()
   57     if orient == wx.HORIZONTAL:
   58         orient_sub = wx.VERTICAL
   59     else:
   60         orient_sub = wx.HORIZONTAL
   61 
   62     # Some sizers.
   63     sizer_sub = wx.BoxSizer(orient_sub)
   64     sizer_cent = wx.BoxSizer(packing)
   65 
   66     # Left and right borders (debugging).
   67     if debug:
   68         # Left coloured panel.
   69         panel = wx.Panel(box.GetContainingWindow(), -1)
   70         panel.SetSize((border, border))
   71         panel.SetBackgroundColour("Red")
   72         box.Add(panel, 0, wx.EXPAND|wx.ALL)
   73 
   74         # Centre.
   75         box.Add(sizer_sub, 1, wx.EXPAND|wx.ALL)
   76 
   77         # Top coloured panel.
   78         panel = wx.Panel(box.GetContainingWindow(), -1)
   79         panel.SetSize((border, border))
   80         panel.SetBackgroundColour("Yellow")
   81         box.Add(panel, 0, wx.EXPAND|wx.ALL)
   82  
   83     # Left and right borders.
   84     else:
   85         box.AddSpacer(border)
   86         box.Add(sizer_sub, 1, wx.EXPAND|wx.ALL)
   87         box.AddSpacer(border)
   88 
   89     # Top and bottom borders (debugging).
   90     if debug:
   91         # Top coloured panel.
   92         panel = wx.Panel(box.GetContainingWindow(), -1)
   93         panel.SetSize((border, border))
   94         panel.SetBackgroundColour("Blue")
   95         sizer_sub.Add(panel, 0, wx.EXPAND|wx.ALL)
   96 
   97         # Centre.
   98         sizer_sub.Add(sizer_cent, 1, wx.EXPAND|wx.ALL)
   99 
  100         # Bottom coloured panel.
  101         panel = wx.Panel(box.GetContainingWindow(), -1)
  102         panel.SetSize((border, border))
  103         panel.SetBackgroundColour("Green")
  104         sizer_sub.Add(panel, 0, wx.EXPAND|wx.ALL)
  105  
  106     # Top and bottom borders.
  107     else:
  108         sizer_sub.AddSpacer(border)
  109         sizer_sub.Add(sizer_cent, 1, wx.EXPAND|wx.ALL)
  110         sizer_sub.AddSpacer(border)
  111  
  112     # Return the central sizer.
  113     return sizer_cent
  114 
  115 
  116 def bitmap_setup(path):
  117     """Build and return the bitmap, handling transparency for all operating systems.
  118 
  119     This function is required to handle alpha in bitmap on MS Windows so that regions with partial transparency are not blended into the default dark grey colour of Windows' windows.
  120 
  121     @param path:    The absolute path to the bitmap image.
  122     @type path:     str
  123     @return:        The processed bitmap object.
  124     @rtype:         wx.Bitmap instance
  125     """
  126 
  127     # Create the bitmap object.
  128     bitmap = wx.Bitmap(path, wx.BITMAP_TYPE_ANY)
  129 
  130     # Return the bitmap object.
  131     return bitmap
  132 
  133 
  134 def format_table(table):
  135     """Format the text by stripping whitespace.
  136 
  137     @param table:       The table.
  138     @type table:        lists of lists of str
  139     @return:            The formatted table.
  140     @rtype:             str
  141     """
  142 
  143     # Initialise some variables.
  144     text = ''
  145     num_rows = len(table.cells)
  146     num_cols = len(table.headings)
  147 
  148     # The column widths.
  149     widths = []
  150     for j in range(num_cols):
  151         widths.append(len(table.headings[j]))
  152     for i in range(num_rows):
  153         for j in range(num_cols):
  154             # The element is larger than the previous.
  155             if len(table.cells[i][j]) > widths[j]:
  156                 widths[j] = len(table.cells[i][j])
  157 
  158     # The free space for the text.
  159     used = 0
  160     used += 2    # Start of the table '  '.
  161     used += 2    # End of the table '  '.
  162     used += 3 * (num_cols - 1)   # Middle of the table '   '.
  163     free_space = status.text_width - used
  164 
  165     # The maximal width for all cells.
  166     free_width = sum(widths)
  167 
  168     # Column wrapping.
  169     if free_width > free_space:
  170         # New structures.
  171         new_widths = deepcopy(widths)
  172         num_cols_wrap = num_cols
  173         free_space_wrap = free_space
  174         col_wrap = [True] * num_cols
  175 
  176         # Loop.
  177         while True:
  178             # The average column width.
  179             ave_width = free_space_wrap / num_cols_wrap
  180 
  181             # Rescale.
  182             rescale = False
  183             for i in range(num_cols):
  184                 # Remove the column from wrapping if smaller than the average wrapped width.
  185                 if col_wrap[i] and new_widths[i] < ave_width:
  186                     # Recalculate.
  187                     free_space_wrap = free_space_wrap - new_widths[i]
  188                     num_cols_wrap -= 1
  189                     rescale = True
  190 
  191                     # Remove the column from wrapping.
  192                     col_wrap[i] = False
  193 
  194             # Done.
  195             if not rescale:
  196                 # Set the column widths.
  197                 for i in range(num_cols):
  198                     if new_widths[i] > ave_width:
  199                         new_widths[i] = ave_width
  200                 break
  201 
  202     # No column wrapping.
  203     else:
  204         new_widths = widths
  205         col_wrap = [False] * num_cols
  206 
  207     # The total table width.
  208     total_width = sum(new_widths) + used
  209 
  210     # The header.
  211     text += " " + "_" * int(total_width - 2) + "\n\n"    # Top rule and black line.
  212     text += table_line(text=table.headings, widths=new_widths)    # The headings.
  213     text += table_line(widths=new_widths, bottom=True)    # Middle rule.
  214 
  215     # The table contents.
  216     for i in range(num_rows):
  217         # Column text, with wrapping.
  218         col_text = [table.cells[i]]
  219         num_lines = 1
  220         for j in range(num_cols):
  221             if col_wrap[j]:
  222                 # Wrap.
  223                 lines = wrap(col_text[0][j], new_widths[j])
  224 
  225                 # Count the lines.
  226                 num_lines = len(lines)
  227 
  228                 # Replace the column text.
  229                 for k in range(num_lines):
  230                     # New row of empty text.
  231                     if len(col_text) <= k:
  232                         col_text.append(['']*num_cols)
  233 
  234                     # Pack the data.
  235                     col_text[k][j] = lines[k]
  236 
  237         # Blank line (between rows when asked, and for the first row after the header).
  238         if table.spacing or i == 1:
  239             text += table_line(widths=new_widths)
  240 
  241         # The contents.
  242         for k in range(num_lines):
  243             text += table_line(text=col_text[k], widths=new_widths)
  244 
  245     # The bottom.
  246     text += table_line(widths=new_widths, bottom=True)    # Bottom rule.
  247 
  248     # Add a newline.
  249     text += '\n'
  250 
  251     # Return the table text.
  252     return text
  253 
  254 
  255 def open_file(file, force_text=False):
  256     """Open the file in the platform's native editor/viewer.
  257 
  258     @param file:            The path of the file to open.
  259     @type file:             str
  260     @keyword force_text:    A flag which if True will cause a text editor to be launched.
  261     @type force_text:       bool
  262     """
  263 
  264     # Windows.
  265     if platform.uname()[0] in ['Windows', 'Microsoft']:
  266         # Text file.
  267         if force_text:
  268             os.system("notepad '%s'" % os.path.normpath(file))
  269 
  270         # All other files.
  271         else:
  272             os.startfile(os.path.normpath(file))
  273 
  274     # Mac OS X.
  275     elif platform.uname()[0] == 'Darwin':
  276         # Text file.
  277         if force_text:
  278             os.system("open -t '%s'" % file)
  279 
  280         # All other files.
  281         else:
  282             os.system("open '%s'" % file)
  283 
  284     # POSIX Systems with xdg-open.
  285     else:
  286         os.system("/usr/bin/xdg-open '%s'" % file)
  287 
  288 
  289 def protected_exec(fn, *args, **kargs):
  290     """Apply the given function, catching all RelaxErrors.
  291 
  292     All args and keyword args supplied will be directly applied to the given function.
  293 
  294     @param fn:      The function to apply.
  295     @type fn:       func
  296     @return:        The status of execution.
  297     @rtype:         bool
  298     """
  299 
  300     # Apply the function.
  301     try:
  302         fn(*args, **kargs)
  303 
  304     # Catch RelaxErrors.
  305     except AllRelaxErrors:
  306         instance = sys.exc_info()[1]
  307 
  308         # Raise the error in debugging mode.
  309         if status.debug:
  310             raise
  311 
  312         # Display a dialog with the error.
  313         gui_raise(instance, raise_flag=False)
  314 
  315         # Failure.
  316         return False
  317 
  318     # Success.
  319     return True
  320 
  321 
  322 def table_line(text=None, widths=None, bottom=False):
  323     """Format a line of a table.
  324 
  325     @keyword text:      The list of table elements.  If not given, an empty line will be be produced.
  326     @type text:         list of str or None
  327     @keyword widths:    The list of column widths for the table.
  328     @type widths:       list of int
  329     @keyword botton:    A flag which if True will cause a table bottom line to be produced.
  330     @type bottom:       bool
  331     @return:            The table line.
  332     @rtype:             str
  333     """
  334 
  335     # Initialise.
  336     if bottom:
  337         line = " _"
  338     else:
  339         line = "  "
  340 
  341     # Loop over the columns.
  342     for i in range(len(widths)):
  343         # The column separator.
  344         if i > 0:
  345             if bottom:
  346                 line += "___"
  347             else:
  348                 line += "   "
  349 
  350         # A bottom line.
  351         if bottom:
  352             line += "_" * int(widths[i])
  353 
  354         # Empty line.
  355         elif text == None:
  356             line += " " * int(widths[i])
  357 
  358         # The text.
  359         else:
  360             line += text[i]
  361             line += " " * int(widths[i] - len(text[i]))
  362 
  363     # Close the line.
  364     if bottom:
  365         line += "_ \n"
  366     else:
  367         line += "  \n"
  368 
  369     # Return the text.
  370     return line