Changeset 1186
- Timestamp:
- 03/13/10 06:31:24 (5 months ago)
- Location:
- trunk/camelot
- Files:
-
- 9 modified
-
admin/validator/entity_validator.py (modified) (1 diff)
-
admin/validator/object_validator.py (modified) (1 diff)
-
view/controls/formview.py (modified) (1 diff)
-
view/controls/tableview.py (modified) (2 diffs)
-
view/elixir_admin.py (modified) (2 diffs)
-
view/field_attributes.py (modified) (10 diffs)
-
view/proxy/collection_proxy.py (modified) (1 diff)
-
view/proxy/queryproxy.py (modified) (9 diffs)
-
view/wizard/pages/form_page.py (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/camelot/admin/validator/entity_validator.py
r987 r1186 37 37 """ 38 38 39 def objectValidity(self, entity_instance): 40 """:return: list of messages explaining invalid data 41 empty list if object is valid 42 """ 43 from camelot.view.controls import delegates 44 messages = [] 45 fields_and_attributes = dict(self.admin.get_columns()) 46 fields_and_attributes.update(dict(self.admin.get_fields())) 47 for field, attributes in fields_and_attributes.items(): 48 # if the field was not editable, don't waste any time 49 if attributes['editable']: 50 value = getattr(entity_instance, field) 51 #@todo: check if field is a primary key instead of checking 52 # whether the name is id 53 if attributes['nullable']!=True and field!='id': 54 logger.debug('column %s is required'%(field)) 55 if 'delegate' not in attributes: 56 raise Exception('no delegate specified for %s'%(field)) 57 is_null = False 58 if value==None: 59 is_null = True 60 elif (attributes['delegate'] == delegates.CodeDelegate) and \ 61 (sum(len(c) for c in value) == 0): 62 is_null = True 63 elif (attributes['delegate'] == delegates.PlainTextDelegate) and (len(value) == 0): 64 is_null = True 65 elif (attributes['delegate'] == delegates.Many2OneDelegate) and (not value.id): 66 is_null = True 67 elif (attributes['delegate'] == delegates.VirtualAddressDelegate) and (not value[1]): 68 is_null = True 69 if is_null: 70 messages.append(u'%s is a required field' % (attributes['name'])) 71 logger.debug(u'messages : %s'%(u','.join(messages))) 72 return messages 39 -
trunk/camelot/admin/validator/object_validator.py
r1060 r1186 46 46 empty list if object is valid 47 47 """ 48 return [] 48 from camelot.view.controls import delegates 49 messages = [] 50 fields_and_attributes = dict(self.admin.get_columns()) 51 fields_and_attributes.update(dict(self.admin.get_fields())) 52 for field, attributes in fields_and_attributes.items(): 53 # if the field was not editable, don't waste any time 54 if attributes['editable']: 55 value = getattr(entity_instance, field) 56 #@todo: check if field is a primary key instead of checking 57 # whether the name is id, but this should only happen in the entity validator 58 if attributes['nullable']!=True and field!='id': 59 logger.debug('column %s is required'%(field)) 60 if 'delegate' not in attributes: 61 raise Exception('no delegate specified for %s'%(field)) 62 is_null = False 63 if value==None: 64 is_null = True 65 elif (attributes['delegate'] == delegates.CodeDelegate) and \ 66 (sum(len(c) for c in value) == 0): 67 is_null = True 68 elif (attributes['delegate'] == delegates.PlainTextDelegate) and (len(value) == 0): 69 is_null = True 70 elif (attributes['delegate'] == delegates.Many2OneDelegate) and (not value.id): 71 is_null = True 72 elif (attributes['delegate'] == delegates.VirtualAddressDelegate) and (not value[1]): 73 is_null = True 74 if is_null: 75 messages.append(u'%s is a required field' % (attributes['name'])) 76 logger.debug(u'messages : %s'%(u','.join(messages))) 77 return messages 49 78 50 79 def isValid(self, row): -
trunk/camelot/view/controls/formview.py
r1185 r1186 55 55 self.setLayout( self._widget_layout ) 56 56 57 def get_model(self): 58 return self._model 59 57 60 def set_model(self, model): 58 61 self._model = model -
trunk/camelot/view/controls/tableview.py
r1184 r1186 127 127 self.number_of_rows = None 128 128 layout.addLayout( widget_layout ) 129 self._expanded_search = QtGui.Q Label('Expanded')129 self._expanded_search = QtGui.QWidget() 130 130 self._expanded_search.hide() 131 131 layout.addWidget(self._expanded_search) … … 133 133 self.setSizePolicy( QSizePolicy.Minimum, QSizePolicy.Fixed ) 134 134 self.setNumberOfRows( 0 ) 135 135 post( admin.get_columns, self._fill_expanded_search_options ) 136 137 def _fill_expanded_search_options(self, columns): 138 layout = QtGui.QHBoxLayout() 139 for field, attributes in columns: 140 if 'operators' in attributes: 141 widget = QtGui.QLabel(field) 142 layout.addWidget( widget ) 143 self._expanded_search.setLayout( layout ) 144 145 136 146 def expand_search_options(self): 137 147 if self._expanded_search.isHidden(): -
trunk/camelot/view/elixir_admin.py
r1146 r1186 169 169 from elixir import entities 170 170 mapped_entities = [str(e) for e in entities] 171 logger.error(u'%s is not a mapped class, mapped classes include %s'%(self.entity, u','.join( mapped_entities)),171 logger.error(u'%s is not a mapped class, mapped classes include %s'%(self.entity, u','.join([unicode(me) for me in mapped_entities])), 172 172 exc_info=exception) 173 173 raise exception … … 401 401 model = QueryTableProxy( 402 402 tableview.admin, 403 tableview._table_model. _query_getter,403 tableview._table_model.get_query_getter(), 404 404 tableview.admin.get_fields, 405 405 max_number_of_rows=1 -
trunk/camelot/view/field_attributes.py
r1179 r1186 31 31 import camelot.types 32 32 import datetime 33 import operator 33 34 34 35 from controls import delegates … … 45 46 ) 46 47 48 _numerical_operators = (operator.eq, operator.lt, operator.le, operator.gt, operator.ge) 47 49 48 50 _sqlalchemy_to_python_type_ = { … … 53 55 'nullable': True, 54 56 'delegate': delegates.BoolDelegate, 55 'from_string': bool_from_string 57 'from_string': bool_from_string, 58 'operators' : (operator.eq,), 56 59 }, 57 60 … … 61 64 'nullable': True, 62 65 'delegate': delegates.BoolDelegate, 63 'from_string': bool_from_string 66 'from_string': bool_from_string, 67 'operators' : (operator.eq,), 64 68 }, 65 69 … … 72 76 'nullable': True, 73 77 'delegate': delegates.DateDelegate, 74 'from_string': date_from_string 78 'from_string': date_from_string, 79 'operators' : _numerical_operators, 75 80 }, 76 81 … … 83 88 'format': constants.camelot_time_format, 84 89 'nullable': True, 85 'from_string': time_from_string 90 'from_string': time_from_string, 91 'operators': _numerical_operators, 86 92 }, 87 93 … … 94 100 'nullable': True, 95 101 'delegate': delegates.DateTimeDelegate, 96 'from_string': datetime_from_string 102 'from_string': datetime_from_string, 103 'operators': _numerical_operators, 97 104 }, 98 105 … … 105 112 'nullable': True, 106 113 'delegate': delegates.FloatDelegate, 107 'from_string': float_from_string 114 'from_string': float_from_string, 115 'operators': _numerical_operators, 108 116 }, 109 117 … … 117 125 'from_string': int_from_string, 118 126 'to_string': unicode, 119 'widget': 'int' 127 'widget': 'int', 128 'operators': _numerical_operators, 120 129 }, 121 130 … … 128 137 'delegate': delegates.IntegerDelegate, 129 138 'from_string': int_from_string, 130 'widget': 'int' 139 'widget': 'int', 140 'operators': _numerical_operators, 131 141 }, 132 142 -
trunk/camelot/view/proxy/collection_proxy.py
r1174 r1186 259 259 self.logger.debug( 'initialization finished' ) 260 260 261 def get_validator(self): 262 return self.validator 263 261 264 def map_to_source(self, sorted_row_number): 262 265 """Converts a sorted row number to a row number of the source -
trunk/camelot/view/proxy/queryproxy.py
r1170 r1186 33 33 logger = logging.getLogger('camelot.view.proxy.queryproxy') 34 34 35 from collection_proxy import CollectionProxy, stripped_data_to_unicode, \ 36 strip_data_from_object, tool_tips_from_object, \ 37 background_colors_from_object 38 from camelot.view.model_thread import model_function, gui_function 35 from collection_proxy import CollectionProxy, strip_data_from_object 36 from camelot.view.model_thread import model_function, gui_function, post 39 37 40 38 … … 50 48 logger.debug('initialize query table') 51 49 self._query_getter = query_getter 50 self._sort_decorator = None 52 51 #rows appended to the table which have not yet been flushed to the 53 52 #database, and as such cannot be a result of the query … … 56 55 columns_getter, max_number_of_rows=10, edits=None) 57 56 57 def get_query_getter(self): 58 if not self._sort_decorator: 59 return self._query_getter 60 else: 61 62 def sorted_query_getter(): 63 return self._sort_decorator(self._query_getter()) 64 65 return sorted_query_getter 66 58 67 @model_function 59 68 def _clean_appended_rows(self): … … 69 78 def getRowCount(self): 70 79 self._clean_appended_rows() 71 return self. _query_getter().count() + len(self._appended_rows)80 return self.get_query_getter()().count() + len(self._appended_rows) 72 81 73 82 @gui_function … … 80 89 81 90 def collection_getter(): 82 return self. _query_getter().all()91 return self.get_query_getter()().all() 83 92 84 93 return collection_getter … … 86 95 @gui_function 87 96 def sort( self, column, order ): 88 pass 97 98 def create_set_sort_decorator(column, order): 99 100 def set_sort_decorator(): 101 from sqlalchemy import orm 102 from sqlalchemy.exceptions import InvalidRequestError 103 field_name = self._columns[column][0] 104 class_attribute = getattr(self.admin.entity, field_name) 105 mapper = orm.class_mapper(self.admin.entity) 106 try: 107 property = mapper.get_property( 108 field_name, 109 resolve_synonyms=True 110 ) 111 except InvalidRequestError: 112 # 113 # If the field name is not a property of the mapper, we cannot 114 # sort it using sql 115 # 116 return self.rows 117 118 def create_sort_decorator(class_attribute, order): 119 120 def sort_decorator(query): 121 if order: 122 return query.order_by(class_attribute.desc()) 123 else: 124 return query.order_by(class_attribute) 125 126 return sort_decorator 127 128 129 self._sort_decorator = create_sort_decorator(class_attribute, order) 130 return self.rows 131 132 return set_sort_decorator 133 134 post( create_set_sort_decorator(column, order), self._refresh_content ) 89 135 90 136 def append(self, o): … … 103 149 def getData(self): 104 150 """Generator for all the data queried by this proxy""" 105 for _i,o in enumerate(self. _query_getter().all()):151 for _i,o in enumerate(self.get_query_getter()().all()): 106 152 yield strip_data_from_object(o, self.getColumns()) 107 153 … … 109 155 def _extend_cache(self, offset, limit): 110 156 """Extend the cache around row""" 111 q = self. _query_getter().offset(offset).limit(limit)157 q = self.get_query_getter()().offset(offset).limit(limit) 112 158 columns = self.getColumns() 113 159 for i, o in enumerate(q.all()): … … 136 182 pass 137 183 # momentary hack for list error that prevents forms to be closed 138 res = self. _query_getter().offset(row)184 res = self.get_query_getter()().offset(row) 139 185 if isinstance(res, list): 140 186 res = res[0] -
trunk/camelot/view/wizard/pages/form_page.py
r1185 r1186 26 26 # ============================================================================ 27 27 28 from PyQt4 import QtGui 28 from PyQt4 import QtGui, QtCore 29 29 30 30 from camelot.core.utils import ugettext as _ 31 31 from camelot.view.art import Icon 32 from camelot.view.model_thread import post 32 33 33 34 class FormPage(QtGui.QWizardPage): … … 37 38 38 39 To access the data stored by the wizard form into a data object, use its 39 get_data method . 40 get_data method. 41 42 The 'Next' button will only be activated when the form is complete. 40 43 """ 41 44 … … 57 60 self.setPixmap(QtGui.QWizard.LogoPixmap, self.get_icon().getQPixmap()) 58 61 self._data = self.Data() 62 self._complete = False 59 63 60 64 admin = self.get_admin() 61 collection_proxy= CollectionProxy(admin, lambda:[self._data], admin.get_fields)65 self._model = CollectionProxy(admin, lambda:[self._data], admin.get_fields) 62 66 63 67 layout = QtGui.QVBoxLayout() 64 68 form = FormWidget(admin) 65 form.set_model(collection_proxy) 69 self.connect(form, FormWidget.changed_signal, self._form_changed) 70 form.set_model(self._model) 66 71 layout.addWidget(form) 67 72 self.setLayout(layout) 73 74 def _form_changed(self): 75 76 def is_valid(): 77 return self._model.get_validator().isValid(0) 78 79 post(is_valid, self._change_complete) 80 81 def _change_complete(self, complete): 82 self._complete = complete 83 self.emit(QtCore.SIGNAL('completeChanged ()')) 68 84 85 def isComplete(self): 86 return self._complete 87 69 88 def get_admin(self): 70 89 from camelot.view.application_admin import get_application_admin
