ogc_services.py 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  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 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. key, value = line.split(':', 1)
  142. key = key.strip().lower()
  143. value = value.strip()
  144. if key == 'layer':
  145. layers[value] = {}
  146. lastLayer = value
  147. elif key == 'title':
  148. layers[lastLayer][key] = value
  149. elif key == 'style':
  150. if not layers[lastLayer].has_key('style'):
  151. layers[lastLayer]['style'] = {}
  152. layers[lastLayer]['style'][value] = ''
  153. lastStyle = value
  154. elif key == 'style title':
  155. layers[lastLayer]['style'][lastStyle] = value
  156. # update list of layers
  157. self.list.LoadData(layers)
  158. if len(layers.keys()) > 0:
  159. self.btn_import.Enable(True)
  160. else:
  161. self.btn_import.Enable(False)
  162. def OnServer(self, event):
  163. """Server settings changed"""
  164. value = event.GetString()
  165. if value:
  166. self.btn_connect.Enable(True)
  167. else:
  168. self.btn_connect.Enable(False)
  169. def GetLayers(self):
  170. """Get list of selected layers/styles to be imported"""
  171. return self.list.GetSelectedLayers()
  172. def GetSettings(self):
  173. """Get connection settings"""
  174. return { 'server' : self.server.GetValue() }
  175. class LayersList(TreeListCtrl, listmix.ListCtrlAutoWidthMixin):
  176. def __init__(self, parent, pos=wx.DefaultPosition):
  177. """List of layers to be imported (dxf, shp...)"""
  178. self.parent = parent
  179. TreeListCtrl.__init__(self, parent, wx.ID_ANY,
  180. style = wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT |
  181. wx.TR_FULL_ROW_HIGHLIGHT | wx.TR_MULTIPLE)
  182. # setup mixins
  183. listmix.ListCtrlAutoWidthMixin.__init__(self)
  184. self.AddColumn(_('Layer / Style'))
  185. self.AddColumn(_('Title'))
  186. self.SetMainColumn(0) # column with the tree
  187. self.SetColumnWidth(0, 175)
  188. self.root = None
  189. def LoadData(self, data = {}):
  190. """Load data into list"""
  191. # detete first all items
  192. self.DeleteAllItems()
  193. self.root = self.AddRoot(_("Layers"))
  194. layers = data.keys()
  195. if not layers:
  196. return
  197. layers.sort()
  198. for layer in layers:
  199. title = data[layer]['title']
  200. lchild = self.AppendItem(self.root, layer)
  201. self.SetItemText(lchild, title, 1)
  202. if data[layer].has_key('style'):
  203. styles = data[layer]['style'].keys()
  204. if not styles:
  205. continue
  206. styles.sort()
  207. for style in styles:
  208. title = data[layer]['style'][style]
  209. schild = self.AppendItem(lchild, style)
  210. self.SetItemText(schild, title, 1)
  211. self.Expand(self.root)
  212. def GetItemCount(self):
  213. """Required for listmix.ListCtrlAutoWidthMixin"""
  214. return 0
  215. def GetCountPerPage(self):
  216. """Required for listmix.ListCtrlAutoWidthMixin"""
  217. return 0
  218. def GetSelectedLayers(self):
  219. """Get selected layers/styles"""
  220. layers = {}
  221. for item in self.GetSelections():
  222. parent = self.GetItemParent(item)
  223. if parent == self.root: # -> layer
  224. layer = self.GetItemText(item, 0)
  225. layers[layer] = []
  226. sitem, cookie = self.GetFirstChild(item)
  227. while sitem:
  228. layers[layer].append(self.GetItemText(sitem, 0))
  229. sitem, cookie = self.GetNextChild(item, cookie)
  230. else: # -> style
  231. layer = self.GetItemText(parent, 0)
  232. layers[layer] = []
  233. layers[layer].append(self.GetItemText(item, 0))
  234. return layers