Esempio n. 1
0
def strip_data_from_object(obj, columns):
    """For every column in columns, get the corresponding value from the
    object.  Getting a value from an object is time consuming, so using
    this function should be minimized.
    :param obj: the object of which to get data
    :param columns: a list of columns for which to get data
    """
    row_data = []

    def create_collection_getter(o, attr):
        return lambda: getattr(o, attr)

    for _i, col in enumerate(columns):
        field_attributes = col[1]
        field_value = None
        try:
            getter = field_attributes['getter']
            if field_attributes['python_type'] == list:
                field_value = DelayedProxy(
                    field_attributes['admin'],
                    create_collection_getter(obj, col[0]),
                    field_attributes['admin'].get_columns)
            else:
                field_value = getter(obj)
        except (Exception, RuntimeError, TypeError, NameError), e:
            message = "could not get field '%s' of object of type %s" % (
                col[0], obj.__class__.__name__)
            log_programming_error(logger, message, exc_info=e)
        finally:
Esempio n. 2
0
def strip_data_from_object(obj, columns):
    """For every column in columns, get the corresponding value from the
    object.  Getting a value from an object is time consuming, so using
    this function should be minimized.
    :param obj: the object of which to get data
    :param columns: a list of columns for which to get data
    """
    row_data = []

    def create_collection_getter(o, attr):
        return lambda: getattr(o, attr)

    for _i, col in enumerate(columns):
        field_attributes = col[1]
        field_value = None
        try:
            getter = field_attributes["getter"]
            if field_attributes["python_type"] == list:
                field_value = DelayedProxy(
                    field_attributes["admin"],
                    create_collection_getter(obj, col[0]),
                    field_attributes["admin"].get_columns,
                )
            else:
                field_value = getter(obj)
        except (Exception, RuntimeError, TypeError, NameError), e:
            message = "could not get field '%s' of object of type %s" % (col[0], obj.__class__.__name__)
            log_programming_error(logger, message, exc_info=e)
        finally:
Esempio n. 3
0
def stripped_data_to_unicode(stripped_data, obj, static_field_attributes,
                             dynamic_field_attributes):
    """Extract for each field in the row data a 'visible' form of
    data"""

    row_data = []

    for field_data, static_attributes, dynamic_attributes in zip(
            stripped_data, static_field_attributes, dynamic_field_attributes):
        unicode_data = u''
        try:
            choices = dynamic_attributes.get(
                'choices', static_attributes.get('choices', None))
            if 'unicode_format' in static_attributes:
                unicode_format = static_attributes['unicode_format']
                if field_data != None:
                    unicode_data = unicode_format(field_data)
            elif choices:
                unicode_data = field_data
                for key, value in choices:
                    if key == field_data:
                        unicode_data = value
            elif isinstance(field_data, list):
                unicode_data = u'.'.join(
                    [six.text_type(e) for e in field_data])
            elif isinstance(field_data, datetime.datetime):
                # datetime should come before date since datetime is a subtype of date
                if field_data.year >= 1900:
                    unicode_data = field_data.strftime('%d/%m/%Y %H:%M')
            elif isinstance(field_data, datetime.date):
                if field_data.year >= 1900:
                    unicode_data = field_data.strftime('%d/%m/%Y')
            elif isinstance(field_data, StoredImage):
                unicode_data = field_data.checkout_thumbnail(100, 100)
            elif field_data != None:
                unicode_data = six.text_type(field_data)
        except (Exception, RuntimeError, TypeError, NameError) as e:
            log_programming_error(
                logger,
                "Could not get view data for field '%s' with of object of type %s"
                % (static_attributes['name'], obj.__class__.__name__),
                exc_info=e)
        finally:
            row_data.append(unicode_data)

    return row_data
