vinfo.py 6.3 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, label="Driver:"))
  58. infoFlexSizer.Add(
  59. StaticText(parent=panel, id=wx.ID_ANY, label=mapDBInfo.layers[layer]["driver"])
  60. )
  61. infoFlexSizer.Add(StaticText(parent=panel, id=wx.ID_ANY, label="Database:"))
  62. infoFlexSizer.Add(
  63. StaticText(
  64. parent=panel, id=wx.ID_ANY, label=mapDBInfo.layers[layer]["database"]
  65. )
  66. )
  67. infoFlexSizer.Add(StaticText(parent=panel, id=wx.ID_ANY, label="Table:"))
  68. infoFlexSizer.Add(
  69. StaticText(parent=panel, id=wx.ID_ANY, label=mapDBInfo.layers[layer]["table"])
  70. )
  71. infoFlexSizer.Add(StaticText(parent=panel, id=wx.ID_ANY, label="Key:"))
  72. infoFlexSizer.Add(
  73. StaticText(parent=panel, id=wx.ID_ANY, label=mapDBInfo.layers[layer]["key"])
  74. )
  75. return infoFlexSizer
  76. class VectorDBInfo(VectorDBInfoBase):
  77. """Class providing information about attribute tables
  78. linked to the vector map"""
  79. def __init__(self, map):
  80. VectorDBInfoBase.__init__(self, map)
  81. def GetColumns(self, table):
  82. """Return list of columns names (based on their index)"""
  83. try:
  84. names = [""] * len(self.tables[table].keys())
  85. except KeyError:
  86. return []
  87. for name, desc in six.iteritems(self.tables[table]):
  88. names[desc["index"]] = name
  89. return names
  90. def SelectByPoint(self, queryCoords, qdist):
  91. """Get attributes by coordinates (all available layers)
  92. Return line id or None if no line is found"""
  93. line = None
  94. nselected = 0
  95. try:
  96. data = grass.vector_what(
  97. map=self.map,
  98. coord=(float(queryCoords[0]), float(queryCoords[1])),
  99. distance=float(qdist),
  100. )
  101. except grass.ScriptError:
  102. GError(
  103. parent=None,
  104. message=_(
  105. "Failed to query vector map <{map}>. "
  106. "Check database settings and topology."
  107. ).format(map=self.map),
  108. )
  109. if len(data) < 1 or all(("Table" not in record) for record in data):
  110. return None
  111. # process attributes
  112. ret = dict()
  113. for key in ["Category", "Layer", "Table", "Id"]:
  114. ret[key] = list()
  115. for record in data:
  116. if "Table" not in record:
  117. continue
  118. table = record["Table"]
  119. for key, value in six.iteritems(record["Attributes"]):
  120. if len(value) < 1:
  121. value = None
  122. else:
  123. if self.tables[table][key]["ctype"] != str:
  124. value = self.tables[table][key]["ctype"](value)
  125. else:
  126. value = GetUnicodeValue(value)
  127. self.tables[table][key]["values"].append(value)
  128. for key, value in six.iteritems(record):
  129. if key == "Attributes":
  130. continue
  131. if key in ret:
  132. ret[key].append(value)
  133. if "Id" not in record.keys():
  134. ret["Id"].append(None)
  135. return ret
  136. def SelectFromTable(self, layer, cols="*", where=None):
  137. """Select records from the table
  138. Return number of selected records, -1 on error
  139. """
  140. if layer <= 0:
  141. return -1
  142. nselected = 0
  143. table = self.layers[layer]["table"] # get table desc
  144. # select values (only one record)
  145. if where is None or where == "":
  146. sql = "SELECT %s FROM %s" % (cols, table)
  147. else:
  148. sql = "SELECT %s FROM %s WHERE %s" % (cols, table, where)
  149. ret = RunCommand(
  150. "db.select",
  151. read=True,
  152. quiet=True,
  153. flags="v",
  154. sql=sql,
  155. database=self.layers[layer]["database"],
  156. driver=self.layers[layer]["driver"],
  157. )
  158. # self.tables[table][key][1] = str(cat)
  159. if ret:
  160. for line in ret.splitlines():
  161. name, value = line.split("|")
  162. # casting ...
  163. if value:
  164. if not isinstance("", self.tables[table][name]["ctype"]):
  165. value = self.tables[table][name]["ctype"](value)
  166. else:
  167. value = GetUnicodeValue(value)
  168. else:
  169. value = None
  170. self.tables[table][name]["values"].append(value)
  171. nselected = 1
  172. return nselected