camelot.camelot.view.forms

Package camelot :: Package camelot :: Package view :: Module forms |
[hide private]
[frames] | no frames]

# Source Code for Module camelot.camelot.view.forms

      1  #  ============================================================================
      2  #
      3  #  Copyright (C) 2007-2008 Conceptive Engineering bvba. All rights reserved.
      4  #  www.conceptive.be / project-camelot@conceptive.be
      5  #
      6  #  This file is part of the Camelot Library.
      7  #
      8  #  This file may be used under the terms of the GNU General Public
      9  #  License version 2.0 as published by the Free Software Foundation
     10  #  and appearing in the file LICENSE.GPL included in the packaging of
     11  #  this file.  Please review the following information to ensure GNU
     12  #  General Public Licensing requirements will be met:
     13  #  http://www.trolltech.com/products/qt/opensource.html
     14  #
     15  #  If you are unsure which license is appropriate for your use, please
     16  #  review the following information:
     17  #  http://www.trolltech.com/products/qt/licensing.html or contact
     18  #  project-camelot@conceptive.be.
     19  #
     20  #  This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
     21  #  WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
     22  #
     23  #  For use of this library in commercial applications, please contact
     24  #  project-camelot@conceptive.be
     25  #
     26  #  ============================================================================
     27
     28  """Python structures to represent interface forms.
     29
     30  These structures can be transformed to QT forms.
     31  """
     32
     33  import logging
     34  logger = logging.getLogger('camelot.view.forms')
     35
     36 -def structure_to_form(structure):
     37    """Convert a python data structure to a form, using the following rules :
     38
     39    if structure is an instance of Form, return structure
     40    if structure is a list, create a Form from this list
     41    """
     42    if isinstance(structure, Form):
     43      return structure
     44    return Form(structure)
     45
     46
     47 -class Form(object):
     48    """Use the QFormLayout widget to render a form"""
     49
     50 -  def __init__(self, content, scrollbars=False):
     51      """@param content: a list with the field names and forms to render"""
     52      assert isinstance(content, list)
     53      self._content = content
     54      self._scrollbars = scrollbars
     55      self._fields = []
     56      for c in content:
     57        if isinstance(c, Form):
     58          self._fields.extend(c.get_fields())
     59        else:
     60          assert isinstance(c, (str, unicode))
     61          self._fields.append(c)
     62
     63 -  def get_fields(self):
     64      """@return : the fields, visible in this form"""
     65      return self._fields
     66
     67 -  def render(self, widgets, parent=None, nomargins=False):
     68      """@param widgets: a dictionary mapping each field in this form to a tuple
     69      of (label, widget editor)
     70
     71      @return : a QWidget into which the form is rendered
     72      """
     73      logger.debug('rendering %s' % self.__class__.__name__)
     74      from camelot.view.controls.editors import One2ManyEditor
     75      from camelot.view.controls.editors import RichTextEditor
     76
     77      from PyQt4 import QtGui
     78      from PyQt4.QtCore import Qt
     79
     80      #form_layout = QtGui.QFormLayout()
     81      #form_layout.setFieldGrowthPolicy(QtGui.QFormLayout.ExpandingFieldsGrow)
     82      #for field in self._content:
     83      #  if isinstance(field, Form):
     84      #    form_layout.addRow(field.render(widgets, parent, True))
     85      #  elif field in widgets:
     86      #    label, editor = widgets[field]
     87      #    if isinstance(editor, One2ManyEditor) or\
     88      #       isinstance(editor, RichTextEditor):
     89      #      form_layout.addRow(label)
     90      #      form_layout.addRow(editor)
     91      #    else:
     92      #      form_layout.addRow(label, editor)
     93
     94      form_layout = QtGui.QGridLayout()
     95      row = 0
     96      for field in self._content:
     97        if isinstance(field, Form):
     98          col = 0
     99          row_span = 1
    100          col_span = 2
    101          f = field.render(widgets, parent, True)
    102          if isinstance(f, QtGui.QLayout):
    103            form_layout.addLayout(f, row, col, row_span, col_span)
    104          else:
    105            form_layout.addWidget(f, row, col, row_span, col_span)
    106          row += 1
    107        elif field in widgets:
    108          col = 0
    109          row_span = 1
    110          label, editor = widgets[field]
    111          if isinstance(editor, (One2ManyEditor, RichTextEditor)):
    112            col_span = 2
    113            form_layout.addWidget(label, row, col, row_span, col_span)
    114            row += 1
    115            form_layout.addWidget(editor, row, col, row_span, col_span)
    116            row += 1
    117          else:
    118            col_span = 1
    119            form_layout.addWidget(label, row, col, row_span, col_span)
    120            form_layout.addWidget(editor, row, col + 1, row_span, col_span)
    121            row += 1
    122
    123      # get last item in the layout
    124      last_item = form_layout.itemAt(form_layout.count() - 1)
    125
    126      # if last item does not contain a widget, 0 is returned
    127      # which is fine with the isinstance test
    128      w = last_item.widget()
    129
    130      # add stretch only if last item is not expandable
    131      if isinstance(w, (One2ManyEditor, RichTextEditor)):
    132        pass
    133      else:
    134        form_layout.setRowStretch(form_layout.rowCount(), 1)
    135
    136      form_widget = QtGui.QWidget()
    137
    138      # fix embedded forms
    139      if nomargins:
    140        form_layout.setContentsMargins(0, 0, 0, 0)
    141
    142      form_widget.setSizePolicy(QtGui.QSizePolicy.Expanding,
    143                                QtGui.QSizePolicy.Expanding)
    144      form_widget.setLayout(form_layout)
    145
    146      if self._scrollbars:
    147        scroll_area = QtGui.QScrollArea()
    148        scroll_area.setWidget(form_widget)
    149        scroll_area.setWidgetResizable(True)
    150        scroll_area.setFrameStyle(QtGui.QFrame.NoFrame)
    151        return scroll_area
    152
    153      return form_widget
    154
    155
    156 -class TabForm(Form):
    157    """Render forms within a QTabWidget"""
    158
    159 -  def __init__(self, tabs):
    160      """@param tabs: a list of tuples of (tab_label, tab_form)"""
    161      assert isinstance(tabs, list)
    162      for tab in tabs:
    163        assert isinstance(tab, tuple)
    164      self.tabs = [(tab_label, structure_to_form(tab_form))
    165                   for tab_label, tab_form in tabs]
    166      super(TabForm, self).__init__(sum((tab_form.get_fields()
    167                                    for tab_label, tab_form in self.tabs), []))
    168
    169 -  def render(self, widgets, parent=None, nomargins=False):
    170      logger.debug('rendering %s' % self.__class__.__name__)
    171      from PyQt4 import QtGui
    172      from PyQt4.QtCore import Qt
    173      widget = QtGui.QTabWidget(parent)
    174      for tab_label, tab_form in self.tabs:
    175        #form = tab_form.render(widgets, widget)
    176        #print form.height()
    177        #widget.addTab(form, tab_label)
    178        widget.addTab(tab_form.render(widgets, widget), tab_label)
    179      return widget
    180
    181
    182 -class HBoxForm(Form):
    183    """Render different forms in a horizontal box"""
    184
    185 -  def __init__(self, columns):
    186      """@param columns: a list of forms to display in the different columns
    187      of the horizontal box"""
    188      assert isinstance(columns, list)
    189      self.columns = [structure_to_form(col) for col in columns]
    190      super(HBoxForm, self).__init__(sum((column_form.get_fields()
    191                                    for column_form in self.columns), []))
    192
    193 -  def render(self, widgets, parent=None, nomargins=False):
    194      logger.debug('rendering %s' % self.__class__.__name__)
    195      from PyQt4 import QtGui
    196      from PyQt4.QtCore import Qt
    197      widget = QtGui.QHBoxLayout()
    198      for form in self.columns:
    199        widget.addWidget(form.render(widgets, parent, nomargins))
    200      return widget
    201
    202
    203 -class VBoxForm(Form):
    204    """Render different forms or widgets in a vertical box"""
    205
    206 -  def __init__(self, rows):
    207      """@param rows: a list of forms to display in the different columns
    208      of the horizontal box
    209      """
    210      assert isinstance(rows, list)
    211      self.rows = [structure_to_form(row) for row in rows]
    212      super(VBoxForm, self).__init__(sum((row_form.get_fields() for row_form in self.rows), []))
    213
    214 -  def render(self, widgets, parent=None, nomargins=False):
    215      logger.debug('rendering %s' % self.__class__.__name__)
    216      from PyQt4 import QtGui
    217      from PyQt4.QtCore import Qt
    218      widget = QtGui.QVBoxLayout()
    219      for form in self.rows:
    220        widget.addWidget(form.render(widgets, parent, nomargins))
    221      return widget
    222
    223
    224 -class WidgetOnlyForm(Form):
    225    """Renders a single widget without its label, typically a one2many widget"""
    226
    227 -  def __init__(self, field):
    228      assert isinstance(field, (str, unicode))
    229      super(WidgetOnlyForm, self).__init__([field])
    230
    231 -  def render(self, widgets, parent=None, nomargins=False):
    232      logger.debug('rendering %s' % self.__class__.__name__)
    233      label, editor = widgets[self.get_fields()[0]]
    234      return editor
    235