| Home | Trees | Indices | Help |
|
|---|
|
|
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 """form view"""
29
30 import logging
31 logger = logging.getLogger('camelot.view.controls.formview')
32
33 from PyQt4 import QtCore
34 from PyQt4 import QtGui
35 from camelot.view.model_thread import model_function
40 super(FormView, self).__init__(None)
41 self.admin = admin
42 self.model = model
43 self.index = index
44 self.setWindowTitle(title)
45 self.widget_mapper = QtGui.QDataWidgetMapper()
46 self.widget_layout = QtGui.QHBoxLayout()
47
48 self.closeAfterValidation = QtCore.SIGNAL('closeAfterValidation()')
49 sig = 'dataChanged(const QModelIndex &, const QModelIndex &)'
50 self.connect(self.model, QtCore.SIGNAL(sig), self.dataChanged)
51
52 self.widget_mapper.setModel(model)
53 self.setLayout(self.widget_layout)
54 self.setMinimumSize(admin.form_size[0], admin.form_size[1])
55
56 self.validator = admin.createValidator(model)
57 self.validate_before_close = True
58
59 def getColumnsAndForm():
60 return (self.model.getColumns(), self.admin.getForm())
61
62 self.admin.mt.post(getColumnsAndForm,
63 lambda (columns, form):
64 self.handleGetColumnsAndForm(columns, form))
65
66 def getActions():
67 return admin.getFormActions(None)
68
69 self.admin.mt.post(getActions, self.setActions)
70
74
76 delegate = self.model.getItemDelegate()
77 self.setColumnsFormAndDelegate(columns, form, delegate)
78
80 """Create value and label widgets"""
81 widgets = {}
82 self.widget_mapper.setItemDelegate(delegate)
83
84 for i, (field_name, field_attributes) in enumerate(columns):
85 option = None
86 model_index = self.model.index(self.index, i)
87 widget_label = QtGui.QLabel(field_attributes['name'])
88 widget_editor = delegate.createEditor(None, option, model_index)
89
90 # required fields font is bold
91 if ('nullable' in field_attributes) and \
92 (not field_attributes['nullable']):
93 font = QtGui.QApplication.font()
94 font.setBold(True)
95 widget_label.setFont(font)
96
97 self.widget_mapper.addMapping(widget_editor, i)
98 widgets[field_name] = (widget_label, widget_editor)
99
100 self.widget_mapper.setCurrentIndex(self.index)
101 self.widget_layout.insertWidget(0, form.render(widgets, self))
102 self.widget_layout.setContentsMargins(7, 7, 7, 7)
103
106
108 if actions:
109 from actions import ActionsBox
110 logger.debug('setting Actions for formview')
111 self.actions_widget = ActionsBox(self, self.admin.mt, self.getEntity)
112 self.actions_widget.setActions(actions)
113 self.widget_layout.insertWidget(1, self.actions_widget)
114
116 """select model's first row"""
117 # submit should not happen a second time, since then we don't want
118 # the widgets data to be written to the model
119 self.widget_mapper.submit()
120 self.widget_mapper.toFirst()
121
123 """select model's last row"""
124 # submit should not happen a second time, since then we don't want
125 # the widgets data to be written to the model
126 self.widget_mapper.submit()
127 self.widget_mapper.toLast()
128
130 """select model's next row"""
131 # submit should not happen a second time, since then we don't want
132 # the widgets data to be written to the model
133 self.widget_mapper.submit()
134 self.widget_mapper.toNext()
135
137 """select model's previous row"""
138 # submit should not happen a second time, since then we don't want
139 # the widgets data to be written to the model
140 self.widget_mapper.submit()
141 self.widget_mapper.toPrevious()
142
144 logger.debug('validate before close : %s' % self.validate_before_close)
145 if self.validate_before_close:
146 # submit should not happen a second time, since then we don't
147 # want the widgets data to be written to the model
148 self.widget_mapper.submit()
149
150 def validate():
151 return self.validator.isValid(self.index)
152
153 def showMessage(valid):
154 if not valid:
155 messages = u'\n'.join(self.validator.validityMessages(self.index))
156 mbmessages = u"Changes in this window could not be saved :\n%s" \
157 u"\n Do you want to lose your changes ?" % messages
158 reply = QtGui.QMessageBox.question(self,
159 u'Unsaved changes',
160 mbmessages,
161 QtGui.QMessageBox.Yes,
162 QtGui.QMessageBox.No)
163 if reply == QtGui.QMessageBox.Yes:
164 # clear mapping to prevent data being written again to the model,
165 # then we reverted the row
166 self.widget_mapper.clearMapping()
167 self.model.revertRow(self.index)
168 from camelot.view.workspace import get_workspace
169 self.validate_before_close = False
170 self.emit(self.closeAfterValidation)
171 else:
172 from camelot.view.workspace import get_workspace
173 self.validate_before_close = False
174 self.emit(self.closeAfterValidation)
175
176 self.admin.mt.post(validate, showMessage)
177 return False
178
179 return True
180
182 logger.debug('formview closed')
183 if self.validateClose():
184 event.accept()
185 else:
186 event.ignore()
187
188 @model_function
190 """generates html of the form"""
191
192 import settings
193 from jinja import Environment
194 from jinja import FileSystemLoader
195
196 def to_html(d=u''):
197 """Jinja 1 filter to convert field values to their default html
198 representation
199 """
200
201 def wrapped_in_table(env, context, value):
202 if isinstance(value, list):
203 return u'<table><tr><td>' +\
204 u'</td></tr><tr><td>'.join([unicode(e) for e in value]) +\
205 u'</td></tr></table>'
206 return unicode(value)
207
208 return wrapped_in_table
209
210 entity = self.getEntity()
211 fields = self.admin.getFields()
212 table = [dict(field_attributes = field_attributes,
213 value = getattr(entity, name))
214 for name, field_attributes in fields]
215
216 context = {
217 'title': self.admin.getName(),
218 'table': table,
219 }
220
221 ld = FileSystemLoader(settings.CAMELOT_TEMPLATES_DIRECTORY)
222 env = Environment(loader=ld)
223 env.filters['to_html'] = to_html
224 tp = env.get_template('form_view.html')
225
226 return tp.render(context)
227
231
| Home | Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1 on Sat Jan 31 18:50:03 2009 | http://epydoc.sourceforge.net |