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