vinfo.py 6.6 KB

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