Changeset 1185

Show
Ignore:
Timestamp:
03/12/10 10:23:39 (5 months ago)
Author:
erikj
Message:

split form view in form view and form widget, add form page

Location:
trunk/camelot/view
Files:
1 added
1 modified

Legend:

Unmodified
Added
Removed
  • trunk/camelot/view/controls/formview.py

    r1178 r1185  
    3737from camelot.view.controls.view import AbstractView 
    3838 
    39 class FormView( AbstractView ): 
    40  
    41     def __init__( self, title, admin, model, index ): 
    42         AbstractView.__init__( self ) 
    43         self.title_prefix = title 
    44         self.admin = admin 
    45         self.model = model 
    46         self.index = index 
    47         self.change_title(title) 
    48         self.widget_mapper = QtGui.QDataWidgetMapper() 
    49         self.widget_layout = QtGui.QHBoxLayout() 
    50         self.widget_layout.setSpacing( 0 ) 
    51         self.widget_layout.setMargin( 0 ) 
    52      
    53         self.closeAfterValidation = QtCore.SIGNAL( 'closeAfterValidation()' ) 
     39class FormWidget( QtGui.QWidget ): 
     40     
     41    changed_signal = QtCore.SIGNAL( 'changed()' ) 
     42     
     43    def __init__(self, admin): 
     44        QtGui.QWidget.__init__(self) 
     45        self._admin = admin 
     46        self._widget_mapper = QtGui.QDataWidgetMapper() 
     47        self._widget_layout = QtGui.QHBoxLayout() 
     48        self._widget_layout.setSpacing( 0 ) 
     49        self._widget_layout.setMargin( 0 ) 
     50        self._index = 0 
     51        self._model = None 
     52        self._form = None 
     53        self._columns = None 
     54        self._delegate = None 
     55        self.setLayout( self._widget_layout ) 
     56                 
     57    def set_model(self, model): 
     58        self._model = model 
    5459        sig = 'dataChanged(const QModelIndex &, const QModelIndex &)' 
    55         self.connect( self.model, QtCore.SIGNAL( sig ), self.dataChanged ) 
    56         self.connect( self.model, QtCore.SIGNAL( 'layoutChanged()' ), self.layout_changed ) 
    57         self.connect( self.model, self.model.item_delegate_changed_signal, self.item_delegate_changed ) 
    58      
    59         self.widget_mapper.setModel( model ) 
    60         self.setLayout( self.widget_layout ) 
    61      
    62         if hasattr( admin, 'form_size' ) and admin.form_size: 
    63             self.setMinimumSize( admin.form_size[0], admin.form_size[1] ) 
    64        
    65         self.validator = admin.create_validator( model ) 
    66         self.validate_before_close = True 
    67         self.form = None 
    68         self.columns = None 
    69         self.delegate = None 
    70      
    71         def getColumnsAndForm(): 
    72             return ( self.model.getColumns(), self.admin.get_form_display() ) 
    73        
    74         post( getColumnsAndForm, self.handleGetColumnsAndForm ) 
    75      
    76         def getActions(): 
    77             return admin.get_form_actions( None ) 
    78        
    79         post( getActions, self.setActions ) 
    80         self.update_title() 
    81      
    82     def update_title( self ): 
    83    
    84         def get_title(): 
    85             obj = self.getEntity() 
    86             return u'%s %s' % ( self.title_prefix, self.admin.get_verbose_identifier( obj ) ) 
    87        
    88         post( get_title, self.change_title ) 
    89      
    90     def dataChanged( self, index_from, index_to ): 
     60        self.connect( self._model, QtCore.SIGNAL( sig ), self._data_changed ) 
     61        self.connect( self._model, QtCore.SIGNAL( 'layoutChanged()' ), self._layout_changed ) 
     62        self.connect( self._model, self._model.item_delegate_changed_signal, self._item_delegate_changed ) 
     63        self._widget_mapper.setModel( model ) 
     64         
     65        def get_columns_and_form(): 
     66            return ( self._model.getColumns(), self._admin.get_form_display() ) 
     67       
     68        post( get_columns_and_form, self._set_columns_and_form ) 
     69         
     70    def clear_mapping(self): 
     71        self._widget_mapper.clearMapping() 
     72          
     73    def _data_changed( self, index_from, index_to ): 
    9174        #@TODO: only revert if this form is in the changed range 
    92         self.widget_mapper.revert() 
    93         self.update_title() 
    94          
    95     def layout_changed(self): 
    96         self.widget_mapper.revert() 
    97         self.update_title()         
    98      
    99     def handleGetColumnsAndForm( self, columns_and_form ): 
    100         self.columns, self.form = columns_and_form 
    101         self.setColumnsFormAndDelegate() 
    102  
    103     def item_delegate_changed(self): 
     75        self._widget_mapper.revert() 
     76        self.emit(self.changed_signal) 
     77         
     78    def _layout_changed(self): 
     79        self._widget_mapper.revert() 
     80        self.emit(self.changed_signal) 
     81         
     82    def _item_delegate_changed(self): 
    10483        from camelot.view.controls.delegates.delegatemanager import DelegateManager 
    105         self.delegate = self.model.getItemDelegate() 
    106         assert self.delegate 
    107         assert isinstance(self.delegate, DelegateManager) 
    108         self.setColumnsFormAndDelegate() 
    109      
    110     def setColumnsFormAndDelegate( self ): 
     84        self._delegate = self._model.getItemDelegate() 
     85        assert self._delegate 
     86        assert isinstance(self._delegate, DelegateManager) 
     87        self._create_widgets() 
     88                      
     89    def set_index(self, index): 
     90        self._index = index 
     91        self._widget_mapper.setCurrentIndex( self._index ) 
     92         
     93    def get_index(self): 
     94        return self._widget_mapper.currentIndex() 
     95         
     96    def submit(self): 
     97        self._widget_mapper.submit() 
     98                 
     99    def to_first(self): 
     100        self._widget_mapper.toFirst() 
     101         
     102    def to_last(self): 
     103        self._widget_mapper.toLast() 
     104         
     105    def to_next(self): 
     106        self._widget_mapper.toNext() 
     107         
     108    def to_previous(self): 
     109        self._widget_mapper.toPrevious() 
     110         
     111    def _set_columns_and_form(self, columns_and_form ): 
     112        self._columns, self._form = columns_and_form 
     113        self._create_widgets() 
     114         
     115    def _create_widgets( self ): 
    111116        """Create value and label widgets""" 
    112117        from camelot.view.controls.user_translatable_label import UserTranslatableLabel 
     
    117122        # it and are sure it will be there if we are running without threads 
    118123        # 
    119         if not self.delegate: 
    120             self.delegate = self.model.getItemDelegate() 
     124        if not self._delegate: 
     125            self._delegate = self._model.getItemDelegate() 
    121126        # 
    122127        # end of dirty trick 
    123128        # 
    124129        # only if all information is available, we can start building the form 
    125         if not (self.form and self.columns and self.delegate): 
     130        if not (self._form and self._columns and self._delegate): 
    126131            return 
    127132        widgets = {} 
    128         self.widget_mapper.setItemDelegate( self.delegate ) 
     133        self._widget_mapper.setItemDelegate( self._delegate ) 
    129134        option = QtGui.QStyleOptionViewItem() 
    130135        # set version to 5 to indicate the widget will appear on a 
     
    132137        option.version = 5 
    133138     
    134         for i, ( field_name, field_attributes ) in enumerate( self.columns ): 
    135             model_index = self.model.index( self.index, i ) 
     139        for i, ( field_name, field_attributes ) in enumerate( self._columns ): 
     140            model_index = self._model.index( self._index, i ) 
    136141            hide_title = False 
    137142            if 'hide_title' in field_attributes: 
    138143                hide_title = field_attributes['hide_title'] 
    139144            widget_label = None 
    140             widget_editor = self.delegate.createEditor( self, option, model_index ) 
     145            widget_editor = self._delegate.createEditor( self, option, model_index ) 
    141146            if not hide_title: 
    142147                widget_label = UserTranslatableLabel( field_attributes['name'] ) 
     
    154159            assert isinstance(widget_editor, QtGui.QWidget) 
    155160             
    156             self.widget_mapper.addMapping( widget_editor, i ) 
     161            self._widget_mapper.addMapping( widget_editor, i ) 
    157162            widgets[field_name] = ( widget_label, widget_editor ) 
    158163     
    159         self.widget_mapper.setCurrentIndex( self.index ) 
    160         self.widget_layout.insertWidget( 0, self.form.render( widgets, self ) ) 
    161         self.widget_layout.setContentsMargins( 7, 7, 7, 7 ) 
     164        self._widget_mapper.setCurrentIndex( self._index ) 
     165        self._widget_layout.insertWidget( 0, self._form.render( widgets, self ) ) 
     166        self._widget_layout.setContentsMargins( 7, 7, 7, 7 ) 
     167         
     168class FormView( AbstractView ): 
     169    """A FormView is the combination of a FormWidget, possible actions and menu items 
     170     
     171.. form_widget: The class to be used as a the form widget inside the form view 
     172 
     173    """ 
     174 
     175    form_widget = FormWidget 
     176     
     177    def __init__( self, title, admin, model, index ): 
     178        AbstractView.__init__( self ) 
     179        layout = QtGui.QVBoxLayout() 
     180        self._form = FormWidget(admin) 
     181        self.model = model 
     182        self.title_prefix = title 
     183        self.admin = admin 
     184        self.connect(self._form, FormWidget.changed_signal, self.update_title) 
     185        self._form.set_model(model) 
     186        self._form.set_index(index) 
     187        layout.addWidget(self._form) 
     188        self.change_title(title) 
     189        self.closeAfterValidation = QtCore.SIGNAL( 'closeAfterValidation()' ) 
     190        self.setLayout( layout ) 
     191     
     192        if hasattr( admin, 'form_size' ) and admin.form_size: 
     193            self.setMinimumSize( admin.form_size[0], admin.form_size[1] ) 
     194       
     195        self.validator = admin.create_validator( model ) 
     196        self.validate_before_close = True 
     197 
     198        def getActions(): 
     199            return admin.get_form_actions( None ) 
     200       
     201        post( getActions, self.setActions ) 
     202        self.update_title() 
     203     
     204    def update_title( self ): 
     205   
     206        def get_title(): 
     207            obj = self.getEntity() 
     208            return u'%s %s' % ( self.title_prefix, self.admin.get_verbose_identifier( obj ) ) 
     209       
     210        post( get_title, self.change_title ) 
    162211     
    163212    def getEntity( self ): 
    164         return self.model._get_object( self.widget_mapper.currentIndex() ) 
     213        return self.model._get_object( self._form.get_index() ) 
    165214     
    166215    def setActions( self, actions ): 
     
    177226    def viewFirst( self ): 
    178227        """select model's first row""" 
    179         # submit should not happen a second time, since then we don't want 
    180         # the widgets data to be written to the model 
    181         self.widget_mapper.submit() 
    182         self.widget_mapper.toFirst() 
     228        self._form.submit() 
     229        self._form.to_first() 
    183230        self.update_title() 
    184231     
     
    187234        # submit should not happen a second time, since then we don't want 
    188235        # the widgets data to be written to the model 
    189         self.widget_mapper.submit() 
    190         self.widget_mapper.toLast() 
     236        self._form.submit() 
     237        self._form.to_last() 
    191238        self.update_title() 
    192239     
     
    195242        # submit should not happen a second time, since then we don't want 
    196243        # the widgets data to be written to the model 
    197         self.widget_mapper.submit() 
    198         self.widget_mapper.toNext() 
     244        self._form.submit() 
     245        self._form.to_next() 
    199246        self.update_title() 
    200247     
     
    203250        # submit should not happen a second time, since then we don't want 
    204251        # the widgets data to be written to the model 
    205         self.widget_mapper.submit() 
    206         self.widget_mapper.toPrevious() 
     252        self._form.submit() 
     253        self._form.to_previous() 
    207254        self.update_title() 
    208255     
     
    210257        import sip 
    211258        if not valid: 
    212             reply = self.validator.validityDialog( self.widget_mapper.currentIndex(), self ).exec_() 
     259            reply = self.validator.validityDialog( self._form.get_index(), self ).exec_() 
    213260            if reply == QtGui.QMessageBox.Discard: 
    214261            # clear mapping to prevent data being written again to the model, 
    215262            # then we reverted the row 
    216                 self.widget_mapper.clearMapping() 
    217                 self.model.revertRow( self.widget_mapper.currentIndex() ) 
     263                self._form.clear_mapping() 
     264                self.model.revertRow( self._form.get_index() ) 
    218265                self.validate_before_close = False 
    219266                self.emit( self.closeAfterValidation ) 
     
    228275            # submit should not happen a second time, since then we don't 
    229276            # want the widgets data to be written to the model 
    230             self.widget_mapper.submit() 
     277            self._form.submit() 
    231278       
    232279            def validate(): 
    233                 return self.validator.isValid( self.widget_mapper.currentIndex() ) 
     280                return self.validator.isValid( self._form.get_index() ) 
    234281         
    235282            post( validate, self.showMessage )