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