2 @package dbm_dialogs.py
4 @brief DBM-related dialogs
7 - DisplayAttributesDialog
10 (C) 2007-2011 by the GRASS Development Team
12 This program is free software under the GNU General Public
13 License (>=v2). Read the file COPYING that comes with GRASS
16 @author Martin Landa <landa.martin gmail.com>
23 import wx.lib.scrolledpanel
as scrolled
26 from debug
import Debug
27 from preferences
import globalSettings
as UserSettings
28 from dbm_base
import VectorDBInfo
32 query =
None, cats =
None, line =
None,
33 style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER,
34 pos = wx.DefaultPosition,
36 """!Standard dialog used to add/update/display attributes linked
39 Attribute data can be selected based on layer and category number
44 @param query query coordinates and distance (used for v.edit)
45 @param cats {layer: cats}
46 @param line feature id (requested for cats)
49 @param action (add, update, display)
63 layers = self.mapDBInfo.layers.keys()
67 label = _(
"Database connection "
68 "is not defined in DB file.")
71 message = _(
"No attribute table linked to "
72 "vector map <%(vector)s> found. %(msg)s\n\n"
73 "New attribute table can be created by "
74 "Attribute Table Manager.") %
75 {
'vector' : self.
map,
'msg' : label})
78 wx.Dialog.__init__(self, parent = self.
parent, id = wx.ID_ANY,
79 title =
"", style = style, pos = pos)
82 mainSizer = wx.BoxSizer(wx.VERTICAL)
85 self.
notebook = wx.Notebook(parent = self, id = wx.ID_ANY, style = wx.BK_DEFAULT)
88 label = _(
"Close dialog on submit"))
89 self.closeDialog.SetValue(
True)
90 if self.
action ==
'display':
91 self.closeDialog.Enable(
False)
94 self.
fidMulti = wx.Choice(parent = self, id = wx.ID_ANY,
96 self.fidMulti.Bind(wx.EVT_CHOICE, self.
OnFeature)
97 self.
fidText = wx.StaticText(parent = self, id = wx.ID_ANY)
99 self.
noFoundMsg = wx.StaticText(parent = self, id = wx.ID_ANY,
100 label = _(
"No attributes found"))
105 if self.
action ==
"update":
106 self.SetTitle(_(
"Update attributes"))
107 elif self.
action ==
"add":
108 self.SetTitle(_(
"Define attributes"))
110 self.SetTitle(_(
"Display attributes"))
113 btnCancel = wx.Button(self, wx.ID_CANCEL)
114 btnReset = wx.Button(self, wx.ID_UNDO, _(
"&Reload"))
115 btnSubmit = wx.Button(self, wx.ID_OK, _(
"&Submit"))
116 if self.
action ==
'display':
117 btnSubmit.Enable(
False)
119 btnSizer = wx.StdDialogButtonSizer()
120 btnSizer.AddButton(btnCancel)
121 btnSizer.AddButton(btnReset)
122 btnSizer.SetNegativeButton(btnReset)
123 btnSubmit.SetDefault()
124 btnSizer.AddButton(btnSubmit)
127 mainSizer.Add(item = self.
noFoundMsg, proportion = 0,
128 flag = wx.EXPAND | wx.ALL, border = 5)
129 mainSizer.Add(item = self.
notebook, proportion = 1,
130 flag = wx.EXPAND | wx.ALL, border = 5)
131 fidSizer = wx.BoxSizer(wx.HORIZONTAL)
132 fidSizer.Add(item = wx.StaticText(parent = self, id = wx.ID_ANY,
133 label = _(
"Feature id:")),
134 proportion = 0, border = 5,
135 flag = wx.ALIGN_CENTER_VERTICAL)
136 fidSizer.Add(item = self.
fidMulti, proportion = 0,
137 flag = wx.EXPAND | wx.ALL, border = 5)
138 fidSizer.Add(item = self.
fidText, proportion = 0,
139 flag = wx.EXPAND | wx.ALL, border = 5)
140 mainSizer.Add(item = fidSizer, proportion = 0,
141 flag = wx.EXPAND | wx.LEFT | wx.RIGHT, border = 5)
142 mainSizer.Add(item = self.
closeDialog, proportion = 0, flag = wx.EXPAND | wx.LEFT | wx.RIGHT,
144 mainSizer.Add(item = btnSizer, proportion = 0,
145 flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border = 5)
148 btnReset.Bind(wx.EVT_BUTTON, self.
OnReset)
149 btnSubmit.Bind(wx.EVT_BUTTON, self.
OnSubmit)
150 btnCancel.Bind(wx.EVT_BUTTON, self.
OnCancel)
152 self.SetSizer(mainSizer)
156 w, h = self.GetBestSize()
158 self.SetMinSize((w, 200))
160 self.SetMinSize(self.GetBestSize())
162 if self.notebook.GetPageCount() == 0:
163 Debug.msg(2,
"DisplayAttributesDialog(): Nothing found!")
166 def __SelectAttributes(self, layer):
167 """!Select attributes"""
171 """!Update SQL statement"""
177 @return True on attributes found
178 @return False attributes not found
180 return bool(self.notebook.GetPageCount())
183 """!Create SQL statement string based on self.sqlStatement
185 If updateValues is True, update dataFrame according to values
190 for layer
in self.mapDBInfo.layers.keys():
191 table = self.mapDBInfo.GetTable(layer)
192 key = self.mapDBInfo.GetKeyColumn(layer)
193 columns = self.mapDBInfo.GetTableDesc(table)
194 for idx
in range(len(columns[key][
'values'])):
197 for name
in columns.keys():
199 cat = columns[name][
'values'][idx]
201 type = columns[name][
'type']
202 value = columns[name][
'values'][idx]
203 id = columns[name][
'ids'][idx]
205 newvalue = self.FindWindowById(id).GetValue()
207 newvalue = self.FindWindowById(id).GetLabel()
212 if newvalue != value:
213 updatedColumns.append(name)
215 updatedValues.append(
'NULL')
217 if type !=
'character':
218 updatedValues.append(newvalue)
220 updatedValues.append(
"'" + newvalue +
"'")
221 columns[name][
'values'][idx] = newvalue
223 if self.
action !=
"add" and len(updatedValues) == 0:
227 sqlString =
"INSERT INTO %s (%s," % (table, key)
229 sqlString =
"UPDATE %s SET " % table
231 for idx
in range(len(updatedColumns)):
232 name = updatedColumns[idx]
234 sqlString += name +
","
236 sqlString += name +
"=" + updatedValues[idx] +
","
238 sqlString = sqlString[:-1]
241 sqlString +=
") VALUES (%s," % cat
242 for value
in updatedValues:
243 sqlString += str(value) +
","
244 sqlString = sqlString[:-1]
247 sqlString +=
" WHERE cat=%s" % cat
248 sqlCommands.append(sqlString)
252 Debug.msg(3,
"DisplayAttributesDialog.GetSQLString(): %s" % sqlCommands)
258 for layer
in self.mapDBInfo.layers.keys():
259 table = self.mapDBInfo.layers[layer][
"table"]
260 key = self.mapDBInfo.layers[layer][
"key"]
261 columns = self.mapDBInfo.tables[table]
262 for idx
in range(len(columns[key][
'values'])):
263 for name
in columns.keys():
264 type = columns[name][
'type']
265 value = columns[name][
'values'][idx]
269 id = columns[name][
'ids'][idx]
273 if name != key
and id != wx.NOT_FOUND:
274 self.FindWindowById(id).SetValue(str(value))
277 """!Cancel button pressed
279 self.parent.parent.dialogs[
'attributes'] =
None
281 if hasattr(self,
"digit"):
282 self.parent.digit.GetDisplay().SetSelected([])
283 self.parent.UpdateMap(render =
False)
285 self.parent.parent.OnRender(
None)
290 """!Submit records"""
293 enc = UserSettings.Get(group =
'atm', key =
'encoding', subkey =
'value')
294 if not enc
and 'GRASS_DB_ENCODING' in os.environ:
295 enc = os.environ[
'GRASS_DB_ENCODING']
297 sql = sql.encode(enc)
299 ret += gcmd.RunCommand(
'db.execute',
304 if ret == 0
and self.closeDialog.IsChecked():
308 self.
fid = int(event.GetString())
312 """!Get id of selected vector object or 'None' if nothing selected
314 @param id if true return ids otherwise cats
322 """!Get selected feature id"""
325 def UpdateDialog(self, map = None, query = None, cats = None, fid = -1,
329 @param map name of vector map
332 @param fid feature id
333 @param action add, update, display or None
335 @return True if updated
340 if action ==
'display':
344 self.closeDialog.Enable(enabled)
345 self.FindWindowById(wx.ID_OK).Enable(enabled)
355 self.mapDBInfo.Reset()
357 layers = self.mapDBInfo.layers.keys()
361 data = self.mapDBInfo.SelectByPoint(query[0],
364 if data
and 'Layer' in data:
366 for layer
in data[
'Layer']:
369 tfid = int(data[
'Id'][idx])
372 if not tfid
in self.
cats:
374 if not layer
in self.
cats[tfid]:
375 self.
cats[tfid][layer] = []
376 cat = int(data[
'Category'][idx])
377 self.
cats[tfid][layer].append(cat)
384 elif len(self.cats.keys()) > 0:
385 self.
fid = self.cats.keys()[0]
389 if len(self.cats.keys()) == 1:
390 self.fidMulti.Show(
False)
391 self.fidText.Show(
True)
393 self.fidText.SetLabel(
"%d" % self.
fid)
395 self.fidText.SetLabel(_(
"Unknown"))
397 self.fidMulti.Show(
True)
398 self.fidText.Show(
False)
400 for tfid
in self.cats.keys():
401 choices.append(str(tfid))
402 self.fidMulti.SetItems(choices)
403 self.fidMulti.SetStringSelection(str(self.
fid))
406 self.notebook.DeleteAllPages()
410 if self.
fid > 0
and layer
in self.
cats[self.
fid]:
411 for cat
in self.
cats[self.
fid][layer]:
412 nselected = self.mapDBInfo.SelectFromTable(layer,
414 (self.mapDBInfo.layers[layer][
'key'],
424 if layer
in self.
cats[self.
fid]:
425 table = self.mapDBInfo.layers[layer][
"table"]
426 key = self.mapDBInfo.layers[layer][
"key"]
427 columns = self.mapDBInfo.tables[table]
428 for name
in columns.keys():
430 for cat
in self.
cats[self.
fid][layer]:
431 self.mapDBInfo.tables[table][name][
'values'].append(cat)
433 self.mapDBInfo.tables[table][name][
'values'].append(
None)
437 table = self.mapDBInfo.layers[layer][
"table"]
438 key = self.mapDBInfo.layers[layer][
"key"]
439 columns = self.mapDBInfo.tables[table]
441 for idx
in range(len(columns[key][
'values'])):
442 for name
in columns.keys():
444 cat = int(columns[name][
'values'][idx])
448 panel = scrolled.ScrolledPanel(parent = self.
notebook, id = wx.ID_ANY,
450 panel.SetupScrolling(scroll_x =
False)
452 self.notebook.AddPage(page = panel, text =
" %s %d / %s %d" % (_(
"Layer"), layer,
456 border = wx.BoxSizer(wx.VERTICAL)
458 flexSizer = wx.FlexGridSizer (cols = 4, hgap = 3, vgap = 3)
459 flexSizer.AddGrowableCol(3)
461 names = [
''] * len(columns.keys())
462 for name
in columns.keys():
463 names[columns[name][
'index']] = name
469 vtype = columns[name][
'type']
471 if columns[name][
'values'][idx]
is not None:
472 if columns[name][
'ctype'] !=
type(
''):
473 value = str(columns[name][
'values'][idx])
475 value = columns[name][
'values'][idx]
479 colName = wx.StaticText(parent = panel, id = wx.ID_ANY,
481 colType = wx.StaticText(parent = panel, id = wx.ID_ANY,
482 label =
"[" + vtype.lower() +
"]")
483 delimiter = wx.StaticText(parent = panel, id = wx.ID_ANY, label =
":")
485 colValue = wx.TextCtrl(parent = panel, id = wx.ID_ANY, value = value)
486 colValue.SetName(name)
488 if self.
action ==
'display':
489 colValue.SetWindowStyle(wx.TE_READONLY)
491 flexSizer.Add(colName, proportion = 0,
492 flag = wx.FIXED_MINSIZE | wx.ALIGN_CENTER_VERTICAL)
493 flexSizer.Add(colType, proportion = 0,
494 flag = wx.FIXED_MINSIZE | wx.ALIGN_CENTER_VERTICAL)
495 flexSizer.Add(delimiter, proportion = 0,
496 flag = wx.FIXED_MINSIZE | wx.ALIGN_CENTER_VERTICAL)
497 flexSizer.Add(colValue, proportion = 1,
498 flag = wx.EXPAND | wx.ALIGN_CENTER_VERTICAL)
500 columns[name][
'ids'].append(colValue.GetId())
502 border.Add(item = flexSizer, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 5)
503 panel.SetSizer(border)
507 if self.notebook.GetPageCount() == 0:
508 self.noFoundMsg.Show(
True)
510 self.noFoundMsg.Show(
False)
517 """!Set attrbute value
519 @param column column name
522 table = self.mapDBInfo.GetTable(layer)
523 columns = self.mapDBInfo.GetTableDesc(table)
525 for key, col
in columns.iteritems():
527 col[
'values'] = [col[
'ctype'](value),]
531 def __init__(self, parent, title, data, keyEditable = (-1,
True),
532 id = wx.ID_ANY, style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER):
533 """!Dialog for inserting/updating table record
535 @param data a list: [(column, value)]
536 @param KeyEditable (id, editable?) indicates if textarea for key column
537 is editable(True) or not
540 wx.Dialog.__init__(self, parent, id, title, style = style)
542 self.CenterOnParent()
546 box = wx.StaticBox(parent = self, id = wx.ID_ANY)
548 self.
dataPanel = scrolled.ScrolledPanel(parent = self, id = wx.ID_ANY,
549 style = wx.TAB_TRAVERSAL)
550 self.dataPanel.SetupScrolling(scroll_x =
False)
554 self.
btnSubmit = wx.Button(self, wx.ID_OK, _(
"&Submit"))
555 self.btnSubmit.SetDefault()
562 for column, value
in data:
563 if self.
keyId == cId:
564 self.
cat = int(value)
565 if not keyEditable[1]:
567 box.SetLabel(
" %s %d " % (_(
"Category"), self.
cat))
569 self.
boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
573 valueWin = wx.SpinCtrl(parent = self.
dataPanel, id = wx.ID_ANY,
574 value = value, min = -1e9, max = 1e9, size = (250, -1))
576 valueWin = wx.TextCtrl(parent = self.
dataPanel, id = wx.ID_ANY,
577 value = value, size = (250, -1))
579 label = wx.StaticText(parent = self.
dataPanel, id = wx.ID_ANY,
580 label = column +
":")
582 self.widgets.append((label.GetId(), valueWin.GetId()))
590 sizer = wx.BoxSizer(wx.VERTICAL)
593 dataSizer = wx.FlexGridSizer (cols = 2, hgap = 3, vgap = 3)
594 dataSizer.AddGrowableCol(1)
596 for labelId, valueId
in self.
widgets:
597 label = self.FindWindowById(labelId)
598 value = self.FindWindowById(valueId)
600 dataSizer.Add(label, proportion = 0,
601 flag = wx.ALIGN_CENTER_VERTICAL)
602 dataSizer.Add(value, proportion = 0,
603 flag = wx.EXPAND | wx.ALIGN_CENTER_VERTICAL)
605 self.dataPanel.SetAutoLayout(
True)
606 self.dataPanel.SetSizer(dataSizer)
610 self.boxSizer.Add(item = self.
dataPanel, proportion = 1,
611 flag = wx.EXPAND | wx.ALL, border = 5)
614 btnSizer = wx.StdDialogButtonSizer()
620 sizer.Add(item = self.
dataPanel, proportion = 1,
621 flag = wx.EXPAND | wx.ALL, border = 5)
623 sizer.Add(item = self.
boxSizer, proportion = 1,
624 flag = wx.EXPAND | wx.ALL, border = 5)
626 sizer.Add(item = btnSizer, proportion = 0,
627 flag = wx.EXPAND | wx.ALL, border = 5)
629 framewidth = self.GetSize()[0]
630 self.SetMinSize((framewidth,250))
632 self.SetAutoLayout(
True)
639 """!Return list of values (casted to string).
641 If columns is given (list), return only values of given columns.
644 for labelId, valueId
in self.
widgets:
645 column = self.FindWindowById(labelId).GetLabel().replace(
':',
'')
646 if columns
is None or column
in columns:
647 value = str(self.FindWindowById(valueId).GetValue())
648 valueList.append(value)
652 valueList.insert(self.
keyId, str(self.
cat))