| Home | Trees | Indices | Help |
|
|---|
|
|
1 # GnuMed form printer design study
2
3 __doc__ = """
4 Module to print a form using the wx. toolkit.
5 includes dialogues for printer calibration, etc.
6 and new form wizard.
7 """
8 # $Source: /home/ncq/Projekte/cvs2git/vcs-mirror/gnumed/gnumed/client/wxpython/gmFormPrinter.py,v $
9 # $Id: gmFormPrinter.py,v 1.12 2009-01-15 11:35:41 ncq Exp $
10 __version__ = "$Revision: 1.12 $"
11 __author__ = "Ian Haywood"
12
13 try:
14 import wxversion
15 import wx
16 except ImportError:
17 from wxPython import wx
18
19 import string
20
21 from Gnumed.pycommon import gmCfg, gmI18N
22
23 try:
24 _('dummy-no-need-to-translate-but-make-epydoc-happy')
25 except NameError:
26 _ = lambda x:x
27
28 cache_form = 0 # cached variables to allow repeat of last form
29 cache_params = {}
30
31 SCRIPT = -100 # fake form ID that maps to the default prescription form
32 # for this locale
33 PATH = -101
34 RADIOL = -102
35
37
39 self._cfg = gmCfg.gmDefCfgFile
40 xos = self._cfg.get ("printer", "x_offset")
41 if xos is None:
42 self.printer_unset = 1
43 gpsd = gmPrinterSetupDialog (self)
44 else:
45 self.printer_unset = 0
46 self.x_off = float (xos) # in mm from paper-edge
47 self.y_off = float (self._cfg.get ("printer", "y_offset")) # in mm from paper-edge
48 self.x_scale = float (self._cfg.get ("printer", "x_scaling")) # no. of logical units = 1mm
49 self.y_scale = float (self._cfg.get ("printer", "y_scaling")) # no. logical units = 1mm
50 self._log = gmLog.gmDefLog.Log
51
53 self._cfg.set ("printer", "x_offset", self.x_off)
54 self._cfg.set ("printer", "y_offset", self.y_off)
55 self._cfg.set ("printer", "x_scaling", self.x_scale)
56 self._cfg.set ("printer", "y_scaling", self.x_scale)
57 self._cfg.store ()
58
60 """
61 Print a form. id is the database ID of the form, params is a dictionary of
62 parameters, defined by the type of form (see gmoffice.sql)
63 """
64 cached_form = id
65 cached_params = param
66 if self.printer_unset: # printer is unset, cache and return
67 return
68 backend = gmPG.GetConnectionPool ()
69 db = backend.GetConnection('office')
70 curs = db.cursor()
71 if id == SCRIPT:
72 curs.execute ("select length, width, fontsize from forms, papersizes where id_papersize = papersizes.id and forms.type = 's' and default")
73 elif id == PATH:
74 curs.execute ("select length, width, fontsize from forms, papersizes where id_papersize = papersizes.id and forms.type = 'p' and default")
75 elif id == RADIOL:
76 curs.execute ("select length, width, fontsize from forms, papersizes where id_papersize = papersizes.id and forms.type = 'r' and default")
77 else:
78 curs.execute('select length, width, fontsize from forms, papersizes where id = %s and id_papersize = papersizes.id' % id)
79 p_len, p_wid, fontsize, font = curs.fetchone()
80 curs.execute('select x, y, wraparound, service, query, page from formfield, queries where id_form = %s and id_query = query.id order by page' % id)
81 curr_page = 1
82 # magic to set up Printer DC
83 pd = wxPrintData ()
84 if wxPlatform == '__WXMSW__':
85 dc = wxPrinterDC (pd)
86 else:
87 # use PostScript
88 # FIXME: how do we print under Mac??
89 dc = wxPostScriptDC (pd)
90 font = wx.Font (fontsize, wxDEFAULT, wx.NORMAL, wx.NORMAL)
91 dc.SetFont (font)
92 dc.SetBrush (wx.BLACK_BRUSH)
93 dc.StartDoc ("")
94 dc.StartPage ()
95 for (x, y, wraparound, service, query, page) in curs.fetchall ():
96 qdb = backend.GetConnection (service)
97 qcurs = qdb.cursor ()
98 qcurs.execute (self.subst_param (query, params))
99 if page <> curr_page:
100 # new page
101 dc.EndPage ()
102 dc.StartPage ()
103 curr_page = page
104 for row in qcurs.fetchall ():
105 text = string.join ([str(i) for i in row], ' ')
106 for line in string.split (text, '\n'): # honour \n in string
107 y = self.printtext (dc, x, y, wraparound, line)
108 qcurs.close ()
109 backend.ReleaseConnection (service)
110 curs.close()
111 dc.EndPage ()
112 dc.EndDoc ()
113 del dc
114
115
116 def subst_param (query, param):
117 for (name, value) in param.items ():
118 query = replace (query, '$' + name, value)
119
120 def printtext (dc, x, y, wrap, text):
121 """
122 Prints text, with word wrapping.
123 Returns where it leaves y (the next virtual line)
124 """
125 w, h = dc.GetTextExtent (text)
126 nextline = ""
127 while w/float (self.x_scale) > wrap: # text is too wide
128 text.strip ()
129 # nibble from the end of text and add to nextline
130 # until we encounter whitespace
131 # re-calculate text width
132 pos = string.rfind (text, ' ') # returns -1 if cannot find
133 nextline = text[pos:] + nextline
134 text = text[:pos]
135 w, h = dc.GetTextExtent (text)
136 px = (x+self.x_off)*self.x_scale
137 py = (y+self.y_off)*self.y_scale
138 dc.DrawText (px, py, text)
139 y += (h/float (self.y_scale))*1.2 # advance one line, give 20% space
140 # do the wrapped line if neccessary
141 if len (nextline) > 0:
142 y = self.printtext (dc, x, y, wrap, nextline)
143 # return new y position
144 return y
145
148 # begin wxGlade: __init__
149 wx.Dialog.__init__(self, None, -1, _("Printer Setup"))
150 self.formprinter = formprinter
151 self.label_1 = wx.StaticText(self, -1, "Horiz. Offset")
152 self.horiz_off_spin = wx.SpinCtrl(self, -1, min=0, max=100, initial=0)
153 self.label_2 = wx.StaticText(self, -1, "Vert. Offset")
154 self.vert_off_spin = wx.SpinCtrl(self, -1, min=0, max=100, initial=0, style=wx.SP_ARROW_KEYS)
155 self.label_3 = wx.StaticText(self, -1, "Horiz. Scaling")
156 self.horiz_scale_spin = wx.SpinCtrl(self, -1, min=0, max=100, initial=0, style=wx.SP_ARROW_KEYS)
157 self.label_4 = wx.StaticText(self, -1, "Vert. Scaling")
158 self.vert_scale_spin = wx.SpinCtrl(self, -1, min=0, max=100, initial=0)
159 REPRINT_ID = wx.NewId ()
160 self.reprint_button = wx.Button(self, REPRINT_ID, "Re-print")
161 CALIB_ID = wx.NewId ()
162 self.calib_button = wx.Button(self, CALIB_ID, "Re-calibrate")
163 DISMISS_ID = wx.NewId ()
164 self.dismiss_button = wx.Button(self, DISMISS_ID, "Dismiss")
165 self.text_ctrl_1 = wxTextCtrl(self, -1, "You need to enter parameters so forms print properly on this printer", style=wx.TE_MULTILINE|wx.TE_READONLY)
166
167 self.__set_properties()
168 self.__do_layout()
169 # end wxGlade
170 if not self.formprinter.printer_unset:
171 self.horiz_off_spin.SetValue (self.formprinter.x_off)
172 self.vert_off_spin.SetValue (self.formprinter.y_off)
173 self.horiz_scale_spin.SetValue (self.formprinter.x_scale)
174 self.vert_scale_spin.SetValue (self.formprinter.y_scale)
175 else:
176 self.horiz_off_spin.SetValue (0)
177 self.horiz_scale_spin.SetValue (28.3)
178 self.vert_off_spin.SetValue (0) # this is a sensible value on UNIX
179 self.vert_scale_spin.SetValue (28.3)
180 wx.EVT_BUTTON (self, REPRINT_ID, self.OnReprint)
181 wx.EVT_BUTTON (self, CALIB_ID, self.OnRecalibrate)
182 wx.EVT_BUTTON (self, DISMISS_ID, self.OnDismiss)
183 self.Show ()
184
186 # load spins back into form engine
187 self.formprinter.x_off = self.horiz_off_spin.GetValue ()
188 self.formprinter.y_off = self.vert_off_spin.GetValue ()
189 self.formprinter.x_scale = self.horiz_scale_spin.GetValue ()
190 self.formprinter.y_scale = self.vert_scale_spin.GetValue ()
191 self.formprinter.save ()
192 self.Destroy ()
193
195 # load spins back into form engine
196 self.formprinter.x_off = self.horiz_off_spin.GetValue ()
197 self.formprinter.y_off = self.vert_off_spin.GetValue ()
198 self.formprinter.x_scale = self.horiz_scale_spin.GetValue ()
199 self.formprinter.y_scale = self.vert_scale_spin.GetValue ()
200 self.formprinter.printer_unset = 0
201 if cache_form != 0:
202 self.formprinter.printform (cache_form, cache_params)
203
205 dialog = gmCalibrationDialog ()
206 pd = wxPrintData ()
207 pd.SetPrinterCommand ("lpr")
208 if wxPlatform == '__WXMSW__':
209 dc = wxPrinterDC (pd)
210 else:
211 dc = wxPostScriptDC (pd)
212 dc.StartDoc ("")
213 dc.StartPage ()
214 dc.SetBrush (wx.BLACK_BRUSH)
215 dc.DrawRectangle (1000, 1000, 200, 200)
216 dc.DrawRectangle (2000, 2000, 200, 200)
217 dc.EndPage ()
218 dc.EndDoc ()
219 del dc
220 dialog.ShowModal ()
221 x1, y1, x2, y2 = dialog.GetValues ()
222 dialog.Destroy ()
223 self.formprinter.x_scale = (x2-x1)/1000.0
224 self.formprinter.y_scale = (y2-y1)/1000.0
225 self.formprinter.x_off = x1-(x2-x1)
226 self.formprinter.y_off = y1-(y2-y1)
227 self.formprinter.printer_unset = 0
228 self.horiz_off_spin.SetValue (self.formprinter.x_off)
229 self.vert_off_spin.SetValue (self.formprinter.y_off)
230 self.horiz_scale_spin.SetValue (self.formprinter.x_scale)
231 self.vert_scale_spin.SetValue (self.formprinter.y_scale)
232 self.formprinter.save ()
233
235 # begin wxGlade: __set_properties
236 self.SetTitle("Setup Printer for Forms")
237 self.vert_off_spin.SetToolTipString("Move text down (in millimetres)")
238 self.horiz_scale_spin.SetToolTipString("Horizontal scaling (units per mm)")
239 self.vert_scale_spin.SetToolTipString("Vertical scaling (units per mm)")
240 self.reprint_button.SetToolTipString("Re-print the last printed form")
241 self.calib_button.SetToolTipString("Print a table to calibrate this printer")
242 self.dismiss_button.SetToolTipString("Dismiss this dialog box")
243 # end wxGlade
244
246 # begin wxGlade: __do_layout
247 sizer_1 = wx.BoxSizer(wx.HORIZONTAL)
248 sizer_2 = wx.BoxSizer(wx.VERTICAL)
249 sizer_3 = wx.BoxSizer(wx.VERTICAL)
250 sizer_7 = wx.BoxSizer(wx.HORIZONTAL)
251 sizer_6 = wx.BoxSizer(wx.HORIZONTAL)
252 sizer_5 = wx.BoxSizer(wx.HORIZONTAL)
253 sizer_4 = wx.BoxSizer(wx.HORIZONTAL)
254 sizer_4.Add(self.label_1, 0, wx.ALL, 10)
255 sizer_4.Add(self.horiz_off_spin, 0, wx.ALL, 10)
256 sizer_3.Add(sizer_4, 1, wx.EXPAND, 0)
257 sizer_5.Add(self.label_2, 0, wx.ALL, 10)
258 sizer_5.Add(self.vert_off_spin, 0, wx.ALL, 10)
259 sizer_3.Add(sizer_5, 1, wx.EXPAND, 0)
260 sizer_6.Add(self.label_3, 0, wx.ALL, 10)
261 sizer_6.Add(self.horiz_scale_spin, 0, wx.ALL, 10)
262 sizer_3.Add(sizer_6, 1, wx.EXPAND, 0)
263 sizer_7.Add(self.label_4, 0, wx.ALL, 10)
264 sizer_7.Add(self.vert_scale_spin, 0, wx.ALL, 10)
265 sizer_3.Add(sizer_7, 1, wx.EXPAND, 0)
266 sizer_1.Add(sizer_3, 1, wx.EXPAND, 0)
267 sizer_2.Add(self.reprint_button, 0, wx.ALL|wx.EXPAND, 10)
268 sizer_2.Add(self.calib_button, 0, wx.ALL|wx.EXPAND, 10)
269 sizer_2.Add(self.dismiss_button, 0, wx.ALL|wx.EXPAND, 10)
270 sizer_2.Add(self.text_ctrl_1, 1, wx.EXPAND, 0)
271 sizer_1.Add(sizer_2, 1, wxALL|wx.EXPAND|wx.ALIGN_RIGHT, 30)
272 self.SetAutoLayout(1)
273 self.SetSizer(sizer_1)
274 sizer_1.Fit(self)
275 self.Layout()
276 # end wxGlade
277
278 # end of class Printer
279
282 # begin wxGlade: __init__
283 #kwds["style"] = wxDIALOG_MODAL|wxCAPTION
284 wx.Dialog.__init__(self, None, -1, _("Calibration"))
285 self.label_9 = wx.StaticText(self, -1, """Calibration Page now printing.\n
286 Measure the position of the boxes and enter""")
287 self.label_5 = wx.StaticText(self, -1, "Distance of first box from top of page")
288 self.first_top_spin = wx.SpinCtrl(self, -1, min=0, max=100, initial=0)
289 self.label_6 = wx.StaticText(self, -1, "Distance of first box from left of page")
290 self.first_left_spin = wx.SpinCtrl(self, -1, min=0, max=100, initial=0)
291 self.label_7 = wx.StaticText(self, -1, "Distance of second box of top of page")
292 self.sec_top_spin = wx.SpinCtrl(self, -1, min=0, max=100, initial=0)
293 self.label_8 = wx.StaticText(self, -1, "Distance of second box from left of page")
294 self.sec_left_spin = wx.SpinCtrl(self, -1, min=0, max=100, initial=0)
295 ID = wx.NewId ()
296 self.ok_button = wx.Button(self, ID, "OK")
297 wx.EVT_BUTTON (self, ID, self.OnOK)
298 self.__set_properties()
299 self.__do_layout()
300 # end wxGlade
301 self.Show ()
302
306 # end wxGlade
307
309 # begin wxGlade: __do_layout
310 sizer_8 = wx.BoxSizer(wx.VERTICAL)
311 grid_sizer_2 = wx.FlexGridSizer(4, 2, 0, 0)
312 sizer_8.Add(self.label_9, 0, wx.ALL|wx.EXPAND, 10)
313 grid_sizer_2.Add(self.label_5, 0, 0, 0)
314 grid_sizer_2.Add(self.first_top_spin, 0, 0, 0)
315 grid_sizer_2.Add(self.label_6, 0, 0, 0)
316 grid_sizer_2.Add(self.first_left_spin, 0, 0, 0)
317 grid_sizer_2.Add(self.label_7, 0, 0, 0)
318 grid_sizer_2.Add(self.sec_top_spin, 0, 0, 0)
319 grid_sizer_2.Add(self.label_8, 0, 0, 0)
320 grid_sizer_2.Add(self.sec_left_spin, 0, 0, 0)
321 grid_sizer_2.AddGrowableRow(0)
322 grid_sizer_2.AddGrowableRow(1)
323 grid_sizer_2.AddGrowableRow(2)
324 grid_sizer_2.AddGrowableRow(3)
325 grid_sizer_2.AddGrowableCol(0)
326 sizer_8.Add(grid_sizer_2, 1, wx.EXPAND, 0)
327 sizer_8.Add(self.ok_button, 0, wx.ALL|wx.ALIGN_CENTER_HORIZONTAL, 10)
328 self.SetAutoLayout(1)
329 self.SetSizer(sizer_8)
330 sizer_8.Fit(self)
331 self.Layout()
332 # end wxGlade
333
336
342
343 # end of class gmCalibrationDialog
344
345 fp = FormPrinter ()
346 psd = gmPrinterSetupDialog (fp)
347
348 #=================================================
349 # $Log: gmFormPrinter.py,v $
350 # Revision 1.12 2009-01-15 11:35:41 ncq
351 # - cleanup
352 #
353 # Revision 1.11 2008/03/06 18:29:29 ncq
354 # - standard lib logging only
355 #
356 # Revision 1.10 2006/10/25 07:21:57 ncq
357 # - no more gmPG
358 #
359 # Revision 1.9 2006/01/03 12:12:03 ncq
360 # - make epydoc happy re _()
361 #
362 # Revision 1.8 2005/09/28 21:27:30 ncq
363 # - a lot of wx2.6-ification
364 #
365 # Revision 1.7 2005/09/28 15:57:48 ncq
366 # - a whole bunch of wx.Foo -> wx.Foo
367 #
368 # Revision 1.6 2005/09/26 18:01:50 ncq
369 # - use proper way to import wx26 vs wx2.4
370 # - note: THIS WILL BREAK RUNNING THE CLIENT IN SOME PLACES
371 # - time for fixup
372 #
373 # Revision 1.5 2004/06/20 16:01:05 ncq
374 # - please epydoc more carefully
375 #
376
| Home | Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1 on Mon Nov 29 04:05:01 2010 | http://epydoc.sourceforge.net |