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:
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:
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
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:
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
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)
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
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)