vinfo.py 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. """
  2. @package dbmgr.vinfo
  3. @brief Support classes for Database Manager
  4. List of classes:
  5. - vinfo::VectorDBInfo
  6. (C) 2007-2013 by the GRASS Development Team
  7. This program is free software under the GNU General Public License
  8. (>=v2). Read the file COPYING that comes with GRASS for details.
  9. @author Martin Landa <landa.martin gmail.com>
  10. """
  11. import os
  12. import types
  13. import wx
  14. from gui_core.gselect import VectorDBInfo as VectorDBInfoBase
  15. from core.gcmd import RunCommand, GError
  16. from core.settings import UserSettings
  17. from core.utils import _
  18. import grass.script as grass
  19. def GetUnicodeValue(value):
  20. """Get unicode value
  21. :param value: value to be recoded
  22. :return: unicode value
  23. """
  24. if isinstance(value, types.UnicodeType):
  25. return value
  26. enc = UserSettings.Get(group='atm', key='encoding', subkey='value')
  27. if not enc and 'GRASS_DB_ENCODING' in os.environ:
  28. enc = os.environ['GRASS_DB_ENCODING']
  29. else:
  30. enc = 'utf-8' # assuming UTF-8
  31. return unicode(str(value), enc, errors='replace')
  32. def CreateDbInfoDesc(panel, mapDBInfo, layer):
  33. """Create database connection information content"""
  34. infoFlexSizer = wx.FlexGridSizer(cols=2, hgap=1, vgap=1)
  35. infoFlexSizer.AddGrowableCol(1)
  36. infoFlexSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  37. label="Driver:"))
  38. infoFlexSizer.Add(
  39. item=wx.StaticText(
  40. parent=panel,
  41. id=wx.ID_ANY,
  42. label=mapDBInfo.layers[layer]['driver']))
  43. infoFlexSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  44. label="Database:"))
  45. infoFlexSizer.Add(
  46. item=wx.StaticText(
  47. parent=panel,
  48. id=wx.ID_ANY,
  49. label=mapDBInfo.layers[layer]['database']))
  50. infoFlexSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  51. label="Table:"))
  52. infoFlexSizer.Add(
  53. item=wx.StaticText(
  54. parent=panel,
  55. id=wx.ID_ANY,
  56. label=mapDBInfo.layers[layer]['table']))
  57. infoFlexSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  58. label="Key:"))
  59. infoFlexSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  60. label=mapDBInfo.layers[layer]['key']))
  61. return infoFlexSizer
  62. class VectorDBInfo(VectorDBInfoBase):
  63. """Class providing information about attribute tables
  64. linked to the vector map"""
  65. def __init__(self, map):
  66. VectorDBInfoBase.__init__(self, map)
  67. def GetColumns(self, table):
  68. """Return list of columns names (based on their index)"""
  69. try:
  70. names = [''] * len(self.tables[table].keys())
  71. except KeyError:
  72. return []
  73. for name, desc in self.tables[table].iteritems():
  74. names[desc['index']] = name
  75. return names
  76. def SelectByPoint(self, queryCoords, qdist):
  77. """Get attributes by coordinates (all available layers)
  78. Return line id or None if no line is found"""
  79. line = None
  80. nselected = 0
  81. try:
  82. data = grass.vector_what(
  83. map=self.map, coord=(
  84. float(
  85. queryCoords[0]), float(
  86. queryCoords[1])), distance=float(qdist))
  87. except grass.ScriptError:
  88. GError(
  89. parent=None, message=_(
  90. "Failed to query vector map <{map}>. "
  91. "Check database settings and topology.").format(
  92. map=self.map))
  93. if len(data) < 1 or all(('Table' not in record) for record in data):
  94. return None
  95. # process attributes
  96. ret = dict()
  97. for key in ['Category', 'Layer', 'Table', 'Id']:
  98. ret[key] = list()
  99. for record in data:
  100. if not 'Table' in record:
  101. continue
  102. table = record['Table']
  103. for key, value in record['Attributes'].iteritems():
  104. if len(value) < 1:
  105. value = None
  106. else:
  107. if self.tables[table][key]['ctype'] != types.StringType:
  108. value = self.tables[table][key]['ctype'](value)
  109. else:
  110. value = GetUnicodeValue(value)
  111. self.tables[table][key]['values'].append(value)
  112. for key, value in record.iteritems():
  113. if key == 'Attributes':
  114. continue
  115. if key in ret:
  116. ret[key].append(value)
  117. if 'Id' not in record.keys():
  118. ret['Id'].append(None)
  119. return ret
  120. def SelectFromTable(self, layer, cols='*', where=None):
  121. """Select records from the table
  122. Return number of selected records, -1 on error
  123. """
  124. if layer <= 0:
  125. return -1
  126. nselected = 0
  127. table = self.layers[layer]["table"] # get table desc
  128. # select values (only one record)
  129. if where is None or where is '':
  130. sql = "SELECT %s FROM %s" % (cols, table)
  131. else:
  132. sql = "SELECT %s FROM %s WHERE %s" % (cols, table, where)
  133. ret = RunCommand('db.select',
  134. read=True,
  135. quiet=True,
  136. flags='v',
  137. sql=sql,
  138. database=self.layers[layer]["database"],
  139. driver=self.layers[layer]["driver"])
  140. # self.tables[table][key][1] = str(cat)
  141. if ret:
  142. for line in ret.splitlines():
  143. name, value = line.split('|')
  144. # casting ...
  145. if value:
  146. if not isinstance('', self.tables[table][name]['ctype']):
  147. value = self.tables[table][name]['ctype'](value)
  148. else:
  149. value = GetUnicodeValue(value)
  150. else:
  151. value = None
  152. self.tables[table][name]['values'].append(value)
  153. nselected = 1
  154. return nselected