1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111 |
- """
- @package web_services.widgets
- @brief Widgets for web services (WMS, WMTS, NasaOnEarh)
- List of classes:
- - widgets::WSPanel
- - widgets::LayersList
- (C) 2012-2013 by the GRASS Development Team
- This program is free software under the GNU General Public License
- (>=v2). Read the file COPYING that comes with GRASS for details.
- @author Martin Landa <landa.martin gmail.com>
- @author Stepan Turek <stepan.turek seznam.cz>
- """
- import os
- import sys
- import shutil
- from copy import deepcopy
- try:
- from xml.etree.ElementTree import ParseError
- except ImportError: # < Python 2.7
- from xml.parsers.expat import ExpatError as ParseError
- import wx
- import wx.lib.flatnotebook as FN
- import wx.lib.colourselect as csel
- import wx.lib.mixins.listctrl as listmix
- from wx.lib.newevent import NewEvent
- from wx.gizmos import TreeListCtrl
- from core import globalvar
- from core.debug import Debug
- from core.gcmd import GWarning, GMessage
- from core.gconsole import CmdThread, GStderr, EVT_CMD_DONE, EVT_CMD_OUTPUT
- from core.utils import _
- from web_services.cap_interface import WMSCapabilities, WMTSCapabilities, OnEarthCapabilities
- from gui_core.widgets import GNotebook
- from gui_core.widgets import ManageSettingsWidget
- import grass.script as grass
- rinwms_path = os.path.join(os.getenv("GISBASE"), "etc", "r.in.wms")
- if rinwms_path not in sys.path:
- sys.path.append(rinwms_path)
- from wms_base import WMSDriversInfo
- from srs import Srs
- from grass.pydispatch.signal import Signal
- class WSPanel(wx.Panel):
- def __init__(self, parent, web_service, **kwargs):
- """Show data from capabilities file.
- Signal: capParsed - this signal is emitted when capabilities file is downloaded
- (after ConnectToServer method was called)
- :param parent: parent widget
- :param web_service: web service to be panel generated for
- """
- wx.Panel.__init__(self, parent = parent, id = wx.ID_ANY)
- self.parent = parent
- self.ws = web_service
- self.capParsed = Signal('WSPanel.capParsed')
- # stores widgets, which represents parameters/flags of d.wms
- self.params = {}
- self.flags = {}
- self.o_layer_name = ''
- # stores err output from r.in.wms during getting capabilities
- self.cmd_err_str = ''
- # stores selected layer from layer list
- self.sel_layers = []
- # downloaded and parsed data from server successfully?
- self.is_connected = False
- # common part of command for r.in.wms -c and d.wms
- self.ws_cmdl = None
- # provides information about driver parameters
- self.drv_info = WMSDriversInfo()
- self.drv_props = self.drv_info.GetDrvProperties(self.ws)
- self.ws_drvs = {
- 'WMS_1.1.1' : {
- 'cmd' : ['wms_version=1.1.1',
- 'driver=WMS_GRASS'],
- 'cap_parser' : lambda temp_file : WMSCapabilities(temp_file, '1.1.1'),
- },
- 'WMS_1.3.0' : {
- 'cmd' : ['wms_version=1.3.0',
- 'driver=WMS_GRASS'],
- 'cap_parser' : lambda temp_file : WMSCapabilities(temp_file, '1.3.0'),
- },
- 'WMTS' : {
- 'cmd' : ['driver=WMTS_GRASS'],
- 'cap_parser' : WMTSCapabilities,
- },
- 'OnEarth' : {
- 'cmd' : ['driver=OnEarth_GRASS'],
- 'cap_parser' : OnEarthCapabilities,
- }
- }
- self.cmdStdErr = GStderr(self)
- self.cmd_thread = CmdThread(self)
- self.cap_file = grass.tempfile()
- reqDataBox = wx.StaticBox(parent=self, label=_(" Requested data settings "))
- self._nb_sizer = wx.StaticBoxSizer(reqDataBox, wx.VERTICAL)
- self.notebook = GNotebook(parent = self,
- style = FN.FNB_FANCY_TABS | FN.FNB_NO_X_BUTTON)
- self._requestPage()
- self._advancedSettsPage()
- self._layout()
- self.layerSelected = self.list.layerSelected
- self.Bind(EVT_CMD_DONE, self.OnCapDownloadDone)
- self.Bind(EVT_CMD_OUTPUT, self.OnCmdOutput)
- def __del__(self):
- self.cmd_thread.abort(abortall =True)
- grass.try_remove(self.cap_file)
- def _layout(self):
- self._nb_sizer.Add(item=self.notebook, proportion=1, flag=wx.EXPAND)
- self.SetSizer(self._nb_sizer)
- def _requestPage(self):
- """Create request page"""
- self.req_page_panel = wx.Panel(parent = self, id = wx.ID_ANY)
- self.notebook.AddPage(page = self.req_page_panel,
- text=_('Request'),
- name = 'request')
- # list of layers
- self.layersBox = wx.StaticBox(parent = self.req_page_panel, id = wx.ID_ANY,
- label=_("List of layers "))
- style = wx.TR_DEFAULT_STYLE | wx.TR_HAS_BUTTONS | wx.TR_FULL_ROW_HIGHLIGHT
- if self.drv_props['req_multiple_layers']:
- style = style | wx.TR_MULTIPLE
- if 'WMS' not in self.ws:
- style = style | wx.TR_HIDE_ROOT
- self.list = LayersList(parent = self.req_page_panel,
- web_service = self.ws,
- style = style)
- self.params['format'] = None
- self.params['srs'] = None
- if 'srs' not in self.drv_props['ignored_params']:
- projText = wx.StaticText(parent = self.req_page_panel, id = wx.ID_ANY, label = _("Source projection:"))
- self.params['srs'] = wx.Choice(parent = self.req_page_panel, id = wx.ID_ANY)
- self.list.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnListSelChanged)
- # layout
- self.req_page_sizer = wx.BoxSizer(wx.VERTICAL)
- layersSizer = wx.StaticBoxSizer(self.layersBox, wx.HORIZONTAL)
- layersSizer.Add(item = self.list, proportion = 1,
- flag = wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border = 5)
- self.req_page_sizer.Add(item = layersSizer, proportion = 1,
- flag = wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border = 5)
- self.source_sizer = wx.BoxSizer(wx.HORIZONTAL)
- if self.params['format'] is not None:
- self.source_sizer.Add(item = self.params['format'],
- flag = wx.LEFT | wx.RIGHT | wx.BOTTOM, border = 5)
- if self.params['srs'] is not None:
- self.source_sizer.Add(item = projText, flag = wx.ALIGN_CENTER_VERTICAL | wx.ALL, border = 5)
- self.source_sizer.Add(item = self.params['srs'],
- flag = wx.ALIGN_CENTER_VERTICAL | wx.RIGHT | wx.TOP | wx.BOTTOM, border = 5)
- self.req_page_sizer.Add(item = self.source_sizer,
- flag = wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border = 5)
- self.req_page_panel.SetSizer(self.req_page_sizer)
- def enableButtons(self, enable = True):
- """Enable/disable up, down, buttons
- """
- self.btnUp.Enable(enable)
- self.btnDown.Enable(enable)
- def _advancedSettsPage(self):
- """Create advanced settings page
- """
- #TODO parse maxcol, maxrow, settings from d.wms module?
- #TODO OnEarth driver - add selection of time
- adv_setts_panel = wx.Panel(parent = self, id = wx.ID_ANY)
- self.notebook.AddPage(page = adv_setts_panel,
- text=_('Advanced request settings'),
- name = 'adv_req_setts')
- labels = {}
- self.l_odrder_list = None
- if 'WMS' in self.ws:
- labels['l_order'] = wx.StaticBox(parent = adv_setts_panel, id = wx.ID_ANY,
- label = _("Order of layers in raster"))
- self.l_odrder_list = wx.ListBox(adv_setts_panel, id = wx.ID_ANY, choices = [],
- style = wx.LB_SINGLE|wx.LB_NEEDED_SB)
- self.btnUp = wx.Button(adv_setts_panel, id = wx.ID_ANY, label = _("Up"))
- self.btnDown = wx.Button(adv_setts_panel, id = wx.ID_ANY, label = _("Down"))
- self.btnUp.Bind(wx.EVT_BUTTON, self.OnUp)
- self.btnDown.Bind(wx.EVT_BUTTON, self.OnDown)
- labels['method'] = wx.StaticText(parent = adv_setts_panel, id = wx.ID_ANY,
- label = _("Reprojection method:"))
- self.reproj_methods = ['nearest', 'linear', 'cubic', 'cubicspline']
- self.params['method'] = wx.Choice(parent = adv_setts_panel, id = wx.ID_ANY,
- choices = [_('Nearest neighbor'), _('Linear interpolation'),
- _('Cubic interpolation'), _('Cubic spline interpolation')])
- labels['maxcols'] = wx.StaticText(parent = adv_setts_panel, id = wx.ID_ANY,
- label = _("Maximum columns to request from server at time:"))
- self.params['maxcols'] = wx.SpinCtrl(parent = adv_setts_panel, id = wx.ID_ANY, size = (100, -1))
- labels['maxrows'] = wx.StaticText(parent = adv_setts_panel, id = wx.ID_ANY,
- label = _("Maximum rows to request from server at time:"))
- self.params['maxrows'] = wx.SpinCtrl(parent = adv_setts_panel, id = wx.ID_ANY, size = (100, -1))
- min = 100
- max = 10000
- self.params['maxcols'].SetRange(min,max)
- self.params['maxrows'].SetRange(min,max)
- val = 500
- self.params['maxcols'].SetValue(val)
- self.params['maxrows'].SetValue(val)
- self.flags['o'] = self.params['bgcolor'] = None
- if not 'o' in self.drv_props['ignored_flags']:
- self.flags['o'] = wx.CheckBox(parent = adv_setts_panel, id = wx.ID_ANY,
- label = _("Do not request transparent data"))
- self.flags['o'].Bind(wx.EVT_CHECKBOX, self.OnTransparent)
- labels['bgcolor'] = wx.StaticText(parent = adv_setts_panel, id = wx.ID_ANY,
- label = _("Background color:"))
- self.params['bgcolor'] = csel.ColourSelect(parent = adv_setts_panel, id = wx.ID_ANY,
- colour = (255, 255, 255),
- size = globalvar.DIALOG_COLOR_SIZE)
- self.params['bgcolor'].Enable(False)
- self.params['urlparams'] = None
- if self.params['urlparams'] not in self.drv_props['ignored_params']:
- labels['urlparams'] = wx.StaticText(parent = adv_setts_panel, id = wx.ID_ANY,
- label = _("Additional query parameters for server:"))
- self.params['urlparams'] = wx.TextCtrl(parent = adv_setts_panel, id = wx.ID_ANY)
- # layout
- border = wx.BoxSizer(wx.VERTICAL)
- if 'WMS' in self.ws:
- boxSizer = wx.StaticBoxSizer(labels['l_order'], wx.VERTICAL)
- gridSizer = wx.GridBagSizer (hgap = 3, vgap = 3)
- gridSizer.Add(self.l_odrder_list,
- pos = (0,0),
- span = (4, 1),
- flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND,
- border = 0)
- gridSizer.Add(self.btnUp,
- pos = (0,1),
- flag = wx.ALIGN_CENTER_VERTICAL,
- border = 0)
- gridSizer.Add(self.btnDown,
- pos = (1,1),
- flag = wx.ALIGN_CENTER_VERTICAL,
- border = 0)
- gridSizer.AddGrowableCol(0)
- boxSizer.Add(gridSizer,
- flag = wx.EXPAND | wx.ALL,
- border = 5)
- border.Add(item = boxSizer,
- flag = wx.LEFT | wx.RIGHT | wx.UP | wx.EXPAND,
- border = 5)
- gridSizer = wx.GridBagSizer (hgap = 3, vgap = 3)
- row = 0
- for k in ['method', 'maxcols', 'maxrows', 'o', 'bgcolor']:
- if self.params.has_key(k):
- param = self.params[k]
- elif self.flags.has_key(k):
- param = self.flags[k]
- if param is None:
- continue
- if labels.has_key(k) or k == 'o':
- if k != 'o':
- label = labels[k]
- else:
- label = param
- gridSizer.Add(label,
- flag = wx.ALIGN_LEFT |
- wx.ALIGN_CENTER_VERTICAL,
- pos = (row, 0))
- if k != 'o':
- gridSizer.Add(item = param,
- flag = wx.ALIGN_RIGHT |
- wx.ALIGN_CENTER_VERTICAL,
- pos = (row, 1))
- row += 1
- gridSizer.AddGrowableCol(0)
- border.Add(item = gridSizer,
- flag = wx.LEFT | wx.RIGHT | wx.TOP | wx.EXPAND,
- border = 5)
- if self.params['urlparams']:
- gridSizer = wx.GridBagSizer (hgap = 3, vgap = 3)
-
- row = 0
- gridSizer.Add(labels['urlparams'],
- flag = wx.ALIGN_LEFT |
- wx.ALIGN_CENTER_VERTICAL,
- pos = (row, 0))
-
- gridSizer.Add(item = self.params['urlparams'],
- flag = wx.ALIGN_RIGHT |
- wx.ALIGN_CENTER_VERTICAL | wx.EXPAND,
- pos = (row, 1))
-
- gridSizer.AddGrowableCol(1)
-
- border.Add(item = gridSizer,
- flag = wx.LEFT | wx.RIGHT | wx.TOP | wx.EXPAND,
- border = 5)
- adv_setts_panel.SetSizer(border)
- def OnUp(self, event):
- """Move selected layer up
- """
- if self.l_odrder_list.GetSelections():
- pos = self.l_odrder_list.GetSelection()
- if pos:
- self.sel_layers.insert(pos - 1, self.sel_layers.pop(pos))
- if pos > 0:
- self._updateLayerOrderList(selected = (pos - 1))
- else:
- self._updateLayerOrderList(selected = 0)
- def OnDown(self, event):
- """Move selected to down
- """
- if self.l_odrder_list.GetSelections():
- pos = self.l_odrder_list.GetSelection()
- if pos != len(self.sel_layers) - 1:
- self.sel_layers.insert(pos + 1, self.sel_layers.pop(pos))
- if pos < len(self.sel_layers) -1:
- self._updateLayerOrderList(selected = (pos + 1))
- else:
- self._updateLayerOrderList(selected = len(self.sel_layers) -1)
- def _updateLayerOrderList(self, selected = None):
- """Update order in list.
- """
- def getlayercaption(layer):
- if l['title']:
- cap = (l['title'])
- else:
- cap = (l['name'])
- if l['style']:
- if l['style']['title']:
- cap += ' / ' + l['style']['title']
- else:
- cap += ' / ' + l['style']['name']
- return cap
- layer_capts = [getlayercaption(l) for l in self.sel_layers]
- self.l_odrder_list.Set(layer_capts)
- if self.l_odrder_list.IsEmpty():
- self.enableButtons(False)
- else:
- self.enableButtons(True)
- if selected is not None:
- self.l_odrder_list.SetSelection(selected)
- self.l_odrder_list.EnsureVisible(selected)
- def OnTransparent(self, event):
- checked = event.IsChecked()
- if checked:
- self.params['bgcolor'].Enable(True)
- else:
- self.params['bgcolor'].Enable(False)
- def ConnectToServer(self, url, username, password):
- """Download and parse data from capabilities file.
- :param url: server url
- :type url: str
- :param username: username for connection
- :type username: str
- :param password: password for connection
- :type password: str
- """
- self._prepareForNewConn(url, username, password)
- cap_cmd = ['r.in.wms', '-c', ('capfile_output=%s' % self.cap_file), '--overwrite'] + self.ws_cmdl
- self.currentPid = self.cmd_thread.GetId()
- self.cmd_thread.RunCmd(cap_cmd, stderr = self.cmdStdErr)
- def OnCmdOutput(self, event):
- """Manage cmd output.
- """
- if Debug.GetLevel() != 0:
- Debug.msg(1, event.text)
- elif event.type != 'message' and event.type != 'warning':
- self.cmd_err_str += event.text + os.linesep
- def _prepareForNewConn(self, url, username, password):
- """Prepare panel for new connection
- """
- self.is_connected = False
- self.sel_layers = []
- self.formats_list = []
- self.projs_list = []
- self.conn = {
- 'url' : url,
- 'password' : password,
- 'username' : username
- }
- conn_cmd = []
- for k, v in self.conn.iteritems():
- if v:
- conn_cmd.append("%s=%s" % (k,v))
- self.ws_cmdl = self.ws_drvs[self.ws]['cmd'] + conn_cmd
- def OnCapDownloadDone(self, event):
- """Process donwloaded capabilities file and emits capParsed
- signal (see class constructor).
- """
- if event.pid != self.currentPid:
- return
- if event.returncode != 0:
- if self.cmd_err_str:
- self.cmd_err_str = _("Unable to download %s capabilities file\nfrom <%s>:\n" % \
- (self.ws.replace('_', ' '), self.conn['url'])) + self.cmd_err_str
- self._postCapParsedEvt(error_msg = self.cmd_err_str)
- self.cmd_err_str = ''
- return
- self._parseCapFile(self.cap_file)
- def _parseCapFile(self, cap_file):
- """Parse capabilities data and emits capParsed signal
- (see class constructor).
- """
- try:
- self.cap = self.ws_drvs[self.ws]['cap_parser'](cap_file)
- except (IOError, ParseError) as error:
- error_msg = _("%s web service was not found in fetched capabilities file from <%s>:\n%s\n" % \
- (self.ws, self.conn['url'], str(error)))
- if Debug.GetLevel() != 0:
- Debug.msg(1, error_msg)
- self._postCapParsedEvt(None)
- else:
- self._postCapParsedEvt(error_msg = error_msg)
- return
- self.is_connected = True
- # WMS standard has formats defined for all layers
- if 'WMS' in self.ws:
- self.formats_list = sorted(self._getFormats())
- self._updateFormatRadioBox(self.formats_list)
- self._setDefaultFormatVal()
- self.list.LoadData(self.cap)
- self.OnListSelChanged(event = None)
- self._postCapParsedEvt(None)
- def ParseCapFile(self, url, username, password, cap_file = None,):
- """Parse capabilities data and emits capParsed signal
- (see class constructor).
- """
- self._prepareForNewConn(url, username, password)
- if cap_file is None or not url:
- self._postCapParsedEvt(None)
- return
- shutil.copyfile(cap_file, self.cap_file)
- self._parseCapFile(self.cap_file)
- def UpdateWidgetsByCmd(self, cmd):
- """Update panel widgets accordnig to passed cmd tuple
- :param cmd: cmd in tuple
- """
- dcmd = cmd[1]
- layers = []
- if dcmd.has_key('layers'):
- layers = dcmd['layers']
- styles = []
- if dcmd.has_key('styles'):
- styles = dcmd['styles']
- if 'WMS' in self.ws:
- layers = layers.split(',')
- styles = styles.split(',')
- else:
- layers = [layers]
- styles = [styles]
- if len(layers) != len(styles):
- styles = [''] * len(layers)
- l_st_list = []
- for i in range(len(layers)):
- l_st_list.append({'style' : styles[i],
- 'layer' : layers[i]})
- # WMS standard - first layer in params is most bottom...
- # therefore layers order need to be reversed
- l_st_list = [l for l in reversed(l_st_list)]
- self.list.SelectLayers(l_st_list)
- params = {}
- if dcmd.has_key('format'):
- params['format'] = dcmd['format']
- if dcmd.has_key('srs'):
- params['srs'] = 'EPSG:' + dcmd['srs']
- if dcmd.has_key('method'):
- params['method'] = dcmd['method']
- for p, v in params.iteritems():
- if self.params[p]:
- self.params[p].SetStringSelection(v)
- for p, conv_f in [('urlparams', None), ('maxcols', int), ('maxrows', int)]:
- if dcmd.has_key(p):
- v = dcmd[p]
- if conv_f:
- v = conv_f(v)
- self.params[p].SetValue(v)
- if dcmd.has_key('flags') and \
- 'o' in dcmd['flags']:
- self.flags['o'].SetValue(1)
- self.params['bgcolor'].Enable(True)
- if dcmd.has_key('bgcolor') and \
- self.params['bgcolor']:
- bgcolor = dcmd['bgcolor'].strip().lower()
- if len(bgcolor) == 8 and \
- '0x' == bgcolor[:2]:
- colour = '#' + bgcolor[2:]
- self.params['bgcolor'].SetColour(colour)
- def IsConnected(self):
- """Was successful in downloading and parsing capabilities data?
- """
- return self.is_connected
- def _postCapParsedEvt(self, error_msg):
- """Helper function
- """
- self.capParsed.emit(error_msg=error_msg)
- def CreateCmd(self):
- """Create d.wms cmd from values of panels widgets
- :return: cmd list
- :return: None if required widgets do not have selected/filled values.
- """
- # check required widgets
- if not self._checkImportValues():
- return None
- # create d.wms command
- lcmd = self.ws_cmdl
- lcmd = ['d.wms'] + lcmd
- layers = "layers="
- styles = 'styles='
- first = True
- # WMS standard - first layer in params is most bottom...
- # therefore layers order need to be reversed
- for layer in reversed(self.sel_layers):
- if not first:
- layers += ','
- styles += ','
- first = False
- layers += layer['name']
- if layer['style'] is not None:
- styles += layer['style']['name']
- lcmd.append(layers)
- lcmd.append(styles)
- if 'format' not in self.drv_props['ignored_params']:
- i_format = self.params['format'].GetSelection()
- lcmd.append("format=%s" % self.formats_list[i_format])
- if 'srs' not in self.drv_props['ignored_params']:
- i_srs = self.params['srs'].GetSelection()
- epsg_num = int(self.projs_list[i_srs].split(':')[-1])
- lcmd.append("srs=%s" % epsg_num)
- for k in ['maxcols', 'maxrows', 'urlparams']:
- lcmd.append(k + '=' + str(self.params[k].GetValue()))
- i_method = self.params['method'].GetSelection()
- lcmd.append('method=' + self.reproj_methods[i_method])
- if not 'o' in self.drv_props['ignored_flags'] and \
- self.flags['o'].IsChecked():
- lcmd.append('-o')
- c = self.params['bgcolor'].GetColour()
- hex_color = wx.Colour(c[0], c[1], c[2]).GetAsString(wx.C2S_HTML_SYNTAX)
- lcmd.append("bgcolor=" + '0x' + hex_color[1:])
- lcmd.append("map=" + self.o_layer_name)
- return lcmd
- def OnListSelChanged(self, event):
- """Update widgets according to selected layer in list.
- """
- curr_sel_ls = self.list.GetSelectedLayers()
- # update self.sel_layers (selected layer list)
- if 'WMS' in self.ws:
- for sel_l in self.sel_layers[:]:
- if sel_l not in curr_sel_ls:
- self.sel_layers.remove(sel_l)
- for l in curr_sel_ls:
- if l not in self.sel_layers:
- self.sel_layers.append(l)
- self._updateLayerOrderList()
- else:
- self.sel_layers = curr_sel_ls
- # update projection
- self.projs_list = []
- projs_list = []
- intersect_proj = []
- first = True
- for l in curr_sel_ls:
- layer_projs = l['cap_intf_l'].GetLayerData('srs')
- if first:
- projs_list = layer_projs
- first = False
- continue
- projs_list = set(projs_list).intersection(layer_projs)
- if 'srs' not in self.drv_props['ignored_params']:
- for proj in projs_list:
- proj_code = Srs(proj.strip()).getcode()
- proj_spl = proj_code.split(':')
- if proj_spl[0].strip().lower() in self.drv_info.GetSrs():
- try:
- int(proj_spl[1])
- self.projs_list.append(proj_code)
- except ValueError, IndexError:
- continue
- cur_sel = self.params['srs'].GetStringSelection()
- self.projs_list = sorted(self.projs_list)
- self.params['srs'].SetItems(self.projs_list)
- if cur_sel:
- self.params['srs'].SetStringSelection(cur_sel)
- else:
- try:
- i = self.projs_list.index('EPSG:4326')
- self.params['srs'].SetSelection(i)
- except ValueError:
- if len(self.projs_list) > 0:
- self.params['srs'].SetSelection(0)
- # update format
- if 'WMS' not in self.ws and \
- 'format' not in self.drv_props['ignored_params']:
- self.formats_list = []
- cur_sel = None
- if self.params['format'] is not None:
- cur_sel = self.params['format'].GetStringSelection()
- if len(curr_sel_ls) > 0:
- self.formats_list = sorted(self._getFormats(curr_sel_ls[0]['cap_intf_l']))
- self._updateFormatRadioBox(self.formats_list)
- if cur_sel:
- self.params['format'].SetStringSelection(cur_sel)
- else:
- self._setDefaultFormatVal()
- self.Layout()
- def _setDefaultFormatVal(self):
- """Set default format value.
- """
- try:
- i = self.formats_list.index('png')
- self.params['format'].SetSelection(i)
- except ValueError:
- pass
- def _updateFormatRadioBox(self, formats_list):
- """Helper function
- """
- if self.params['format'] is not None:
- self.req_page_sizer.Detach(self.params['format'])
- self.params['format'].Destroy()
- if len(self.formats_list) > 0:
- self.params['format'] = wx.RadioBox(parent = self.req_page_panel, id = wx.ID_ANY,
- label = _("Source image format"), pos = wx.DefaultPosition,
- choices = formats_list, majorDimension = 4,
- style = wx.RA_SPECIFY_COLS)
- self.source_sizer.Insert(item=self.params['format'], before=2,
- flag=wx.LEFT | wx.RIGHT | wx.BOTTOM,
- border=5)
- def _getFormats(self, layer=None):
- """Get formats
- WMS has formats defined generally for whole cap.
- In WMTS and NASA OnEarh formats are defined for layer.
- """
- formats_label = []
- if layer is None:
- formats_list = self.cap.GetFormats()
- else:
- formats_list = layer.GetLayerData('format')
- for frmt in formats_list:
- frmt = frmt.strip()
- label = self.drv_info.GetFormatLabel(frmt)
- if label:
- formats_label.append(label)
- return formats_label
- def _checkImportValues(self,):
- """Check if required widgets are selected/filled
- """
- warning_str = ""
- show_war = False
- if not self.list or not self.list.GetSelectedLayers():
- warning_str += _("Select layer in layer list.\n")
- show_war = True
- if self.params['format'] is not None and \
- self.params['format'].GetSelection() == -1:
- warning_str += _("Select source image format.\n")
- show_war = True
- if self.params['srs'] is not None and \
- self.params['srs'].GetSelection() == -1:
- warning_str += _("Select source projection.\n")
- show_war = True
- if not self.o_layer_name:
- warning_str += _("Choose output layer name.\n")
- show_war = True
- if show_war:
- GMessage(parent=self.parent, message=warning_str)
- return False
- return True
- def SetOutputLayerName(self, name):
- """Set name of layer to be added to layer tree
- """
- self.o_layer_name = name
- def GetOutputLayerName(self):
- return self.o_layer_name
- def GetCapFile(self):
- """Get path to file where capabilities are saved
- """
- return self.cap_file
- def GetWebService(self):
- """Get web service
- """
- return self.ws
- class LayersList(TreeListCtrl, listmix.ListCtrlAutoWidthMixin):
- def __init__(self, parent, web_service, style, pos=wx.DefaultPosition):
- """List of layers and styles available in capabilities file
- """
- self.parent = parent
- self.ws = web_service
- TreeListCtrl.__init__(self, parent = parent, id = wx.ID_ANY, style = style)
- # setup mixins
- listmix.ListCtrlAutoWidthMixin.__init__(self)
- if self.ws != 'OnEarth':
- self.AddColumn(_('Name'))
- self.AddColumn(_('Type'))
- else:
- self.AddColumn(_('Layer name'))
- self.SetMainColumn(0) # column with the tree
- self.setResizeColumn(0)
- self.root = None
- self.Bind(wx.EVT_TREE_SEL_CHANGING, self.OnListSelChanging)
- self.layerSelected = Signal('LayersList.layerSelected')
- def LoadData(self, cap = None):
- """Load data into list
- """
- # detete first all items
- self.DeleteAllItems()
- if not cap:
- return
- def AddLayerChildrenToTree(parent_layer, parent_item):
- """Recursive function which adds all capabilities
- layers/styles to the LayersList.
- """
- def gettitle(layer):
- """Helper function"""
- if layer.GetLayerData('title') is not None:
- layer_title = layer.GetLayerData('title')
- elif layer.GetLayerData('name') is not None:
- layer_title = layer.GetLayerData('name')
- else:
- layer_title = str(layer.GetId())
- return layer_title
- def addlayer(layer, item):
- if self.ws != 'OnEarth':
- self.SetItemText(item, _('layer'), 1)
- styles = layer.GetLayerData('styles')
- def_st = None
- for st in styles:
- if st['name']:
- style_name = st['name']
- else:
- continue
- if st['title']:
- style_name = st['title']
- if st['isDefault']:
- def_st = st
- style_item = self.AppendItem(item, style_name)
- if self.ws != 'OnEarth':
- self.SetItemText(style_item, _('style'), 1)
- self.SetPyData(style_item, {'type' : 'style',
- 'layer' : layer, # it is parent layer of style
- 'style' : st})
- self.SetPyData(item, {'type' : 'layer', # is it layer or style?
- 'layer' : layer, # Layer instance from web_services.cap_interface
- 'style' : def_st}) # layer can have assigned default style
- if parent_layer is None:
- parent_layer = cap.GetRootLayer()
- layer_title = gettitle(parent_layer)
- parent_item = self.AddRoot(layer_title)
- addlayer(parent_layer, parent_item)
- for layer in parent_layer.GetChildren():
- item = self.AppendItem(parent_item, gettitle(layer))
- addlayer(layer, item)
- AddLayerChildrenToTree(layer, item)
- AddLayerChildrenToTree(None, None)
- #self.ExpandAll(self.GetRootItem())
- def GetSelectedLayers(self):
- """Get selected layers/styles in LayersList
- :return: dict with these items:
- * 'name' : layer name used for request
- if it is style, it is name of parent layer
- * 'title' : layer title
- * 'style' : {'name' : 'style name', title : 'style title'}
- * 'cap_intf_l' : \*Layer instance from web_services.cap_interface
- """
- sel_layers = self.GetSelections()
- sel_layers_dict = []
- for s in sel_layers:
- try:
- layer = self.GetPyData(s)['layer']
- except ValueError:
- continue
- sel_layers_dict.append({
- 'name' : layer.GetLayerData('name'),
- 'title' : layer.GetLayerData('title'),
- 'style' : self.GetPyData(s)['style'],
- 'cap_intf_l' : layer
- })
- return sel_layers_dict
- def OnListSelChanging(self, event):
- """Do not allow selecting items, which cannot be requested from server.
- """
- def _emitSelected(layer):
- title = layer.GetLayerData('title')
- self.layerSelected.emit(title = title)
- def _selectRequestableChildren(item, list_to_check, items_to_sel):
- self.Expand(item)
- child_item, cookie = self.GetFirstChild(item)
- while child_item.IsOk():
- if self.GetPyData(child_item)['layer'].IsRequestable() \
- and not self.IsSelected(child_item):
- items_to_sel.append(child_item)
- elif not self.GetPyData(child_item)['layer'].IsRequestable():
- list_to_check.append(child_item)
- child_item, cookie = self.GetNextChild(item, cookie)
- cur_item = event.GetItem()
- if not self.GetPyData(cur_item)['layer'].IsRequestable():
- event.Veto()
- if not self.HasFlag(wx.TR_MULTIPLE):
- return
- _emitSelected(self.GetPyData(cur_item)['layer'])
- items_to_chck = []
- items_to_sel = []
- chck_item = cur_item
- while True:
- _selectRequestableChildren(chck_item, items_to_chck, items_to_sel)
- if items_to_chck:
- chck_item = items_to_chck.pop()
- else:
- break
- while items_to_sel:
- self.SelectItem(items_to_sel.pop(), unselect_others=False)
- else:
- _emitSelected(self.GetPyData(cur_item)['layer'])
- def GetItemCount(self):
- """Required for listmix.ListCtrlAutoWidthMixin
- """
- return 0
- def GetCountPerPage(self):
- """Required for listmix.ListCtrlAutoWidthMixin
- """
- return 0
- def SelectLayers(self, l_st_list):
- """Select layers/styles in LayersList
- :param l_st_list: [{style : 'style_name', layer : 'layer_name'}, ...]
- :return: items from l_st_list which were not found
- """
- def checknext(item, l_st_list, items_to_sel):
- def compare(item, l_name, st_name):
- it_l_name = self.GetPyData(item)['layer'].GetLayerData('name')
- it_st = self.GetPyData(item)['style']
- it_type = self.GetPyData(item)['type']
- if it_l_name == l_name and \
- ( (not it_st and not st_name) or \
- (it_st and it_st['name'] == st_name and it_type == 'style')):
- return True
- return False
- for i, l_st in enumerate(l_st_list):
- l_name = l_st['layer']
- st_name = l_st['style']
- if compare(item, l_name, st_name):
- items_to_sel[i] = [item, l_st]
- break
- if len(items_to_sel) == len(l_st_list):
- item = self.GetNext(item)
- if not item.IsOk():
- return
- checknext(item, l_st_list, items_to_sel)
- self.UnselectAll()
- l_st_list = deepcopy(l_st_list)
- root_item = self.GetRootItem()
- items_to_sel = [None] * len(l_st_list)
- checknext(root_item, l_st_list, items_to_sel)
- # items are selected according to position in l_st_list
- # to be added to Layers order list in right order
- for i in items_to_sel:
- if not i:
- continue
- item, l_st = i
- un_o = True
- if self.HasFlag(wx.TR_MULTIPLE):
- un_o = False
- self.SelectItem(item, unselect_others=un_o)
- l_st_list.remove(l_st)
- return l_st_list
- class WSManageSettingsWidget(ManageSettingsWidget):
- def __init__(self, parent, settingsFile, default_servers):
- ManageSettingsWidget.__init__(self, parent, settingsFile)
- self.default_servers = default_servers
- def _layout(self):
- self.btnAddDefaultServers = wx.Button(parent=self, id=wx.ID_ANY,
- label=_("Add default servers"))
- self.btnAddDefaultServers.Bind(wx.EVT_BUTTON, self.OnAddDefaultServers)
- ManageSettingsWidget._layout(self)
- self.settingsSizer.Add(item=self.btnAddDefaultServers,
- flag=wx.RIGHT,
- border=5)
- def OnAddDefaultServers(self, event):
- setts = self.GetSettings()
- self.servers_to_add = {}
- for k, v in self.default_servers.iteritems():
- if k not in setts.iterkeys():
- self.servers_to_add[k] = v
- elif v != setts[k]:
- GMessage(parent=self,
- message=_("User defined server with same name "
- "as default server <%s> already exists.\n"
- "Keeping user defined server") % (k))
- if self.servers_to_add:
- self.AddSettings(self.servers_to_add)
|