vinfo.py 6.0 KB

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