ogc_services.py 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. """!
  2. @package ogc_services.py
  3. @brief Dialogs for OGC services
  4. Currently only implemeted WMS.
  5. List of classes:
  6. - WMSDialog
  7. - LayersList
  8. (C) 2009 by the GRASS Development Team
  9. This program is free software under the GNU General Public License
  10. (>=v2). Read the file COPYING that comes with GRASS for details.
  11. @author Martin Landa <landa.martin gmail.com>
  12. """
  13. import wx
  14. from wx.gizmos import TreeListCtrl
  15. import wx.lib.mixins.listctrl as listmix
  16. import gcmd
  17. from preferences import globalSettings as UserSettings
  18. class WMSDialog(wx.Dialog):
  19. def __init__(self, parent, service = 'wms',
  20. id=wx.ID_ANY,
  21. style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER):
  22. """!Dialog to import data from WMS server"""
  23. self.parent = parent # GMFrame
  24. self.service = service # currently only WMS is implemented
  25. wx.Dialog.__init__(self, parent, id, style=style)
  26. if self.service == 'wms':
  27. self.SetTitle(_("Import data from WMS server"))
  28. self.panel = wx.Panel(parent = self, id = wx.ID_ANY)
  29. self.__createWidgets()
  30. self.__doLayout()
  31. self.SetMinSize((550, 400))
  32. def __createWidgets(self):
  33. """!Create dialog widgets"""
  34. #
  35. # settings
  36. #
  37. self.settingsBox = wx.StaticBox(parent = self.panel, id = wx.ID_ANY,
  38. label = _(" Server settings "))
  39. self.serverText = wx.StaticText(parent = self.panel, id = wx.ID_ANY, label = _("Server:"))
  40. self.server = wx.TextCtrl(parent = self.panel, id = wx.ID_ANY)
  41. #
  42. # list of layers
  43. #
  44. self.layersBox = wx.StaticBox(parent = self.panel, id = wx.ID_ANY,
  45. label=_(" List of layers "))
  46. self.list = LayersList(self.panel)
  47. self.list.LoadData()
  48. self.add = wx.CheckBox(parent=self.panel, id=wx.ID_ANY,
  49. label=_("Add imported layers into layer tree"))
  50. self.add.SetValue(UserSettings.Get(group='cmd', key='addNewLayer', subkey='enabled'))
  51. #
  52. # buttons
  53. #
  54. # cancel
  55. self.btn_cancel = wx.Button(parent = self.panel, id = wx.ID_CANCEL)
  56. self.btn_cancel.SetToolTipString(_("Close dialog"))
  57. # connect
  58. self.btn_connect = wx.Button(parent = self.panel, id = wx.ID_ANY, label = _("&Connect"))
  59. self.btn_connect.SetToolTipString(_("Connect to the server"))
  60. self.btn_connect.SetDefault()
  61. if not self.server.GetValue():
  62. self.btn_connect.Enable(False)
  63. # import
  64. self.btn_import = wx.Button(parent = self.panel, id = wx.ID_OK, label = _("&Import"))
  65. self.btn_import.SetToolTipString(_("Import selected layers"))
  66. self.btn_import.Enable(False)
  67. #
  68. # bindings
  69. #
  70. self.btn_cancel.Bind(wx.EVT_BUTTON, self.OnCancel)
  71. self.btn_connect.Bind(wx.EVT_BUTTON, self.OnConnect)
  72. self.server.Bind(wx.EVT_TEXT, self.OnServer)
  73. def __doLayout(self):
  74. """!Do dialog layout"""
  75. dialogSizer = wx.BoxSizer(wx.VERTICAL)
  76. #
  77. # settings
  78. #
  79. settingsSizer = wx.StaticBoxSizer(self.settingsBox, wx.HORIZONTAL)
  80. gridSizer = wx.FlexGridSizer(cols=2, vgap=5, hgap=5)
  81. gridSizer.Add(item=self.serverText,
  82. flag=wx.ALIGN_CENTER_VERTICAL)
  83. gridSizer.AddGrowableCol(1)
  84. gridSizer.Add(item=self.server,
  85. flag=wx.EXPAND | wx.ALL)
  86. settingsSizer.Add(item=gridSizer, proportion=1,
  87. flag=wx.EXPAND | wx.ALL)
  88. dialogSizer.Add(item=settingsSizer, proportion=0,
  89. flag=wx.ALL | wx.EXPAND, border=5)
  90. #
  91. # list of layers
  92. #
  93. layersSizer = wx.StaticBoxSizer(self.layersBox, wx.HORIZONTAL)
  94. layersSizer.Add(item=self.list, proportion=1,
  95. flag=wx.ALL | wx.EXPAND, border=5)
  96. dialogSizer.Add(item=layersSizer, proportion=1,
  97. flag=wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border=5)
  98. dialogSizer.Add(item=self.add, proportion=0,
  99. flag=wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border=5)
  100. #
  101. # buttons
  102. #
  103. btnsizer = wx.BoxSizer(orient=wx.HORIZONTAL)
  104. btnsizer.Add(item=self.btn_cancel, proportion=0,
  105. flag=wx.ALL | wx.ALIGN_CENTER,
  106. border=10)
  107. btnsizer.Add(item=self.btn_connect, proportion=0,
  108. flag=wx.ALL | wx.ALIGN_CENTER,
  109. border=10)
  110. btnsizer.Add(item=self.btn_import, proportion=0,
  111. flag=wx.ALL | wx.ALIGN_CENTER,
  112. border=10)
  113. dialogSizer.Add(item=btnsizer, proportion=0,
  114. flag=wx.ALIGN_CENTER)
  115. self.panel.SetAutoLayout(True)
  116. self.panel.SetSizer(dialogSizer)
  117. dialogSizer.Fit(self.panel)
  118. self.Layout()
  119. def OnCancel(self, event):
  120. """!Button 'Cancel' pressed -> close the dialog"""
  121. self.Close()
  122. def OnConnect(self, event):
  123. """!Button 'Connect' pressed"""
  124. server = self.server.GetValue()
  125. if not server:
  126. self.btn_import.Enable(False)
  127. return # not reachable
  128. layers = {}
  129. ret = gcmd.RunCommand('r.in.wms',
  130. quiet = True,
  131. parent = self,
  132. read = True,
  133. flags = 'l',
  134. mapserver = server)
  135. if not ret:
  136. self.list.LoadData()
  137. self.btn_import.Enable(False)
  138. return # no layers found
  139. lastLayer = lastStyle = ''
  140. for line in ret.splitlines():
  141. try:
  142. key, value = line.split(':', 1)
  143. except ValueError:
  144. continue
  145. key = key.strip().lower()
  146. value = value.strip()
  147. if key == 'layer':
  148. layers[value] = {}
  149. lastLayer = value
  150. elif key == 'title':
  151. layers[lastLayer][key] = value
  152. elif key == 'style':
  153. if 'style' not in layers[lastLayer]:
  154. layers[lastLayer]['style'] = {}
  155. layers[lastLayer]['style'][value] = ''
  156. lastStyle = value
  157. elif key == 'style title':
  158. layers[lastLayer]['style'][lastStyle] = value
  159. # update list of layers
  160. self.list.LoadData(layers)
  161. if len(layers.keys()) > 0:
  162. self.btn_import.Enable(True)
  163. else:
  164. self.btn_import.Enable(False)
  165. def OnServer(self, event):
  166. """!Server settings changed"""
  167. value = event.GetString()
  168. if value:
  169. self.btn_connect.Enable(True)
  170. else:
  171. self.btn_connect.Enable(False)
  172. def GetLayers(self):
  173. """!Get list of selected layers/styles to be imported"""
  174. return self.list.GetSelectedLayers()
  175. def GetSettings(self):
  176. """!Get connection settings"""
  177. return { 'server' : self.server.GetValue() }
  178. class LayersList(TreeListCtrl, listmix.ListCtrlAutoWidthMixin):
  179. def __init__(self, parent, pos=wx.DefaultPosition):
  180. """!List of layers to be imported (dxf, shp...)"""
  181. self.parent = parent
  182. TreeListCtrl.__init__(self, parent, wx.ID_ANY,
  183. style = wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT |
  184. wx.TR_FULL_ROW_HIGHLIGHT | wx.TR_MULTIPLE)
  185. # setup mixins
  186. listmix.ListCtrlAutoWidthMixin.__init__(self)
  187. self.AddColumn(_('Layer / Style'))
  188. self.AddColumn(_('Title'))
  189. self.SetMainColumn(0) # column with the tree
  190. self.SetColumnWidth(0, 175)
  191. self.root = None
  192. def LoadData(self, data = {}):
  193. """!Load data into list"""
  194. # detete first all items
  195. self.DeleteAllItems()
  196. self.root = self.AddRoot(_("Layers"))
  197. layers = data.keys()
  198. if not layers:
  199. return
  200. layers.sort()
  201. for layer in layers:
  202. title = data[layer]['title']
  203. lchild = self.AppendItem(self.root, layer)
  204. self.SetItemText(lchild, title, 1)
  205. if 'style' in data[layer]:
  206. styles = data[layer]['style'].keys()
  207. if not styles:
  208. continue
  209. styles.sort()
  210. for style in styles:
  211. title = data[layer]['style'][style]
  212. schild = self.AppendItem(lchild, style)
  213. self.SetItemText(schild, title, 1)
  214. self.Expand(self.root)
  215. def GetItemCount(self):
  216. """!Required for listmix.ListCtrlAutoWidthMixin"""
  217. return 0
  218. def GetCountPerPage(self):
  219. """!Required for listmix.ListCtrlAutoWidthMixin"""
  220. return 0
  221. def GetSelectedLayers(self):
  222. """!Get selected layers/styles"""
  223. layers = dict()
  224. for item in self.GetSelections():
  225. parent = self.GetItemParent(item)
  226. if parent == self.root: # -> layer
  227. layer = self.GetItemText(item, 0)
  228. layers[layer] = list()
  229. sitem, cookie = self.GetFirstChild(item)
  230. while sitem:
  231. layers[layer].append(self.GetItemText(sitem, 0))
  232. sitem, cookie = self.GetNextChild(item, cookie)
  233. else: # -> style
  234. layer = self.GetItemText(parent, 0)
  235. layers[layer] = list()
  236. layers[layer].append(self.GetItemText(item, 0))
  237. return layers