16 |
# write to the Free Software Foundation, Inc., 59 Temple Place |
# write to the Free Software Foundation, Inc., 59 Temple Place |
17 |
# - Suite 330, Boston, MA 02111-1307, USA. |
# - Suite 330, Boston, MA 02111-1307, USA. |
18 |
# |
# |
19 |
# Copyright 2001-2002 Free Software Foundation |
# Copyright 2001-2003 Free Software Foundation |
20 |
# |
# |
21 |
# FILE: |
# FILE: |
22 |
# GFInstance.py |
# GFInstance.py |
23 |
# |
# |
24 |
# DESCRIPTION: |
# DESCRIPTION: |
25 |
# Client startup file that parses args, builds form from file |
# GFInstance manages forms instances in a 1:N relationship. |
26 |
# and passes control to a UI. |
# It sits between the UI and the form and passes events |
27 |
|
# between the two in a semi-intelligent manner. |
28 |
# |
# |
29 |
# NOTES: |
# NOTES: |
30 |
# Once all the events are moved back in here |
# Once all the events are moved back in here |
|
# debug |
|
31 |
# make the next/prec methods more generic in the GFForm |
# make the next/prec methods more generic in the GFForm |
32 |
# change self._form in here to a list |
# change self._form in here to a list |
33 |
|
|
36 |
from gnue.forms.GFForm import * |
from gnue.forms.GFForm import * |
37 |
from gnue.forms.GFParser import loadFile |
from gnue.forms.GFParser import loadFile |
38 |
from gnue.forms import VERSION |
from gnue.forms import VERSION |
39 |
from gnue.common import GDebug, GDataObjects |
from gnue.forms import GFKeyMapper |
40 |
|
from gnue.common import GDebug, GDataObjects, GConnections |
41 |
from gnue.common import events |
from gnue.common import events |
42 |
|
from gnue.common.FileUtils import openResource |
43 |
|
|
44 |
from gnue.common.GClientApp import * |
from gnue.common.GClientApp import * |
45 |
|
|
47 |
# |
# |
48 |
# Initialize the class |
# Initialize the class |
49 |
# |
# |
50 |
def __init__(self, manager, serial, connections, ui, disableSplash=0, |
def __init__(self, manager, connections, ui, disableSplash=0, |
51 |
parameters={}): |
parameters={}): |
52 |
|
# |
53 |
|
# Configure event handling |
54 |
|
# |
55 |
self.eventController = events.EventController() |
self.eventController = events.EventController() |
|
|
|
56 |
events.EventAware.__init__(self, self.eventController) |
events.EventAware.__init__(self, self.eventController) |
|
|
|
|
self.connections = connections |
|
|
self.manager = manager |
|
|
self._serial = serial |
|
|
self._uimodule = ui |
|
|
self._disableSplash = disableSplash |
|
|
self._parameters = parameters |
|
|
|
|
|
# Incoming events |
|
57 |
self.registerEventListeners( { |
self.registerEventListeners( { |
58 |
# Datasource trigger events |
# Datasource trigger events |
59 |
'preCommit' : self.preCommit, |
'preCommit' : self.preCommit, |
61 |
'preInsert' : self.preInsert, |
'preInsert' : self.preInsert, |
62 |
'preDelete' : self.preDelete, |
'preDelete' : self.preDelete, |
63 |
'onRecordTouched' : self.onRecordTouched, |
'onRecordTouched' : self.onRecordTouched, |
64 |
|
'onQueryNewRecord' : self.onQueryNewRecord, |
65 |
|
|
66 |
# Focus-related events |
# Focus-related events |
67 |
'requestNEXTENTRY' : self.nextEntry, |
'requestNEXTENTRY' : self.nextEntry, |
92 |
'requestABOUT' : self.executeAbout, |
'requestABOUT' : self.executeAbout, |
93 |
'requestMODETOGGLE' : self.toggleInsertMode, |
'requestMODETOGGLE' : self.toggleInsertMode, |
94 |
'fireTRIGGER' : self.fireTrigger, |
'fireTRIGGER' : self.fireTrigger, |
95 |
|
'buttonActivated' : self.fireButton, |
96 |
|
|
97 |
# "Entry" events (proxied) |
# "Entry" events (proxied) |
98 |
'requestKEYPRESS' : self.proxyEntryEvent, |
'requestKEYPRESS' : self.proxyEntryEvent, |
117 |
'requestCOPY' : self.proxyEntryEvent, |
'requestCOPY' : self.proxyEntryEvent, |
118 |
'requestCUT' : self.proxyEntryEvent, |
'requestCUT' : self.proxyEntryEvent, |
119 |
'requestPASTE' : self.proxyEntryEvent, |
'requestPASTE' : self.proxyEntryEvent, |
|
|
|
120 |
} ) |
} ) |
121 |
|
|
122 |
|
self.connections = connections # Link to the GBaseApp's GConnections |
123 |
|
self.manager = manager # Link to the GBaseApp Instance that |
124 |
|
# created this GFInstance |
125 |
|
self._uimodule = ui # The UI created in the GBaseApp |
126 |
|
self._disableSplash = disableSplash # Disable splashscreen |
127 |
|
self._parameters = parameters # The parameters passed to the |
128 |
|
# GBaseApp instance |
129 |
|
self._formsDictionary = {} # A dictionary containing all the |
130 |
|
# forms loaded from a file |
131 |
|
|
132 |
|
# |
133 |
|
# Load user customized key mappings |
134 |
|
# |
135 |
|
options = gConfigDict() |
136 |
|
mapping = {} |
137 |
|
|
138 |
|
for key in options.keys(): |
139 |
|
if string.lower(key)[:4] == 'key_': |
140 |
|
mapping[key[4:]] = options[key] |
141 |
|
|
142 |
|
GFKeyMapper.KeyMapper.loadUserKeyMap(mapping) |
143 |
|
|
144 |
|
# |
145 |
|
# addFormFromFile |
146 |
|
# |
147 |
|
# Loads a GObj based form tree when passed a valid file name. |
148 |
|
# A copy of the instance is passed into the parser so that |
149 |
|
# it can work with things like the GConnections stored in |
150 |
|
# the base app |
151 |
|
# |
152 |
|
def addFormFromFile(self,fileName): |
153 |
|
# |
154 |
|
# Load the file bypassing the initialization |
155 |
|
# We bypass the initialization because <dialog>s are |
156 |
|
# really <form>s and they don't like being children |
157 |
|
# of another form |
158 |
|
# |
159 |
|
try: |
160 |
|
fileHandle=openResource(fileName) |
161 |
|
form = loadFile (fileHandle, self, initialize=0) |
162 |
|
fileHandle.close() |
163 |
|
except IOError, mesg: |
164 |
|
self.manager.handleStartupError(_("Unable to open file\n\n %s")%mesg) |
165 |
|
|
166 |
|
# |
167 |
|
# Add the main form into the dictionary |
168 |
|
# |
169 |
|
self._formsDictionary['__main__'] = form |
170 |
|
|
171 |
|
# |
172 |
|
# Extract the child <dialog>s from the main form tree |
173 |
|
# |
174 |
|
self.reapSubforms(form) |
175 |
|
|
176 |
|
# |
177 |
|
# Initialize all the forms |
178 |
|
# |
179 |
|
for dialog in self._formsDictionary.keys(): |
180 |
|
object = self._formsDictionary[dialog] |
181 |
|
object.phaseInit() |
182 |
|
|
183 |
|
self._form = form # TODO: temp hack to keep it working |
184 |
|
|
185 |
|
# |
186 |
|
# removes the subforms from the main tree before |
187 |
|
# any UI stuff is constructed |
188 |
|
# |
189 |
|
def reapSubforms(self,formTree): |
190 |
|
for child in formTree._children: |
191 |
|
if isinstance(child, GFForm): |
192 |
|
child._parent = None |
193 |
|
self._formsDictionary[child.name] = child |
194 |
|
formTree._children.remove(child) |
195 |
|
|
196 |
|
# |
197 |
|
# activate |
198 |
|
# |
199 |
|
# Tells the instance to bring up it's UI, activate the __main__ form, |
200 |
|
# and pass control to the UI |
201 |
|
# |
202 |
|
def activate(self): |
203 |
|
# |
204 |
|
# Construct the |
205 |
|
self._uiinstance = self._uimodule.GFUserInterface(self.eventController, self._disableSplash) |
206 |
|
|
207 |
|
# |
208 |
|
# Build the UIs for all the forms |
209 |
|
# |
210 |
|
for dialog in self._formsDictionary.keys(): |
211 |
|
self.buildForm(dialog) |
212 |
|
|
213 |
|
## for dialog in self._formsDictionary.keys(): |
214 |
|
## print dialog |
215 |
|
## print self._uiinstance._uiDictionary[dialog]._formToUIWidget |
216 |
|
|
217 |
|
# |
218 |
|
# Bring up the main form |
219 |
|
# |
220 |
|
self.activateForm('__main__') |
221 |
|
# TODO : Hard coded test case for use w/ dialog.gfd |
222 |
|
#self.activateForm('selector') |
223 |
|
|
224 |
|
self._uiinstance.mainLoop() |
225 |
|
|
226 |
|
# |
227 |
|
# Builds a UI based upon a specific form and |
228 |
|
# sets that form to active status |
229 |
|
# |
230 |
|
def activateForm(self,formName='__main__'): |
231 |
|
self._form = self._formsDictionary[formName] |
232 |
|
## print "Current entry", self._form._currentEntry |
233 |
|
|
234 |
|
if not self._form._currentEntry: |
235 |
|
raise _('There are no navigable widgets in this form. Unable to display.') |
236 |
|
|
237 |
|
self._uiinstance.activateForm(formName) |
238 |
|
|
239 |
|
self.dispatchEvent('gotoENTRY',object=self._form._currentEntry, |
240 |
|
_form=self._form) |
241 |
|
self.dispatchEvent('updateENTRY',self._form._currentEntry) |
242 |
|
self._form.refreshDisplay(self._form) |
243 |
|
self.updateStatus() |
244 |
|
|
245 |
|
# |
246 |
|
# buildForm |
247 |
|
# |
248 |
|
# Requests that the ui driver build a user interface |
249 |
|
# for a form tree. |
250 |
|
# |
251 |
|
def buildForm(self,formName='__main__'): |
252 |
|
form = self._formsDictionary[formName] |
253 |
|
|
254 |
|
try: |
255 |
|
self._uiinstance.buildForm(form, formName) |
256 |
|
|
257 |
|
except GConnections.Error, mesg: |
258 |
|
self.handleStartupError(mesg) |
259 |
|
|
260 |
|
except GDataObjects.ConnectError, mesg: |
261 |
|
self.handleStartupError( |
262 |
|
_("Unable to login to datasource.\n\n %s") %mesg) |
263 |
|
|
264 |
|
except GDataObjects.ConnectionError, mesg: |
265 |
|
self.handleStartupError( |
266 |
|
_("Error while communicating with datasource.\n\n %s") %mesg) |
267 |
|
|
268 |
|
except GDataObjects.Error, mesg: |
269 |
|
self.handleStartupError(mesg) |
270 |
|
|
271 |
|
|
272 |
|
# |
273 |
|
# |
274 |
|
# UI FUNCTIONS |
275 |
|
# |
276 |
|
# Routines to update parts of the UI's status bar |
277 |
|
# |
278 |
|
def updateInsertMode(self): |
279 |
|
self.updateStatusBar(insertMode=self._form._insertMode) |
280 |
|
|
281 |
|
def updateRecordCounter(self): |
282 |
|
self.updateStatusBar(currentRecord=self._form._currentBlock._currentRecord+1, |
283 |
|
maxRecord=self._form._currentBlock._recordCount) |
284 |
|
|
285 |
|
def updatePageCounter(self): |
286 |
|
maxPages = len(self._form._layout._pageList) |
287 |
|
count = self._form._layout._pageList.index(self._form._currentPage) |
288 |
|
self.updateStatusBar(currentPage=count+1,maxPage=maxPages) |
289 |
|
|
290 |
|
def updateTip(self): |
291 |
|
tip = '' |
292 |
|
if self._form._currentEntry: |
293 |
|
if self._form._currentEntry.getOption('tip'): |
294 |
|
tip = self._form._currentEntry.getOption('tip') |
295 |
|
self.updateStatusBar(tip=tip) |
296 |
|
|
297 |
|
def updateRecordStatus(self): |
298 |
|
if self._form._currentBlock._resultSet.current.isPending(): |
299 |
|
status = 'modified' |
300 |
|
elif self._form._currentBlock.mode == 'query': |
301 |
|
status = 'query' |
302 |
|
elif self._form._currentBlock._resultSet.current.isDeleted(): |
303 |
|
status = 'deleted' |
304 |
|
else: |
305 |
|
status = 'saved' |
306 |
|
self.updateStatusBar(recordStatus=status) |
307 |
|
|
308 |
|
def updateStatus(self): |
309 |
|
self.updateTip() |
310 |
|
self.updateInsertMode() |
311 |
|
self.updateRecordCounter() |
312 |
|
self.updateRecordStatus() |
313 |
|
self.updatePageCounter() |
314 |
|
|
315 |
|
def updateStatusBar(self, tip=None, recordStatus=None, insertMode=None, |
316 |
|
currentRecord=None,maxRecord=None, currentPage=None, |
317 |
|
maxPage=None): |
318 |
|
self.dispatchEvent('uiUPDATESTATUS',tip=tip, recordStatus=recordStatus, |
319 |
|
insertMode=insertMode, currentRecord=currentRecord, |
320 |
|
maxRecord=maxRecord, currentPage=currentPage, |
321 |
|
maxPage=maxPage) |
322 |
|
|
323 |
|
# |
324 |
# |
# |
325 |
# Associate a form object with this instance |
# EVENT FUNCTIONS |
326 |
|
# |
327 |
|
# From here down should be nothing but eventListeners listed |
328 |
|
# in the __init__ above. |
329 |
# |
# |
|
def setForm(self, form): |
|
|
self._form = form |
|
330 |
|
|
331 |
# |
# |
332 |
# Return this instance's serial number |
# _entryUpdated |
333 |
# |
# |
334 |
def getSerialNumber(self): |
# Common code snipped called when something has changed with an |
335 |
return self._serial |
# entry and it has to update the stat bar. Used to cut down on |
336 |
|
# repeated code. |
337 |
|
# |
338 |
|
def _entryUpdated(self): |
339 |
|
self.dispatchEvent('gotoENTRY',object=self._form._currentEntry, _form=self._form) |
340 |
|
self.updateRecordCounter() |
341 |
|
self.updateRecordStatus() |
342 |
|
|
343 |
# |
# |
344 |
# Return this instance's manager |
# scroll |
345 |
# |
# |
346 |
def getManager(self): |
# Called when a scrollbar is pressed. it should detect the type of scroll and call the right thing |
347 |
return self.manager |
def scroll (self, event): |
348 |
|
(ev, page)= event.data |
349 |
|
# print "->", ev, page |
350 |
|
if ev==0: |
351 |
|
self.prevRecord (event) |
352 |
|
elif ev==1: |
353 |
|
event.data= -page+1 |
354 |
|
self.jumpRecords (event) |
355 |
|
elif ev==2: |
356 |
|
# free scroll |
357 |
|
# dunno how to handle... |
358 |
|
pass |
359 |
|
elif ev==3: |
360 |
|
event.data= page-1 |
361 |
|
self.jumpRecords (event) |
362 |
|
elif ev==4: |
363 |
|
self.nextRecord (event) |
364 |
|
|
365 |
|
|
366 |
|
|
367 |
|
|
368 |
# |
# |
369 |
# proxyEntryEvent |
# proxyEntryEvent |
374 |
# any relevant events here and pass on to the entry. |
# any relevant events here and pass on to the entry. |
375 |
# |
# |
376 |
def proxyEntryEvent(self, event): |
def proxyEntryEvent(self, event): |
377 |
|
if event._form._currentEntry and \ |
378 |
|
event._form._currentEntry._type != 'GFButton': |
379 |
|
|
380 |
if self._form._currentEntry != None and \ |
handler = event._form._currentEntry._displayHandler |
|
self._form._currentEntry._type != 'GFButton': |
|
|
|
|
|
handler = self._form._currentEntry._displayHandler |
|
381 |
|
|
382 |
# If the display will need to be refreshed, |
# If the display will need to be refreshed, |
383 |
# then the proxied event should set this to 1 |
# then the proxied event should set this to 1 |
384 |
|
# TODO: Maybe this needs set to 0 and the handlers adjusted - jst |
385 |
event.refreshDisplay = 1 |
event.refreshDisplay = 1 |
386 |
|
|
387 |
# Pass off the event to the current entry's event handler |
# Pass off the event to the current entry's event handler |
399 |
messageBox = GFMsgBox(self, event.__errortext__) |
messageBox = GFMsgBox(self, event.__errortext__) |
400 |
messageBox.show() |
messageBox.show() |
401 |
|
|
|
|
|
402 |
# |
# |
403 |
# nextEntry |
# nextEntry |
404 |
# |
# |
406 |
# focus change to the next data entry object |
# focus change to the next data entry object |
407 |
# |
# |
408 |
def nextEntry(self, event): |
def nextEntry(self, event): |
409 |
if not self._form.endEditing(): |
if not event._form.endEditing(): |
410 |
return |
return |
411 |
message = self._form.nextEntry() |
message = event._form.nextEntry() |
412 |
if message: |
if message: |
413 |
messageBox = GFMsgBox(self, message) |
messageBox = GFMsgBox(self, message) |
414 |
messageBox.show() |
messageBox.show() |
415 |
return |
return |
416 |
self.dispatchEvent(events.Event('gotoENTRY',{'object':self._form._currentEntry})) |
self.dispatchEvent('gotoENTRY',object=event._form._currentEntry, _form=event._form) |
417 |
self.updateRecordStatus() |
self.updateRecordStatus() |
418 |
self.updateTip() |
self.updateTip() |
419 |
|
|
424 |
# focus change to the next data entry object |
# focus change to the next data entry object |
425 |
# |
# |
426 |
def previousEntry(self, event): |
def previousEntry(self, event): |
427 |
if not self._form.endEditing(): |
if not event._form.endEditing(): |
428 |
return |
return |
429 |
self._form.previousEntry() |
event._form.previousEntry() |
430 |
self.dispatchEvent(events.Event('gotoENTRY',{'object':self._form._currentEntry})) |
self.dispatchEvent('gotoENTRY',object=event._form._currentEntry, _form=event._form) |
431 |
self.updateRecordStatus() |
self.updateRecordStatus() |
432 |
self.updateTip() |
self.updateTip() |
433 |
|
|
438 |
# focus change to the next data entry block |
# focus change to the next data entry block |
439 |
# |
# |
440 |
def nextBlock(self,event): |
def nextBlock(self,event): |
441 |
if not self._form.endEditing(): |
if not event._form.endEditing(): |
442 |
return |
return |
443 |
self._form.nextBlock() |
event._form.nextBlock() |
444 |
self.dispatchEvent(events.Event('gotoENTRY',{'object':self._form._currentEntry})) |
self.dispatchEvent('gotoENTRY',object=event._form._currentEntry, _form=event._form) |
|
|
|
445 |
self.updateStatus() |
self.updateStatus() |
446 |
|
|
447 |
# |
# |
451 |
# focus change to the next data entry block |
# focus change to the next data entry block |
452 |
# |
# |
453 |
def previousBlock(self, event): |
def previousBlock(self, event): |
454 |
if not self._form.endEditing(): |
if not event._form.endEditing(): |
455 |
return |
return |
456 |
self._form.previousBlock() |
event._form.previousBlock() |
457 |
self.dispatchEvent(events.Event('gotoENTRY',{'object':self._form._currentEntry})) |
self.dispatchEvent('gotoENTRY',object=event._form._currentEntry, _form=event._form) |
458 |
self.updateStatus() |
self.updateStatus() |
459 |
|
|
460 |
# |
# |
463 |
# Called to make the form jump to a specific page |
# Called to make the form jump to a specific page |
464 |
# |
# |
465 |
def gotoPage(self,event): |
def gotoPage(self,event): |
466 |
if not self._form.endEditing(): |
if not event._form.endEditing(): |
467 |
return |
return |
468 |
self._form.findAndChangeFocus(self._form._pageList[event.data]) |
event._form.findAndChangeFocus(event._form._layout._pageList[event.data]) |
469 |
self.dispatchEvent(events.Event('gotoENTRY',{'object':self._form._currentEntry})) |
self.dispatchEvent('gotoENTRY',object=event._form._currentEntry, _form=event._form) |
470 |
self.updateStatus() |
self.updateStatus() |
471 |
|
|
472 |
# |
# |
|
# _entryUpdated |
|
|
# |
|
|
# Common code snipped called when something has changed with an |
|
|
# entry and it has to update the stat bar. Used to cut down on |
|
|
# repeated code. |
|
|
# |
|
|
def _entryUpdated(self): |
|
|
self.dispatchEvent(events.Event('gotoENTRY',{'object':self._form._currentEntry})) |
|
|
self.updateRecordCounter() |
|
|
self.updateRecordStatus() |
|
|
|
|
|
# |
|
|
# scroll |
|
|
# |
|
|
# Called when a scrollbar is pressed. it should detect the type of scroll and call the right thing |
|
|
def scroll (self, event): |
|
|
(ev, page)= event.data |
|
|
# print "->", ev, page |
|
|
if ev==0: |
|
|
self.prevRecord (event) |
|
|
elif ev==1: |
|
|
event.data= -page+1 |
|
|
self.jumpRecords (event) |
|
|
elif ev==2: |
|
|
# free scroll |
|
|
# dunno how to handle... |
|
|
pass |
|
|
elif ev==3: |
|
|
event.data= page-1 |
|
|
self.jumpRecords (event) |
|
|
elif ev==4: |
|
|
self.nextRecord (event) |
|
|
|
|
|
|
|
|
# |
|
473 |
# previousRecord |
# previousRecord |
474 |
# |
# |
475 |
# Called enever an event source has requested that the |
# Called enever an event source has requested that the |
476 |
# form advance to the next record in memory |
# form advance to the next record in memory |
477 |
# |
# |
478 |
def prevRecord(self, event): |
def prevRecord(self, event): |
479 |
if not self._form.endEditing(): |
if not event._form.endEditing(): |
480 |
return |
return |
481 |
message = self._form.prevRecord() |
message = event._form.prevRecord() |
482 |
if message: |
if message: |
483 |
messageBox = GFMsgBox(self,message) |
messageBox = GFMsgBox(self,message) |
484 |
messageBox.show() |
messageBox.show() |
492 |
# form advance to the next record in memory |
# form advance to the next record in memory |
493 |
# |
# |
494 |
def nextRecord(self, event): |
def nextRecord(self, event): |
495 |
if not self._form.endEditing(): |
if not event._form.endEditing(): |
496 |
return |
return |
497 |
message = self._form.nextRecord() |
message = event._form.nextRecord() |
498 |
if message: |
if message: |
499 |
messageBox = GFMsgBox(self,message) |
messageBox = GFMsgBox(self,message) |
500 |
messageBox.show() |
messageBox.show() |
508 |
# form advance to the first record in memory |
# form advance to the first record in memory |
509 |
# |
# |
510 |
def firstRecord(self, event): |
def firstRecord(self, event): |
511 |
if not self._form.endEditing(): |
if not event._form.endEditing(): |
512 |
return |
return |
513 |
message = self._form.firstRecord() |
message = event._form.firstRecord() |
514 |
if message: |
if message: |
515 |
messageBox = GFMsgBox(self,message) |
messageBox = GFMsgBox(self,message) |
516 |
messageBox.show() |
messageBox.show() |
524 |
# form advance to the last record in memory |
# form advance to the last record in memory |
525 |
# |
# |
526 |
def lastRecord(self, event): |
def lastRecord(self, event): |
527 |
if not self._form.endEditing(): |
if not event._form.endEditing(): |
528 |
return |
return |
529 |
message = self._form.lastRecord() |
message = event._form.lastRecord() |
530 |
if message: |
if message: |
531 |
messageBox = GFMsgBox(self,message) |
messageBox = GFMsgBox(self,message) |
532 |
messageBox.show() |
messageBox.show() |
540 |
# form move a specific record |
# form move a specific record |
541 |
# |
# |
542 |
def jumpToRecord(self,event): |
def jumpToRecord(self,event): |
543 |
if not self._form.endEditing(): |
if not event._form.endEditing(): |
544 |
return |
return |
545 |
try: |
try: |
546 |
count = abs(int(event.data))-1 |
count = abs(int(event.data))-1 |
547 |
except ValueError: |
except ValueError: |
548 |
message = _("Invalid numeric value entered.") |
message = _("Invalid numeric value entered.") |
549 |
else: |
else: |
550 |
message = self._form.jumpRecord(count) |
message = event._form.jumpRecord(count) |
551 |
|
|
552 |
if message: |
if message: |
553 |
messageBox = GFMsgBox(self,message) |
messageBox = GFMsgBox(self,message) |
556 |
|
|
557 |
self._entryUpdated() |
self._entryUpdated() |
558 |
|
|
559 |
|
# |
560 |
|
# jumpRecords |
561 |
|
# |
562 |
|
# jump a specified number of records |
563 |
|
# forward or backward. |
564 |
|
# |
565 |
def jumpRecords(self,event): |
def jumpRecords(self,event): |
566 |
if not self._form.endEditing(): |
if not event._form.endEditing(): |
567 |
return |
return |
568 |
|
|
569 |
count = event.data |
count = event.data |
570 |
# Doing this to reduce comparisons in the loop |
# Doing this to reduce comparisons in the loop |
571 |
if count > 0: |
if count > 0: |
572 |
method = self._form.nextRecord |
method = event._form.nextRecord |
573 |
else: |
else: |
574 |
method = self._form.prevRecord |
method = event._form.prevRecord |
575 |
for jumps in range(abs(int(count))): |
for jumps in range(abs(int(count))): |
576 |
method() |
method() |
577 |
|
|
578 |
self._entryUpdated() |
self._entryUpdated() |
579 |
|
|
580 |
|
# |
581 |
|
# executeExit |
582 |
|
# |
583 |
|
# When exit is requested verify that the data |
584 |
|
# has been saved |
585 |
|
# |
586 |
def executeExit(self, event): |
def executeExit(self, event): |
587 |
if not self._form.isSaved(): |
if not event._form.isSaved(): |
588 |
message = GFMsgBox(self, _('Data not saved. Save changes or clear the form to proceed.')) |
message = GFMsgBox(self, _('Data not saved. Save changes or clear the form to proceed.')) |
589 |
message.show() |
message.show() |
590 |
else: |
else: |
591 |
self._form.processTrigger('On-Exit') |
event._form.processTrigger('On-Exit') |
592 |
self.dispatchEvent(events.Event('exitApplication',_('Current data is saved'))) |
self.dispatchEvent('exitApplication',_('Current data is saved')) |
593 |
|
|
594 |
return |
return |
595 |
|
|
599 |
# Tells the form to mark a record for delete |
# Tells the form to mark a record for delete |
600 |
# |
# |
601 |
def deleteRecord(self, event): |
def deleteRecord(self, event): |
602 |
if self._form.readonly: |
if event._form.readonly: |
603 |
self.dispatchEvent(events.Event('formALERT',_('Form is readonly'))) |
self.dispatchEvent('formALERT',_('Form is readonly')) |
604 |
elif self._form._currentBlock.restrictDelete: |
elif event._form._currentBlock.restrictDelete: |
605 |
self.dispatchEvent(events.Event('formALERT',_('Block does not allow delete'))); |
self.dispatchEvent('formALERT',_('Block does not allow delete')) |
606 |
else: |
else: |
607 |
self._form.deleteRecord() |
event._form.deleteRecord() |
608 |
self.updateRecordStatus() |
self.updateRecordStatus() |
609 |
|
|
610 |
# |
# |
613 |
# Tells the form to create a new record |
# Tells the form to create a new record |
614 |
# |
# |
615 |
def newRecord(self, event): |
def newRecord(self, event): |
616 |
if not self._form.endEditing(): |
if not event._form.endEditing(): |
617 |
return |
return |
618 |
if self._form.readonly: |
if event._form.readonly: |
619 |
self.dispatchEvent(events.Event('formALERT',_('Form is readonly'))) |
self.dispatchEvent('formALERT',_('Form is readonly')) |
620 |
elif self._form._currentBlock.restrictInsert: |
elif event._form._currentBlock.restrictInsert: |
621 |
self.dispatchEvent(events.Event('formALERT',_('Block does not allow insert'))); |
self.dispatchEvent('formALERT',_('Block does not allow insert')) |
622 |
else: |
else: |
623 |
self._form.newRecord() |
event._form.newRecord() |
624 |
self._entryUpdated() |
self._entryUpdated() |
625 |
|
|
626 |
# |
# |
629 |
# Displays the about dialog |
# Displays the about dialog |
630 |
# |
# |
631 |
def executeAbout(self,event): |
def executeAbout(self,event): |
632 |
global VERSION |
name = event._form.title or "Unknown" |
633 |
version = VERSION; |
formversion = event._form.getOption('version') or "Unknown" |
634 |
name = self._form.title or "Unknown" |
author = event._form.getOption('author') or "Unknown" |
635 |
formversion = self._form.getOption('version') or "Unknown" |
description = event._form.getOption('description') or "Unknown" |
636 |
author = self._form.getOption('author') or "Unknown" |
self.dispatchEvent('uiABOUT',[VERSION,name,formversion,author,description]) |
|
description = self._form.getOption('description') or "Unknown" |
|
|
self.dispatchEvent(events.Event('uiABOUT',[version,name,formversion,author,description])) |
|
637 |
|
|
638 |
# |
# |
639 |
# toggleInsertMode(self): |
# toggleInsertMode(self): |
641 |
# tells the form to toggle mode |
# tells the form to toggle mode |
642 |
# |
# |
643 |
def toggleInsertMode(self, event): |
def toggleInsertMode(self, event): |
644 |
self._form.toggleInsertMode() |
event._form.toggleInsertMode() |
645 |
self.updateInsertMode() |
self.updateInsertMode() |
646 |
|
|
647 |
# |
# |
650 |
# If the form has a trigger named process-printout then fire it |
# If the form has a trigger named process-printout then fire it |
651 |
# |
# |
652 |
def executePrintout(self,event): |
def executePrintout(self,event): |
653 |
if self._form._triggerDictionary.has_key('process-printout'): |
if event._form._triggerDictionary.has_key('process-printout'): |
654 |
self._form.fireTrigger('process-printout') |
event._form.fireTrigger('process-printout') |
655 |
else: |
else: |
656 |
# TODO: should probably do something else as a default if trigger not available |
# TODO: should probably do something else as a default if trigger not available |
657 |
# TODO: like a screen print |
# TODO: like a screen print |
663 |
# Tells the form to rollback everything it contains |
# Tells the form to rollback everything it contains |
664 |
# |
# |
665 |
def executeRollback(self,event): |
def executeRollback(self,event): |
666 |
self._form.rollback() |
event._form.rollback() |
667 |
self._entryUpdated() |
self._entryUpdated() |
668 |
|
|
669 |
# |
# |
|
# Routines to update parts of the UI's status bar |
|
|
# |
|
|
def updateInsertMode(self): |
|
|
self.dispatchEvent(events.Event('uiUPDATESTATUS',[None,None,self._form._insertMode,None,None,None,None])) |
|
|
|
|
|
def updateRecordCounter(self): |
|
|
self.dispatchEvent(events.Event('uiUPDATESTATUS',[None,None,None,self._form._currentBlock._currentRecord+1,self._form._currentBlock._recordCount,None,None])) |
|
|
|
|
|
def updatePageCounter(self): |
|
|
maxPages = len(self._form._pageList) |
|
|
count = self._form._pageList.index(self._form._currentPage) |
|
|
self.dispatchEvent(events.Event('uiUPDATESTATUS',[None,None,None,None,None,count+1,maxPages])) |
|
|
|
|
|
def updateTip(self): |
|
|
tip = '' |
|
|
if self._form._currentEntry: |
|
|
if self._form._currentEntry.getOption('tip'): |
|
|
tip = self._form._currentEntry.getOption('tip') |
|
|
else: |
|
|
tip = '' |
|
|
|
|
|
self.dispatchEvent(events.Event('uiUPDATESTATUS',[tip,None,None,None,None,None,None])) |
|
|
|
|
|
def updateRecordStatus(self): |
|
|
if self._form._currentBlock.mode == 'query': |
|
|
status = 'query' |
|
|
elif self._form._currentBlock._resultSet.current.isDeleted(): |
|
|
status = 'deleted' |
|
|
elif self._form._currentBlock._resultSet.current.isPending(): |
|
|
status = 'modified' |
|
|
else: |
|
|
status = 'saved' |
|
|
|
|
|
self.dispatchEvent(events.Event('uiUPDATESTATUS',[None,status,None,None,None,None,None])) |
|
|
|
|
|
def updateStatus(self): |
|
|
self.updateTip() |
|
|
self.updateInsertMode() |
|
|
self.updateRecordCounter() |
|
|
self.updateRecordStatus() |
|
|
self.updatePageCounter() |
|
|
|
|
|
# |
|
670 |
# changeFocus |
# changeFocus |
671 |
# |
# |
672 |
# changes to the requested entry object requested by |
# changes to the requested entry object requested by |
673 |
# an event source |
# an event source |
674 |
# |
# |
675 |
def changeFocus(self, event): |
def changeFocus(self, event): |
676 |
if not self._form.endEditing(): |
if not event._form.endEditing(): |
677 |
return |
return |
678 |
if event.data._type=='GFEntry': |
if event.data._type=='GFEntry': |
679 |
if event.data.hidden: |
if not event.data._navigable: |
680 |
# is it possible ever to get into hidden field? |
# is it possible ever to get into non-navigable field? |
681 |
return |
return |
682 |
if (event.data.readonly and self._form._currentBlock.mode!='query'): |
if (event.data.readonly and event._form._currentBlock.mode!='query'): |
683 |
GDebug.printMesg(2,"You can focus readonly field, but you won't be able to change it.") |
GDebug.printMesg(2,"You can focus readonly field, but you won't be able to change it.") |
684 |
|
|
685 |
newEntry = event.data |
newEntry = event.data |
686 |
message = self._form.changeFocus(newEntry) |
message = event._form.changeFocus(newEntry) |
687 |
if message: |
if message: |
688 |
messageBox = GFMsgBox(self, message) |
messageBox = GFMsgBox(self, message) |
689 |
messageBox.show() |
messageBox.show() |
690 |
return |
return |
691 |
|
|
692 |
self.dispatchEvent(events.Event('gotoENTRY',{'object':self._form._currentEntry})) |
self.dispatchEvent('gotoENTRY',object=event._form._currentEntry, _form=event._form) |
693 |
self.updateRecordStatus() |
self.updateRecordStatus() |
694 |
self.updateTip() |
self.updateTip() |
695 |
|
|
696 |
|
# |
697 |
|
# requestQuery |
698 |
|
# |
699 |
def requestQuery(self, event): |
def requestQuery(self, event): |
700 |
if not self._form.endEditing(): |
if not event._form.endEditing(): |
701 |
return |
return |
702 |
|
|
703 |
# if hasattr(self._form._currentBlock._dataSourceLink,"master"): |
message = event._form.initQuery() |
|
# messageBox = GFMsgBox(self, _("Query from detail blocks currently not supported")) |
|
|
# messageBox.show() |
|
|
# return |
|
|
|
|
|
message = self._form.prepQuery() |
|
704 |
|
|
705 |
if message: |
if message: |
706 |
messageBox = GFMsgBox(self,message) |
messageBox = GFMsgBox(self,message) |
707 |
messageBox.show() |
messageBox.show() |
708 |
return |
return |
709 |
|
|
710 |
self._form.refreshDisplay(self._form) |
event._form.refreshDisplay(event._form) |
711 |
self.dispatchEvent(events.Event('gotoENTRY',{'object':self._form._currentEntry})) |
self.dispatchEvent('gotoENTRY',object=event._form._currentEntry, _form=event._form) |
712 |
self.updateStatus() |
self.updateStatus() |
713 |
|
|
714 |
|
# |
715 |
|
# requestQuery |
716 |
|
# |
717 |
def executeCommit(self, event): |
def executeCommit(self, event): |
718 |
if not self._form.endEditing(): |
if not event._form.endEditing(): |
719 |
return |
return |
720 |
message = self._form.commit() |
message = event._form.commit() |
721 |
if message: |
if message: |
722 |
messageBox = GFMsgBox(self,message) |
messageBox = GFMsgBox(self,message) |
723 |
messageBox.show() |
messageBox.show() |
724 |
return |
return |
725 |
self._form.refreshDisplay(self._form._currentBlock) |
event._form.refreshDisplay(event._form._currentBlock) |
726 |
self._entryUpdated() |
self._entryUpdated() |
727 |
|
|
728 |
|
# |
729 |
|
# executeQuery |
730 |
|
# |
731 |
def executeQuery(self, event): |
def executeQuery(self, event): |
732 |
if not self._form.endEditing(): |
if not event._form.endEditing(): |
733 |
return |
return |
734 |
message = self._form.executeQuery() |
message = event._form.executeQuery() |
735 |
if message: |
if message: |
736 |
messageBox = GFMsgBox(self,message) |
messageBox = GFMsgBox(self,message) |
737 |
messageBox.show() |
messageBox.show() |
738 |
self._form.refreshDisplay(self._form._currentBlock) |
event._form.refreshDisplay(event._form._currentBlock) |
739 |
self._entryUpdated() |
self._entryUpdated() |
740 |
|
|
741 |
|
|
|
|
|
|
def _handlePreCommit(self, event, trigger): |
|
|
try: |
|
|
block = event.record._parent._block |
|
|
except AttributeError: |
|
|
return |
|
|
|
|
|
saveMode = block.mode |
|
|
block._preCommitWorkingRecord = event.record |
|
|
block.mode = 'precommit' |
|
|
block.processTrigger(trigger) |
|
|
for child in block._children: |
|
|
if child._type == 'GFEntry': |
|
|
child.processTrigger(trigger) |
|
|
block.mode = saveMode |
|
|
|
|
|
|
|
742 |
def preCommit(self, event): |
def preCommit(self, event): |
743 |
self._handlePreCommit(event, 'PRE-COMMIT') |
self._handlePreCommit(event, 'PRE-COMMIT') |
744 |
|
|
|
|
|
745 |
def preInsert(self, event): |
def preInsert(self, event): |
746 |
self._handlePreCommit(event, 'PRE-INSERT') |
self._handlePreCommit(event, 'PRE-INSERT') |
747 |
|
|
755 |
|
|
756 |
|
|
757 |
def onRecordTouched(self, event): |
def onRecordTouched(self, event): |
758 |
self._handlePreCommit(event, 'PRE-MODIFY') |
self._handlePreCommit(event, 'PRE-CHANGE') |
759 |
|
|
760 |
|
|
761 |
|
def _handlePreCommit(self, event, trigger): |
762 |
|
try: |
763 |
|
block = event.record._parent._block |
764 |
|
except AttributeError: |
765 |
|
return |
766 |
|
|
767 |
|
saveMode = block.mode |
768 |
|
block._preCommitWorkingRecord = event.record |
769 |
|
block.mode = 'precommit' |
770 |
|
block.processTrigger(trigger) |
771 |
|
for child in block._fieldList: |
772 |
|
child.processTrigger(trigger) |
773 |
|
block.mode = saveMode |
774 |
|
|
775 |
|
|
776 |
|
def onQueryNewRecord(self, event): |
777 |
|
try: |
778 |
|
block = event.record._parent._block |
779 |
|
except AttributeError: |
780 |
|
return |
781 |
|
|
782 |
|
block.processTrigger('POST-QUERY') |
783 |
|
for child in block._fieldList: |
784 |
|
child.processTrigger('POST-QUERY') |
785 |
|
|
786 |
# |
# |
787 |
# fireTrigger |
# fireTrigger |
788 |
# |
# |
789 |
def fireTrigger(self, event): |
def fireTrigger(self, event): |
790 |
self._form.fireTrigger(event.data) |
event._form.fireTrigger(event.data) |
791 |
|
|
792 |
# |
# |
793 |
# Activate this puppy... |
# fireButton |
794 |
# |
# |
795 |
def activate(self): |
def fireButton(self, event): |
796 |
ui = self._uiinstance = self._uimodule.GFUserInterface(self.eventController, self._disableSplash) |
event.data.processTrigger('On-Action') |
|
ui.buildForm(self._form) |
|
|
ui.activateForm(self._form) |
|
|
|
|
|
currentEntry = self._form._currentEntry |
|
|
if not currentEntry: |
|
|
raise _('There are no navigable widgets in this form. Unable to display.') |
|
|
|
|
|
self.dispatchEvent(events.Event('gotoENTRY',{'object':currentEntry})) |
|
|
self.dispatchEvent(events.Event('updateENTRY',currentEntry)) |
|
|
self._form.refreshDisplay(self._form) |
|
|
self.updateStatus() |
|
|
self._ui = ui |
|
797 |
|
|
|
# pass control to UI |
|
|
ui.mainLoop() |
|