Esempio n. 4
0
def stripped_data_to_unicode(stripped_data, obj, static_field_attributes, dynamic_field_attributes):
    """Extract for each field in the row data a 'visible' form of
    data"""

    row_data = []

    for field_data, static_attributes, dynamic_attributes in zip(
        stripped_data, static_field_attributes, dynamic_field_attributes
    ):
        unicode_data = u""
        try:
            choices = dynamic_attributes.get("choices", static_attributes.get("choices", None))
            if "unicode_format" in static_attributes:
                unicode_format = static_attributes["unicode_format"]
                if field_data != None:
                    unicode_data = unicode_format(field_data)
            elif choices:
                unicode_data = field_data
                for key, value in choices:
                    if key == field_data:
                        unicode_data = value
            elif isinstance(field_data, list):
                unicode_data = u".".join([unicode(e) for e in field_data])
            elif isinstance(field_data, datetime.datetime):
                # datetime should come before date since datetime is a subtype of date
                if field_data.year >= 1900:
                    unicode_data = field_data.strftime("%d/%m/%Y %H:%M")
            elif isinstance(field_data, datetime.date):
                if field_data.year >= 1900:
                    unicode_data = field_data.strftime("%d/%m/%Y")
            elif isinstance(field_data, StoredImage):
                unicode_data = field_data.checkout_thumbnail(100, 100)
            elif field_data != None:
                unicode_data = unicode(field_data)
        except (Exception, RuntimeError, TypeError, NameError), e:
            log_programming_error(
                logger,
                "Could not get view data for field '%s' with of object of type %s"
                % (static_attributes["name"], obj.__class__.__name__),
                exc_info=e,
            )
        finally:
Esempio n. 5
0
def strip_data_from_object(obj, columns):
    """For every column in columns, get the corresponding value from the
    object.  Getting a value from an object is time consuming, so using
    this function should be minimized.
    :param obj: the object of which to get data
    :param columns: a list of columns for which to get data
    """
    row_data = []

    for _i, col in enumerate(columns):
        field_value = None
        try:
            field_value = getattr(obj, col[0])
        except (Exception, RuntimeError, TypeError, NameError) as e:
            message = "could not get field '%s' of object of type %s" % (
                col[0], obj.__class__.__name__)
            log_programming_error(logger, message, exc_info=e)
        finally:
            row_data.append(field_value)
    return row_data
Esempio n. 6
0
    def setColumns(self, columns):
        """Callback method to set the columns

        :param columns: a list with fields to be displayed of the form [('field_name', field_attributes), ...] as
        returned by the getColumns method of the ElixirAdmin class
        """
        assert object_thread(self)
        self.logger.debug("setColumns")
        self._columns = columns

        delegate_manager = delegates.DelegateManager()
        delegate_manager.set_columns_desc(columns)

        # set a delegate for the vertical header
        delegate_manager.insertColumnDelegate(-1, delegates.PlainTextDelegate(parent=delegate_manager))
        index = QtCore.QModelIndex()
        option = QtGui.QStyleOptionViewItem()
        self.settings.beginGroup("column_width")
        self.settings.beginGroup("0")

        #
        # this loop can take a while to complete, so processEvents is called regulary
        #
        for i, c in enumerate(columns):
            #
            # Construct the delegate
            #
            field_name = c[0]
            self.logger.debug("creating delegate for %s" % field_name)
            try:
                delegate = c[1]["delegate"](parent=delegate_manager, **c[1])
            except Exception, e:
                log_programming_error(logger, "Could not create delegate for field %s" % field_name, exc_info=e)
                delegate = delegates.PlainTextDelegate(parent=delegate_manager, **c[1])
            delegate_manager.insertColumnDelegate(i, delegate)
            #
            # Set the header data
            #
            header_item = QtGui.QStandardItem()
            header_item.setData(QtCore.QVariant(unicode(c[1]["name"])), Qt.DisplayRole)
            if c[1].get("nullable", True) == False:
                header_item.setData(self._header_font_required, Qt.FontRole)
            else:
                header_item.setData(self._header_font, Qt.FontRole)

            settings_width = int(variant_to_pyobject(self.settings.value(field_name, 0)))
            label_size = QtGui.QFontMetrics(self._header_font_required).size(
                Qt.TextSingleLine, unicode(c[1]["name"]) + u" "
            )
            minimal_widths = [label_size.width() + 10]
            if "minimal_column_width" in c[1]:
                minimal_widths.append(self._header_font_metrics.averageCharWidth() * c[1]["minimal_column_width"])
            if c[1].get("editable", True) != False:
                minimal_widths.append(delegate.sizeHint(option, index).width())
            column_width = c[1].get("column_width", None)
            if column_width != None:
                minimal_widths = [self._header_font_metrics.averageCharWidth() * column_width]
            if settings_width:
                header_item.setData(
                    QtCore.QVariant(QtCore.QSize(settings_width, self._horizontal_header_height)), Qt.SizeHintRole
                )
            else:
                header_item.setData(
                    QtCore.QVariant(QtCore.QSize(max(minimal_widths), self._horizontal_header_height)), Qt.SizeHintRole
                )

            self.source_model.setHorizontalHeaderItem(i, header_item)
