GRASS Programmer's Manual  6.4.2(2012)
ogc_services.py
Go to the documentation of this file.
00001 """!
00002 @package ogc_services.py
00003 
00004 @brief Dialogs for OGC services
00005 
00006 Currently only implemeted WMS.
00007 
00008 List of classes:
00009  - WMSDialog
00010  - LayersList
00011 
00012 (C) 2009 by the GRASS Development Team
00013 
00014 This program is free software under the GNU General Public License
00015 (>=v2). Read the file COPYING that comes with GRASS for details.
00016 
00017 @author Martin Landa <landa.martin gmail.com>
00018 """
00019 
00020 import wx
00021 from wx.gizmos import TreeListCtrl
00022 import wx.lib.mixins.listctrl as listmix
00023 
00024 import gcmd
00025 
00026 from preferences import globalSettings as UserSettings
00027 
00028 class WMSDialog(wx.Dialog):
00029     def __init__(self, parent, service = 'wms',
00030                  id=wx.ID_ANY,
00031                  style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER):
00032         """!Dialog to import data from WMS server"""
00033         self.parent  = parent  # GMFrame 
00034         self.service = service # currently only WMS is implemented
00035         
00036         wx.Dialog.__init__(self, parent, id, style=style)
00037         if self.service == 'wms':
00038             self.SetTitle(_("Import data from WMS server"))
00039             
00040         self.panel = wx.Panel(parent = self, id = wx.ID_ANY)
00041         
00042         self.__createWidgets()
00043         
00044         self.__doLayout()
00045 
00046         self.SetMinSize((550, 400))
00047         
00048     def __createWidgets(self):
00049         """!Create dialog widgets"""
00050         #
00051         # settings
00052         #
00053         self.settingsBox = wx.StaticBox(parent = self.panel, id = wx.ID_ANY,
00054                                         label = _(" Server settings "))
00055 
00056         self.serverText = wx.StaticText(parent = self.panel, id = wx.ID_ANY, label = _("Server:"))
00057         self.server  = wx.TextCtrl(parent = self.panel, id = wx.ID_ANY)
00058         
00059         #
00060         # list of layers
00061         #
00062         self.layersBox = wx.StaticBox(parent = self.panel, id = wx.ID_ANY,
00063                                 label=_(" List of layers "))
00064 
00065         self.list = LayersList(self.panel)
00066         self.list.LoadData()
00067 
00068         self.add = wx.CheckBox(parent=self.panel, id=wx.ID_ANY,
00069                                label=_("Add imported layers into layer tree"))
00070         self.add.SetValue(UserSettings.Get(group='cmd', key='addNewLayer', subkey='enabled'))
00071                 
00072         #
00073         # buttons
00074         #
00075         # cancel
00076         self.btn_cancel = wx.Button(parent = self.panel, id = wx.ID_CANCEL)
00077         self.btn_cancel.SetToolTipString(_("Close dialog"))
00078         # connect
00079         self.btn_connect = wx.Button(parent = self.panel, id = wx.ID_ANY, label = _("&Connect"))
00080         self.btn_connect.SetToolTipString(_("Connect to the server"))
00081         self.btn_connect.SetDefault()
00082         if not self.server.GetValue():
00083             self.btn_connect.Enable(False)
00084         # import
00085         self.btn_import = wx.Button(parent = self.panel, id = wx.ID_OK, label = _("&Import"))
00086         self.btn_import.SetToolTipString(_("Import selected layers"))
00087         self.btn_import.Enable(False)
00088         
00089         #
00090         # bindings
00091         #
00092         self.btn_cancel.Bind(wx.EVT_BUTTON, self.OnCancel)
00093         self.btn_connect.Bind(wx.EVT_BUTTON, self.OnConnect)
00094         self.server.Bind(wx.EVT_TEXT, self.OnServer)
00095         
00096     def __doLayout(self):
00097         """!Do dialog layout"""
00098         dialogSizer = wx.BoxSizer(wx.VERTICAL)
00099         
00100         #
00101         # settings
00102         #
00103         settingsSizer = wx.StaticBoxSizer(self.settingsBox, wx.HORIZONTAL)
00104         
00105         gridSizer = wx.FlexGridSizer(cols=2, vgap=5, hgap=5)
00106 
00107         gridSizer.Add(item=self.serverText,
00108                       flag=wx.ALIGN_CENTER_VERTICAL)
00109         gridSizer.AddGrowableCol(1)
00110         gridSizer.Add(item=self.server,
00111                       flag=wx.EXPAND | wx.ALL)
00112         
00113         settingsSizer.Add(item=gridSizer, proportion=1,
00114                        flag=wx.EXPAND | wx.ALL)
00115         
00116         dialogSizer.Add(item=settingsSizer, proportion=0,
00117                         flag=wx.ALL | wx.EXPAND, border=5)
00118         
00119         #
00120         # list of layers
00121         #
00122         layersSizer = wx.StaticBoxSizer(self.layersBox, wx.HORIZONTAL)
00123 
00124         layersSizer.Add(item=self.list, proportion=1,
00125                         flag=wx.ALL | wx.EXPAND, border=5)
00126         
00127         dialogSizer.Add(item=layersSizer, proportion=1,
00128                         flag=wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border=5)
00129 
00130         dialogSizer.Add(item=self.add, proportion=0,
00131                         flag=wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border=5)
00132         
00133         #
00134         # buttons
00135         #
00136         btnsizer = wx.BoxSizer(orient=wx.HORIZONTAL)
00137 
00138         btnsizer.Add(item=self.btn_cancel, proportion=0,
00139                      flag=wx.ALL | wx.ALIGN_CENTER,
00140                      border=10)
00141         
00142         btnsizer.Add(item=self.btn_connect, proportion=0,
00143                      flag=wx.ALL | wx.ALIGN_CENTER,
00144                      border=10)
00145         
00146         btnsizer.Add(item=self.btn_import, proportion=0,
00147                      flag=wx.ALL | wx.ALIGN_CENTER,
00148                      border=10)
00149         
00150         dialogSizer.Add(item=btnsizer, proportion=0,
00151                         flag=wx.ALIGN_CENTER)
00152         
00153         self.panel.SetAutoLayout(True)
00154         self.panel.SetSizer(dialogSizer)
00155         dialogSizer.Fit(self.panel)
00156         self.Layout()
00157 
00158     def OnCancel(self, event):
00159         """!Button 'Cancel' pressed -> close the dialog"""
00160         self.Close()
00161 
00162     def OnConnect(self, event):
00163         """!Button 'Connect' pressed"""
00164         server = self.server.GetValue()
00165         if not server:
00166             self.btn_import.Enable(False)
00167             return # not reachable
00168 
00169         layers = {}
00170         ret = gcmd.RunCommand('r.in.wms',
00171                               quiet = True,
00172                               parent = self,
00173                               read = True,
00174                               flags = 'l',
00175                               mapserver = server)
00176         
00177         if not ret:
00178             self.list.LoadData()
00179             self.btn_import.Enable(False)
00180             return # no layers found
00181         
00182         lastLayer = lastStyle = ''
00183         for line in ret.splitlines():
00184             try:
00185                 key, value = line.split(':', 1)
00186             except ValueError:
00187                 continue
00188             key = key.strip().lower()
00189             value = value.strip()
00190             
00191             if key == 'layer':
00192                 layers[value] = {}
00193                 lastLayer = value
00194             elif key == 'title':
00195                 layers[lastLayer][key] = value
00196             elif key == 'style':
00197                 if 'style' not in layers[lastLayer]:
00198                     layers[lastLayer]['style'] = {}
00199                 layers[lastLayer]['style'][value] = ''
00200                 lastStyle = value
00201             elif key == 'style title':
00202                 layers[lastLayer]['style'][lastStyle] = value
00203         
00204         # update list of layers
00205         self.list.LoadData(layers)
00206         
00207         if len(layers.keys()) > 0:
00208             self.btn_import.Enable(True)
00209         else:
00210             self.btn_import.Enable(False)
00211         
00212     def OnServer(self, event):
00213         """!Server settings changed"""
00214         value = event.GetString()
00215         if value:
00216             self.btn_connect.Enable(True)
00217         else:
00218             self.btn_connect.Enable(False)
00219         
00220     def GetLayers(self):
00221         """!Get list of selected layers/styles to be imported"""
00222         return self.list.GetSelectedLayers()
00223 
00224     def GetSettings(self):
00225         """!Get connection settings"""
00226         return { 'server' : self.server.GetValue() }
00227     
00228 class LayersList(TreeListCtrl, listmix.ListCtrlAutoWidthMixin):
00229     def __init__(self, parent, pos=wx.DefaultPosition):
00230         """!List of layers to be imported (dxf, shp...)"""
00231         self.parent = parent
00232         
00233         TreeListCtrl.__init__(self, parent, wx.ID_ANY,
00234                               style = wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT |
00235                               wx.TR_FULL_ROW_HIGHLIGHT | wx.TR_MULTIPLE)
00236         
00237         # setup mixins
00238         listmix.ListCtrlAutoWidthMixin.__init__(self)
00239         
00240         self.AddColumn(_('Layer / Style'))
00241         self.AddColumn(_('Title'))
00242         self.SetMainColumn(0) # column with the tree
00243         self.SetColumnWidth(0, 175)
00244         
00245         self.root = None
00246         
00247     def LoadData(self, data = {}):
00248         """!Load data into list"""
00249         # detete first all items
00250         self.DeleteAllItems()
00251         self.root = self.AddRoot(_("Layers"))
00252 
00253         layers = data.keys()
00254         if not layers:
00255             return
00256         
00257         layers.sort()
00258 
00259         for layer in layers:
00260             title = data[layer]['title']
00261             lchild = self.AppendItem(self.root, layer)
00262             self.SetItemText(lchild, title, 1)
00263             if 'style' in data[layer]:
00264                 styles = data[layer]['style'].keys()
00265                 if not styles:
00266                     continue
00267                 styles.sort()
00268                 for style in styles:
00269                     title = data[layer]['style'][style]
00270                     schild = self.AppendItem(lchild, style)
00271                     self.SetItemText(schild, title, 1)
00272         
00273         self.Expand(self.root)
00274         
00275     def GetItemCount(self):
00276         """!Required for listmix.ListCtrlAutoWidthMixin"""
00277         return 0
00278 
00279     def GetCountPerPage(self):
00280         """!Required for listmix.ListCtrlAutoWidthMixin"""
00281         return 0
00282 
00283     def GetSelectedLayers(self):
00284         """!Get selected layers/styles"""
00285         layers = dict()
00286 
00287         for item in self.GetSelections():
00288             parent = self.GetItemParent(item)
00289             if parent == self.root: # -> layer
00290                 layer = self.GetItemText(item, 0)
00291                 layers[layer] = list()
00292                 sitem, cookie = self.GetFirstChild(item)
00293                 while sitem:
00294                     layers[layer].append(self.GetItemText(sitem, 0))
00295                     sitem, cookie = self.GetNextChild(item, cookie)
00296             else: # -> style
00297                 layer = self.GetItemText(parent, 0)
00298                 layers[layer] = list()
00299                 layers[layer].append(self.GetItemText(item, 0))
00300         
00301         return layers
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines