4 @brief GRASS Attribute Table Manager
6 This program is based on FileHunter, published in 'The wxPython Linux
7 Tutorial' on wxPython WIKI pages.
9 It also uses some functions at
10 http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/426407
13 python dbm.py vector@mapset
18 - manager::VirtualAttributeList
19 - manager::AttributeManager
20 - manager::TableListCtrl
21 - manager::LayerListCtrl
24 (C) 2007-2009, 2011 by the GRASS Development Team
26 This program is free software under the GNU General Public License
27 (>=v2). Read the file COPYING that comes with GRASS for details.
29 @author Jachym Cepicky <jachym.cepicky gmail.com>
30 @author Martin Landa <landa.martin gmail.com>
40 if __name__ ==
"__main__":
41 sys.path.append(os.path.join(os.getenv(
'GISBASE'),
'etc',
'wxpython'))
42 from core
import globalvar
44 import wx.lib.mixins.listctrl
as listmix
45 import wx.lib.flatnotebook
as FN
50 from core.gcmd import RunCommand, GException, GError, GMessage, GWarning
53 from dbmgr.vinfo
import VectorDBInfo, unicodeValue, createDbInfoDesc
61 The log output is redirected to the status bar of the containing frame.
67 """!Update status bar"""
68 self.parent.SetStatusText(text_string.strip())
72 listmix.ListCtrlAutoWidthMixin,
73 listmix.ColumnSorterMixin):
75 Support virtual list class
77 def __init__(self, parent, log, mapDBInfo, layer):
88 wx.ListCtrl.__init__(self, parent = parent, id = wx.ID_ANY,
89 style = wx.LC_REPORT | wx.LC_HRULES |
90 wx.LC_VRULES | wx.LC_VIRTUAL | wx.LC_SORT_ASCENDING)
103 self.attr1.SetBackgroundColour(wx.Colour(238,238,238))
105 self.attr2.SetBackgroundColour(
"white")
106 self.
il = wx.ImageList(16, 16)
107 self.
sm_up = self.il.Add(wx.ArtProvider_GetBitmap(wx.ART_GO_UP, wx.ART_TOOLBAR,
109 self.
sm_dn = self.il.Add(wx.ArtProvider_GetBitmap(wx.ART_GO_DOWN, wx.ART_TOOLBAR,
111 self.SetImageList(self.
il, wx.IMAGE_LIST_SMALL)
114 listmix.ListCtrlAutoWidthMixin.__init__(self)
115 listmix.ColumnSorterMixin.__init__(self, len(self.
columns))
119 self.SortListItems(col = keyColumn, ascending =
True)
121 self.SortListItems(col = 0, ascending =
True)
127 self.Bind(wx.EVT_LIST_COL_RIGHT_CLICK, self.
OnColumnMenu)
130 """!Update list according new mapDBInfo description"""
134 def LoadData(self, layer, columns = None, where = None, sql = None):
135 """!Load data into list
137 @param layer layer number
138 @param columns list of columns for output (-> v.db.select)
139 @param where where statement (-> v.db.select)
140 @param sql full sql statement (-> db.select)
142 @return id of key column
143 @return -1 if key column is not displayed
145 self.log.write(_(
"Loading data..."))
147 tableName = self.mapDBInfo.layers[layer][
'table']
148 keyColumn = self.mapDBInfo.layers[layer][
'key']
150 self.
columns = self.mapDBInfo.tables[tableName]
152 raise GException(_(
"Attribute table <%s> not found. "
153 "For creating the table switch to "
154 "'Manage layers' tab.") % tableName)
157 columns = self.mapDBInfo.GetColumns(tableName)
159 all = self.mapDBInfo.GetColumns(tableName)
162 GError(parent = self,
163 message = _(
"Column <%(column)s> not found in "
164 "in the table <%(table)s>.") % \
165 {
'column' : col,
'table' : tableName })
170 keyId = columns.index(keyColumn)
181 outFile = tempfile.NamedTemporaryFile(mode =
'w+b')
188 cmdParams = dict(quiet =
True,
194 cmdParams.update(dict(sql = sql,
195 output = outFile.name))
199 cmdParams.update(dict(map = self.mapDBInfo.map,
204 cmdParams.update(dict(columns =
','.join(columns)))
215 self.DeleteAllItems()
218 for i
in range(self.GetColumnCount()):
223 info.m_mask = wx.LIST_MASK_TEXT | wx.LIST_MASK_IMAGE | wx.LIST_MASK_FORMAT
226 for column
in columns:
228 self.InsertColumnInfo(i, info)
232 self.log.write(_(
"Can display only 256 columns."))
239 record = outFile.readline().replace(
'\n',
'')
244 record = record.split(fs)
245 if len(columns) != len(record):
246 GError(parent = self,
247 message = _(
"Inconsistent number of columns "
248 "in the table <%(table)s>.") % \
249 {
'table' : tableName })
257 self.log.write(_(
"Viewing limit: 100000 records."))
264 width = self.
columns[col][
'length'] * 6
269 self.SetColumnWidth(col = i, width = width)
274 self.log.write(_(
"Number of loaded records: %d") % \
280 """!Add row to the data list"""
282 keyColumn = self.mapDBInfo.layers[self.
layer][
'key']
286 if keyColumn ==
'OGC_FID':
292 if self.
columns[columns[j]][
'ctype'] != types.StringType:
303 except UnicodeDecodeError:
304 self.
itemDataMap[i].append(_(
"Unable to decode value. "
305 "Set encoding in GUI preferences ('Attributes')."))
307 if not cat
and keyId > -1
and keyId == j:
309 cat = self.
columns[columns[j]][
'ctype'] (value)
310 except ValueError, e:
312 GError(parent = self,
313 message = _(
"Error loading attribute data. "
314 "Record number: %(rec)d. Unable to convert value '%(val)s' in "
315 "key column (%(key)s) to integer.\n\n"
316 "Details: %(detail)s") % \
317 {
'rec' : i + 1,
'val' : value,
318 'key' : keyColumn,
'detail' : e})
321 self.itemIndexMap.append(i)
326 """!Item selected. Add item to selected cats..."""
335 """!Item deselected. Remove item from selected cats..."""
344 """!Return list of selected items (category numbers)"""
346 item = self.GetFirstSelected()
348 cats.append(self.GetItemText(item))
349 item = self.GetNextSelected(item)
354 """!Return column text"""
355 item = self.GetItem(index, col)
356 return item.GetText()
369 """!Get item attributes"""
376 """!Column heading right mouse button -> pop-up menu"""
377 self.
_col = event.GetColumn()
379 popupMenu = wx.Menu()
381 if not hasattr (self,
"popupID1"):
395 popupMenu.Append(self.
popupID1, text = _(
"Sort ascending"))
396 popupMenu.Append(self.
popupID2, text = _(
"Sort descending"))
397 popupMenu.AppendSeparator()
399 popupMenu.AppendMenu(self.
popupID3, _(
"Calculate (only numeric columns)"),
401 if not self.log.parent.editable
or \
402 self.
columns[self.GetColumn(self.
_col).GetText()][
'ctype']
not in (types.IntType, types.FloatType):
403 popupMenu.Enable(self.
popupID3,
False)
405 subMenu.Append(self.
popupID4, text = _(
"Area size"))
406 subMenu.Append(self.
popupID5, text = _(
"Line length"))
407 subMenu.Append(self.
popupID6, text = _(
"Compactness of an area"))
408 subMenu.Append(self.
popupID7, text = _(
"Fractal dimension of boundary defining a polygon"))
409 subMenu.Append(self.
popupID8, text = _(
"Perimeter length of an area"))
410 subMenu.Append(self.
popupID9, text = _(
"Number of features for each category"))
411 subMenu.Append(self.
popupID10, text = _(
"Slope steepness of 3D line"))
412 subMenu.Append(self.
popupID11, text = _(
"Line sinuousity"))
413 subMenu.Append(self.
popupID12, text = _(
"Line azimuth"))
422 self.PopupMenu(popupMenu)
426 """!Column heading left mouse button -> sorting"""
427 self.
_col = event.GetColumn()
434 """!Sort values of selected column (ascending)"""
435 self.SortListItems(col = self.
_col, ascending =
True)
439 """!Sort values of selected column (descending)"""
440 self.SortListItems(col = self.
_col, ascending =
False)
444 """!Compute values of selected column"""
472 map = self.mapDBInfo.map,
475 columns = self.GetColumn(self.
_col).GetText())
480 """!Sort values of selected column (self._col)"""
484 info.m_mask = wx.LIST_MASK_TEXT | wx.LIST_MASK_IMAGE
486 for column
in range(self.GetColumnCount()):
487 info.m_text = self.GetColumn(column).GetText()
488 self.SetColumn(column, info)
492 items = list(self.itemDataMap.keys())
500 colName = self.GetColumn(self.
_col).GetText()
501 ascending = self._colSortFlag[self.
_col]
509 if type(item1) == types.StringType
or type(item2) == types.StringTypes:
510 cmpVal = locale.strcoll(str(item1), str(item2))
512 cmpVal = cmp(item1, item2)
517 cmpVal = apply(cmp, self.GetSecondarySortValues(self.
_col, key1, key2))
525 """!Used by the ColumnSorterMixin, see wx/lib/mixins/listctrl.py"""
529 """!Check if list if empty"""
536 def __init__(self, parent, id = wx.ID_ANY,
537 title =
None, vectorName =
None, item =
None, log =
None,
538 selection =
None, **kwargs):
539 """!GRASS Attribute Table Manager window
541 @param parent parent window
543 @param title window title or None for default title
544 @param vetorName name of vector map
545 @param item item from Layer Tree
546 @param log log window
547 @param selection name of page to be selected
548 @param kwagrs other wx.Frame's arguments
553 if self.
parent and self.parent.GetName() ==
"LayerManager" and \
555 maptree = self.parent.GetLayerTree()
556 name = maptree.GetPyData(self.
treeItem)[0][
'maplayer'].GetName()
561 if grass.find_file(name = self.
vectorName, element =
'vector')[
'mapset'] == grass.gisenv()[
'MAPSET']:
568 wx.Frame.__init__(self, parent, id, *kwargs)
572 self.SetTitle(
"%s - <%s>" % (_(
"GRASS GIS Attribute Table Manager"),
578 self.SetIcon(wx.Icon(os.path.join(globalvar.ETCICONDIR,
'grass_sql.ico'), wx.BITMAP_TYPE_ICO))
580 self.
panel = wx.Panel(parent = self, id = wx.ID_ANY)
583 self.
map = self.parent.GetLayerTree().GetMap()
600 if len(self.mapDBInfo.layers.keys()) == 0:
601 GMessage(parent = self.
parent,
602 message = _(
"Database connection for vector map <%s> "
603 "is not defined in DB file. "
604 "You can define new connection in "
613 self.CreateStatusBar(number = 1)
622 dbmStyle = {
'agwStyle' : globalvar.FNPageStyle }
624 dbmStyle = {
'style' : globalvar.FNPageStyle }
628 self.notebook.AddPage(page = self.
browsePage, text = _(
"Browse data"),
630 self.browsePage.SetTabAreaColour(globalvar.FNPageColor)
634 self.notebook.AddPage(page = self.
manageTablePage, text = _(
"Manage tables"),
637 self.notebook.GetPage(self.notebook.GetPageCount()-1).Enable(
False)
638 self.manageTablePage.SetTabAreaColour(globalvar.FNPageColor)
642 self.notebook.AddPage(page = self.
manageLayerPage, text = _(
"Manage layers"),
644 self.manageLayerPage.SetTabAreaColour(globalvar.FNPageColor)
646 self.notebook.GetPage(self.notebook.GetPageCount()-1).Enable(
False)
653 wx.CallAfter(self.notebook.SetSelectionByName, selection)
655 wx.CallAfter(self.notebook.SetSelection, 0)
659 self.btnQuit.SetToolTipString(_(
"Close Attribute Table Manager"))
661 self.btnReload.SetToolTipString(_(
"Reload attribute data (selected layer only)"))
666 self.notebook.Bind(FN.EVT_FLATNOTEBOOK_PAGE_CHANGED, self.
OnPageChanged)
675 self.SetSize((700, 550))
676 self.SetMinSize(self.GetSize())
678 def _createBrowsePage(self, onlyLayer = -1):
679 """!Create browse tab page"""
680 for layer
in self.mapDBInfo.layers.keys():
681 if onlyLayer > 0
and layer != onlyLayer:
684 panel = wx.Panel(parent = self.
browsePage, id = wx.ID_ANY)
690 listBox = wx.StaticBox(parent = panel, id = wx.ID_ANY,
691 label =
" %s " % _(
"Attribute data - right-click to edit/manage records"))
692 listSizer = wx.StaticBoxSizer(listBox, wx.VERTICAL)
702 self.
layerPage[layer] = {
'browsePage': panel.GetId()}
706 label += _(
" (readonly)")
707 self.browsePage.AddPage(page = panel, text =
" %d / %s %s" % \
708 (layer, label, self.mapDBInfo.layers[layer][
'table']))
710 pageSizer = wx.BoxSizer(wx.VERTICAL)
713 sqlBox = wx.StaticBox(parent = panel, id = wx.ID_ANY,
714 label =
" %s " % _(
"SQL Query"))
716 sqlSizer = wx.StaticBoxSizer(sqlBox, wx.VERTICAL)
720 if UserSettings.Get(group =
'atm', key =
'leftDbClick', subkey =
'selection') == 0:
727 listSizer.Add(item = win, proportion = 1,
728 flag = wx.EXPAND | wx.ALL,
732 btnApply = wx.Button(parent = panel, id = wx.ID_APPLY)
733 btnApply.SetToolTipString(_(
"Apply SELECT statement and reload data records"))
735 btnSqlBuilder = wx.Button(parent = panel, id = wx.ID_ANY, label = _(
"SQL Builder"))
736 btnSqlBuilder.Bind(wx.EVT_BUTTON, self.
OnBuilder)
738 sqlSimple = wx.RadioButton(parent = panel, id = wx.ID_ANY,
740 sqlSimple.SetValue(
True)
741 sqlAdvanced = wx.RadioButton(parent = panel, id = wx.ID_ANY,
742 label = _(
"Advanced"))
743 sqlSimple.Bind(wx.EVT_RADIOBUTTON, self.
OnChangeSql)
744 sqlAdvanced.Bind(wx.EVT_RADIOBUTTON, self.
OnChangeSql)
746 sqlWhereColumn = wx.ComboBox(parent = panel, id = wx.ID_ANY,
748 style = wx.CB_SIMPLE | wx.CB_READONLY,
749 choices = self.mapDBInfo.GetColumns(self.mapDBInfo.layers[layer][
'table']))
750 sqlWhereColumn.SetSelection(0)
751 sqlWhereCond = wx.Choice(parent = panel, id = wx.ID_ANY,
753 choices = [
'=',
'!=',
'<',
'<=',
'>',
'>='])
754 sqlWhereValue = wx.TextCtrl(parent = panel, id = wx.ID_ANY, value =
"",
755 style = wx.TE_PROCESS_ENTER)
756 sqlWhereValue.SetToolTipString(_(
"Example: %s") %
"MULTILANE = 'no' AND OBJECTID < 10")
758 sqlStatement = wx.TextCtrl(parent = panel, id = wx.ID_ANY,
759 value =
"SELECT * FROM %s" % \
760 self.mapDBInfo.layers[layer][
'table'],
761 style = wx.TE_PROCESS_ENTER)
762 sqlStatement.SetToolTipString(_(
"Example: %s") %
"SELECT * FROM roadsmajor WHERE MULTILANE = 'no' AND OBJECTID < 10")
766 sqlLabel = wx.StaticText(parent = panel, id = wx.ID_ANY,
767 label =
"SELECT * FROM %s WHERE " % \
768 self.mapDBInfo.layers[layer][
'table'])
769 label_query = wx.StaticText(parent = panel, id = wx.ID_ANY,
772 sqlFlexSizer = wx.FlexGridSizer (cols = 3, hgap = 5, vgap = 5)
774 sqlFlexSizer.Add(item = sqlSimple,
775 flag = wx.ALIGN_CENTER_VERTICAL)
776 sqlSimpleSizer = wx.BoxSizer(wx.HORIZONTAL)
777 sqlSimpleSizer.Add(item = sqlLabel,
778 flag = wx.ALIGN_CENTER_VERTICAL)
779 sqlSimpleSizer.Add(item = sqlWhereColumn,
780 flag = wx.EXPAND | wx.ALIGN_CENTER_VERTICAL)
781 sqlSimpleSizer.Add(item = sqlWhereCond,
782 flag = wx.EXPAND | wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT,
784 sqlSimpleSizer.Add(item = sqlWhereValue, proportion = 1,
785 flag = wx.EXPAND | wx.ALIGN_CENTER_VERTICAL)
786 sqlFlexSizer.Add(item = sqlSimpleSizer,
787 flag = wx.ALIGN_CENTER_VERTICAL | wx.EXPAND)
788 sqlFlexSizer.Add(item = btnApply,
789 flag = wx.ALIGN_RIGHT)
790 sqlFlexSizer.Add(item = sqlAdvanced,
791 flag = wx.ALIGN_CENTER_VERTICAL)
792 sqlFlexSizer.Add(item = sqlStatement,
794 sqlFlexSizer.Add(item = btnSqlBuilder,
795 flag = wx.ALIGN_RIGHT)
796 sqlFlexSizer.AddGrowableCol(1)
798 sqlSizer.Add(item = sqlFlexSizer,
799 flag = wx.ALL | wx.EXPAND,
802 pageSizer.Add(item = listSizer,
804 flag = wx.ALL | wx.EXPAND,
807 pageSizer.Add(item = sqlSizer,
809 flag = wx.BOTTOM | wx.LEFT | wx.RIGHT | wx.EXPAND,
812 panel.SetSizer(pageSizer)
814 self.
layerPage[layer][
'data'] = win.GetId()
815 self.
layerPage[layer][
'simple'] = sqlSimple.GetId()
816 self.
layerPage[layer][
'advanced'] = sqlAdvanced.GetId()
817 self.
layerPage[layer][
'whereColumn'] = sqlWhereColumn.GetId()
818 self.
layerPage[layer][
'whereOperator'] = sqlWhereCond.GetId()
819 self.
layerPage[layer][
'where'] = sqlWhereValue.GetId()
820 self.
layerPage[layer][
'builder'] = btnSqlBuilder.GetId()
821 self.
layerPage[layer][
'statement'] = sqlStatement.GetId()
824 self.browsePage.SetSelection(0)
826 self.
layer = self.mapDBInfo.layers.keys()[0]
828 self.log.write(_(
"Number of loaded records: %d") % \
829 self.FindWindowById(self.
layerPage[self.
layer][
'data']).GetItemCount())
830 except (IndexError, KeyError):
833 def _createManageTablePage(self, onlyLayer = -1):
834 """!Create manage page (create/link and alter tables)"""
835 for layer
in self.mapDBInfo.layers.keys():
836 if onlyLayer > 0
and layer != onlyLayer:
843 self.
layerPage[layer][
'tablePage'] = panel.GetId()
846 label += _(
" (readonly)")
847 self.manageTablePage.AddPage(page = panel,
848 text =
" %d / %s %s" % (layer, label,
849 self.mapDBInfo.layers[layer][
'table']))
851 pageSizer = wx.BoxSizer(wx.VERTICAL)
856 dbBox = wx.StaticBox(parent = panel, id = wx.ID_ANY,
857 label =
" %s " % _(
"Database connection"))
858 dbSizer = wx.StaticBoxSizer(dbBox, wx.VERTICAL)
861 flag = wx.EXPAND | wx.ALL,
867 table = self.mapDBInfo.layers[layer][
'table']
868 tableBox = wx.StaticBox(parent = panel, id = wx.ID_ANY,
869 label =
" %s " % _(
"Table <%s> - right-click to delete column(s)") % table)
871 tableSizer = wx.StaticBoxSizer(tableBox, wx.VERTICAL)
876 self.
layerPage[layer][
'tableData'] = tlist.GetId()
879 addBox = wx.StaticBox(parent = panel, id = wx.ID_ANY,
880 label =
" %s " % _(
"Add column"))
881 addSizer = wx.StaticBoxSizer(addBox, wx.HORIZONTAL)
883 column = wx.TextCtrl(parent = panel, id = wx.ID_ANY, value =
'',
884 size = (150, -1), style = wx.TE_PROCESS_ENTER)
887 self.
layerPage[layer][
'addColName'] = column.GetId()
888 addSizer.Add(item = wx.StaticText(parent = panel, id = wx.ID_ANY, label = _(
"Column")),
889 flag = wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT,
891 addSizer.Add(item = column, proportion = 1,
892 flag = wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT,
895 ctype = wx.Choice (parent = panel, id = wx.ID_ANY,
896 choices = [
"integer",
900 ctype.SetSelection(0)
902 self.
layerPage[layer][
'addColType'] = ctype.GetId()
903 addSizer.Add(item = wx.StaticText(parent = panel, id = wx.ID_ANY, label = _(
"Type")),
904 flag = wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT,
906 addSizer.Add(item = ctype,
907 flag = wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT,
910 length = wx.SpinCtrl(parent = panel, id = wx.ID_ANY, size = (65, -1),
914 self.
layerPage[layer][
'addColLength'] = length.GetId()
915 addSizer.Add(item = wx.StaticText(parent = panel, id = wx.ID_ANY, label = _(
"Length")),
916 flag = wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT,
918 addSizer.Add(item = length,
919 flag = wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT,
922 btnAddCol = wx.Button(parent = panel, id = wx.ID_ADD)
924 btnAddCol.Enable(
False)
925 self.
layerPage[layer][
'addColButton'] = btnAddCol.GetId()
926 addSizer.Add(item = btnAddCol, flag = wx.ALL | wx.ALIGN_RIGHT | wx.EXPAND,
930 renameBox = wx.StaticBox(parent = panel, id = wx.ID_ANY,
931 label =
" %s " % _(
"Rename column"))
932 renameSizer = wx.StaticBoxSizer(renameBox, wx.HORIZONTAL)
934 column = wx.ComboBox(parent = panel, id = wx.ID_ANY, size = (150, -1),
935 style = wx.CB_SIMPLE | wx.CB_READONLY,
936 choices = self.mapDBInfo.GetColumns(table))
937 column.SetSelection(0)
938 self.
layerPage[layer][
'renameCol'] = column.GetId()
939 renameSizer.Add(item = wx.StaticText(parent = panel, id = wx.ID_ANY, label = _(
"Column")),
940 flag = wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT,
942 renameSizer.Add(item = column, proportion = 1,
943 flag = wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT,
946 columnTo = wx.TextCtrl(parent = panel, id = wx.ID_ANY, value =
'',
947 size = (150, -1), style = wx.TE_PROCESS_ENTER)
950 self.
layerPage[layer][
'renameColTo'] = columnTo.GetId()
951 renameSizer.Add(item = wx.StaticText(parent = panel, id = wx.ID_ANY, label = _(
"To")),
952 flag = wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT,
954 renameSizer.Add(item = columnTo, proportion = 1,
955 flag = wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT,
958 btnRenameCol = wx.Button(parent = panel, id = wx.ID_ANY, label = _(
"&Rename"))
960 btnRenameCol.Enable(
False)
961 self.
layerPage[layer][
'renameColButton'] = btnRenameCol.GetId()
962 renameSizer.Add(item = btnRenameCol, flag = wx.ALL | wx.ALIGN_RIGHT | wx.EXPAND,
965 tableSizer.Add(item = tlist,
966 flag = wx.ALL | wx.EXPAND,
970 pageSizer.Add(item=dbSizer,
971 flag = wx.ALL | wx.EXPAND,
975 pageSizer.Add(item = tableSizer,
976 flag = wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND,
980 pageSizer.Add(item = addSizer,
981 flag = wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND,
984 pageSizer.Add(item = renameSizer,
985 flag = wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND,
989 panel.SetSizer(pageSizer)
991 self.manageTablePage.SetSelection(0)
993 self.
layer = self.mapDBInfo.layers.keys()[0]
997 def _createTableDesc(self, parent, table):
998 """!Create list with table description"""
1000 table = self.mapDBInfo.tables[table],
1001 columns = self.mapDBInfo.GetColumns(table))
1009 def _createManageLayerPage(self):
1010 """!Create manage page"""
1011 splitterWin = wx.SplitterWindow(parent = self.
manageLayerPage, id = wx.ID_ANY)
1012 splitterWin.SetMinimumPaneSize(100)
1014 label = _(
"Layers of vector map")
1016 label += _(
" (readonly)")
1017 self.manageLayerPage.AddPage(page = splitterWin,
1023 panelList = wx.Panel(parent = splitterWin, id = wx.ID_ANY)
1025 panelListSizer = wx.BoxSizer(wx.VERTICAL)
1026 layerBox = wx.StaticBox(parent = panelList, id = wx.ID_ANY,
1027 label =
" %s " % _(
"List of layers"))
1028 layerSizer = wx.StaticBoxSizer(layerBox, wx.VERTICAL)
1031 self.layerList.Bind(wx.EVT_COMMAND_RIGHT_CLICK, self.
OnLayerRightUp)
1035 flag = wx.ALL | wx.EXPAND,
1039 panelListSizer.Add(item = layerSizer,
1040 flag = wx.ALL | wx.EXPAND,
1044 panelList.SetSizer(panelListSizer)
1049 panelManage = wx.Panel(parent = splitterWin, id = wx.ID_ANY)
1051 manageSizer = wx.BoxSizer(wx.VERTICAL)
1054 parentDialog = self)
1058 flag = wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND,
1061 panelManage.SetSizer(manageSizer)
1062 splitterWin.SplitHorizontally(panelList, panelManage, 100)
1065 def _createLayerDesc(self, parent):
1066 """!Create list of linked layers"""
1068 layers = self.mapDBInfo.layers)
1080 mainSizer = wx.BoxSizer(wx.VERTICAL)
1083 btnSizer = wx.BoxSizer(wx.HORIZONTAL)
1084 btnSizer.Add(item = self.
btnReload, proportion = 1,
1085 flag = wx.ALL | wx.ALIGN_RIGHT, border = 5)
1086 btnSizer.Add(item = self.
btnQuit, proportion = 1,
1087 flag = wx.ALL | wx.ALIGN_RIGHT, border = 5)
1089 mainSizer.Add(item = self.
notebook, proportion = 1, flag = wx.EXPAND)
1090 mainSizer.Add(item = btnSizer, flag = wx.ALIGN_RIGHT | wx.ALL, border = 5)
1092 self.panel.SetAutoLayout(
True)
1093 self.panel.SetSizer(mainSizer)
1094 mainSizer.Fit(self.
panel)
1098 """!Table description area, context menu"""
1099 if not hasattr(self,
"popupDataID1"):
1127 menu.Append(self.
popupDataID1, _(
"Edit selected record"))
1128 selected = tlist.GetFirstSelected()
1129 if not self.
editable or selected == -1
or tlist.GetNextSelected(selected) != -1:
1132 menu.Append(self.
popupDataID3, _(
"Delete selected record(s)"))
1133 menu.Append(self.
popupDataID4, _(
"Delete all records"))
1138 menu.AppendSeparator()
1141 menu.AppendSeparator()
1142 menu.Append(self.
popupDataID7, _(
"Highlight selected features"))
1143 menu.Append(self.
popupDataID8, _(
"Highlight selected features and zoom"))
1144 if not self.
map or len(tlist.GetSelectedItems()) == 0:
1147 menu.Append(self.
popupDataID9, _(
"Extract selected features"))
1148 menu.Append(self.
popupDataID11, _(
"Delete selected features"))
1151 if tlist.GetFirstSelected() == -1:
1155 menu.AppendSeparator()
1158 self.PopupMenu(menu)
1162 self.log.write(_(
"Number of loaded records: %d") % \
1163 tlist.GetItemCount())
1166 """!Delete selected item(s) from the tlist (layer/category pair)"""
1168 item = dlist.GetFirstSelected()
1170 table = self.mapDBInfo.layers[self.
layer][
"table"]
1171 key = self.mapDBInfo.layers[self.
layer][
"key"]
1176 index = dlist.itemIndexMap[item]
1177 indeces.append(index)
1179 cat = dlist.itemCatsMap[index]
1181 self.listOfSQLStatements.append(
'DELETE FROM %s WHERE %s=%d' % \
1184 item = dlist.GetNextSelected(item)
1186 if UserSettings.Get(group =
'atm', key =
'askOnDeleteRec', subkey =
'enabled'):
1187 deleteDialog = wx.MessageBox(parent = self,
1188 message = _(
"Selected data records (%d) will be permanently deleted "
1189 "from table. Do you want to delete them?") % \
1191 caption = _(
"Delete records"),
1192 style = wx.YES_NO | wx.CENTRE)
1193 if deleteDialog != wx.YES:
1199 indexTemp = copy.copy(dlist.itemIndexMap)
1200 dlist.itemIndexMap = []
1201 dataTemp = copy.deepcopy(dlist.itemDataMap)
1202 dlist.itemDataMap = {}
1203 catsTemp = copy.deepcopy(dlist.itemCatsMap)
1204 dlist.itemCatsMap = {}
1207 for index
in indexTemp:
1208 if index
in indeces:
1210 dlist.itemIndexMap.append(i)
1211 dlist.itemDataMap[i] = dataTemp[index]
1212 dlist.itemCatsMap[i] = catsTemp[index]
1216 dlist.SetItemCount(len(dlist.itemIndexMap))
1219 item = dlist.GetFirstSelected()
1221 dlist.SetItemState(item, 0, wx.LIST_STATE_SELECTED | wx.LIST_STATE_FOCUSED)
1222 item = dlist.GetNextSelected(item)
1230 """!Delete all items from the list"""
1232 if UserSettings.Get(group =
'atm', key =
'askOnDeleteRec', subkey =
'enabled'):
1233 deleteDialog = wx.MessageBox(parent = self,
1234 message = _(
"All data records (%d) will be permanently deleted "
1235 "from table. Do you want to delete them?") % \
1236 (len(dlist.itemIndexMap)),
1237 caption = _(
"Delete records"),
1238 style = wx.YES_NO | wx.CENTRE)
1239 if deleteDialog != wx.YES:
1242 dlist.DeleteAllItems()
1243 dlist.itemDataMap = {}
1244 dlist.itemIndexMap = []
1245 dlist.SetItemCount(0)
1247 table = self.mapDBInfo.layers[self.
layer][
"table"]
1248 self.listOfSQLStatements.append(
'DELETE FROM %s' % table)
1254 def _drawSelected(self, zoom):
1255 """!Highlight selected features"""
1260 cats =
map(int, tlist.GetSelectedItems())
1262 digitToolbar = self.mapdisplay.GetToolbar(
'vdigit')
1263 if digitToolbar
and digitToolbar.GetLayer()
and \
1264 digitToolbar.GetLayer().GetName() == self.
vectorName:
1265 display = self.mapdisplay.GetMapWindow().GetDisplay()
1266 display.SetSelected(cats, layer = self.
layer)
1268 n, s, w, e = display.GetRegionSelected()
1269 self.mapdisplay.Map.GetRegion(n = n, s = s, w = w, e = e,
1276 if self.
parent and self.parent.GetName() ==
"LayerManager" and \
1278 maptree = self.parent.GetLayerTree()
1279 opacity = maptree.GetPyData(self.
treeItem)[0][
'maplayer'].GetOpacity(float =
True)
1280 self.qlayer.SetOpacity(opacity)
1282 keyColumn = self.mapDBInfo.layers[self.
layer][
'key']
1286 min, max = range.split(
'-')
1287 where +=
'%s >= %d and %s <= %d or ' % \
1288 (keyColumn, int(min),
1289 keyColumn, int(max))
1291 where +=
'%s = %d or ' % (keyColumn, int(range))
1292 where = where.rstrip(
'or ')
1299 map = self.mapDBInfo.map,
1300 layer = int(self.layer),
1304 for line
in select.splitlines():
1305 key, value = line.split(
'=')
1306 region[key.strip()] = float(value.strip())
1309 renderer = self.mapdisplay.GetMap()
1310 nsdist = 10 * ((renderer.GetCurrentRegion()[
'n'] - renderer.GetCurrentRegion()[
's']) /
1312 ewdist = 10 * ((renderer.GetCurrentRegion()[
'e'] - renderer.GetCurrentRegion()[
'w']) /
1314 north = region[
'n'] + nsdist
1315 south = region[
's'] - nsdist
1316 west = region[
'w'] - ewdist
1317 east = region[
'e'] + ewdist
1318 renderer.GetRegion(n = north, s = south, w = west, e = east, update =
True)
1319 self.mapdisplay.GetMapWindow().ZoomHistory(n = north, s = south, w = west, e = east)
1322 self.mapdisplay.Map.AdjustRegion()
1323 self.mapdisplay.Map.AlignExtentFromDisplay()
1324 self.mapdisplay.MapWindow.UpdateMap(render =
True, renderVector =
True)
1326 self.mapdisplay.MapWindow.UpdateMap(render =
False, renderVector =
True)
1329 """!Reload table description"""
1338 """!Add new record to the attribute table"""
1340 table = self.mapDBInfo.layers[self.
layer][
'table']
1341 keyColumn = self.mapDBInfo.layers[self.
layer][
'key']
1348 for i
in range(tlist.GetColumnCount()):
1349 columnName.append(tlist.GetColumn(i).GetText())
1352 if len(tlist.itemCatsMap.values()) > 0:
1353 maxCat =
max(tlist.itemCatsMap.values())
1358 if keyColumn
not in columnName:
1359 columnName.insert(0, keyColumn)
1360 data.append((keyColumn, str(maxCat + 1)))
1368 for col
in columnName:
1369 ctype = self.mapDBInfo.tables[table][col][
'ctype']
1370 ctypeStr = self.mapDBInfo.tables[table][col][
'type']
1371 if col == keyColumn:
1372 if missingKey
is False:
1373 data.append((col, ctype, ctypeStr, str(maxCat + 1)))
1376 data.append((col, ctype, ctypeStr,
''))
1380 dlg = ModifyTableRecord(parent = self,
1381 title = _(
"Insert new record"),
1382 data = data, keyEditable = (keyId,
True))
1384 if dlg.ShowModal() == wx.ID_OK:
1386 cat = int(dlg.GetValues(columns = [keyColumn])[0])
1391 if cat
in tlist.itemCatsMap.values():
1392 raise ValueError(_(
"Record with category number %d "
1393 "already exists in the table.") % cat)
1395 values = dlg.GetValues()
1399 for i
in range(len(values)):
1400 if len(values[i]) == 0:
1401 if columnName[i] == keyColumn:
1402 raise ValueError(_(
"Category number (column %s)"
1403 " is missing.") % keyColumn)
1408 if tlist.columns[columnName[i]][
'ctype'] == int:
1410 value = float(values[i])
1413 values[i] = tlist.columns[columnName[i]][
'ctype'] (value)
1416 raise ValueError(_(
"Value '%(value)s' needs to be entered as %(type)s.") %
1417 {
'value' : str(values[i]),
1418 'type' : tlist.columns[columnName[i]][
'type']})
1419 columnsString +=
'%s,' % columnName[i]
1420 if tlist.columns[columnName[i]][
'ctype'] == str:
1421 valuesString +=
"'%s'," % values[i]
1423 valuesString +=
"%s," % values[i]
1425 except ValueError, err:
1426 GError(parent = self,
1427 message = _(
"Unable to insert new record.\n%s") % err,
1428 showTraceback =
False)
1433 if missingKey
is True:
1437 if len(tlist.itemIndexMap) > 0:
1438 index =
max(tlist.itemIndexMap) + 1
1442 tlist.itemIndexMap.append(index)
1443 tlist.itemDataMap[index] = values
1444 tlist.itemCatsMap[index] = cat
1445 tlist.SetItemCount(tlist.GetItemCount() + 1)
1447 self.listOfSQLStatements.append(
'INSERT INTO %s (%s) VALUES(%s)' % \
1449 columnsString.strip(
','),
1450 valuesString.strip(
',')))
1454 """!Edit selected record of the attribute table"""
1456 item = tlist.GetFirstSelected()
1460 table = self.mapDBInfo.layers[self.
layer][
'table']
1461 keyColumn = self.mapDBInfo.layers[self.
layer][
'key']
1462 cat = tlist.itemCatsMap[tlist.itemIndexMap[item]]
1469 for i
in range(tlist.GetColumnCount()):
1470 columnName.append(tlist.GetColumn(i).GetText())
1474 if keyColumn
not in columnName:
1475 columnName.insert(0, keyColumn)
1476 data.append((keyColumn, str(cat)))
1483 for i
in range(len(columnName)):
1484 ctype = self.mapDBInfo.tables[table][columnName[i]][
'ctype']
1485 ctypeStr = self.mapDBInfo.tables[table][columnName[i]][
'type']
1486 if columnName[i] == keyColumn:
1487 if missingKey
is False:
1488 data.append((columnName[i], ctype, ctypeStr, str(cat)))
1491 if missingKey
is True:
1492 value = tlist.GetItem(item, i-1).GetText()
1494 value = tlist.GetItem(item, i).GetText()
1495 data.append((columnName[i], ctype, ctypeStr, value))
1497 dlg = ModifyTableRecord(parent = self,
1498 title = _(
"Update existing record"),
1499 data = data, keyEditable = (keyId,
False))
1501 if dlg.ShowModal() == wx.ID_OK:
1502 values = dlg.GetValues()
1505 for i
in range(len(values)):
1508 if tlist.GetItem(item, i).GetText() != values[i]:
1509 if len(values[i]) > 0:
1511 if missingKey
is True:
1515 if tlist.columns[columnName[i]][
'ctype'] != types.StringType:
1516 if tlist.columns[columnName[i]][
'ctype'] == int:
1517 value = float(values[i])
1520 tlist.itemDataMap[item][idx] = \
1521 tlist.columns[columnName[i]][
'ctype'] (value)
1523 tlist.itemDataMap[item][idx] = values[i]
1525 raise ValueError(_(
"Value '%(value)s' needs to be entered as %(type)s.") % \
1526 {
'value' : str(values[i]),
1527 'type' : tlist.columns[columnName[i]][
'type']})
1529 if tlist.columns[columnName[i]][
'ctype'] == str:
1530 updateString +=
"%s='%s'," % (columnName[i], values[i])
1532 updateString +=
"%s=%s," % (columnName[i], values[i])
1534 updateString +=
"%s=NULL," % (columnName[i])
1536 except ValueError, err:
1537 GError(parent = self,
1538 message = _(
"Unable to update existing record.\n%s") % err,
1539 showTraceback =
False)
1543 if len(updateString) > 0:
1544 self.listOfSQLStatements.append(
'UPDATE %s SET %s WHERE %s=%d' % \
1545 (table, updateString.strip(
','),
1552 """!Reload tlist of records"""
1557 """!Select all items"""
1562 item = tlist.GetNextItem(item)
1565 tlist.SetItemState(item, wx.LIST_STATE_SELECTED, wx.LIST_STATE_SELECTED)
1570 """!Deselect items"""
1575 item = tlist.GetNextItem(item, wx.LIST_STATE_SELECTED)
1578 tlist.SetItemState(item, 0, wx.LIST_STATE_SELECTED | wx.LIST_STATE_FOCUSED)
1584 """!Data type for new column changed. Enable or disable
1585 data length widget"""
1586 win = self.FindWindowById(self.
layerPage[self.
layer][
'addColLength'])
1587 if event.GetString() ==
"varchar":
1593 """!Editing column name to be added to the table"""
1594 btn = self.FindWindowById(self.
layerPage[self.
layer][
'renameColButton'])
1595 col = self.FindWindowById(self.
layerPage[self.
layer][
'renameCol'])
1596 colTo = self.FindWindowById(self.
layerPage[self.
layer][
'renameColTo'])
1597 if len(col.GetValue()) > 0
and len(colTo.GetValue()) > 0:
1605 """!Editing column name to be added to the table"""
1606 btn = self.FindWindowById(self.
layerPage[self.
layer][
'addColButton'])
1607 if len(event.GetString()) > 0:
1615 """!Rename column in the table"""
1616 tlist = self.FindWindowById(self.
layerPage[self.
layer][
'tableData'])
1620 table = self.mapDBInfo.layers[self.
layer][
"table"]
1622 if not name
or not nameTo:
1623 GError(parent = self,
1624 message = _(
"Unable to rename column. "
1625 "No column name defined."))
1628 item = tlist.FindItem(start = -1, str = name)
1630 if tlist.FindItem(start = -1, str = nameTo) > -1:
1631 GError(parent = self,
1632 message = _(
"Unable to rename column <%(column)s> to "
1633 "<%(columnTo)s>. Column already exists "
1634 "in the table <%(table)s>.") % \
1635 {
'column' : name,
'columnTo' : nameTo,
1639 tlist.SetItemText(item, nameTo)
1641 self.listOfCommands.append((
'v.db.renamecol',
1643 'layer' : self.
layer,
1644 'column' :
'%s,%s' % (name, nameTo) }
1647 GError(parent = self,
1648 message = _(
"Unable to rename column. "
1649 "Column <%(column)s> doesn't exist in the table <%(table)s>.") %
1650 {
'column' : name,
'table' : table})
1657 self.FindWindowById(self.
layerPage[self.
layer][
'renameCol']).SetItems(self.mapDBInfo.GetColumns(table))
1658 self.FindWindowById(self.
layerPage[self.
layer][
'renameCol']).SetSelection(0)
1664 """!Table description area, context menu"""
1665 if not hasattr(self,
"popupTableID"):
1676 if self.FindWindowById(self.
layerPage[self.
layer][
'tableData']).GetFirstSelected() == -1:
1679 menu.AppendSeparator()
1682 self.PopupMenu(menu)
1686 """!Delete selected item(s) from the list"""
1687 tlist = self.FindWindowById(self.
layerPage[self.
layer][
'tableData'])
1689 item = tlist.GetFirstSelected()
1691 if UserSettings.Get(group =
'atm', key =
'askOnDeleteRec', subkey =
'enabled'):
1692 deleteDialog = wx.MessageBox(parent = self,
1693 message = _(
"Selected column '%s' will PERMANENTLY removed "
1694 "from table. Do you want to drop the column?") % \
1695 (tlist.GetItemText(item)),
1696 caption = _(
"Drop column(s)"),
1697 style = wx.YES_NO | wx.CENTRE)
1698 if deleteDialog != wx.YES:
1702 self.listOfCommands.append((
'v.db.dropcol',
1704 'layer' : self.
layer,
1705 'column' : tlist.GetItemText(item) }
1707 tlist.DeleteItem(item)
1708 item = tlist.GetFirstSelected()
1714 table = self.mapDBInfo.layers[self.
layer][
'table']
1715 self.FindWindowById(self.
layerPage[self.
layer][
'renameCol']).SetItems(self.mapDBInfo.GetColumns(table))
1716 self.FindWindowById(self.
layerPage[self.
layer][
'renameCol']).SetSelection(0)
1721 """!Delete all items from the list"""
1722 table = self.mapDBInfo.layers[self.
layer][
'table']
1723 cols = self.mapDBInfo.GetColumns(table)
1724 keyColumn = self.mapDBInfo.layers[self.
layer][
'key']
1725 if keyColumn
in cols:
1726 cols.remove(keyColumn)
1728 if UserSettings.Get(group =
'atm', key =
'askOnDeleteRec', subkey =
'enabled'):
1729 deleteDialog = wx.MessageBox(parent = self,
1730 message = _(
"Selected columns\n%s\nwill PERMANENTLY removed "
1731 "from table. Do you want to drop the columns?") % \
1733 caption = _(
"Drop column(s)"),
1734 style = wx.YES_NO | wx.CENTRE)
1735 if deleteDialog != wx.YES:
1739 self.listOfCommands.append((
'v.db.dropcol',
1741 'layer' : self.
layer,
1744 self.FindWindowById(self.
layerPage[self.
layer][
'tableData']).DeleteAllItems()
1750 table = self.mapDBInfo.layers[self.
layer][
'table']
1751 self.FindWindowById(self.
layerPage[self.
layer][
'renameCol']).SetItems(self.mapDBInfo.GetColumns(table))
1752 self.FindWindowById(self.
layerPage[self.
layer][
'renameCol']).SetSelection(0)
1757 """!Reload table description"""
1758 self.FindWindowById(self.
layerPage[self.
layer][
'tableData']).Populate(update =
True)
1762 """!Add new column to the table"""
1763 table = self.mapDBInfo.layers[self.layer][
'table']
1764 name = self.FindWindowById(self.layerPage[self.layer][
'addColName']).
GetValue()
1767 GError(parent = self,
1768 message = _(
"Unable to add column to the table. "
1769 "No column name defined."))
1772 ctype = self.FindWindowById(self.layerPage[self.layer][
'addColType']). \
1773 GetStringSelection()
1776 if ctype ==
'double':
1777 ctype =
'double precision'
1778 if ctype ==
'varchar':
1779 length = int(self.FindWindowById(self.layerPage[self.layer][
'addColLength']). \
1785 tlist = self.FindWindowById(self.layerPage[self.layer][
'tableData'])
1787 if tlist.FindItem(start = -1, str = name) > -1:
1788 GError(parent = self,
1789 message = _(
"Column <%(column)s> already exists in table <%(table)s>.") % \
1790 {
'column' : name,
'table' : self.mapDBInfo.layers[self.layer][
"table"]})
1792 index = tlist.InsertStringItem(sys.maxint, str(name))
1793 tlist.SetStringItem(index, 0, str(name))
1794 tlist.SetStringItem(index, 1, str(ctype))
1795 tlist.SetStringItem(index, 2, str(length))
1798 if ctype ==
'varchar':
1799 ctype +=
' (%d)' % length
1800 self.listOfCommands.append((
'v.db.addcol',
1801 {
'map' : self.vectorName,
1802 'layer' : self.layer,
1803 'columns' :
'%s %s' % (name, ctype) }
1806 self.ApplyCommands()
1809 self.FindWindowById(self.layerPage[self.layer][
'addColName']).
SetValue(
'')
1810 self.FindWindowById(self.layerPage[self.layer][
'renameCol']).SetItems(self.mapDBInfo.GetColumns(table))
1811 self.FindWindowById(self.layerPage[self.layer][
'renameCol']).SetSelection(0)
1816 """!Layer tab changed"""
1817 pageNum = event.GetSelection()
1818 self.
layer = self.mapDBInfo.layers.keys()[pageNum]
1828 self.log.write(_(
"Number of loaded records: %d") % \
1835 winCol = self.FindWindowById(idCol)
1836 table = self.mapDBInfo.layers[self.
layer][
"table"]
1837 self.mapDBInfo.GetColumns(table)
1847 if event.GetSelection() == 0
and id:
1848 win = self.FindWindowById(id)
1850 self.log.write(_(
"Number of loaded records: %d") % win.GetItemCount())
1853 self.btnReload.Enable()
1856 self.btnReload.Enable(
False)
1861 """!Layer description area, context menu"""
1865 """!Switch simple/advanced sql statement"""
1866 if self.FindWindowById(self.layerPage[self.layer][
'simple']).
GetValue():
1867 self.FindWindowById(self.layerPage[self.layer][
'where']).Enable(
True)
1868 self.FindWindowById(self.layerPage[self.layer][
'statement']).Enable(
False)
1869 self.FindWindowById(self.layerPage[self.layer][
'builder']).Enable(
False)
1871 self.FindWindowById(self.layerPage[self.layer][
'where']).Enable(
False)
1872 self.FindWindowById(self.layerPage[self.layer][
'statement']).Enable(
True)
1873 self.FindWindowById(self.layerPage[self.layer][
'builder']).Enable(
True)
1876 """!Apply changes"""
1878 wx.BeginBusyCursor()
1888 table = self.mapDBInfo.layers[self.
layer][
'table']
1891 tlist = self.FindWindowById(self.
layerPage[self.
layer][
'tableData'])
1892 tlist.Update(table = self.mapDBInfo.tables[table],
1893 columns = self.mapDBInfo.GetColumns(table))
1905 fd, sqlFilePath = tempfile.mkstemp(text=
True)
1906 sqlFile = open(sqlFilePath,
'w')
1908 enc = UserSettings.Get(group =
'atm', key =
'encoding', subkey =
'value')
1909 if not enc
and 'GRASS_DB_ENCODING' in os.environ:
1910 enc = os.environ[
'GRASS_DB_ENCODING']
1912 sqlFile.write(sql.encode(enc) +
';')
1914 sqlFile.write(sql +
';')
1915 sqlFile.write(os.linesep)
1918 driver = self.mapDBInfo.layers[self.
layer][
"driver"]
1919 database = self.mapDBInfo.layers[self.
layer][
"database"]
1921 Debug.msg(3,
'AttributeManger.ApplyCommands(): %s' %
1926 input = sqlFilePath,
1928 database = database)
1931 os.remove(sqlFilePath)
1938 """!Apply simple/advanced sql statement"""
1940 listWin = self.FindWindowById(self.
layerPage[self.
layer][
'data'])
1946 wx.BeginBusyCursor()
1949 whereCol = self.FindWindowById(self.
layerPage[self.
layer][
'whereColumn']).GetStringSelection()
1950 whereOpe = self.FindWindowById(self.
layerPage[self.
layer][
'whereOperator']).GetStringSelection()
1953 if len(whereVal) > 0:
1954 keyColumn = listWin.LoadData(self.
layer, where = whereCol + whereOpe + whereVal)
1956 keyColumn = listWin.LoadData(self.
layer)
1957 except GException, e:
1958 GError(parent = self,
1959 message = _(
"Loading attribute data failed.\n\n%s") % e.value)
1963 win = self.FindWindowById(self.
layerPage[self.
layer][
'statement'])
1966 if cols
is None and where
is None:
1967 sql = win.GetValue()
1969 GError(parent = self,
1970 message = _(
"Loading attribute data failed.\n"
1971 "Invalid SQL select statement.\n\n%s") % win.GetValue())
1972 win.SetValue(
"SELECT * FROM %s" % self.mapDBInfo.layers[self.
layer][
'table'])
1976 if cols
or where
or sql:
1978 keyColumn = listWin.LoadData(self.
layer, columns = cols,
1979 where = where, sql = sql)
1980 except GException, e:
1981 GError(parent = self,
1982 message = _(
"Loading attribute data failed.\n\n%s") % e.value)
1983 win.SetValue(
"SELECT * FROM %s" % self.mapDBInfo.layers[self.
layer][
'table'])
1986 if sql
and 'order by' in sql.lower():
1990 listWin.SortListItems(col = keyColumn, ascending =
True)
1992 listWin.SortListItems(col = 0, ascending =
True)
1997 self.log.write(_(
"Number of loaded records: %d") % \
1998 self.FindWindowById(self.
layerPage[self.
layer][
'data']).GetItemCount())
2001 """!Validate SQL select statement
2003 @return (columns, where)
2004 @return None on error
2006 if statement[0:7].lower() !=
'select ':
2011 for c
in statement[index:]:
2019 cols = cols.split(
',')
2021 tablelen = len(self.mapDBInfo.layers[self.
layer][
'table'])
2023 if statement[index+1:index+6].lower() !=
'from ' or \
2024 statement[index+6:index+6+tablelen] !=
'%s' % \
2025 (self.mapDBInfo.layers[self.
layer][
'table']):
2028 if len(statement[index+7+tablelen:]) > 0:
2029 index = statement.lower().find(
'where ')
2031 where = statement[index+6:]
2037 return (cols, where)
2040 """!Cancel button pressed"""
2041 if self.
parent and self.parent.GetName() ==
'LayerManager':
2043 self.parent.dialogs[
'atm'].remove(self)
2045 if not isinstance(event, wx.CloseEvent):
2051 """!SQL Builder button pressed -> show the SQLBuilder dialog"""
2053 self.
builder = SQLFrame(parent = self, id = wx.ID_ANY,
2054 title = _(
"SQL Builder"),
2059 self.builder.Raise()
2062 if event ==
'apply':
2063 sqlstr = self.builder.GetSQLStatement()
2066 self.listOfSQLStatements.append(sqlstr)
2069 if self.builder.CloseOnApply():
2071 elif event ==
'close':
2078 """!Item activated, highlight selected item"""
2079 self.OnDataDrawSelected(event)
2084 """!Extract vector objects selected in attribute browse window
2089 cats = tlist.GetSelectedItems()
2091 GMessage(parent = self,
2092 message = _(
'Nothing to extract.'))
2096 dlg =
CreateNewVector(parent = self, title = _(
'Extract selected features'),
2098 cmd = ((
'v.extract',
2102 disableTable =
True)
2106 name = dlg.GetName(full =
True)
2107 if name
and dlg.IsChecked(
'add'):
2109 self.parent.GetLayerTree().AddLayer(ltype =
'vector',
2111 lcmd = [
'd.vect',
'map=%s' % name])
2115 """!Delete vector objects selected in attribute browse window
2116 (attribures and geometry)
2119 cats = tlist.GetSelectedItems()
2121 GMessage(parent = self,
2122 message = _(
'Nothing to delete.'))
2125 if 'vdigit' in self.mapdisplay.toolbars:
2126 digitToolbar = self.mapdisplay.toolbars[
'vdigit']
2127 if digitToolbar
and digitToolbar.GetLayer()
and \
2128 digitToolbar.GetLayer().GetName() == self.
vectorName:
2129 display = self.mapdisplay.GetMapWindow().GetDisplay()
2130 display.SetSelected(
map(int, cats), layer = self.
layer)
2131 self.mapdisplay.MapWindow.UpdateMap(render =
True, renderVector =
True)
2135 self.mapdisplay.GetMapWindow().digit.DeleteSelectedLines()
2144 self.mapdisplay.MapWindow.UpdateMap(render =
True, renderVector =
True)
2149 Return True if map has been redrawn, False if no map is given
2153 self.
layer : tlist.GetSelectedItems()
2156 if self.mapdisplay.Map.GetLayerIndex(self.
qlayer) < 0:
2160 self.qlayer.SetCmd(self.mapdisplay.AddTmpVectorMapLayer(self.
vectorName, cats, addLayer =
False))
2167 """!Updates dialog layout for given layer"""
2169 if layer
in self.mapDBInfo.layers.keys():
2175 self.browsePage.DeletePage(self.mapDBInfo.layers.keys().index(layer))
2176 self.manageTablePage.DeletePage(self.mapDBInfo.layers.keys().index(layer))
2178 self.notebook.SetSelectionByName(
'layers')
2186 if layer
in self.mapDBInfo.layers.keys():
2192 self.notebook.SetSelectionByName(
'layers')
2198 self.layerList.Update(self.mapDBInfo.layers)
2199 self.layerList.Populate(update =
True)
2201 listOfLayers =
map(str, self.mapDBInfo.layers.keys())
2203 self.manageLayerBook.deleteLayer.SetItems(listOfLayers)
2204 if len(listOfLayers) > 0:
2205 self.manageLayerBook.deleteLayer.SetStringSelection(listOfLayers[0])
2206 tableName = self.mapDBInfo.layers[int(listOfLayers[0])][
'table']
2207 maxLayer =
max(self.mapDBInfo.layers.keys())
2211 self.manageLayerBook.deleteTable.SetLabel( \
2212 _(
'Drop also linked attribute table (%s)') % \
2215 self.manageLayerBook.addLayerWidgets[
'layer'][1].
SetValue(\
2218 self.manageLayerBook.modifyLayerWidgets[
'layer'][1].SetItems(listOfLayers)
2219 self.manageLayerBook.OnChangeLayer(event =
None)
2222 """!Get vector name"""
2225 def LoadData(self, layer, columns = None, where = None, sql = None):
2226 """!Load data into list
2228 @param layer layer number
2229 @param columns list of columns for output
2230 @param where where statement
2231 @param sql full sql statement
2233 @return id of key column
2234 @return -1 if key column is not displayed
2236 listWin = self.FindWindowById(self.
layerPage[layer][
'data'])
2237 return listWin.LoadData(layer, columns, where, sql)
2240 listmix.ListCtrlAutoWidthMixin):
2242 """!Table description list"""
2244 def __init__(self, parent, id, table, columns, pos = wx.DefaultPosition,
2245 size = wx.DefaultSize):
2250 wx.ListCtrl.__init__(self, parent, id, pos, size,
2251 style = wx.LC_REPORT | wx.LC_HRULES | wx.LC_VRULES |
2254 listmix.ListCtrlAutoWidthMixin.__init__(self)
2258 """!Update column description"""
2263 """!Populate the list"""
2267 headings = [_(
"Column name"), _(
"Data type"), _(
"Data length")]
2270 self.InsertColumn(col = i, heading = h)
2272 self.SetColumnWidth(col = 0, width = 350)
2273 self.SetColumnWidth(col = 1, width = 175)
2275 self.DeleteAllItems()
2279 index = self.InsertStringItem(sys.maxint, str(column))
2280 self.SetStringItem(index, 0, str(column))
2281 self.SetStringItem(index, 1, str(self.
table[column][
'type']))
2282 self.SetStringItem(index, 2, str(self.
table[column][
'length']))
2283 self.SetItemData(index, i)
2284 itemData[i] = (str(column),
2285 str(self.
table[column][
'type']),
2286 int(self.
table[column][
'length']))
2289 self.SendSizeEvent()
2294 listmix.ListCtrlAutoWidthMixin):
2297 """!Layer description list"""
2299 def __init__(self, parent, id, layers,
2300 pos = wx.DefaultPosition,
2301 size = wx.DefaultSize):
2305 wx.ListCtrl.__init__(self, parent, id, pos, size,
2306 style = wx.LC_REPORT | wx.LC_HRULES | wx.LC_VRULES |
2309 listmix.ListCtrlAutoWidthMixin.__init__(self)
2313 """!Update description"""
2317 """!Populate the list"""
2321 headings = [_(
"Layer"), _(
"Driver"), _(
"Database"), _(
"Table"), _(
"Key")]
2324 self.InsertColumn(col = i, heading = h)
2327 self.DeleteAllItems()
2330 for layer
in self.layers.keys():
2331 index = self.InsertStringItem(sys.maxint, str(layer))
2332 self.SetStringItem(index, 0, str(layer))
2333 database = str(self.
layers[layer][
'database'])
2334 driver = str(self.
layers[layer][
'driver'])
2335 table = str(self.
layers[layer][
'table'])
2336 key = str(self.
layers[layer][
'key'])
2337 self.SetStringItem(index, 1, driver)
2338 self.SetStringItem(index, 2, database)
2339 self.SetStringItem(index, 3, table)
2340 self.SetStringItem(index, 4, key)
2341 self.SetItemData(index, i)
2342 itemData[i] = (str(layer),
2349 for i
in range(self.GetColumnCount()):
2350 self.SetColumnWidth(col = i, width = wx.LIST_AUTOSIZE)
2351 if self.GetColumnWidth(col = i) < 60:
2352 self.SetColumnWidth(col = i, width = 60)
2354 self.SendSizeEvent()
2359 """!Manage layers (add, delete, modify)"""
2362 style = wx.BK_DEFAULT):
2363 wx.Notebook.__init__(self, parent, id, style = style)
2378 for drv
in drivers.splitlines():
2379 self.listOfDrivers.append(drv.strip())
2390 for line
in connect.splitlines():
2391 item, value = line.split(
':', 1)
2396 GWarning(parent = self.
parent,
2397 message = _(
"Unknown default DB connection. "
2398 "Please define DB connection using db.connect module."))
2413 def _createAddPage(self):
2414 """!Add new layer"""
2415 self.
addPanel = wx.Panel(parent = self, id = wx.ID_ANY)
2416 self.AddPage(page = self.
addPanel, text = _(
"Add layer"))
2419 maxLayer =
max(self.mapDBInfo.layers.keys())
2425 layerBox = wx.StaticBox (parent = self.
addPanel, id = wx.ID_ANY,
2426 label =
" %s " % (_(
"Layer description")))
2427 layerSizer = wx.StaticBoxSizer(layerBox, wx.VERTICAL)
2433 (wx.StaticText(parent = self.
addPanel, id = wx.ID_ANY,
2434 label =
'%s:' % _(
"Layer")),
2435 wx.SpinCtrl(parent = self.
addPanel, id = wx.ID_ANY, size = (65, -1),
2436 initial = maxLayer+1,
2437 min = 1, max = 1e6)),
2439 (wx.StaticText(parent = self.
addPanel, id = wx.ID_ANY,
2440 label =
'%s:' % _(
"Driver")),
2441 wx.Choice(parent = self.
addPanel, id = wx.ID_ANY, size = (200, -1),
2444 (wx.StaticText(parent = self.
addPanel, id = wx.ID_ANY,
2445 label =
'%s:' % _(
"Database")),
2446 wx.TextCtrl(parent = self.
addPanel, id = wx.ID_ANY,
2448 style = wx.TE_PROCESS_ENTER)),
2450 (wx.StaticText(parent = self.
addPanel, id = wx.ID_ANY,
2451 label =
'%s:' % _(
"Table")),
2452 wx.Choice(parent = self.
addPanel, id = wx.ID_ANY, size = (200, -1),
2455 (wx.StaticText(parent = self.
addPanel, id = wx.ID_ANY,
2456 label =
'%s:' % _(
"Key column")),
2457 wx.Choice(parent = self.
addPanel, id = wx.ID_ANY, size = (200, -1),
2460 (wx.CheckBox(parent = self.
addPanel, id = wx.ID_ANY,
2461 label = _(
"Insert record for each category into table")),
2476 self.
addLayerWidgets[
'addCat'][0].SetToolTipString(_(
"You need to add categories "
2477 "by v.category module."))
2480 tableBox = wx.StaticBox (parent = self.
addPanel, id = wx.ID_ANY,
2481 label =
" %s " % (_(
"Table description")))
2482 tableSizer = wx.StaticBoxSizer(tableBox, wx.VERTICAL)
2487 keyCol = UserSettings.Get(group =
'atm', key =
'keycolumn', subkey =
'value')
2489 label =
'%s:' % _(
"Table name")),
2490 wx.TextCtrl(parent = self.
addPanel, id = wx.ID_ANY,
2492 style = wx.TE_PROCESS_ENTER)),
2493 'key': (wx.StaticText(parent = self.
addPanel, id = wx.ID_ANY,
2494 label =
'%s:' % _(
"Key column")),
2495 wx.TextCtrl(parent = self.
addPanel, id = wx.ID_ANY,
2497 style = wx.TE_PROCESS_ENTER))}
2502 btnTable = wx.Button(self.
addPanel, wx.ID_ANY, _(
"&Create table"),
2506 btnLayer = wx.Button(self.
addPanel, wx.ID_ANY, _(
"&Add layer"),
2508 btnLayer.Bind(wx.EVT_BUTTON, self.
OnAddLayer)
2510 btnDefault = wx.Button(self.
addPanel, wx.ID_ANY, _(
"&Set default"),
2516 pageSizer = wx.BoxSizer(wx.HORIZONTAL)
2519 dataSizer = wx.GridBagSizer(hgap = 5, vgap = 5)
2521 for key
in (
'layer',
'driver',
'database',
'table',
'key',
'addCat'):
2527 dataSizer.Add(item = label,
2528 flag = wx.ALIGN_CENTER_VERTICAL, pos = (row, 0),
2536 style = wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT
2538 style = wx.ALIGN_CENTER_VERTICAL | wx.EXPAND
2540 dataSizer.Add(item = value,
2541 flag = style, pos = (row, 1))
2544 dataSizer.AddGrowableCol(1)
2546 layerSizer.Add(item = dataSizer,
2548 flag = wx.ALL | wx.EXPAND,
2551 btnSizer = wx.BoxSizer(wx.HORIZONTAL)
2552 btnSizer.Add(item = btnDefault,
2554 flag = wx.ALL | wx.ALIGN_LEFT,
2557 btnSizer.Add(item = (5, 5),
2559 flag = wx.ALL | wx.EXPAND,
2562 btnSizer.Add(item = btnLayer,
2564 flag = wx.ALL | wx.ALIGN_RIGHT,
2567 layerSizer.Add(item = btnSizer,
2569 flag = wx.ALL | wx.EXPAND,
2573 dataSizer = wx.FlexGridSizer(cols = 2, hgap = 5, vgap = 5)
2574 for key
in [
'table',
'key']:
2576 dataSizer.Add(item = label,
2577 flag = wx.ALIGN_CENTER_VERTICAL)
2578 dataSizer.Add(item = value,
2579 flag = wx.ALIGN_CENTER_VERTICAL | wx.EXPAND)
2580 dataSizer.AddGrowableCol(1)
2582 tableSizer.Add(item = dataSizer,
2584 flag = wx.ALL | wx.EXPAND,
2587 tableSizer.Add(item = btnTable,
2589 flag = wx.ALL | wx.ALIGN_BOTTOM | wx.ALIGN_RIGHT,
2592 pageSizer.Add(item = layerSizer,
2594 flag = wx.ALL | wx.EXPAND,
2597 pageSizer.Add(item = tableSizer,
2599 flag = wx.TOP | wx.BOTTOM | wx.RIGHT | wx.EXPAND,
2602 layerSizer.SetVirtualSizeHints(self.
addPanel)
2603 self.addPanel.SetAutoLayout(
True)
2604 self.addPanel.SetSizer(pageSizer)
2607 def _createDeletePage(self):
2610 self.AddPage(page = self.
deletePanel, text = _(
"Remove layer"))
2612 label = wx.StaticText(parent = self.
deletePanel, id = wx.ID_ANY,
2613 label =
'%s:' % _(
"Layer to remove"))
2616 style = wx.CB_SIMPLE | wx.CB_READONLY,
2617 choices = map(str, self.mapDBInfo.layers.keys()))
2618 self.deleteLayer.SetSelection(0)
2622 tableName = self.mapDBInfo.layers[int(self.deleteLayer.GetStringSelection())][
'table']
2627 label = _(
'Drop also linked attribute table (%s)') % \
2631 self.deleteLayer.Enable(
False)
2632 self.deleteTable.Enable(
False)
2634 btnDelete = wx.Button(self.
deletePanel, wx.ID_DELETE, _(
"&Remove layer"),
2641 pageSizer = wx.BoxSizer(wx.VERTICAL)
2643 dataSizer = wx.BoxSizer(wx.VERTICAL)
2645 flexSizer = wx.FlexGridSizer(cols = 2, hgap = 5, vgap = 5)
2647 flexSizer.Add(item = label,
2648 flag = wx.ALIGN_CENTER_VERTICAL)
2650 flag = wx.ALIGN_CENTER_VERTICAL)
2651 flexSizer.AddGrowableCol(1)
2653 dataSizer.Add(item = flexSizer,
2655 flag = wx.ALL | wx.EXPAND,
2660 flag = wx.ALL | wx.EXPAND,
2663 pageSizer.Add(item = dataSizer,
2665 flag = wx.ALL | wx.EXPAND,
2668 pageSizer.Add(item = btnDelete,
2670 flag = wx.ALL | wx.ALIGN_RIGHT,
2673 self.deletePanel.SetSizer(pageSizer)
2675 def _createModifyPage(self):
2678 self.AddPage(page = self.
modifyPanel, text = _(
"Modify layer"))
2684 (wx.StaticText(parent = self.
modifyPanel, id = wx.ID_ANY,
2685 label =
'%s:' % _(
"Layer")),
2686 wx.ComboBox(parent = self.
modifyPanel, id = wx.ID_ANY,
2688 style = wx.CB_SIMPLE | wx.CB_READONLY,
2690 self.mapDBInfo.layers.keys()))),
2692 (wx.StaticText(parent = self.
modifyPanel, id = wx.ID_ANY,
2693 label =
'%s:' % _(
"Driver")),
2694 wx.Choice(parent = self.
modifyPanel, id = wx.ID_ANY,
2698 (wx.StaticText(parent = self.
modifyPanel, id = wx.ID_ANY,
2699 label =
'%s:' % _(
"Database")),
2700 wx.TextCtrl(parent = self.
modifyPanel, id = wx.ID_ANY,
2701 value =
'', size = (350, -1),
2702 style = wx.TE_PROCESS_ENTER)),
2704 (wx.StaticText(parent = self.
modifyPanel, id = wx.ID_ANY,
2705 label =
'%s:' % _(
"Table")),
2706 wx.Choice(parent = self.
modifyPanel, id = wx.ID_ANY,
2710 (wx.StaticText(parent = self.
modifyPanel, id = wx.ID_ANY,
2711 label =
'%s:' % _(
"Key column")),
2712 wx.Choice(parent = self.
modifyPanel, id = wx.ID_ANY,
2722 for label
in self.modifyLayerWidgets.keys():
2726 driver = self.mapDBInfo.layers[layer][
'driver']
2727 database = self.mapDBInfo.layers[layer][
'database']
2728 table = self.mapDBInfo.layers[layer][
'table']
2730 listOfColumns = self.
_getColumns(driver, database, table)
2739 table =
'public.' + table
2750 btnModify = wx.Button(self.
modifyPanel, wx.ID_DELETE, _(
"&Modify layer"),
2757 pageSizer = wx.BoxSizer(wx.VERTICAL)
2760 dataSizer = wx.FlexGridSizer(cols = 2, hgap = 5, vgap = 5)
2761 for key
in (
'layer',
'driver',
'database',
'table',
'key'):
2763 dataSizer.Add(item = label,
2764 flag = wx.ALIGN_CENTER_VERTICAL)
2766 dataSizer.Add(item = value,
2767 flag = wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT)
2769 dataSizer.Add(item = value,
2770 flag = wx.ALIGN_CENTER_VERTICAL)
2771 dataSizer.AddGrowableCol(1)
2773 pageSizer.Add(item = dataSizer,
2775 flag = wx.ALL | wx.EXPAND,
2778 pageSizer.Add(item = btnModify,
2780 flag = wx.ALL | wx.ALIGN_RIGHT,
2783 self.modifyPanel.SetSizer(pageSizer)
2785 def _getTables(self, driver, database):
2786 """!Get list of tables for given driver and database"""
2794 database = database)
2797 GError(parent = self,
2798 message = _(
"Unable to get list of tables.\n"
2799 "Please use db.connect to set database parameters."))
2803 for table
in ret.splitlines():
2804 tables.append(table)
2808 def _getColumns(self, driver, database, table):
2809 """!Get list of column of given table"""
2817 database = database,
2823 for column
in ret.splitlines():
2824 columns.append(column)
2829 """!Driver selection changed, update list of tables"""
2830 driver = event.GetString()
2837 winTable.SetItems(tables)
2838 winTable.SetSelection(0)
2840 if len(tables) == 0:
2846 """!Database selection changed, update list of tables"""
2850 """!Table name changed, update list of columns"""
2853 table = event.GetString()
2863 """!Set default values"""
2873 table.SetItems(tables)
2874 table.SetSelection(0)
2875 if len(tables) == 0:
2887 """!Create new table (name and key column given)"""
2893 if not table
or not key:
2894 GError(parent = self,
2895 message = _(
"Unable to create new table. "
2896 "Table name or key column name is missing."))
2900 GError(parent = self,
2901 message = _(
"Unable to create new table. "
2902 "Table <%s> already exists in the database.") % table)
2906 sql =
'CREATE TABLE %s (%s INTEGER)' % (table, key)
2913 database = database)
2917 tableList.SetItems(self.
_getTables(driver, database))
2918 tableList.SetStringSelection(table)
2922 keyList.SetItems(self.
_getColumns(driver, database, table))
2923 keyList.SetStringSelection(key)
2928 """!Add new layer to vector map"""
2936 if layer
in self.mapDBInfo.layers.keys():
2937 GError(parent = self,
2938 message = _(
"Unable to add new layer to vector map <%(vector)s>. "
2939 "Layer %(layer)d already exists.") % \
2940 {
'vector' : self.mapDBInfo.map,
'layer' : layer})
2947 map = self.mapDBInfo.map,
2949 database = database,
2959 map = self.mapDBInfo.map,
2967 self.parentDialog.UpdateDialog(layer = layer)
2969 self.
mapDBInfo = self.parentDialog.mapDBInfo
2971 layerWin.SetValue(layer+1)
2973 if len(self.mapDBInfo.layers.keys()) == 1:
2975 self.deleteLayer.Enable()
2976 self.deleteTable.Enable()
2977 for label
in self.modifyLayerWidgets.keys():
2983 layer = int(self.deleteLayer.GetValue())
2990 map = self.mapDBInfo.map,
2994 if self.deleteTable.IsChecked():
2997 table = self.mapDBInfo.layers[layer][
'table']
2998 sql =
'DROP TABLE %s' % (table)
3005 database = database)
3009 tableList.SetItems(self.
_getTables(driver, database))
3010 tableList.SetStringSelection(table)
3013 self.parentDialog.UpdateDialog(layer = layer)
3015 self.
mapDBInfo = self.parentDialog.mapDBInfo
3017 if len(self.mapDBInfo.layers.keys()) == 0:
3019 self.deleteLayer.Enable(
False)
3020 self.deleteTable.Enable(
False)
3021 for label
in self.modifyLayerWidgets.keys():
3027 """!Layer number of layer to be deleted is changed"""
3029 layer = int(event.GetString())
3032 layer = self.mapDBInfo.layers.keys()[0]
3037 driver = self.mapDBInfo.layers[layer][
'driver']
3038 database = self.mapDBInfo.layers[layer][
'database']
3039 table = self.mapDBInfo.layers[layer][
'table']
3040 listOfColumns = self.
_getColumns(driver, database, table)
3047 self.deleteTable.SetLabel(_(
'Drop also linked attribute table (%s)') % \
3048 self.mapDBInfo.layers[layer][
'table'])
3053 """!Modify layer connection settings"""
3059 self.mapDBInfo.layers[layer][
'driver']
or \
3061 self.mapDBInfo.layers[layer][
'database']
or \
3063 self.mapDBInfo.layers[layer][
'table']
or \
3065 self.mapDBInfo.layers[layer][
'key']:
3074 map = self.mapDBInfo.map,
3080 map = self.mapDBInfo.map,
3088 self.parentDialog.UpdateDialog(layer = layer)
3090 self.
mapDBInfo = self.parentDialog.mapDBInfo
3096 gettext.install(
'grasswxpy', os.path.join(os.getenv(
"GISBASE"),
'locale'), unicode =
True)
3102 print >> sys.stderr, __doc__
3106 wx.InitAllImageHandlers()
3108 app = wx.PySimpleApp()
3110 title =
"%s - <%s>" % (_(
"GRASS GIS Attribute Table Manager"),
3112 size = (900,600), vectorName = argv[1])
3117 if __name__ ==
'__main__':
def OnColumnMenu
Column heading right mouse button -> pop-up menu.
def IsEmpty
Check if list if empty.
def OnExtractSelected
Extract vector objects selected in attribute browse window to new vector map.
def UpdateDialog
Updates dialog layout for given layer.
def LoadData
Load data into list.
def OnItemDeselected
Item deselected.
def OnDataItemDeleteAll
Delete all items from the list.
def Update
Update description.
def OnLayerPageChanged
Layer tab changed.
def ListOfCatsToRange
Convert list of category number to range(s)
def Update
Update column description.
layerPage
{layer: list, widgets...}
def OnLayerRightUp
Layer description area, context menu.
def OnColumnSortAsc
Sort values of selected column (ascending)
def OnCloseWindow
Cancel button pressed.
def unicodeValue
Encode value.
def OnDataDrawSelected
Reload table description.
def OnDataItemAdd
Add new record to the attribute table.
def OnDataItemEdit
Edit selected record of the attribute table.
def __init__
GRASS Attribute Table Manager window.
def createDbInfoDesc
Create database connection information content.
def GetColumnText
Return column text.
def OnColumnSort
Column heading left mouse button -> sorting.
def OnTableChanged
Table name changed, update list of columns.
def GetVectorName
Get vector name.
def GetSortImages
Used by the ColumnSorterMixin, see wx/lib/mixins/listctrl.py.
def _getTables
Get list of tables for given driver and database.
def Update
Update list according new mapDBInfo description.
def OnGetItemText
Get item text.
def _createBrowsePage
Create browse tab page.
def OnTableChangeType
Data type for new column changed.
def ColumnSort
Sort values of selected column (self._col)
def OnDataDrawSelectedZoom
def OnDataItemDelete
Delete selected item(s) from the tlist (layer/category pair)
Various dialogs used in wxGUI.
def split
Platform spefic shlex.split.
def OnTableItemChange
Rename column in the table.
def OnDeleteLayer
Delete layer.
def _createDeletePage
Delete layer.
def OnDeleteSelected
Delete vector objects selected in attribute browse window (attribures and geometry) ...
def GetSelectedItems
Return list of selected items (category numbers)
def OnColumnCompute
Compute values of selected column.
def OnCreateTable
Create new table (name and key column given)
def _createManageLayerPage
Create manage page.
def Populate
Populate the list.
def _createLayerDesc
Create list of linked layers.
def _createManageTablePage
Create manage page (create/link and alter tables)
def OnTableRenameColumnName
Editing column name to be added to the table.
def ApplyCommands
Apply changes.
def OnAddLayer
Add new layer to vector map.
def write
Update status bar.
Manage layers (add, delete, modify)
def ValidateSelectStatement
Validate SQL select statement.
def OnItemSelected
Item selected.
def OnTableAddColumnName
Editing column name to be added to the table.
def GetListCtrl
Returt list.
def OnGetItemAttr
Get item attributes.
def OnDriverChanged
Driver selection changed, update list of tables.
def CreateNewVector
Create new vector map layer.
def OnDataRightUp
Table description area, context menu.
def AddDataRow
Add row to the data list.
def Populate
Populate the list.
def OnDataItemActivated
Item activated, highlight selected item.
def OnDataSelectNone
Deselect items.
def OnModifyLayer
Modify layer connection settings.
def OnSetDefault
Set default values.
def OnDataReload
Reload tlist of records.
Misc utilities for wxGUI.
def OnChangeLayer
Layer number of layer to be deleted is changed.
def _createAddPage
Add new layer.
def LoadData
Load data into list.
def _createTableDesc
Create list with table description.
def _getColumns
Get list of column of given table.
def _createModifyPage
Modify layer.
def AddQueryMapLayer
Redraw a map.
def OnTableItemAdd
Add new column to the table.
def OnTableReload
Reload table description.
def OnBuilder
SQL Builder button pressed -> show the SQLBuilder dialog.
def OnApplySqlStatement
Apply simple/advanced sql statement.
def OnTableItemDeleteAll
Delete all items from the list.
def OnDataSelectAll
Select all items.
def OnDatabaseChanged
Database selection changed, update list of tables.
def _drawSelected
Highlight selected features.
def OnColumnSortDesc
Sort values of selected column (descending)
def OnTableItemDelete
Delete selected item(s) from the list.
def OnChangeSql
Switch simple/advanced sql statement.
def RunCommand
Run GRASS command.
def OnTableRightUp
Table description area, context menu.