28
|
1 # Copyright (C) 2000-2001 The OpenRPG Project
|
|
2 #
|
|
3 # openrpg-dev@lists.sourceforge.net
|
|
4 #
|
|
5 # This program is free software; you can redistribute it and/or modify
|
|
6 # it under the terms of the GNU General Public License as published by
|
|
7 # the Free Software Foundation; either version 2 of the License, or
|
|
8 # (at your option) any later version.
|
|
9 #
|
|
10 # This program is distributed in the hope that it will be useful,
|
|
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13 # GNU General Public License for more details.
|
|
14 #
|
|
15 # You should have received a copy of the GNU General Public License
|
|
16 # along with this program; if not, write to the Free Software
|
|
17 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
18 # --
|
|
19 #
|
|
20 # File: minilib.py
|
|
21 # Author: Ted Berg
|
|
22 # Maintainer:
|
|
23 # Version:
|
|
24 # $Id: minilib.py,v Traipse 'Ornery-Orc' prof.ebral Exp $
|
|
25 #
|
|
26 # Description: nodehandler for a collection of miniatures.
|
|
27 #
|
|
28
|
|
29 __version__ = "$Id: minilib.py,v Traipse 'Ornery-Orc' prof.ebral Exp $"
|
|
30
|
|
31 """Nodehandler for collections of miniatures. User can add, delete, edit
|
|
32 miniatures as sending them to the map singly or in batches.
|
|
33 """
|
|
34 from core import *
|
|
35 from orpg.dirpath import dir_struct
|
|
36 import string
|
|
37 import map_miniature_nodehandler
|
18
|
38 import orpg.mapper.map_msg
|
27
|
39 import orpg.minidom as minidom
|
36
|
40 from orpg.tools.InterParse import Parse
|
28
|
41 # import scriptkit
|
|
42
|
|
43 # Constants
|
|
44 TO_MINILIB_MAP = {'path':'url', 'label':'name', 'id':None, 'action':None}
|
|
45 FROM_MINILIB_MAP = {'url':'path', 'name':'label', 'unique':None}
|
|
46 CORE_ATTRIBUTES = ['name', 'url', 'unique', 'posy', 'posx', 'hide', 'face', 'heading', 'align', 'locked', 'width', 'height']
|
|
47
|
|
48 # <nodehandler name='?' module='minilib' class='minilib_handler'>
|
|
49 # <miniature name='?' url='?' unique='?'></miniature>
|
|
50 # </nodehandler>
|
|
51
|
|
52 class minilib_handler( node_handler ):
|
|
53 """A nodehandler that manages a collection of miniatures for the
|
|
54 map.
|
|
55 <pre>
|
|
56 <nodehandler name='?' module='minilib' class='minilib_handler'>
|
|
57 <miniature name='?' url='?' unique='?'></miniature>
|
|
58 </nodehandler>
|
|
59 </pre>
|
|
60 """
|
|
61 def __init__(self, xml, tree_node):
|
|
62 """Instantiates the class, and sets all vars to their default state
|
|
63 """
|
|
64 node_handler.__init__(self, xml, tree_node)
|
|
65 self.myeditor = None
|
|
66 self.mywindow = None
|
|
67 self.tree_node = tree_node
|
|
68 self.update_leaves()
|
|
69 self.sanity_check_nodes()
|
|
70
|
|
71 def get_design_panel( self, parent ):
|
|
72 """returns an instance of the miniature library edit control ( see
|
|
73 on_design ). This is for use with the the 'edit multiple nodes in a
|
|
74 single frame' code.
|
|
75 """
|
|
76 return minpedit( parent, self )
|
|
77
|
|
78 def get_use_panel( self, parent ):
|
|
79 """returns an instance of the miniature library view control ( see
|
|
80 on_use ). This is for use with the the 'view multiple nodes in a
|
|
81 single frame' code.
|
|
82 """
|
|
83 return minilib_use_panel( parent, self )
|
|
84
|
|
85 def tohtml( self ):
|
|
86 """Returns an HTML representation of this node in string format.
|
|
87 The table columnwidths are currently being forced, as the wxHTML
|
|
88 widgets being used don't handle cells wider than the widgets are
|
|
89 expecting for a given column.
|
|
90 """
|
|
91 str = '<table border="2" >'
|
|
92 str += "<tr><th width='20%'>Label</th><th>Image</th><th width='65%'>URL</th><th>Unique</th></tr>"
|
36
|
93 for mini in self.xml.findall('miniature'):
|
|
94 url = mini.get('url')
|
|
95 label = mini.get('name')
|
28
|
96 flag = 0
|
36
|
97 try: flag = eval( mini.get('unique') )
|
28
|
98 except: pass
|
|
99 show = 'yes'
|
|
100 if flag: show = 'no'
|
|
101 str += """<tr>
|
|
102 <td> %s </td>
|
|
103 <td><img src="%s"></td>
|
|
104 <td> %s </td>
|
|
105 <td> %s </td>
|
|
106 </tr>""" % ( label, url, url, show )
|
|
107 str += "</table>"
|
|
108 return str
|
|
109
|
|
110 def html_view( self ):
|
|
111 """see to_html
|
|
112 """
|
|
113 return self.tohtml()
|
|
114
|
|
115 def on_drop(self, evt):
|
|
116 drag_obj = self.tree.drag_obj
|
|
117 if drag_obj == self or self.tree.is_parent_node( self.mytree_node, drag_obj.mytree_node ): return
|
|
118 elif isinstance( drag_obj, map_miniature_nodehandler.map_miniature_handler ):
|
|
119 drop_xml = self.tree.drag_obj.xml#.delete()
|
|
120 obj = drop_xml[0]
|
|
121 dict = {}
|
|
122 unique = ''
|
|
123 for attrib in obj.keys():
|
|
124 key = TO_MINILIB_MAP.get( attrib, attrib )
|
|
125 if key != None: dict[ key ] = obj.get( attrib )
|
36
|
126 dict[ 'unique' ] = unique
|
28
|
127 self.new_mini( dict )
|
|
128 else: node_handler.on_drop(self, evt)
|
|
129
|
|
130
|
|
131 def new_mini( self, data={}, add=1 ):
|
36
|
132 mini = Element( 'miniature' )
|
28
|
133 for key in data.keys(): mini.set( key, data[ key ] )
|
|
134 for key in CORE_ATTRIBUTES:
|
31
|
135 if mini.get( key ) == ('' or None): mini.set( key, '0' )
|
28
|
136 if add:
|
|
137 self.add_mini( mini )
|
|
138 self.add_leaf( mini )
|
|
139 return mini
|
|
140
|
|
141 def add_mini( self, mini ):
|
|
142 self.xml.append( mini )
|
|
143
|
|
144 def add_leaf( self, mini, icon='gear' ):
|
|
145 tree = self.tree
|
|
146 icons = tree.icons
|
36
|
147 key = mini.get( 'name' )
|
28
|
148 self.mydata.append( mini )
|
|
149
|
|
150 def update_leaves( self ):
|
|
151 self.mydata = []
|
36
|
152 for n in self.xml.findall('miniature'): self.add_leaf( n )
|
28
|
153
|
|
154 def on_drag( self, evt ):
|
|
155 print 'drag event caught'
|
|
156
|
|
157 def send_mini_to_map( self, mini, count=1, addName=True ):
|
|
158 if mini == None: return
|
36
|
159 if mini.get( 'url' ) == '' or mini.get( 'url' ) == 'http://':
|
|
160 Parse.Post( self.chat.colorize(self.chat.syscolor,
|
|
161 '"%s" is not a valid URL, the mini "%s" will not be added to the map' % (
|
|
162 mini.get( 'url' ), mini.get( 'name' ) )) )
|
28
|
163 return
|
36
|
164 session = component.get( 'session' )
|
28
|
165 if (session.my_role() != session.ROLE_GM) and (session.my_role() != session.ROLE_PLAYER):
|
|
166 component.get("chat").InfoPost("You must be either a player or GM to use the miniature Layer")
|
|
167 return
|
36
|
168 canvas = component.get('map')
|
28
|
169 for loop in range( count ):
|
|
170 msg = self.get_miniature_XML( mini, addName)
|
|
171 msg = str("<map action='update'><miniatures>" + msg + "</miniatures></map>")
|
36
|
172 canvas.new_data( msg )
|
28
|
173 session.send( msg )
|
|
174
|
|
175 def get_miniature_XML( self, mini_xml, addName = True ):
|
|
176 msg = orpg.mapper.map_msg.mini_msg()
|
36
|
177 canvas = component.get( 'map' )
|
|
178 session = component.get( 'session' )
|
|
179 msg.init_prop( 'id', session.get_next_id() )
|
28
|
180 msg.init_prop('selected', '1')# this will make the mini initially selected
|
|
181 for k in mini_xml.keys():
|
|
182 # translate our attributes to map attributes
|
|
183 key = FROM_MINILIB_MAP.get( k, k )
|
|
184 if key != None:
|
|
185 if not addName and k == 'name': pass
|
|
186 else: msg.init_prop( key, mini_xml.get( k ) )
|
|
187 unique = self.is_unique( mini_xml )
|
36
|
188 if addName: label = mini_xml.get( 'name' )
|
28
|
189 else: label = ''
|
|
190 return msg.get_all_xml()
|
|
191
|
|
192 def is_unique( self, mini ):
|
36
|
193 unique = mini.get( 'unique' )
|
28
|
194 val = 0
|
|
195 try: val = eval( unique )
|
|
196 except: val = len( unique )
|
|
197 return val
|
|
198
|
|
199 def sanity_check_nodes( self ):
|
36
|
200 for node in self.xml.findall('miniature'):
|
|
201 if node.get( 'posx' ) == '': node.set( 'posx', '0' )
|
|
202 if node.get( 'posy' ) == '': node.set( 'posy', '0' )
|
28
|
203
|
|
204 def get_mini( self, index ):
|
36
|
205 try: return self.xml.findall('miniature')[index]
|
28
|
206 except: return None
|
|
207
|
|
208 class mini_handler( node_handler ):
|
|
209 def __init__( self, xml, tree_node, handler ):
|
|
210 node_handler.__init__( self, xml, tree_node)
|
|
211 self.handler = handler
|
|
212
|
|
213 def on_ldclick( self, evt ):
|
|
214 self.handler.send_mini_to_map( self.xml )
|
|
215
|
|
216 def on_drop( self, evt ):
|
|
217 pass
|
|
218
|
|
219 def on_lclick( self, evt ):
|
|
220 print 'hi'
|
|
221 evt.Skip()
|
|
222
|
|
223 class minilib_use_panel(wx.Panel):
|
|
224 """This panel will be displayed when the user double clicks on the
|
|
225 miniature library node. It is a sorted listbox of miniature labels,
|
|
226 a text field for entering a count ( for batch adds ) and 'add'/'done'
|
|
227 buttons.
|
|
228 """
|
|
229 def __init__( self, frame, handler ):
|
|
230 """Constructor.
|
|
231 """
|
|
232 wx.Panel.__init__( self, frame, -1 )
|
|
233 self.handler = handler
|
|
234 self.frame = frame
|
|
235
|
|
236 self.map = component.get('map')
|
|
237 names = self.buildList()
|
|
238
|
|
239 s = self.GetClientSizeTuple()
|
|
240
|
|
241 self.sizer = wx.BoxSizer(wx.VERTICAL)
|
|
242 box = wx.BoxSizer(wx.HORIZONTAL)
|
|
243 self.listbox = wx.ListBox(self, wx.ID_ANY, (10, 10), (s[0] - 10, s[1] - 30 ), names, wx.LB_EXTENDED)
|
|
244 self.count = wx.TextCtrl(self, wx.ID_ANY, '1')
|
|
245
|
|
246 box.Add( wx.StaticText( self, -1, 'Minis to add' ), 0, wx.EXPAND )
|
|
247 box.Add(wx.Size(10,10))
|
|
248 box.Add(self.count, 1, wx.EXPAND)
|
|
249
|
|
250 self.sizer.Add( self.listbox, 1, wx.EXPAND )
|
|
251 self.sizer.Add( box, 0, wx.EXPAND )
|
|
252
|
|
253 box = wx.BoxSizer( wx.HORIZONTAL )
|
|
254 self.okBtn = wx.Button(self, wx.ID_ANY, 'Add')
|
|
255 box.Add(self.okBtn, 0, wx.EXPAND)
|
|
256 self.addBtn = wx.Button(self, wx.ID_ANY, 'Add No Label')
|
|
257 box.Add(self.addBtn, 0, wx.EXPAND)
|
|
258 self.cancleBtn = wx.Button(self, wx.ID_ANY, 'Done')
|
|
259 box.Add(self.cancleBtn, 0, wx.EXPAND)
|
|
260
|
|
261 self.sizer.Add(wx.Size(10,10))
|
|
262 self.sizer.Add(box, 0, wx.EXPAND)
|
|
263 self.Bind(wx.EVT_BUTTON, self.on_ok, self.okBtn)
|
|
264 self.Bind(wx.EVT_BUTTON, self.on_ok, self.addBtn)
|
|
265 self.Bind(wx.EVT_BUTTON, self.on_close, self.cancleBtn)
|
|
266 self.SetSizer(self.sizer)
|
|
267 self.SetAutoLayout(True)
|
|
268 self.Fit()
|
|
269
|
|
270 def buildList( self ):
|
|
271 """Returns a dictionary of label => game tree miniature DOM node mappings.
|
|
272 """
|
|
273 self.list = []
|
36
|
274 for mini in self.handler.xml.findall('miniature'): self.list.append( mini.get( 'name' ) )
|
28
|
275 return self.list
|
|
276
|
|
277 def on_close(self, evt):
|
|
278 self.frame.Close()
|
|
279
|
|
280 def on_ok( self, evt ):
|
|
281 """Event handler for the 'add' button.
|
|
282 """
|
|
283 btn = self.FindWindowById(evt.GetId())
|
|
284 sendName = True
|
|
285 try: count = eval( self.count.GetValue() )
|
|
286 except: count = 1
|
|
287 try:
|
|
288 if eval( unique ): count = 1
|
|
289 unique = eval( unique )
|
|
290 except: pass
|
|
291
|
|
292 if btn.GetLabel() == 'Add No Label': sendName = False
|
|
293 for index in self.listbox.GetSelections(): self.handler.send_mini_to_map( self.handler.get_mini( index ), count, sendName )
|
|
294
|
|
295
|
|
296 class minpedit(wx.Panel):
|
|
297 """Panel for editing game tree miniature nodes. Node information
|
|
298 is displayed in a grid, and buttons are provided for adding, deleting
|
|
299 nodes, and for sending minis to the map ( singly and in batches ).
|
|
300 """
|
|
301 def __init__( self, frame, handler ):
|
|
302 """Constructor.
|
|
303 """
|
|
304 wx.Panel.__init__( self, frame, -1 )
|
|
305 self.handler = handler
|
|
306 self.frame = frame
|
|
307
|
|
308 self.sizer = wx.BoxSizer( wx.VERTICAL )
|
31
|
309
|
|
310 self.text = wx.TextCtrl(self, 3, handler.xml.get('name'))
|
|
311 self.sizer.Add(wx.StaticText(self, -1, "Title:"), 0, wx.EXPAND)
|
|
312 self.sizer.Add(self.text, 0, wx.EXPAND)
|
|
313
|
28
|
314 self.grid = minilib_grid( self, handler )
|
|
315
|
|
316 bbox = wx.BoxSizer( wx.HORIZONTAL )
|
|
317 newMiniBtn = wx.Button( self, wx.ID_ANY, "New mini" )
|
|
318 delMiniBtn = wx.Button( self, wx.ID_ANY, "Del mini" )
|
|
319 addMiniBtn = wx.Button( self, wx.ID_ANY, "Add 1" )
|
|
320 addBatchBtn = wx.Button( self, wx.ID_ANY, "Add Batch" )
|
|
321 bbox.Add(newMiniBtn, 0, wx.EXPAND )
|
|
322 bbox.Add(delMiniBtn, 0, wx.EXPAND )
|
|
323 bbox.Add(wx.Size(10,10))
|
|
324 bbox.Add(addMiniBtn, 0, wx.EXPAND )
|
|
325 bbox.Add(addBatchBtn, 0, wx.EXPAND )
|
|
326
|
|
327 self.sizer.Add( self.grid, 1, wx.EXPAND)
|
|
328 self.sizer.Add( bbox, 0)
|
|
329 self.SetSizer(self.sizer)
|
|
330 self.SetAutoLayout(True)
|
|
331 self.Fit()
|
|
332
|
31
|
333 self.Bind(wx.EVT_TEXT, self.on_text, id=3)
|
28
|
334 self.Bind(wx.EVT_BUTTON, self.add_mini, newMiniBtn)
|
|
335 self.Bind(wx.EVT_BUTTON, self.del_mini, delMiniBtn)
|
|
336 self.Bind(wx.EVT_BUTTON, self.send_to_map, addMiniBtn)
|
|
337 self.Bind(wx.EVT_BUTTON, self.send_group_to_map, addBatchBtn)
|
|
338
|
|
339 def add_mini( self, evt=None ):
|
|
340 """Event handler for the 'New mini' button. It calls
|
|
341 minilib_grid.add_row
|
|
342 """
|
|
343 self.grid.add_row()
|
|
344
|
|
345 def del_mini( self, evt=None ):
|
|
346 """Event handler for the 'Del mini' button. It calls
|
|
347 minilib_grid.del_row
|
|
348 """
|
|
349 self.grid.del_row()
|
|
350
|
|
351 def send_to_map( self, evt=None ):
|
|
352 """Event handler for the 'Add 1' button. Sends the
|
|
353 miniature defined by the currently selected row to the map, once.
|
|
354 """
|
31
|
355 index = self.grid.GetSelectedRows()[0] if len(self.grid.GetSelectedRows()) > 0 else 0
|
28
|
356 self.handler.send_mini_to_map( self.handler.get_mini( index ) )
|
|
357
|
|
358 def send_group_to_map( self, evt=None ):
|
|
359 """Event handler for the 'Add batch' button. Querys the user
|
|
360 for a mini count and sends the miniature defined by the currently
|
|
361 selected row to the map, the specified number of times.
|
|
362 """
|
|
363 if self.grid.GetNumberRows() > 0:
|
|
364 dlg = wx.TextEntryDialog( self.frame,
|
|
365 'How many %s\'s do you want to add?' %
|
|
366 ( self.grid.getSelectedLabel() ), 'Batch mini add', '2' )
|
|
367 if dlg.ShowModal() == wx.ID_OK:
|
|
368 try: value = eval( dlg.GetValue() )
|
|
369 except: value = 0
|
|
370 print 'getting selected index for batch send'
|
31
|
371 index = self.grid.GetSelectedRows()[0] if len(self.grid.GetSelectedRows()) > 0 else 0
|
28
|
372 print 'sending batch to map'
|
|
373 self.handler.send_mini_to_map( self.handler.get_mini( index ), value )
|
|
374
|
31
|
375 def on_text(self, evt):
|
|
376 txt = self.text.GetValue()
|
|
377 if txt != "":
|
36
|
378 #self.handler.xml.set('name',txt)
|
31
|
379 self.handler.rename(txt)
|
|
380
|
28
|
381 class minilib_grid(wx.grid.Grid):
|
|
382 """A wxGrid subclass designed for editing game tree miniature library
|
|
383 nodes.
|
|
384 """
|
|
385 def __init__( self, parent, handler ):
|
|
386 """Constructor.
|
|
387 """
|
|
388 wx.grid.Grid.__init__(self, parent, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS )
|
|
389 self.parent = parent
|
|
390 self.handler = handler
|
|
391 self.keys = CORE_ATTRIBUTES
|
|
392 self.CreateGrid( 1, len( self.keys ) )
|
|
393 for key in self.keys: self.SetColLabelValue( self.keys.index( key ), key )
|
|
394 self.update_all()
|
|
395 self.selectedRow = 0
|
|
396 self.AutoSizeColumns()
|
|
397 self.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_change)
|
|
398 self.Bind(wx.grid.EVT_GRID_SELECT_CELL, self.select_cell)
|
31
|
399 self.Bind(wx.grid.EVT_GRID_LABEL_LEFT_CLICK, self.select_cell)
|
28
|
400
|
|
401 def update_cols( self ):
|
36
|
402 for n in self.handler.xml.findall('miniature'):
|
28
|
403 for k in n.keys():
|
|
404 if k not in self.keys: self.keys.append( k )
|
|
405
|
|
406 def select_cell( self, evt ):
|
|
407 """Event handler for grid cell selection changes. It stores the
|
|
408 last selected row in a variable for use by the add[*] and del_row
|
|
409 operations.
|
|
410 """
|
|
411 self.BeginBatch()
|
|
412 self.selectedRow = evt.GetRow()
|
|
413 self.SelectRow( self.selectedRow )
|
|
414 self.EndBatch()
|
|
415 evt.Skip()
|
|
416
|
|
417 def getList( self ):
|
|
418 """Returns the list of 'miniature' DOM elements associated with this
|
|
419 miniature library.
|
|
420 """
|
36
|
421 return self.handler.xml.findall( 'miniature' )
|
28
|
422
|
|
423 def add_row( self, count = 1 ):
|
|
424 """creates a new miniature node, and then adds it to the current
|
|
425 miniature library, and to the grid.
|
|
426 """
|
|
427 self.AppendRows( count )
|
|
428 node = self.handler.new_mini( {
|
36
|
429 'name' :' ',
|
|
430 'url' :'http://'} )# minidom.Element( 'miniature' )
|
28
|
431 self.update_all()
|
|
432 #self.handler.xml.append( node )
|
|
433
|
|
434 def del_row( self ):
|
|
435 """deletes the miniature associated with the currently selected
|
|
436 row. BUG BUG BUG this method should drop a child from the DOM but
|
|
437 does not.
|
|
438 """
|
|
439 if self.selectedRow > -1:
|
|
440 pos = self.selectedRow
|
36
|
441 list = self.handler.xml.findall('miniature')
|
28
|
442 self.handler.xml.remove( list[pos] )
|
|
443 self.DeleteRows( pos, 1 )
|
|
444
|
|
445 def on_cell_change( self, evt ):
|
|
446 """Event handler for cell selection changes. selected row is used
|
|
447 to update data for that row.
|
|
448 """
|
|
449 row = evt.GetRow()
|
|
450 self.update_data_row( row )
|
|
451
|
|
452 def update_all( self ):
|
|
453 """ensures that the grid is displaying the correct number of
|
|
454 rows, and then updates all data displayed by the grid
|
|
455 """
|
|
456 list = self.getList()
|
|
457 count = 0
|
|
458 for n in list:
|
|
459 for k in n.keys():
|
|
460 if k not in self.keys: self.keys.append( k )
|
|
461 count = len( self.keys )
|
|
462 if self.GetNumberCols() < count:
|
|
463 self.AppendCols( count - self.GetNumberCols() )
|
|
464 for k in self.keys: self.SetColLabelValue( self.keys.index( k ), k )
|
|
465 count = len( list )
|
|
466 rowcount = self.GetNumberRows()
|
|
467 if ( count > rowcount ):
|
|
468 total = count - rowcount
|
|
469 self.AppendRows( total )
|
|
470 elif ( count < rowcount ):
|
|
471 total = rowcount - count
|
|
472 self.DeleteRows( 0, total );
|
|
473 for index in range( 0, count ):
|
|
474 self.update_grid_row( index )
|
|
475
|
|
476 def getSelectedLabel( self ):
|
|
477 """Returns the label for the selected row
|
|
478 """
|
|
479 return self.GetTable().GetValue( self.selectedRow, 0 )
|
|
480
|
|
481 def getSelectedURL( self ):
|
|
482 """Returns the URL for the selected row
|
|
483 """
|
|
484 return self.GetTable().GetValue( self.selectedRow, 1 )
|
|
485
|
|
486 def getSelectedSerial( self ):
|
36
|
487 """Returns the 'unique' value for the selected row
|
28
|
488 """
|
|
489 return self.GetTable().GetValue( self.selectedRow, 2 )
|
|
490
|
|
491 def update_grid_row( self, row ):
|
|
492 """Updates the specified grid row with data from the DOM node
|
|
493 specified by 'row'
|
|
494 """
|
|
495 list = self.getList()
|
|
496 item = list[ row ]
|
|
497 for key in self.keys: self.GetTable().SetValue( row, self.keys.index( key ), item.get( key ) )
|
|
498
|
|
499 def update_data_row( self, row ):
|
|
500 """Updates the DOM nodw 'row' with grid data from 'row'
|
|
501 """
|
|
502 list = self.getList()
|
|
503 item = list[ row ]
|
|
504 for key in self.keys: item.set( key, string.strip( self.GetTable().GetValue( row, self.keys.index( key ) ) ) )
|