ogc_services.py 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. """
  2. @package ogc_services.py
  3. @brief Dialogs for OGC services
  4. Currently is implemeted only 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 grass
  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. value = 'http://wms.jpl.nasa.gov/wms.cgi')
  42. #
  43. # list of layers
  44. #
  45. self.layersBox = wx.StaticBox(parent = self.panel, id = wx.ID_ANY,
  46. label=_(" List of layers "))
  47. self.list = LayersList(self.panel)
  48. self.list.LoadData()
  49. self.add = wx.CheckBox(parent=self.panel, id=wx.ID_ANY,
  50. label=_("Add imported layers into layer tree"))
  51. self.add.SetValue(UserSettings.Get(group='cmd', key='addNewLayer', subkey='enabled'))
  52. #
  53. # buttons
  54. #
  55. # cancel
  56. self.btn_cancel = wx.Button(parent = self.panel, id = wx.ID_CANCEL)
  57. self.btn_cancel.SetToolTipString(_("Close dialog"))
  58. # connect
  59. self.btn_connect = wx.Button(parent = self.panel, id = wx.ID_ANY, label = _("&Connect"))
  60. self.btn_connect.SetToolTipString(_("Connect to the server"))
  61. self.btn_connect.SetDefault()
  62. if not self.server.GetValue():
  63. self.btn_connect.Enable(False)
  64. # import
  65. self.btn_import = wx.Button(parent = self.panel, id = wx.ID_OK, label = _("&Import"))
  66. self.btn_import.SetToolTipString(_("Import selected layers"))
  67. self.btn_import.Enable(False)
  68. #
  69. # bindings
  70. #
  71. self.btn_cancel.Bind(wx.EVT_BUTTON, self.OnCancel)
  72. self.btn_connect.Bind(wx.EVT_BUTTON, self.OnConnect)
  73. self.server.Bind(wx.EVT_TEXT, self.OnServer)
  74. def __doLayout(self):
  75. """Do dialog layout"""
  76. dialogSizer = wx.BoxSizer(wx.VERTICAL)
  77. #
  78. # settings
  79. #
  80. settingsSizer = wx.StaticBoxSizer(self.settingsBox, wx.HORIZONTAL)
  81. gridSizer = wx.FlexGridSizer(cols=2, vgap=5, hgap=5)
  82. gridSizer.Add(item=self.serverText,
  83. flag=wx.ALIGN_CENTER_VERTICAL)
  84. gridSizer.AddGrowableCol(1)
  85. gridSizer.Add(item=self.server,
  86. flag=wx.EXPAND | wx.ALL)
  87. settingsSizer.Add(item=gridSizer, proportion=1,
  88. flag=wx.EXPAND | wx.ALL)
  89. dialogSizer.Add(item=settingsSizer, proportion=0,
  90. flag=wx.ALL | wx.EXPAND, border=5)
  91. #
  92. # list of layers
  93. #
  94. layersSizer = wx.StaticBoxSizer(self.layersBox, wx.HORIZONTAL)
  95. layersSizer.Add(item=self.list, proportion=1,
  96. flag=wx.ALL | wx.EXPAND, border=5)
  97. dialogSizer.Add(item=layersSizer, proportion=1,
  98. flag=wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border=5)
  99. dialogSizer.Add(item=self.add, proportion=0,
  100. flag=wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border=5)
  101. #
  102. # buttons
  103. #
  104. btnsizer = wx.BoxSizer(orient=wx.HORIZONTAL)
  105. btnsizer.Add(item=self.btn_cancel, proportion=0,
  106. flag=wx.ALL | wx.ALIGN_CENTER,
  107. border=10)
  108. btnsizer.Add(item=self.btn_connect, proportion=0,
  109. flag=wx.ALL | wx.ALIGN_CENTER,
  110. border=10)
  111. btnsizer.Add(item=self.btn_import, proportion=0,
  112. flag=wx.ALL | wx.ALIGN_CENTER,
  113. border=10)
  114. dialogSizer.Add(item=btnsizer, proportion=0,
  115. flag=wx.ALIGN_CENTER)
  116. self.panel.SetAutoLayout(True)
  117. self.panel.SetSizer(dialogSizer)
  118. dialogSizer.Fit(self.panel)
  119. self.Layout()
  120. def OnCancel(self, event):
  121. """Button 'Cancel' pressed -> close the dialog"""
  122. self.Close()
  123. def OnConnect(self, event):
  124. """Button 'Connect' pressed"""
  125. server = self.server.GetValue()
  126. if not server:
  127. self.btn_import.Enable(False)
  128. return # not reachable
  129. layers = {}
  130. ret = grass.read_command('r.in.wms',
  131. quiet = True,
  132. flags = 'l',
  133. mapserver = server)
  134. if not ret:
  135. self.btn_import.Enable(False)
  136. return layers # no layers found
  137. lastLayer = lastStyle = ''
  138. for line in ret.splitlines():
  139. key, value = line.split(':', 1)
  140. key = key.strip().lower()
  141. value = value.strip()
  142. if key == 'layer':
  143. layers[value] = {}
  144. lastLayer = value
  145. elif key == 'title':
  146. layers[lastLayer][key] = value
  147. elif key == 'style':
  148. if not layers[lastLayer].has_key('style'):
  149. layers[lastLayer]['style'] = {}
  150. layers[lastLayer]['style'][value] = ''
  151. lastStyle = value
  152. elif key == 'style title':
  153. layers[lastLayer]['style'][lastStyle] = value
  154. # update list of layers
  155. self.list.LoadData(layers)
  156. if len(layers.keys()) > 0:
  157. self.btn_import.Enable(True)
  158. else:
  159. self.btn_import.Enable(False)
  160. def OnServer(self, event):
  161. """Server settings changed"""
  162. value = event.GetString()
  163. if value:
  164. self.btn_connect.Enable(True)
  165. else:
  166. self.btn_connect.Enable(False)
  167. def GetLayers(self):
  168. """Get list of selected layers/styles to be imported"""
  169. return self.list.GetSelectedLayers()
  170. def GetSettings(self):
  171. """Get connection settings"""
  172. return { 'server' : self.server.GetValue() }
  173. class LayersList(TreeListCtrl, listmix.ListCtrlAutoWidthMixin):
  174. def __init__(self, parent, pos=wx.DefaultPosition):
  175. """List of layers to be imported (dxf, shp...)"""
  176. self.parent = parent
  177. TreeListCtrl.__init__(self, parent, wx.ID_ANY,
  178. style = wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT |
  179. wx.TR_FULL_ROW_HIGHLIGHT | wx.TR_MULTIPLE)
  180. # setup mixins
  181. listmix.ListCtrlAutoWidthMixin.__init__(self)
  182. self.AddColumn(_('Layer / Style'))
  183. self.AddColumn(_('Title'))
  184. self.SetMainColumn(0) # column with the tree
  185. self.SetColumnWidth(0, 175)
  186. self.root = None
  187. def LoadData(self, data = {}):
  188. """Load data into list"""
  189. # detete first all items
  190. self.DeleteAllItems()
  191. self.root = self.AddRoot(_("Layers"))
  192. layers = data.keys()
  193. if not layers:
  194. return
  195. layers.sort()
  196. for layer in layers:
  197. title = data[layer]['title']
  198. lchild = self.AppendItem(self.root, layer)
  199. self.SetItemText(lchild, title, 1)
  200. if data[layer].has_key('style'):
  201. styles = data[layer]['style'].keys()
  202. if not styles:
  203. continue
  204. styles.sort()
  205. for style in styles:
  206. title = data[layer]['style'][style]
  207. schild = self.AppendItem(lchild, style)
  208. self.SetItemText(schild, title, 1)
  209. self.Expand(self.root)
  210. def GetItemCount(self):
  211. """Required for listmix.ListCtrlAutoWidthMixin"""
  212. return 0
  213. def GetCountPerPage(self):
  214. """Required for listmix.ListCtrlAutoWidthMixin"""
  215. return 0
  216. def GetSelectedLayers(self):
  217. """Get selected layers/styles"""
  218. layers = {}
  219. for item in self.GetSelections():
  220. parent = self.GetItemParent(item)
  221. if parent == self.root: # -> layer
  222. layer = self.GetItemText(item, 0)
  223. layers[layer] = []
  224. sitem, cookie = self.GetFirstChild(item)
  225. while sitem:
  226. layers[layer].append(self.GetItemText(sitem, 0))
  227. sitem, cookie = self.GetNextChild(item, cookie)
  228. else: # -> style
  229. layer = self.GetItemText(parent, 0)
  230. layers[layer] = []
  231. layers[layer].append(self.GetItemText(item, 0))
  232. return layers