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