Esempio n. 7
0
    def render( self, widgets, parent = None, toplevel = False):
        """
        :param widgets: a :class:`camelot.view.controls.formview.FormEditors` object
            that is able to create the widgets for this form
        :param parent: the :class:`QtGui.QWidget` in which the form is placed
        :param toplevel: a :keyword:`boolean` indicating if this form is toplevel,
            or a child form of another form.  A toplevel form will be expanding,
            while a non toplevel form is only expanding if it contains other
            expanding elements.

        :return: a :class:`QtGui.QWidget` into which the form is rendered
        """
        logger.debug( 'rendering %s' % (self.__class__.__name__) )
        from camelot.view.controls.editors.wideeditor import WideEditor
        form_widget = QtGui.QWidget( parent )
        form_layout = QtGui.QGridLayout()
        # where 1 column in the form is a label and a field, so two columns in the grid
        columns = min(self._columns, len(self))
        # make sure all columns have the same width
        for i in range(columns*2):
            if i%2:
                form_layout.setColumnStretch(i, 1)

        row_span = 1

        class cursor(object):

            def __init__(self):
                self.row = 0
                self.col = 0

            def next_row(self):
                self.row = self.row + 1
                self.col = 0

            def next_col(self):
                self.col = self.col + 2
                if self.col >= columns * 2:
                    self.next_row()

            def next_empty_row(self):
                if self.col!=0:
                    self.next_row()

            def __str__(self):
                return '%s,%s'%(self.row, self.col)

        c = cursor()

        has_vertical_expanding_row = False
        for field in self:
            size_policy = None
            if isinstance( field, Form ):
                c.next_empty_row()
                col_span = 2 * columns
                f = field.render( widgets, parent, False )
                if isinstance( f, QtGui.QLayout ):
                    #
                    # this should maybe be recursive ??
                    #
                    for layout_item_index in range( f.count() ):
                        layout_item = f.itemAt( layout_item_index )
                        layout_item_widget = layout_item.widget()
                        if layout_item_widget and layout_item_widget.sizePolicy().verticalPolicy() == QtGui.QSizePolicy.Expanding:
                            has_vertical_expanding_row = True
                    form_layout.addLayout( f, c.row, c.col, row_span, col_span )
                elif isinstance( f, QtGui.QLayoutItem ):
                    form_layout.addItem( f )
                else:
                    form_layout.addWidget( f, c.row, c.col, row_span, col_span )
                    size_policy = f.sizePolicy()
                c.next_row()
            else:
                editor = widgets.create_editor( field, form_widget )
                if editor != None:
                    if isinstance( editor, ( WideEditor, ) ):
                        c.next_empty_row()
                        col_span = 2 * columns
                        label = widgets.create_label( field, editor, form_widget )
                        if label:
                            form_layout.addWidget( label, c.row, c.col, row_span, col_span )
                            c.next_row()
                        form_layout.addWidget( editor, c.row, c.col, row_span, col_span )
                        c.next_row()
                    else:
                        col_span = 1
                        label = widgets.create_label( field, editor, form_widget )
                        if label:
                            form_layout.addWidget( label, c.row, c.col, row_span, col_span )
                        form_layout.addWidget( editor, c.row, c.col + 1, row_span, col_span )
                        c.next_col()
                    size_policy = editor.sizePolicy()
                else:
                    log_programming_error( logger, 'widgets should contain a widget for field %s'%unicode(field) )
            if size_policy and size_policy.verticalPolicy() == QtGui.QSizePolicy.Expanding:
                has_vertical_expanding_row = True

        if (not has_vertical_expanding_row) and toplevel and form_layout.rowCount():
            form_layout.setRowStretch( form_layout.rowCount(), 1 )

        # fix embedded forms
        if not toplevel:
            form_layout.setContentsMargins( 0, 0, 0, 0 )
  
        if toplevel or has_vertical_expanding_row:
            form_widget.setSizePolicy( QtGui.QSizePolicy.Expanding,
                                       QtGui.QSizePolicy.Expanding )
        form_widget.setLayout( form_layout )

        if self._scrollbars:
            scroll_area = QtGui.QScrollArea( parent )
            # we should inherit parent's background color
            scroll_area.setWidget( form_widget )
            scroll_area.setWidgetResizable( True )
            scroll_area.setFrameStyle( QtGui.QFrame.NoFrame )
            return scroll_area

        logger.debug( 'end rendering %s' % self.__class__.__name__ )
        
        return form_widget
