dbm_dialogs.py 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665
  1. """
  2. @package dbm_dialogs.py
  3. @brief DBM-related dialogs
  4. List of classes:
  5. - DisplayAttributesDialog
  6. - ModifyTableRecord
  7. (C) 2007-2009 by the GRASS Development Team
  8. This program is free software under the GNU General Public
  9. License (>=v2). Read the file COPYING that comes with GRASS
  10. for details.
  11. @author Martin Landa <landa.martin gmail.com>
  12. """
  13. import os
  14. import globalvar
  15. if not os.getenv("GRASS_WXBUNDLED"):
  16. globalvar.CheckForWx()
  17. import wx
  18. import wx.lib.scrolledpanel as scrolled
  19. import gcmd
  20. from debug import Debug
  21. from preferences import globalSettings as UserSettings
  22. from dbm_base import VectorDBInfo
  23. class DisplayAttributesDialog(wx.Dialog):
  24. """
  25. Standard dialog used to add/update/display attributes linked
  26. to the vector map.
  27. Attribute data can be selected based on layer and category number
  28. or coordinates.
  29. @param parent
  30. @param map vector map
  31. @param query query coordinates and distance (used for v.edit)
  32. @param cats {layer: cats}
  33. @param line feature id (requested for cats)
  34. @param style
  35. @param pos
  36. @param action (add, update, display)
  37. """
  38. def __init__(self, parent, map,
  39. query=None, cats=None, line=None,
  40. style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER,
  41. pos=wx.DefaultPosition,
  42. action="add"):
  43. self.parent = parent # mapdisplay.BufferedWindow
  44. self.map = map
  45. self.action = action
  46. # ids/cats of selected features
  47. # fid : {layer : cats}
  48. self.cats = {}
  49. self.fid = -1 # feature id
  50. # get layer/table/column information
  51. self.mapDBInfo = VectorDBInfo(self.map)
  52. layers = self.mapDBInfo.layers.keys() # get available layers
  53. # check if db connection / layer exists
  54. if len(layers) <= 0:
  55. label = _("Database connection "
  56. "is not defined in DB file.")
  57. wx.MessageBox(parent=self.parent,
  58. message=_("No attribute table linked to "
  59. "vector map <%(vector)s> found. %(msg)s"
  60. "\nYou can disable this message from digitization settings. Or "
  61. "you can create and link attribute table to the vector map "
  62. "using Attribute Table Manager.") %
  63. {'vector' : self.map, 'msg' : label},
  64. caption=_("Message"), style=wx.OK | wx.ICON_EXCLAMATION | wx.CENTRE)
  65. self.mapDBInfo = None
  66. wx.Dialog.__init__(self, parent=self.parent, id=wx.ID_ANY,
  67. title="", style=style, pos=pos)
  68. # dialog body
  69. mainSizer = wx.BoxSizer(wx.VERTICAL)
  70. # notebook
  71. self.notebook = wx.Notebook(parent=self, id=wx.ID_ANY, style=wx.BK_DEFAULT)
  72. self.closeDialog = wx.CheckBox(parent=self, id=wx.ID_ANY,
  73. label=_("Close dialog on submit"))
  74. self.closeDialog.SetValue(True)
  75. # feature id (text/choice for duplicates)
  76. self.fidMulti = wx.Choice(parent=self, id=wx.ID_ANY,
  77. size=(150, -1))
  78. self.fidMulti.Bind(wx.EVT_CHOICE, self.OnFeature)
  79. self.fidText = wx.StaticText(parent=self, id=wx.ID_ANY)
  80. self.noFoundMsg = wx.StaticText(parent=self, id=wx.ID_ANY,
  81. label=_("No attributes found"))
  82. self.UpdateDialog(query=query, cats=cats)
  83. # set title
  84. if self.action == "update":
  85. self.SetTitle(_("Update attributes"))
  86. elif self.action == "add":
  87. self.SetTitle(_("Add attributes"))
  88. else:
  89. self.SetTitle(_("Display attributes"))
  90. # buttons
  91. btnCancel = wx.Button(self, wx.ID_CANCEL)
  92. btnReset = wx.Button(self, wx.ID_UNDO, _("&Reload"))
  93. btnSubmit = wx.Button(self, wx.ID_OK, _("&Submit"))
  94. btnSizer = wx.StdDialogButtonSizer()
  95. btnSizer.AddButton(btnCancel)
  96. btnSizer.AddButton(btnReset)
  97. btnSizer.SetNegativeButton(btnReset)
  98. btnSubmit.SetDefault()
  99. btnSizer.AddButton(btnSubmit)
  100. btnSizer.Realize()
  101. mainSizer.Add(item=self.noFoundMsg, proportion=0,
  102. flag=wx.EXPAND | wx.ALL, border=5)
  103. mainSizer.Add(item=self.notebook, proportion=1,
  104. flag=wx.EXPAND | wx.ALL, border=5)
  105. fidSizer = wx.BoxSizer(wx.HORIZONTAL)
  106. fidSizer.Add(item=wx.StaticText(parent=self, id=wx.ID_ANY,
  107. label=_("Feature id:")),
  108. proportion=0, border=5,
  109. flag=wx.ALIGN_CENTER_VERTICAL)
  110. fidSizer.Add(item=self.fidMulti, proportion=0,
  111. flag=wx.EXPAND | wx.ALL, border=5)
  112. fidSizer.Add(item=self.fidText, proportion=0,
  113. flag=wx.EXPAND | wx.ALL, border=5)
  114. mainSizer.Add(item=fidSizer, proportion=0,
  115. flag=wx.EXPAND | wx.LEFT | wx.RIGHT, border=5)
  116. mainSizer.Add(item=self.closeDialog, proportion=0, flag=wx.EXPAND | wx.LEFT | wx.RIGHT,
  117. border=5)
  118. mainSizer.Add(item=btnSizer, proportion=0,
  119. flag=wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border=5)
  120. # bindigs
  121. btnReset.Bind(wx.EVT_BUTTON, self.OnReset)
  122. btnSubmit.Bind(wx.EVT_BUTTON, self.OnSubmit)
  123. btnCancel.Bind(wx.EVT_BUTTON, self.OnCancel)
  124. self.SetSizer(mainSizer)
  125. mainSizer.Fit(self)
  126. # set min size for dialog
  127. w, h = self.GetBestSize()
  128. if h < 200:
  129. self.SetMinSize((w, 200))
  130. else:
  131. self.SetMinSize(self.GetBestSize())
  132. if self.notebook.GetPageCount() == 0:
  133. Debug.msg(2, "DisplayAttributesDialog(): Nothing found!")
  134. ### self.mapDBInfo = None
  135. def __SelectAttributes(self, layer):
  136. """!Select attributes"""
  137. pass
  138. def OnSQLStatement(self, event):
  139. """!Update SQL statement"""
  140. pass
  141. def GetSQLString(self, updateValues=False):
  142. """!Create SQL statement string based on self.sqlStatement
  143. If updateValues is True, update dataFrame according to values
  144. in textfields.
  145. """
  146. sqlCommands = []
  147. # find updated values for each layer/category
  148. for layer in self.mapDBInfo.layers.keys(): # for each layer
  149. table = self.mapDBInfo.GetTable(layer)
  150. key = self.mapDBInfo.GetKeyColumn(layer)
  151. columns = self.mapDBInfo.GetTableDesc(table)
  152. for idx in range(len(columns[key]['values'])): # for each category
  153. updatedColumns = []
  154. updatedValues = []
  155. for name in columns.keys():
  156. if name == key:
  157. cat = columns[name]['values'][idx]
  158. continue
  159. type = columns[name]['type']
  160. value = columns[name]['values'][idx]
  161. id = columns[name]['ids'][idx]
  162. try:
  163. newvalue = self.FindWindowById(id).GetValue()
  164. except:
  165. newvalue = self.FindWindowById(id).GetLabel()
  166. if newvalue == '':
  167. newvalue = None
  168. if newvalue != value:
  169. updatedColumns.append(name)
  170. if newvalue is None:
  171. updatedValues.append('NULL')
  172. else:
  173. if type != 'character':
  174. updatedValues.append(newvalue)
  175. else:
  176. updatedValues.append("'" + newvalue + "'")
  177. columns[name]['values'][idx] = newvalue
  178. if self.action != "add" and len(updatedValues) == 0:
  179. continue
  180. if self.action == "add":
  181. sqlString = "INSERT INTO %s (%s," % (table, key)
  182. else:
  183. sqlString = "UPDATE %s SET " % table
  184. for idx in range(len(updatedColumns)):
  185. name = updatedColumns[idx]
  186. if self.action == "add":
  187. sqlString += name + ","
  188. else:
  189. sqlString += name + "=" + updatedValues[idx] + ","
  190. sqlString = sqlString[:-1] # remove last comma
  191. if self.action == "add":
  192. sqlString += ") VALUES (%s," % cat
  193. for value in updatedValues:
  194. sqlString += str(value) + ","
  195. sqlString = sqlString[:-1] # remove last comma
  196. sqlString += ")"
  197. else:
  198. sqlString += " WHERE cat=%s" % cat
  199. sqlCommands.append(sqlString)
  200. # for each category
  201. # for each layer END
  202. Debug.msg(3, "DisplayAttributesDialog.GetSQLString(): %s" % sqlCommands)
  203. return sqlCommands
  204. def OnReset(self, event = None):
  205. """!Reset form"""
  206. for layer in self.mapDBInfo.layers.keys():
  207. table = self.mapDBInfo.layers[layer]["table"]
  208. key = self.mapDBInfo.layers[layer]["key"]
  209. columns = self.mapDBInfo.tables[table]
  210. for idx in range(len(columns[key]['values'])):
  211. for name in columns.keys():
  212. type = columns[name]['type']
  213. value = columns[name]['values'][idx]
  214. if value is None:
  215. value = ''
  216. try:
  217. id = columns[name]['ids'][idx]
  218. except IndexError:
  219. id = wx.NOT_FOUND
  220. if name != key and id != wx.NOT_FOUND:
  221. self.FindWindowById(id).SetValue(str(value))
  222. def OnCancel(self, event):
  223. """!Cancel button pressed"""
  224. self.parent.parent.dialogs['attributes'] = None
  225. if self.parent.parent.digit:
  226. self.parent.parent.digit.driver.SetSelected([])
  227. self.parent.UpdateMap(render=False)
  228. else:
  229. self.parent.parent.OnRender(None)
  230. self.Close()
  231. def OnSubmit(self, event):
  232. """!Submit records"""
  233. for sql in self.GetSQLString(updateValues=True):
  234. enc = UserSettings.Get(group='atm', key='encoding', subkey='value')
  235. if not enc and \
  236. os.environ.has_key('GRASS_DB_ENCODING'):
  237. enc = os.environ['GRASS_DB_ENCODING']
  238. if enc:
  239. sql = sql.encode(enc)
  240. gcmd.RunCommand('db.execute',
  241. quiet = True,
  242. input = '-',
  243. stdin = sql)
  244. if self.closeDialog.IsChecked():
  245. self.OnCancel(event)
  246. def OnFeature(self, event):
  247. self.fid = int(event.GetString())
  248. self.UpdateDialog(cats=self.cats, fid=self.fid)
  249. def GetCats(self):
  250. """!Get id of selected vector object or 'None' if nothing selected
  251. @param id if true return ids otherwise cats
  252. """
  253. if self.fid < 0:
  254. return None
  255. return self.cats[self.fid]
  256. def GetFid(self):
  257. """!Get selected feature id"""
  258. return self.fid
  259. def UpdateDialog(self, map=None, query=None, cats=None, fid=-1):
  260. """!Update dialog
  261. Return True if updated otherwise False
  262. """
  263. if map:
  264. self.map = map
  265. # get layer/table/column information
  266. self.mapDBInfo = VectorDBInfo(self.map)
  267. if not self.mapDBInfo:
  268. return False
  269. self.mapDBInfo.Reset()
  270. layers = self.mapDBInfo.layers.keys() # get available layers
  271. # id of selected line
  272. if query: # select by position
  273. data = self.mapDBInfo.SelectByPoint(query[0],
  274. query[1])
  275. self.cats = {}
  276. if data and data.has_key('Layer'):
  277. idx = 0
  278. for layer in data['Layer']:
  279. layer = int(layer)
  280. if data.has_key('Id'):
  281. tfid = int(data['Id'][idx])
  282. else:
  283. tfid = 0 # Area / Volume
  284. if not self.cats.has_key(tfid):
  285. self.cats[tfid] = {}
  286. if not self.cats[tfid].has_key(layer):
  287. self.cats[tfid][layer] = []
  288. cat = int(data['Category'][idx])
  289. self.cats[tfid][layer].append(cat)
  290. idx += 1
  291. else:
  292. self.cats = cats
  293. if fid > 0:
  294. self.fid = fid
  295. elif len(self.cats.keys()) > 0:
  296. self.fid = self.cats.keys()[0]
  297. else:
  298. self.fid = -1
  299. if len(self.cats.keys()) == 1:
  300. self.fidMulti.Show(False)
  301. self.fidText.Show(True)
  302. if self.fid > 0:
  303. self.fidText.SetLabel("%d" % self.fid)
  304. else:
  305. self.fidText.SetLabel(_("Unknown"))
  306. else:
  307. self.fidMulti.Show(True)
  308. self.fidText.Show(False)
  309. choices = []
  310. for tfid in self.cats.keys():
  311. choices.append(str(tfid))
  312. self.fidMulti.SetItems(choices)
  313. self.fidMulti.SetStringSelection(str(self.fid))
  314. # reset notebook
  315. self.notebook.DeleteAllPages()
  316. for layer in layers: # for each layer
  317. if not query: # select by layer/cat
  318. if self.fid > 0 and self.cats[self.fid].has_key(layer):
  319. for cat in self.cats[self.fid][layer]:
  320. nselected = self.mapDBInfo.SelectFromTable(layer,
  321. where="%s=%d" % \
  322. (self.mapDBInfo.layers[layer]['key'],
  323. cat))
  324. else:
  325. nselected = 0
  326. # if nselected <= 0 and self.action != "add":
  327. # continue # nothing selected ...
  328. if self.action == "add":
  329. if nselected <= 0:
  330. if self.cats[self.fid].has_key(layer):
  331. table = self.mapDBInfo.layers[layer]["table"]
  332. key = self.mapDBInfo.layers[layer]["key"]
  333. columns = self.mapDBInfo.tables[table]
  334. for name in columns.keys():
  335. if name == key:
  336. for cat in self.cats[self.fid][layer]:
  337. self.mapDBInfo.tables[table][name]['values'].append(cat)
  338. else:
  339. self.mapDBInfo.tables[table][name]['values'].append(None)
  340. else: # change status 'add' -> 'update'
  341. self.action = "update"
  342. table = self.mapDBInfo.layers[layer]["table"]
  343. key = self.mapDBInfo.layers[layer]["key"]
  344. columns = self.mapDBInfo.tables[table]
  345. for idx in range(len(columns[key]['values'])):
  346. for name in columns.keys():
  347. if name == key:
  348. cat = int(columns[name]['values'][idx])
  349. break
  350. # use scrolled panel instead (and fix initial max height of the window to 480px)
  351. panel = scrolled.ScrolledPanel(parent=self.notebook, id=wx.ID_ANY,
  352. size=(-1, 150))
  353. panel.SetupScrolling(scroll_x=False)
  354. self.notebook.AddPage(page=panel, text=" %s %d / %s %d" % (_("Layer"), layer,
  355. _("Category"), cat))
  356. # notebook body
  357. border = wx.BoxSizer(wx.VERTICAL)
  358. flexSizer = wx.FlexGridSizer (cols=4, hgap=3, vgap=3)
  359. flexSizer.AddGrowableCol(3)
  360. # columns (sorted by index)
  361. names = [''] * len(columns.keys())
  362. for name in columns.keys():
  363. names[columns[name]['index']] = name
  364. for name in names:
  365. if name == key: # skip key column (category)
  366. continue
  367. vtype = columns[name]['type']
  368. if columns[name]['values'][idx] is not None:
  369. if columns[name]['ctype'] != type(''):
  370. value = str(columns[name]['values'][idx])
  371. else:
  372. value = columns[name]['values'][idx]
  373. else:
  374. value = ''
  375. colName = wx.StaticText(parent=panel, id=wx.ID_ANY,
  376. label=name)
  377. colType = wx.StaticText(parent=panel, id=wx.ID_ANY,
  378. label="[" + vtype.lower() + "]")
  379. delimiter = wx.StaticText(parent=panel, id=wx.ID_ANY, label=":")
  380. colValue = wx.TextCtrl(parent=panel, id=wx.ID_ANY, value=value)
  381. colValue.SetName(name)
  382. self.Bind(wx.EVT_TEXT, self.OnSQLStatement, colValue)
  383. flexSizer.Add(colName, proportion=0,
  384. flag=wx.FIXED_MINSIZE | wx.ALIGN_CENTER_VERTICAL)
  385. flexSizer.Add(colType, proportion=0,
  386. flag=wx.FIXED_MINSIZE | wx.ALIGN_CENTER_VERTICAL)
  387. flexSizer.Add(delimiter, proportion=0,
  388. flag=wx.FIXED_MINSIZE | wx.ALIGN_CENTER_VERTICAL)
  389. flexSizer.Add(colValue, proportion=1,
  390. flag=wx.EXPAND | wx.ALIGN_CENTER_VERTICAL)
  391. # add widget reference to self.columns
  392. columns[name]['ids'].append(colValue.GetId()) # name, type, values, id
  393. # for each attribute (including category) END
  394. border.Add(item=flexSizer, proportion=1, flag=wx.ALL | wx.EXPAND, border=5)
  395. panel.SetSizer(border)
  396. # for each category END
  397. # for each layer END
  398. if self.notebook.GetPageCount() == 0:
  399. self.noFoundMsg.Show(True)
  400. else:
  401. self.noFoundMsg.Show(False)
  402. self.Layout()
  403. return True
  404. def SetColumnValue(self, layer, column, value):
  405. """!Set attrbute value
  406. @param column column name
  407. @param value value
  408. """
  409. table = self.mapDBInfo.GetTable(layer)
  410. columns = self.mapDBInfo.GetTableDesc(table)
  411. for key, col in columns.iteritems():
  412. if key == column:
  413. col['values'] = [col['ctype'](value),]
  414. break
  415. class ModifyTableRecord(wx.Dialog):
  416. """!Dialog for inserting/updating table record"""
  417. def __init__(self, parent, id, title, data, keyEditable=(-1, True),
  418. style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER):
  419. """
  420. Notes:
  421. 'Data' is a list: [(column, value)]
  422. 'KeyEditable' (id, editable?) indicates if textarea for key column
  423. is editable(True) or not.
  424. """
  425. wx.Dialog.__init__(self, parent, id, title, style=style)
  426. self.CenterOnParent()
  427. self.keyId = keyEditable[0]
  428. self.panel = wx.Panel(parent=self, id=wx.ID_ANY)
  429. box = wx.StaticBox(parent=self.panel, id=wx.ID_ANY, label='')
  430. self.dataPanel = scrolled.ScrolledPanel(parent=self.panel, id=wx.ID_ANY,
  431. style=wx.TAB_TRAVERSAL)
  432. self.dataPanel.SetupScrolling(scroll_x=False)
  433. #
  434. # buttons
  435. #
  436. self.btnCancel = wx.Button(self.panel, wx.ID_CANCEL)
  437. self.btnSubmit = wx.Button(self.panel, wx.ID_OK, _("Submit"))
  438. self.btnSubmit.SetDefault()
  439. #
  440. # data area
  441. #
  442. self.widgets = []
  443. id = 0
  444. self.usebox = False
  445. self.cat = None
  446. for column, value in data:
  447. if keyEditable[0] == id:
  448. self.cat = int(value)
  449. if keyEditable[1] == False:
  450. self.usebox = True
  451. box.SetLabel =" %s %d " % (_("Category"), self.cat)
  452. self.boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  453. id += 1
  454. continue
  455. else:
  456. valueWin = wx.SpinCtrl(parent=self.dataPanel, id=wx.ID_ANY,
  457. value=value, min=-1e9, max=1e9, size=(250, -1))
  458. else:
  459. valueWin = wx.TextCtrl(parent=self.dataPanel, id=wx.ID_ANY,
  460. value=value, size=(250, -1))
  461. label = wx.StaticText(parent=self.dataPanel, id=wx.ID_ANY,
  462. label=column + ":")
  463. self.widgets.append((label.GetId(),
  464. valueWin.GetId()))
  465. id += 1
  466. self.__Layout()
  467. # winSize = self.GetSize()
  468. # fix height of window frame if needed
  469. # if winSize[1] > 480:
  470. # winSize[1] = 480
  471. # self.SetSize(winSize)
  472. # self.SetMinSize(winSize)
  473. def __Layout(self):
  474. """!Do layout"""
  475. sizer = wx.BoxSizer(wx.VERTICAL)
  476. # data area
  477. dataSizer = wx.FlexGridSizer (cols=2, hgap=3, vgap=3)
  478. dataSizer.AddGrowableCol(1)
  479. for labelId, valueId in self.widgets:
  480. label = self.FindWindowById(labelId)
  481. value = self.FindWindowById(valueId)
  482. dataSizer.Add(label, proportion=0,
  483. flag=wx.ALIGN_CENTER_VERTICAL)
  484. dataSizer.Add(value, proportion=0,
  485. flag=wx.EXPAND | wx.ALIGN_CENTER_VERTICAL)
  486. self.dataPanel.SetAutoLayout(True)
  487. self.dataPanel.SetSizer(dataSizer)
  488. dataSizer.Fit(self.dataPanel)
  489. if self.usebox:
  490. self.boxSizer.Add(item=self.dataPanel, proportion=1,
  491. flag=wx.EXPAND | wx.ALL, border=5)
  492. # buttons
  493. btnSizer = wx.StdDialogButtonSizer()
  494. btnSizer.AddButton(self.btnCancel)
  495. btnSizer.AddButton(self.btnSubmit)
  496. btnSizer.Realize()
  497. if not self.usebox:
  498. sizer.Add(item=self.dataPanel, proportion=1,
  499. flag=wx.EXPAND | wx.ALL, border=5)
  500. else:
  501. sizer.Add(item=self.boxSizer, proportion=1,
  502. flag=wx.EXPAND | wx.ALL, border=5)
  503. sizer.Add(item=btnSizer, proportion=0,
  504. flag=wx.EXPAND | wx.ALL, border=5)
  505. framewidth = self.GetSize()[0]
  506. self.SetMinSize((framewidth,150))
  507. self.SetMaxSize((framewidth,300))
  508. #sizer.SetSizeHints(self.panel)
  509. self.panel.SetAutoLayout(True)
  510. self.panel.SetSizer(sizer)
  511. sizer.Fit(self.panel)
  512. self.Layout()
  513. # # set window frame size (min & max)
  514. # minFrameHeight = 150
  515. # maxFrameHeight = 2 * minFrameHeight
  516. # if self.GetSize()[1] > minFrameHeight:
  517. # print 'size ='+str(self.GetSize()[1])
  518. # print 'if 1'
  519. # self.SetMinSize((self.GetSize()[0], minFrameHeight))
  520. # else:
  521. # print 'else 1'
  522. # self.SetMinSize(self.GetSize())
  523. # if self.GetSize()[1] > maxFrameHeight:
  524. # print 'if 2'
  525. # self.SetSize((self.GetSize()[0], maxFrameHeight))
  526. # else:
  527. # print 'else 2'
  528. # self.SetSize(self.panel.GetSize())
  529. def GetValues(self, columns=None):
  530. """!Return list of values (casted to string).
  531. If columns is given (list), return only values of given columns.
  532. """
  533. valueList = []
  534. for labelId, valueId in self.widgets:
  535. column = self.FindWindowById(labelId).GetLabel().replace(':', '')
  536. if columns is None or column in columns:
  537. value = str(self.FindWindowById(valueId).GetValue())
  538. valueList.append(value)
  539. # add key value
  540. if self.usebox:
  541. valueList.insert(self.keyId, str(self.cat))
  542. return valueList