GRASS Programmer's Manual  6.5.svn(2012)-r51648
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
dbmgr/dialogs.py
Go to the documentation of this file.
00001 """!
00002 @package dbmgr.dialogs
00003 
00004 @brief DBM-related dialogs
00005 
00006 List of classes:
00007  - dialogs::DisplayAttributesDialog
00008  - dialogs::ModifyTableRecord
00009 
00010 (C) 2007-2011 by the GRASS Development Team
00011 
00012 This program is free software under the GNU General Public License
00013 (>=v2). Read the file COPYING that comes with GRASS for details.
00014 
00015 @author Martin Landa <landa.martin gmail.com>
00016 """
00017 
00018 import os
00019 import types
00020 
00021 from core import globalvar
00022 import wx
00023 import wx.lib.scrolledpanel as scrolled
00024 
00025 from core.gcmd        import RunCommand, GError
00026 from core.debug       import Debug
00027 from core.settings    import UserSettings
00028 from dbmgr.vinfo      import VectorDBInfo
00029 from gui_core.widgets import IntegerValidator, FloatValidator
00030 
00031 class DisplayAttributesDialog(wx.Dialog):
00032     def __init__(self, parent, map,
00033                  query = None, cats = None, line = None,
00034                  style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER,
00035                  pos = wx.DefaultPosition,
00036                  action = "add", ignoreError = False):
00037         """!Standard dialog used to add/update/display attributes linked
00038         to the vector map.
00039         
00040         Attribute data can be selected based on layer and category number
00041         or coordinates.
00042         
00043         @param parent
00044         @param map vector map
00045         @param query query coordinates and distance (used for v.edit)
00046         @param cats {layer: cats}
00047         @param line feature id (requested for cats)
00048         @param style
00049         @param pos
00050         @param action (add, update, display)
00051         @param ignoreError True to ignore errors
00052         """
00053         self.parent = parent # mapdisplay.BufferedWindow
00054         self.map    = map
00055         self.action = action
00056 
00057         # ids/cats of selected features
00058         # fid : {layer : cats}
00059         self.cats = {}
00060         self.fid = -1 # feature id
00061         
00062         # get layer/table/column information
00063         self.mapDBInfo = VectorDBInfo(self.map)
00064         
00065         layers = self.mapDBInfo.layers.keys() # get available layers
00066 
00067         # check if db connection / layer exists
00068         if len(layers) <= 0:
00069             if not ignoreError:
00070                 dlg = wx.MessageDialog(parent = self.parent,
00071                                        message = _("No attribute table found.\n\n"
00072                                                    "Do you want to create a new attribute table "
00073                                                    "and defined a link to vector map <%s>?") % self.map,
00074                                        caption = _("Create table?"),
00075                                        style = wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
00076                 if dlg.ShowModal() == wx.ID_YES:
00077                     lmgr = self.parent.lmgr
00078                     lmgr.OnShowAttributeTable(event = None, selection = 'layers')
00079                 
00080                 dlg.Destroy()
00081             
00082             self.mapDBInfo = None
00083         
00084         wx.Dialog.__init__(self, parent = self.parent, id = wx.ID_ANY,
00085                            title = "", style = style, pos = pos)
00086 
00087         # dialog body
00088         mainSizer = wx.BoxSizer(wx.VERTICAL)
00089 
00090         # notebook
00091         self.notebook = wx.Notebook(parent = self, id = wx.ID_ANY, style = wx.BK_DEFAULT)
00092 
00093         self.closeDialog = wx.CheckBox(parent = self, id = wx.ID_ANY,
00094                                        label = _("Close dialog on submit"))
00095         self.closeDialog.SetValue(True)
00096         if self.action == 'display':
00097             self.closeDialog.Enable(False)
00098         
00099         # feature id (text/choice for duplicates)
00100         self.fidMulti = wx.Choice(parent = self, id = wx.ID_ANY,
00101                                   size = (150, -1))
00102         self.fidMulti.Bind(wx.EVT_CHOICE, self.OnFeature)
00103         self.fidText = wx.StaticText(parent = self, id = wx.ID_ANY)
00104 
00105         self.noFoundMsg = wx.StaticText(parent = self, id = wx.ID_ANY,
00106                                         label = _("No attributes found"))
00107         
00108         self.UpdateDialog(query = query, cats = cats)
00109 
00110         # set title
00111         if self.action == "update":
00112             self.SetTitle(_("Update attributes"))
00113         elif self.action == "add":
00114             self.SetTitle(_("Define attributes"))
00115         else:
00116             self.SetTitle(_("Display attributes"))
00117 
00118         # buttons
00119         btnCancel = wx.Button(self, wx.ID_CANCEL)
00120         btnReset  = wx.Button(self, wx.ID_UNDO, _("&Reload"))
00121         btnSubmit = wx.Button(self, wx.ID_OK, _("&Submit"))
00122         if self.action == 'display':
00123             btnSubmit.Enable(False)
00124         
00125         btnSizer = wx.StdDialogButtonSizer()
00126         btnSizer.AddButton(btnCancel)
00127         btnSizer.AddButton(btnReset)
00128         btnSizer.SetNegativeButton(btnReset)
00129         btnSubmit.SetDefault()
00130         btnSizer.AddButton(btnSubmit)
00131         btnSizer.Realize()
00132 
00133         mainSizer.Add(item = self.noFoundMsg, proportion = 0,
00134                       flag = wx.EXPAND | wx.ALL, border = 5)
00135         mainSizer.Add(item = self.notebook, proportion = 1,
00136                       flag = wx.EXPAND | wx.ALL, border = 5)
00137         fidSizer = wx.BoxSizer(wx.HORIZONTAL)
00138         fidSizer.Add(item = wx.StaticText(parent = self, id = wx.ID_ANY,
00139                                         label = _("Feature id:")),
00140                      proportion = 0, border = 5,
00141                      flag = wx.ALIGN_CENTER_VERTICAL)
00142         fidSizer.Add(item = self.fidMulti, proportion = 0,
00143                      flag = wx.EXPAND | wx.ALL,  border = 5)
00144         fidSizer.Add(item = self.fidText, proportion = 0,
00145                      flag = wx.EXPAND | wx.ALL,  border = 5)
00146         mainSizer.Add(item = fidSizer, proportion = 0,
00147                       flag = wx.EXPAND | wx.LEFT | wx.RIGHT, border = 5)
00148         mainSizer.Add(item = self.closeDialog, proportion = 0, flag = wx.EXPAND | wx.LEFT | wx.RIGHT,
00149                       border = 5)
00150         mainSizer.Add(item = btnSizer, proportion = 0,
00151                       flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border = 5)
00152 
00153         # bindigs
00154         btnReset.Bind(wx.EVT_BUTTON, self.OnReset)
00155         btnSubmit.Bind(wx.EVT_BUTTON, self.OnSubmit)
00156         btnCancel.Bind(wx.EVT_BUTTON, self.OnCancel)
00157 
00158         self.SetSizer(mainSizer)
00159         mainSizer.Fit(self)
00160 
00161         # set min size for dialog
00162         w, h = self.GetBestSize()
00163         w += 50
00164         if h < 200:
00165             self.SetMinSize((w, 200))
00166         else:
00167             self.SetMinSize((w, h))
00168         
00169         if self.notebook.GetPageCount() == 0:
00170             Debug.msg(2, "DisplayAttributesDialog(): Nothing found!")
00171             ### self.mapDBInfo = None
00172         
00173     def __SelectAttributes(self, layer):
00174         """!Select attributes"""
00175         pass
00176 
00177     def OnSQLStatement(self, event):
00178         """!Update SQL statement"""
00179         pass
00180 
00181     def IsFound(self):
00182         """!Check for status
00183 
00184         @return True on attributes found
00185         @return False attributes not found
00186         """
00187         return bool(self.notebook.GetPageCount())
00188     
00189     def GetSQLString(self, updateValues = False):
00190         """!Create SQL statement string based on self.sqlStatement
00191 
00192         Show error message when invalid values are entered.
00193         
00194         If updateValues is True, update dataFrame according to values
00195         in textfields.
00196         """
00197         sqlCommands = []
00198         # find updated values for each layer/category
00199         for layer in self.mapDBInfo.layers.keys(): # for each layer
00200             table = self.mapDBInfo.GetTable(layer)
00201             key = self.mapDBInfo.GetKeyColumn(layer)
00202             columns = self.mapDBInfo.GetTableDesc(table)
00203             for idx in range(len(columns[key]['values'])): # for each category
00204                 updatedColumns = []
00205                 updatedValues = []
00206                 for name in columns.keys():
00207                     if name == key:
00208                         cat = columns[name]['values'][idx]
00209                         continue
00210                     ctype  = columns[name]['ctype']
00211                     value = columns[name]['values'][idx]
00212                     id    = columns[name]['ids'][idx]
00213                     try:
00214                         newvalue = self.FindWindowById(id).GetValue()
00215                     except:
00216                         newvalue = self.FindWindowById(id).GetLabel()
00217                   
00218                     if newvalue:
00219                         try:
00220                             if ctype == int:
00221                                 newvalue = int(newvalue)
00222                             elif ctype == float:
00223                                 newvalue = float(newvalue)
00224                         except ValueError:
00225                             GError(parent = self,
00226                                    message = _("Column <%(col)s>: Value '%(value)s' needs to be entered as %(type)s.") % \
00227                                        {'col' : name,
00228                                         'value' : str(newvalue),
00229                                         'type' : columns[name]['type'].lower()},
00230                                    showTraceback = False)
00231                             sqlCommands.append(None)
00232                             continue
00233                     else:
00234                         if self.action == 'add':
00235                             continue
00236                     
00237                     if newvalue != value:
00238                         updatedColumns.append(name)
00239                         if not newvalue:
00240                             updatedValues.append('NULL')
00241                         else:
00242                             if ctype != str:
00243                                 updatedValues.append(str(newvalue))
00244                             else:
00245                                 updatedValues.append("'" + str(newvalue) + "'")
00246                         columns[name]['values'][idx] = newvalue
00247 
00248                 if self.action != "add" and len(updatedValues) == 0:
00249                     continue
00250 
00251                 if self.action == "add":
00252                     sqlString = "INSERT INTO %s (%s," % (table, key)
00253                 else:
00254                     sqlString = "UPDATE %s SET " % table
00255 
00256                 for idx in range(len(updatedColumns)):
00257                     name = updatedColumns[idx]
00258                     if self.action == "add":
00259                         sqlString += name + ","
00260                     else:
00261                         sqlString += name + "=" + updatedValues[idx] + ","
00262 
00263                 sqlString = sqlString[:-1] # remove last comma
00264 
00265                 if self.action == "add":
00266                     sqlString += ") VALUES (%s," % cat
00267                     for value in updatedValues:
00268                         sqlString += str(value) + ","
00269                     sqlString = sqlString[:-1] # remove last comma
00270                     sqlString += ")"
00271                 else:
00272                     sqlString += " WHERE cat=%s" % cat
00273                 sqlCommands.append(sqlString)
00274             # for each category
00275         # for each layer END
00276 
00277         Debug.msg(3, "DisplayAttributesDialog.GetSQLString(): %s" % sqlCommands)
00278 
00279         return sqlCommands
00280 
00281     def OnReset(self, event = None):
00282         """!Reset form"""
00283         for layer in self.mapDBInfo.layers.keys():
00284             table = self.mapDBInfo.layers[layer]["table"]
00285             key = self.mapDBInfo.layers[layer]["key"]
00286             columns = self.mapDBInfo.tables[table]
00287             for idx in range(len(columns[key]['values'])):
00288                 for name in columns.keys():
00289                     type  = columns[name]['type']
00290                     value = columns[name]['values'][idx]
00291                     if value is None:
00292                         value = ''
00293                     try:
00294                         id = columns[name]['ids'][idx]
00295                     except IndexError:
00296                         id = wx.NOT_FOUND
00297                     
00298                     if name != key and id != wx.NOT_FOUND:
00299                         self.FindWindowById(id).SetValue(str(value))
00300 
00301     def OnCancel(self, event):
00302         """!Cancel button pressed
00303         """
00304         self.parent.parent.dialogs['attributes'] = None
00305         
00306         if hasattr(self, "digit"):
00307             self.parent.digit.GetDisplay().SetSelected([])
00308             self.parent.UpdateMap(render = False)
00309         else:
00310             self.parent.parent.OnRender(None)
00311         
00312         self.Close()
00313 
00314     def OnSubmit(self, event):
00315         """!Submit records"""
00316         close = True
00317         enc = UserSettings.Get(group = 'atm', key = 'encoding', subkey = 'value')
00318         if not enc and 'GRASS_DB_ENCODING' in os.environ:
00319             enc = os.environ['GRASS_DB_ENCODING']
00320         
00321         for sql in self.GetSQLString(updateValues = True):
00322             if not sql:
00323                 close = False
00324                 continue
00325             if enc:
00326                 sql = sql.encode(enc)
00327             
00328             RunCommand('db.execute',
00329                        parent = self,
00330                        quiet = True,
00331                        stdin = sql)
00332         
00333         if close and self.closeDialog.IsChecked():
00334             self.OnCancel(event)
00335 
00336     def OnFeature(self, event):
00337         self.fid = int(event.GetString())
00338         self.UpdateDialog(cats = self.cats, fid = self.fid)
00339         
00340     def GetCats(self):
00341         """!Get id of selected vector object or 'None' if nothing selected
00342 
00343         @param id if true return ids otherwise cats
00344         """
00345         if self.fid < 0:
00346             return None
00347         
00348         return self.cats[self.fid]
00349 
00350     def GetFid(self):
00351         """!Get selected feature id"""
00352         return self.fid
00353     
00354     def UpdateDialog(self, map = None, query = None, cats = None, fid = -1,
00355                      action = None):
00356         """!Update dialog
00357         
00358         @param map name of vector map
00359         @param query
00360         @param cats
00361         @param fid feature id
00362         @param action add, update, display or None
00363         
00364         @return True if updated
00365         @return False
00366         """
00367         if action:
00368             self.action = action
00369             if action == 'display':
00370                 enabled = False
00371             else:
00372                 enabled = True
00373             self.closeDialog.Enable(enabled)
00374             self.FindWindowById(wx.ID_OK).Enable(enabled)
00375         
00376         if map:
00377             self.map = map
00378             # get layer/table/column information
00379             self.mapDBInfo = VectorDBInfo(self.map)
00380         
00381         if not self.mapDBInfo:
00382             return False
00383         
00384         self.mapDBInfo.Reset()
00385         
00386         layers = self.mapDBInfo.layers.keys() # get available layers
00387         
00388         # id of selected line
00389         if query: # select by position
00390             data = self.mapDBInfo.SelectByPoint(query[0],
00391                                                 query[1])
00392             self.cats = {}
00393             if data and 'Layer' in data:
00394                 idx = 0
00395                 for layer in data['Layer']:
00396                     layer = int(layer)
00397                     if 'Id' in data:
00398                         tfid = int(data['Id'][idx])
00399                     else:
00400                         tfid = 0 # Area / Volume
00401                     if not tfid in self.cats:
00402                         self.cats[tfid] = {}
00403                     if not layer in self.cats[tfid]:
00404                         self.cats[tfid][layer] = []
00405                     cat = int(data['Category'][idx])
00406                     self.cats[tfid][layer].append(cat)
00407                     idx += 1
00408         else:
00409             self.cats = cats
00410         
00411         if fid > 0:
00412             self.fid = fid
00413         elif len(self.cats.keys()) > 0:
00414             self.fid = self.cats.keys()[0]
00415         else:
00416             self.fid = -1
00417         
00418         if len(self.cats.keys()) == 1:
00419             self.fidMulti.Show(False)
00420             self.fidText.Show(True)
00421             if self.fid > 0:
00422                 self.fidText.SetLabel("%d" % self.fid)
00423             else:
00424                 self.fidText.SetLabel(_("Unknown"))
00425         else:
00426             self.fidMulti.Show(True)
00427             self.fidText.Show(False)
00428             choices = []
00429             for tfid in self.cats.keys():
00430                 choices.append(str(tfid))
00431             self.fidMulti.SetItems(choices)
00432             self.fidMulti.SetStringSelection(str(self.fid))
00433         
00434         # reset notebook
00435         self.notebook.DeleteAllPages()
00436         
00437         for layer in layers: # for each layer
00438             if not query: # select by layer/cat
00439                 if self.fid > 0 and layer in self.cats[self.fid]:
00440                     for cat in self.cats[self.fid][layer]:
00441                         nselected = self.mapDBInfo.SelectFromTable(layer,
00442                                                                    where = "%s=%d" % \
00443                                                                    (self.mapDBInfo.layers[layer]['key'],
00444                                                                     cat))
00445                 else:
00446                     nselected = 0
00447             
00448             # if nselected <= 0 and self.action != "add":
00449             #    continue # nothing selected ...
00450             
00451             if self.action == "add":
00452                 if nselected <= 0:
00453                     if layer in self.cats[self.fid]:
00454                         table = self.mapDBInfo.layers[layer]["table"]
00455                         key = self.mapDBInfo.layers[layer]["key"]
00456                         columns = self.mapDBInfo.tables[table]
00457                         for name in columns.keys():
00458                             if name == key:
00459                                 for cat in self.cats[self.fid][layer]:
00460                                     self.mapDBInfo.tables[table][name]['values'].append(cat)
00461                             else:
00462                                 self.mapDBInfo.tables[table][name]['values'].append(None)
00463                 else: # change status 'add' -> 'update'
00464                     self.action = "update"
00465             
00466             table   = self.mapDBInfo.layers[layer]["table"]
00467             key   = self.mapDBInfo.layers[layer]["key"]
00468             columns = self.mapDBInfo.tables[table]
00469             
00470             for idx in range(len(columns[key]['values'])):
00471                 for name in columns.keys():
00472                     if name == key:
00473                         cat = int(columns[name]['values'][idx])
00474                         break
00475 
00476                 # use scrolled panel instead (and fix initial max height of the window to 480px)
00477                 panel = scrolled.ScrolledPanel(parent = self.notebook, id = wx.ID_ANY,
00478                                                size = (-1, 150))
00479                 panel.SetupScrolling(scroll_x = False)
00480                 
00481                 self.notebook.AddPage(page = panel, text = " %s %d / %s %d" % (_("Layer"), layer,
00482                                                                            _("Category"), cat))
00483                 
00484                 # notebook body
00485                 border = wx.BoxSizer(wx.VERTICAL)
00486                 
00487                 flexSizer = wx.FlexGridSizer (cols = 3, hgap = 3, vgap = 3)
00488                 flexSizer.AddGrowableCol(2)
00489                 # columns (sorted by index)
00490                 names = [''] * len(columns.keys())
00491                 for name in columns.keys():
00492                     names[columns[name]['index']] = name
00493                 
00494                 for name in names:
00495                     if name == key: # skip key column (category)
00496                         continue
00497                     
00498                     vtype  = columns[name]['type'].lower()
00499                     ctype  = columns[name]['ctype']
00500                     
00501                     if columns[name]['values'][idx] is not None:
00502                         if columns[name]['ctype'] != types.StringType:
00503                             value = str(columns[name]['values'][idx])
00504                         else:
00505                             value = columns[name]['values'][idx]
00506                     else:
00507                         value = ''
00508                     
00509                     colName = wx.StaticText(parent = panel, id = wx.ID_ANY,
00510                                             label = name)
00511                     colType = wx.StaticText(parent = panel, id = wx.ID_ANY,
00512                                             label = "[%s]:" % vtype)
00513                     colValue = wx.TextCtrl(parent = panel, id = wx.ID_ANY, value = value)
00514                     colValue.SetName(name)
00515                     if ctype == int:
00516                         colValue.SetValidator(IntegerValidator())
00517                     elif ctype == float:
00518                         colValue.SetValidator(FloatValidator())
00519                     
00520                     self.Bind(wx.EVT_TEXT, self.OnSQLStatement, colValue)
00521                     if self.action == 'display':
00522                         colValue.SetWindowStyle(wx.TE_READONLY)
00523                     
00524                     flexSizer.Add(colName, proportion = 0,
00525                                   flag = wx.ALIGN_CENTER_VERTICAL)
00526                     flexSizer.Add(colType, proportion = 0,
00527                                   flag = wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT)
00528                     flexSizer.Add(colValue, proportion = 1,
00529                                   flag = wx.EXPAND | wx.ALIGN_CENTER_VERTICAL)
00530                     # add widget reference to self.columns
00531                     columns[name]['ids'].append(colValue.GetId()) # name, type, values, id
00532                 # for each attribute (including category) END
00533                 border.Add(item = flexSizer, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 5)
00534                 panel.SetSizer(border)
00535             # for each category END
00536         # for each layer END
00537         
00538         if self.notebook.GetPageCount() == 0:
00539             self.noFoundMsg.Show(True)
00540         else:
00541             self.noFoundMsg.Show(False)
00542         
00543         self.Layout()
00544         
00545         return True
00546 
00547     def SetColumnValue(self, layer, column, value):
00548         """!Set attrbute value
00549 
00550         @param column column name
00551         @param value value
00552         """
00553         table = self.mapDBInfo.GetTable(layer)
00554         columns = self.mapDBInfo.GetTableDesc(table)
00555         
00556         for key, col in columns.iteritems():
00557             if key == column:
00558                 col['values'] = [col['ctype'](value),]
00559                 break
00560         
00561 class ModifyTableRecord(wx.Dialog):
00562     def __init__(self, parent, title, data, keyEditable = (-1, True),
00563                  id = wx.ID_ANY, style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER):
00564         """!Dialog for inserting/updating table record
00565         
00566         @param data a list: [(column, value)]
00567         @param KeyEditable (id, editable?) indicates if textarea for key column
00568         is editable(True) or not
00569         """
00570         # parent -> VDigitWindow
00571         wx.Dialog.__init__(self, parent, id, title, style = style)
00572         
00573         self.CenterOnParent()
00574         
00575         self.keyId = keyEditable[0]
00576         
00577         box = wx.StaticBox(parent = self, id = wx.ID_ANY)
00578         box.Hide()
00579         self.dataPanel = scrolled.ScrolledPanel(parent = self, id = wx.ID_ANY,
00580                                                 style = wx.TAB_TRAVERSAL)
00581         self.dataPanel.SetupScrolling(scroll_x = False)
00582         
00583         # buttons
00584         self.btnCancel = wx.Button(self, wx.ID_CANCEL)
00585         self.btnSubmit = wx.Button(self, wx.ID_OK, _("&Submit"))
00586         self.btnSubmit.SetDefault()
00587         
00588         # data area
00589         self.widgets = []
00590         cId = 0
00591         self.usebox = False
00592         self.cat = None
00593         winFocus = False
00594         
00595         for column, ctype, ctypeStr, value in data:
00596             if self.keyId == cId:
00597                 self.cat = int(value)
00598                 if not keyEditable[1]:
00599                     self.usebox = True
00600                     box.SetLabel(" %s %d " % (_("Category"), self.cat))
00601                     box.Show()
00602                     self.boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
00603                     cId += 1
00604                     continue
00605                 else:
00606                     valueWin = wx.SpinCtrl(parent = self.dataPanel, id = wx.ID_ANY,
00607                                            value = value, min = -1e9, max = 1e9, size = (250, -1))
00608             else:
00609                 valueWin = wx.TextCtrl(parent = self.dataPanel, id = wx.ID_ANY,
00610                                        value = value, size = (250, -1))
00611                 if ctype == int:
00612                     valueWin.SetValidator(IntegerValidator())
00613                 elif ctype == float:
00614                     valueWin.SetValidator(FloatValidator())
00615                 if not winFocus:
00616                     wx.CallAfter(valueWin.SetFocus)
00617                     winFocus = True
00618             
00619             label = wx.StaticText(parent = self.dataPanel, id = wx.ID_ANY,
00620                                   label = column)
00621             ctype = wx.StaticText(parent = self.dataPanel, id = wx.ID_ANY,
00622                                   label = "[%s]:" % ctypeStr.lower())
00623             self.widgets.append((label.GetId(), ctype.GetId(), valueWin.GetId()))
00624             
00625             cId += 1
00626         
00627         self._layout()
00628         
00629     def _layout(self):
00630         """!Do layout"""
00631         sizer = wx.BoxSizer(wx.VERTICAL)
00632         
00633         # data area
00634         dataSizer = wx.FlexGridSizer(cols = 3, hgap = 3, vgap = 3)
00635         dataSizer.AddGrowableCol(2)
00636         
00637         for labelId, ctypeId, valueId in self.widgets:
00638             label = self.FindWindowById(labelId)
00639             ctype = self.FindWindowById(ctypeId)
00640             value = self.FindWindowById(valueId)
00641             
00642             dataSizer.Add(label, proportion = 0,
00643                           flag = wx.ALIGN_CENTER_VERTICAL)
00644             dataSizer.Add(ctype, proportion = 0,
00645                           flag = wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT)
00646             dataSizer.Add(value, proportion = 0,
00647                           flag = wx.EXPAND | wx.ALIGN_CENTER_VERTICAL)
00648         
00649         self.dataPanel.SetAutoLayout(True)
00650         self.dataPanel.SetSizer(dataSizer)
00651         dataSizer.Fit(self.dataPanel)
00652         
00653         if self.usebox:
00654             self.boxSizer.Add(item = self.dataPanel, proportion = 1,
00655                               flag = wx.EXPAND | wx.ALL, border = 5)
00656             
00657         # buttons
00658         btnSizer = wx.StdDialogButtonSizer()
00659         btnSizer.AddButton(self.btnCancel)
00660         btnSizer.AddButton(self.btnSubmit)
00661         btnSizer.Realize()
00662         
00663         if not self.usebox:
00664             sizer.Add(item = self.dataPanel, proportion = 1,
00665                       flag = wx.EXPAND | wx.ALL, border = 5)
00666         else:
00667             sizer.Add(item = self.boxSizer, proportion = 1,
00668                       flag = wx.EXPAND | wx.ALL, border = 5)
00669         
00670         sizer.Add(item = btnSizer, proportion = 0,
00671                   flag = wx.EXPAND | wx.ALL, border = 5)
00672         
00673         framewidth = self.GetBestSize()[0] + 25
00674         self.SetMinSize((framewidth, 250))
00675 
00676         self.SetAutoLayout(True)
00677         self.SetSizer(sizer)
00678         sizer.Fit(self)
00679         
00680         self.Layout()
00681         
00682     def GetValues(self, columns = None):
00683         """!Return list of values (casted to string).
00684         
00685         If columns is given (list), return only values of given columns.
00686         """
00687         valueList = []
00688         for labelId, ctypeId, valueId in self.widgets:
00689             column = self.FindWindowById(labelId).GetLabel().replace(':', '')
00690             if columns is None or column in columns:
00691                 value = str(self.FindWindowById(valueId).GetValue())
00692                 valueList.append(value)
00693         
00694         # add key value
00695         if self.usebox:
00696             valueList.insert(self.keyId, str(self.cat))
00697                              
00698         return valueList