Esempio n. 8
0
    def setColumns(self, columns):
        """Callback method to set the columns

        :param columns: a list with fields to be displayed of the form [('field_name', field_attributes), ...] as
        returned by the getColumns method of the ElixirAdmin class
        """
        assert object_thread(self)
        self.logger.debug('setColumns')
        self._columns = columns

        delegate_manager = delegates.DelegateManager()
        delegate_manager.set_columns_desc(columns)

        # set a delegate for the vertical header
        delegate_manager.insertColumnDelegate(
            -1, delegates.PlainTextDelegate(parent=delegate_manager))
        index = QtCore.QModelIndex()
        option = QtGui.QStyleOptionViewItem()
        self.settings.beginGroup('column_width')
        self.settings.beginGroup('0')

        #
        # this loop can take a while to complete, so processEvents is called regulary
        #
        for i, c in enumerate(columns):
            #
            # Construct the delegate
            #
            field_name = c[0]
            self.logger.debug('creating delegate for %s' % field_name)
            try:
                delegate = c[1]['delegate'](parent=delegate_manager, **c[1])
            except Exception, e:
                log_programming_error(
                    logger,
                    'Could not create delegate for field %s' % field_name,
                    exc_info=e)
                delegate = delegates.PlainTextDelegate(parent=delegate_manager,
                                                       **c[1])
            delegate_manager.insertColumnDelegate(i, delegate)
            #
            # Set the header data
            #
            header_item = QtGui.QStandardItem()
            header_item.setData(QtCore.QVariant(unicode(c[1]['name'])),
                                Qt.DisplayRole)
            if c[1].get('nullable', True) == False:
                header_item.setData(self._header_font_required, Qt.FontRole)
            else:
                header_item.setData(self._header_font, Qt.FontRole)

            settings_width = int(
                variant_to_pyobject(self.settings.value(field_name, 0)))
            label_size = QtGui.QFontMetrics(self._header_font_required).size(
                Qt.TextSingleLine,
                unicode(c[1]['name']) + u' ')
            minimal_widths = [label_size.width() + 10]
            if 'minimal_column_width' in c[1]:
                minimal_widths.append(
                    self._header_font_metrics.averageCharWidth() *
                    c[1]['minimal_column_width'])
            if c[1].get('editable', True) != False:
                minimal_widths.append(delegate.sizeHint(option, index).width())
            column_width = c[1].get('column_width', None)
            if column_width != None:
                minimal_widths = [
                    self._header_font_metrics.averageCharWidth() * column_width
                ]
            if settings_width:
                header_item.setData(
                    QtCore.QVariant(
                        QtCore.QSize(settings_width,
                                     self._horizontal_header_height)),
                    Qt.SizeHintRole)
            else:
                header_item.setData(
                    QtCore.QVariant(
                        QtCore.QSize(max(minimal_widths),
                                     self._horizontal_header_height)),
                    Qt.SizeHintRole)

            self.source_model.setHorizontalHeaderItem(i, header_item)
