1
2 """GNUmed configuration editor.
3
4 Works quite similar to the Windows Registry editor (but is
5 a clean-room implementation).
6
7 @license: GPL"""
8
9
10 __version__ = "$Revision: 1.43 $"
11 __author__ = "H.Berger, S.Hilbert, K.Hilbert"
12
13 import sys, os, string, types
14
15 _log = gmLog.gmDefLog
16 if __name__ == '__main__':
17 _log.SetAllLogLevels(gmLog.lData)
18
19 from Gnumed.pycommon import gmCfg, gmConfigCommon, gmI18N
20 from Gnumed.wxpython import gmPlugin, gmGuiHelpers, gmRegetMixin
21 from Gnumed.business import gmPerson, gmPraxis
22
23 import wx
24
25 _cfg = gmCfg.gmDefCfgFile
26
27 _log.Log(gmLog.lInfo, __version__)
28
29 [ ConfigTreeCtrlID,
30 ConfigTreeBoxID,
31 ParamBoxID,
32 ConfigEntryParamCtrlID,
33 ButtonParamApplyID,
34 ButtonParamRevertID,
35 DescriptionBoxID,
36 ConfigDescriptionTextID
37 ] = map(lambda _init_ctrls: wx.NewId(), range(8))
38
39
41 """This wx.TreeCtrl derivative displays a tree view of configuration
42 parameter names.
43 """
44 - def __init__(self, parent, id, size=wx.DefaultSize,pos=wx.DefaultPosition,
45 style=None,configSources = None,rootLabel = "",paramWidgets=None):
46 """Set up our specialised tree."""
47
48 self.paramTextCtrl = paramWidgets[0]
49 self.paramDescription = paramWidgets[1]
50 self.mConfSources = configSources
51 for src in configSources:
52 _log.Log(gmLog.lData, 'config source: [%s]' % str(src))
53 self.rootLabel = rootLabel
54
55 wx.TreeCtrl.__init__(self, parent, id, pos, size, style)
56
57 self.root = None
58 self.param_list = None
59
60 self.currSelParam = None
61 self.currSelSubtree = None
62
63
64 wx.EVT_TREE_ITEM_ACTIVATED (self, self.GetId(), self.OnActivate)
65 wx.EVT_RIGHT_DOWN(self,self.OnRightDown)
66
67
69
70 if self.param_list is not None:
71 del self.param_list
72
73 if self.__populate_tree() is None:
74 return None
75
76 return True
77
79
80
81
82 if not self.root is None:
83 self.DeleteAllItems()
84
85
86 self.root = self.AddRoot(self.rootLabel, -1, -1)
87 self.SetPyData(self.root, {'type': 'root', 'name': self.rootLabel})
88 self.SetItemHasChildren(self.root, False)
89
90
91
92 for nodeDescription in (self.mConfSources.keys()):
93
94 _log.Log(gmLog.lData, 'adding first level node: [%s]' % nodeDescription)
95 node = self.AppendItem(self.root, nodeDescription)
96 self.SetPyData(node, {'type': 'defaultSubtree', 'name': nodeDescription})
97
98
99 subTree = self.__getSubTree(nodeDescription)
100 if subTree is None:
101 self.SetItemHasChildren(node, False)
102 _log.Log(gmLog.lData, 'node has no children')
103 continue
104 self.__addSubTree(node, subTree)
105
106 self.SortChildren(node)
107 self.SetItemHasChildren(node, True)
108
109 self.SetItemHasChildren(self.root, True)
110 self.SortChildren(self.root)
111
112 self.Expand(self.root)
113
114 return True
115
116
118 """
119 Adds a subtree of parameter names to an existing tree.
120 Returns resulting tree.
121 """
122 _log.Log(gmLog.lData, 'adding sub tree: [%s]' % str(aSubTree))
123
124
125 if aSubTree[1] == {}:
126 return None
127
128
129 childrenList = aSubTree[1].keys()
130 if childrenList is None:
131 return None
132 self.SetItemHasChildren(aNode, True)
133
134
135
136 for subTreeNode in childrenList:
137 nodeEntry = aSubTree[1][subTreeNode]
138 nodeName = nodeEntry[2]
139 node = self.AppendItem(aNode, nodeName)
140 self.SetPyData(node, nodeEntry[0])
141 self.SetItemHasChildren(node, False)
142
143 if not nodeEntry[1] == {}:
144 self.__addSubTree(node,nodeEntry)
145 self.SortChildren(node)
146
147
149 """
150 get a subtree from the backend via ConfigData layer.
151 the subtree must have a special structure (see addTreeItem).
152 """
153
154 if self.mConfSources[nodeDescription] is None:
155 return None
156
157
158 tmpParamList = self.mConfSources[nodeDescription].getAllParamNames()
159 if tmpParamList is None:
160 return None
161
162
163 currSubTree = [None,{},""]
164
165
166 for paramName in tmpParamList:
167 self.__addTreeItem (
168 currSubTree,
169 paramName,
170 {'type': 'parameter', 'ref': paramName, 'subtree': nodeDescription}
171 )
172
173 return currSubTree
174
176 """
177 adds a name of the form "a.b.c.d" to a dict so that
178 dict['a']['b']['c']['d'] is a valid tree entry
179 each subTree entry consists of a 3 element list:
180 element [0] is an optional arbitrary object that should be connected
181 with the tree element(ID, etc.), element [1] a dictionary
182 holding the children of this element (again elements of type subTree)
183 list element [3] is the branch name
184 """
185 nameParts = string.split(str(aStructuredName), '.')
186
187 tmpFunc = "aSubTree"
188 tmpDict = None
189 branchName = ""
190
191 for part in (nameParts):
192
193 if branchName == "":
194 branchName = branchName + part
195 else:
196 branchName = branchName + "." + part
197
198 tmpDict = eval(tmpFunc)[1]
199 if part not in tmpDict:
200
201 tmpDict[part]=[]
202 tmpDict[part].append({ 'type': 'branch', 'name': branchName })
203 tmpDict[part].append({})
204 tmpDict[part].append(part)
205
206 tmpFunc = tmpFunc + "[1]['%s']" % part
207
208 eval(tmpFunc)[0]=object
209 return aSubTree
210
212 """save parameter dialog"""
213
214
215
216
217 if not (self.currSelParam is None or self.currSelSubtree is None):
218
219
220 val = self.paramTextCtrl.GetValue()
221
222 currConfSource = self.mConfSources[self.currSelSubtree]
223 newValue = currConfSource.castType(self.currSelParam,val)
224
225 if newValue is None:
226 gmGuiHelpers.gm_show_error (
227 _('Type of entered value is not compatible with type expected.'),
228 _('saving configuration')
229 )
230
231
232
233
234 defParamName = currConfSource.getRawName(self.currSelParam)
235
236
237 confDefinition = currConfSource.hasDefinition()
238
239
240
241
242 if not confDefinition or not currConfSource.hasParameterDefinition(defParamName):
243 if gmGuiHelpers.gm_show_question (
244 _("There is no config definition for this parameter.\nThus it can't be checked for validity.\n\nSave anyway ?"),
245 _('saving configuration')):
246 currConfSource.setConfigData( self.currSelParam,newValue)
247
248
249 self.__show_parameter(self.currSelSubtree,self.currSelParam)
250 return
251
252
253
254 if currConfSource.isValid(defParamName,newValue):
255 currConfSource.setConfigData(self.currSelParam,newValue)
256
257
258 self.__show_parameter(self.currSelSubtree,self.currSelParam)
259 else:
260
261 gmGuiHelpers.gm_show_error (
262 _('Entered value is not valid.'),
263 _('saving configuration')
264 )
265
266
268 item = event.GetItem()
269 data = self.GetItemData(item)
270
271 self.paramDescription.Clear()
272 self.paramTextCtrl.SetEditable(0)
273 type = data['type']
274 if type == 'parameter':
275
276 self.currSelParam = data['ref']
277
278 self.currSelSubtree = data ['subtree']
279 self.__show_parameter(self.currSelSubtree,self.currSelParam)
280 return 1
281 elif type == 'branch':
282 message=_("(Branch)")
283 elif type == 'defaultSubtree':
284 message=_("(Subtree root)")
285 elif type == 'root':
286 message=_("<Options for current/default user and workplace>")
287
288 self.paramTextCtrl.ShowMessage(message)
289
290 if self.ItemHasChildren(item):
291 if self.IsExpanded(item):
292 self.Collapse(item)
293 else:
294 self.Expand(item)
295 return True
296
297
303
305
306 value = self.mConfSources[aSubtree].getConfigData(aParam)
307 currType = self.mConfSources[aSubtree].getParamType(aParam)
308
309 description = self.mConfSources[aSubtree].getDescription(aParam)
310
311
312
313
314
315 self.paramTextCtrl.ShowParam(aParam,currType,value)
316 self.paramTextCtrl.SetEditable(1)
317 self.paramDescription.SetValue(description)
318
320 - def __init__(self, parent, id,value,pos,size,style,type ):
323
324 - def ShowParam(self,aParam=None,aType=None,aValue=None):
325 self.Clear()
326 if aParam is None:
327 return
328
329 self.currParam = aParam
330 self.value = aValue
331 self.type = aType
332
333 if self.type == 'string':
334 self.SetValue(self.value)
335 elif self.type == 'str_array':
336
337
338 first = 1
339 all = ''
340 for line in (self.value):
341 if first:
342 first = 0
343 else:
344 all = all + '\n'
345 all = all + line
346 self.SetValue(all)
347 elif self.type == 'numeric':
348 self.SetValue(str(self.value))
349
351 self.currParam = None
352 self.Clear()
353 self.SetValue(aMessage)
354
355
357 if not self.currParam is None:
358 self.ShowParam(self.currParam, self.type, self.value)
359
360
361
362
364 - def __init__(self, parent, aUser,aWorkplace, plugin = 1):
365 """aUser and aWorkplace can be set such that an admin
366 could potentially edit another user ...
367 """
368 wx.Panel.__init__(self, parent, -1)
369
370 self.currUser = aUser
371 self.currWorkplace = aWorkplace
372
373
374
375
376
377
378
379
380
381 self.mConfSources = {}
382
383
384 cfgFileDefault = gmConfigCommon.ConfigSourceFile("gnumed.conf")
385 cfgFileName = cfgFileDefault.GetFullPath()
386
387 if cfgFileName is None:
388 cfgFileName = "gnumed.conf not found"
389
390 self.mConfSources['FILE:%s' % cfgFileName] = cfgFileDefault
391 try:
392 if not (self.currUser is None or self.currWorkplace is None):
393 self.mConfSources['DB:CURRENT_USER_CURRENT_WORKPLACE'] = gmConfigCommon.ConfigSourceDB('DB:CURRENT_USER_CURRENT_WORKPLACE',aWorkplace=self.currWorkplace)
394 except Exception: pass
395 try:
396 if not (self.currUser is None) :
397 self.mConfSources['DB:CURRENT_USER_DEFAULT_WORKPLACE'] = gmConfigCommon.ConfigSourceDB('DB:CURRENT_USER_DEFAULT_WORKPLACE')
398 except Exception: pass
399 try:
400 if not (self.currWorkplace is None):
401 self.mConfSources['DB:DEFAULT_USER_CURRENT_WORKPLACE'] = gmConfigCommon.ConfigSourceDB('DB:DEFAULT_USER_CURRENT_WORKPLACE',aUser='xxxDEFAULTxxx',aWorkplace=self.currWorkplace)
402 except Exception: pass
403 try:
404
405 self.mConfSources['DB:DEFAULT_USER_DEFAULT_WORKPLACE'] = gmConfigCommon.ConfigSourceDB('DB:DEFAULT_USER_DEFAULT_WORKPLACE',aUser='xxxDEFAULTxxx')
406 except Exception:
407 pass
408
409 self.mainSizer = wx.BoxSizer(wx.HORIZONTAL)
410 self.rightSizer = wx.BoxSizer(wx.VERTICAL)
411
412
413 self.configEntryParamBox = wx.StaticBox( self, ParamBoxID, _("Parameters") )
414 self.configEntryParamBoxSizer = wx.StaticBoxSizer( self.configEntryParamBox, wx.HORIZONTAL )
415
416 self.configEntryParamCtrl = cParamCtrl( parent = self,
417 id = ConfigEntryParamCtrlID,
418 pos = wx.DefaultPosition,
419 size = wx.Size(250,200),
420 value = "" ,
421 style = wx.LB_SINGLE,
422 type = None)
423
424 self.paramButtonSizer = wx.BoxSizer(wx.HORIZONTAL)
425 self.paramCtrlSizer = wx.BoxSizer(wx.VERTICAL)
426 self.buttonApply = wx.Button(parent=self,
427 id = ButtonParamApplyID,
428 label = "Apply changes" )
429 self.buttonRevert = wx.Button(parent=self,
430 id = ButtonParamRevertID,
431 label = "Revert to saved" )
432
433 wx.EVT_BUTTON(self,ButtonParamApplyID,self.ApplyChanges)
434 wx.EVT_BUTTON(self,ButtonParamRevertID,self.RevertChanges)
435
436
437
438 self.configEntryDescriptionBox = wx.StaticBox( self, DescriptionBoxID, _("Parameter Description") )
439 self.configEntryDescriptionBoxSizer = wx.StaticBoxSizer( self.configEntryDescriptionBox, wx.HORIZONTAL )
440
441 self.configEntryDescription = wx.TextCtrl(parent = self,
442 id = ConfigDescriptionTextID,
443 pos = wx.DefaultPosition,
444 size = wx.Size(250,100),
445 style = wx.TE_READONLY | wx.LB_SINGLE,
446 value ="" )
447 self.configEntryDescriptionBoxSizer.Add( self.configEntryDescription, 1, wx.ALIGN_CENTRE|wx.ALL|wx.EXPAND, 2 )
448
449 self.configTreeBox = wx.StaticBox( self, ConfigTreeBoxID, _("Config Options") )
450 self.configTreeBoxSizer = wx.StaticBoxSizer( self.configTreeBox, wx.HORIZONTAL )
451
452
453 rootLabel = "%s@%s" % (self.currUser,self.currWorkplace)
454 self.configTree = cConfTree( parent = self,
455 id = ConfigTreeCtrlID ,
456 pos = wx.Point(0, 0),
457 size = wx.Size(200, 300),
458 style = wx.TR_HAS_BUTTONS|wx.TAB_TRAVERSAL,
459 configSources = self.mConfSources,
460 rootLabel = rootLabel,
461 paramWidgets=(self.configEntryParamCtrl,self.configEntryDescription)
462 )
463 self.configTree.SetFocus()
464 self.configTreeBoxSizer.Add( self.configTree, 1, wx.ALIGN_CENTRE|wx.ALL|wx.EXPAND, 5 )
465
466 self.paramCtrlSizer.Add(self.configEntryParamCtrl,1,wx.ALIGN_CENTRE|wx.ALL|wx.EXPAND, 2 )
467 self.paramButtonSizer.Add(self.buttonApply,1,wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 2 )
468 self.paramButtonSizer.Add(self.buttonRevert,1,wx.ALIGN_RIGHT|wx.ALL|wx.EXPAND, 2 )
469 self.paramCtrlSizer.Add(self.paramButtonSizer,0,wx.ALIGN_BOTTOM, 2 )
470 self.configEntryParamBoxSizer.Add(self.paramCtrlSizer , 1, wx.ALIGN_CENTRE|wx.ALL|wx.EXPAND, 2 )
471
472
473 self.rightSizer.Add(self.configEntryParamBoxSizer, 1, wx.EXPAND, 0)
474 self.rightSizer.Add(self.configEntryDescriptionBoxSizer, 1, wx.EXPAND, 0)
475
476
477 self.mainSizer.Add(self.configTreeBoxSizer, 1, wx.EXPAND, 0)
478 self.mainSizer.Add(self.rightSizer, 1, wx.EXPAND, 0)
479 self.SetAutoLayout(1)
480 self.SetSizer(self.mainSizer)
481 self.mainSizer.Fit(self)
482 self.mainSizer.SetSizeHints(self)
483 self.Layout()
484
486 if self.configEntryParamCtrl.IsModified():
487 self.configTree.SaveCurrParam()
488
491
494
495
496
497
498 if __name__ == '__main__':
499 from Gnumed.wx.python import gmPlugin
500 _log.Log (gmLog.lInfo, "starting config browser")
501 workplace = input("Please enter a workplace name: ")
502
503 application = wx.PyWidgetTester(size=(640,480))
504 application.SetWidget(gmConfigEditorPanel,"any-doc",workplace, 0)
505 application.MainLoop()
506 _log.Log (gmLog.lInfo, "closing config browser")
507
508 else:
510 """Class to load this module from an environment that wants a notebook plugin
511 """
514
522
524 return ('tools', _('&ConfigRegistry'))
525
532
533
534