Esempio n. 9
0
    def render( self, widgets, parent = None, toplevel = False):
        """
        :param widgets: a :class:`camelot.view.controls.formview.FormEditors` object
            that is able to create the widgets for this form
        :param parent: the :class:`QtGui.QWidget` in which the form is placed
        :param toplevel: a :keyword:`boolean` indicating if this form is toplevel,
            or a child form of another form.  A toplevel form will be expanding,
            while a non toplevel form is only expanding if it contains other
            expanding elements.

        :return: a :class:`QtGui.QWidget` into which the form is rendered
        """
        logger.debug( 'rendering %s' % (self.__class__.__name__) )
        from camelot.view.controls.editors.wideeditor import WideEditor
        form_widget = QtGui.QWidget( parent )
        form_layout = QtGui.QGridLayout()
        # where 1 column in the form is a label and a field, so two columns in the grid
        columns = min(self._columns, len(self))
        # make sure all columns have the same width
        for i in range(columns*2):
            if i%2:
                form_layout.setColumnStretch(i, 1)

        row_span = 1

        class cursor(object):

            def __init__(self):
                self.row = 0
                self.col = 0

            def next_row(self):
                self.row = self.row + 1
                self.col = 0

            def next_col(self):
                self.col = self.col + 2
                if self.col >= columns * 2:
                    self.next_row()

            def next_empty_row(self):
                if self.col!=0:
                    self.next_row()

            def __str__(self):
                return '%s,%s'%(self.row, self.col)

        c = cursor()

        has_vertical_expanding_row = False
        for field in self:
            size_policy = None
            if isinstance( field, Form ):
                c.next_empty_row()
                col_span = 2 * columns
                f = field.render( widgets, parent, False )
                if isinstance( f, QtGui.QLayout ):
                    #
                    # this should maybe be recursive ??
                    #
                    for layout_item_index in range( f.count() ):
                        layout_item = f.itemAt( layout_item_index )
                        layout_item_widget = layout_item.widget()
                        if layout_item_widget and layout_item_widget.sizePolicy().verticalPolicy() == QtGui.QSizePolicy.Expanding:
                            has_vertical_expanding_row = True
                    form_layout.addLayout( f, c.row, c.col, row_span, col_span )
                elif isinstance( f, QtGui.QLayoutItem ):
                    form_layout.addItem( f )
                else:
                    form_layout.addWidget( f, c.row, c.col, row_span, col_span )
                    size_policy = f.sizePolicy()
                c.next_row()
            else:
                editor = widgets.create_editor( field, form_widget )
                if editor != None:
                    if isinstance( editor, ( WideEditor, ) ):
                        c.next_empty_row()
                        col_span = 2 * columns
                        label = widgets.create_label( field, editor, form_widget )
                        if label:
                            form_layout.addWidget( label, c.row, c.col, row_span, col_span )
                            c.next_row()
                        form_layout.addWidget( editor, c.row, c.col, row_span, col_span )
                        c.next_row()
                    else:
                        col_span = 1
                        label = widgets.create_label( field, editor, form_widget )
                        if label:
                            form_layout.addWidget( label, c.row, c.col, row_span, col_span )
                        form_layout.addWidget( editor, c.row, c.col + 1, row_span, col_span )
                        c.next_col()
                    size_policy = editor.sizePolicy()
                else:
                    log_programming_error( logger, 'widgets should contain a widget for field %s'%unicode(field) )
            if size_policy and size_policy.verticalPolicy() == QtGui.QSizePolicy.Expanding:
                has_vertical_expanding_row = True

        if (not has_vertical_expanding_row) and toplevel and form_layout.rowCount():
            form_layout.setRowStretch( form_layout.rowCount(), 1 )

        # fix embedded forms
        if not toplevel:
            form_layout.setContentsMargins( 0, 0, 0, 0 )
  
        if toplevel or has_vertical_expanding_row:
            form_widget.setSizePolicy( QtGui.QSizePolicy.Expanding,
                                       QtGui.QSizePolicy.Expanding )
        form_widget.setLayout( form_layout )

        if self._scrollbars:
            scroll_area = QtGui.QScrollArea( parent )
            # we should inherit parent's background color
            scroll_area.setWidget( form_widget )
            scroll_area.setWidgetResizable( True )
            scroll_area.setFrameStyle( QtGui.QFrame.NoFrame )
            return scroll_area

        logger.debug( 'end rendering %s' % self.__class__.__name__ )
        
        return form_widget