2
@package web_services.dialogs
4
@brief Dialogs for web services.
7
- dialogs::WSDialogBase
9
- dialogs::WSPropertiesDialog
10
- dialogs::SaveWMSLayerDialog
12
(C) 2009-2013 by the GRASS Development Team
14
This program is free software under the GNU General Public License
15
(>=v2). Read the file COPYING that comes with GRASS for details.
17
@author Martin Landa <landa.martin gmail.com>
18
@author Stepan Turek <stepan.turek seznam.cz>
27
from copy import deepcopy
29
import grass.script as grass
31
from core import globalvar
32
from core.debug import Debug
33
from core.gcmd import GMessage, GWarning, GError, RunCommand
34
from core.utils import GetSettingsPath, CmdToTuple, CmdTupleToList, _
35
from core.gconsole import CmdThread, GStderr, EVT_CMD_DONE, EVT_CMD_OUTPUT
37
from gui_core.gselect import Select
39
from web_services.widgets import WSPanel, WSManageSettingsWidget
41
class WSDialogBase(wx.Dialog):
42
"""Base class for web service dialogs.
44
def __init__(self, parent, id = wx.ID_ANY,
45
style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER, **kwargs):
47
wx.Dialog.__init__(self, parent, id, style = style, **kwargs)
51
# contains panel for every web service on server
52
self.ws_panels = {'WMS_1.1.1' : {'panel' : None,
53
'label' : 'WMS 1.1.1'},
54
'WMS_1.3.0' : {'panel' : None,
55
'label' : 'WMS 1.3.0'},
56
'WMTS' : {'panel' : None,
58
'OnEarth' : {'panel' : None,
62
#TODO: should be in file
63
self.default_servers = { 'OSM-WMS-EUROPE' : ['http://watzmann-geog.urz.uni-heidelberg.de/cached/osm', '', ''],
64
'irs.gis-lab.info (OSM)' : ['http://irs.gis-lab.info', '', ''],
65
'NASA OnEarth' : ['http://onearth.jpl.nasa.gov/wms.cgi', '', '']
68
# holds reference to web service panel which is showed
69
self.active_ws_panel = None
71
# buttons which are disabled when the dialog is not connected
74
# stores error messages for GError dialog showed when all web service connections were unsuccessful
80
def _createWidgets(self):
82
settingsFile = os.path.join(GetSettingsPath(), 'wxWS')
84
self.settsManager = WSManageSettingsWidget(parent=self,
85
settingsFile=settingsFile,
86
default_servers=self.default_servers)
88
self.settingsBox = wx.StaticBox(parent = self,
90
label = _(" Server settings "))
92
self.serverText = wx.StaticText(parent = self,
93
id = wx.ID_ANY, label = _("Server:"))
94
self.server = wx.TextCtrl(parent = self, id = wx.ID_ANY)
96
self.btn_connect = wx.Button(parent = self,
97
id = wx.ID_ANY, label = _("&Connect"))
98
self.btn_connect.SetToolTipString(_("Connect to the server"))
99
if not self.server.GetValue():
100
self.btn_connect.Enable(False)
102
self.infoCollapseLabelExp = _('Show advanced connection settings')
103
self.infoCollapseLabelCol = _('Hide advanced connection settings')
105
self.adv_conn = wx.CollapsiblePane(parent = self,
106
label = self.infoCollapseLabelExp,
107
style = wx.CP_DEFAULT_STYLE |
108
wx.CP_NO_TLW_RESIZE | wx.EXPAND)
110
self.MakeAdvConnPane(pane = self.adv_conn.GetPane())
111
self.adv_conn.Collapse(True)
112
self.Bind(wx.EVT_COLLAPSIBLEPANE_CHANGED, self.OnAdvConnPaneChanged, self.adv_conn)
114
self.reqDataPanel = wx.Panel(parent = self, id = wx.ID_ANY)
116
self.layerNameBox = wx.StaticBox(parent = self.reqDataPanel,
118
label = _(" Layer Manager Settings "))
120
self.layerNameText = wx.StaticText(parent = self.reqDataPanel, id = wx.ID_ANY,
121
label = _("Output layer name:"))
122
self.layerName = wx.TextCtrl(parent = self.reqDataPanel, id = wx.ID_ANY)
124
for ws in self.ws_panels.iterkeys():
125
self.ws_panels[ws]['panel'] = WSPanel(parent = self.reqDataPanel,
127
self.ws_panels[ws]['panel'].capParsed.connect(self.OnPanelCapParsed)
128
self.ws_panels[ws]['panel'].layerSelected.connect(self.OnLayerSelected)
131
self.btn_close = wx.Button(parent = self, id = wx.ID_CLOSE)
132
self.btn_close.SetToolTipString(_("Close dialog"))
135
self.statusbar = wx.StatusBar(parent = self, id = wx.ID_ANY)
138
self.btn_close.Bind(wx.EVT_BUTTON, self.OnClose)
139
self.Bind(wx.EVT_CLOSE, self.OnClose)
140
self.btn_connect.Bind(wx.EVT_BUTTON, self.OnConnect)
142
self.server.Bind(wx.EVT_TEXT, self.OnServer)
143
self.layerName.Bind(wx.EVT_TEXT, self.OnOutputLayerName)
145
self.settsManager.settingsChanged.connect(self.OnSettingsChanged)
146
self.settsManager.settingsSaving.connect(self.OnSettingsSaving)
148
def OnLayerSelected(self, title):
150
if not self.layerName.GetValue().strip():
151
self.layerName.SetValue(title)
155
dialogSizer = wx.BoxSizer(wx.VERTICAL)
157
dialogSizer.Add(item = self.settsManager, proportion = 0,
158
flag = wx.EXPAND | wx.TOP | wx.LEFT | wx.RIGHT, border = 5)
161
settingsSizer = wx.StaticBoxSizer(self.settingsBox, wx.VERTICAL)
163
serverSizer = wx.FlexGridSizer(cols = 3, vgap = 5, hgap = 5)
165
serverSizer.Add(item = self.serverText,
166
flag = wx.ALIGN_CENTER_VERTICAL)
167
serverSizer.AddGrowableCol(1)
168
serverSizer.Add(item = self.server,
169
flag = wx.EXPAND | wx.ALL)
171
serverSizer.Add(item = self.btn_connect)
173
settingsSizer.Add(item = serverSizer, proportion = 0,
174
flag = wx.EXPAND | wx.LEFT | wx.RIGHT, border = 5)
176
settingsSizer.Add(item = self.adv_conn,
177
flag = wx.ALL | wx.EXPAND, border = 5)
179
dialogSizer.Add(item = settingsSizer, proportion = 0,
180
flag = wx.EXPAND | wx.TOP | wx.LEFT | wx.RIGHT, border = 5)
182
# layer name, parsed capabilites
184
reqDataSizer = wx.BoxSizer(wx.VERTICAL)
186
layerNameSizer = wx.StaticBoxSizer(self.layerNameBox, wx.HORIZONTAL)
188
layerNameSizer.Add(item = self.layerNameText,
189
flag = wx.ALIGN_CENTER_VERTICAL | wx.ALL, border = 5)
191
layerNameSizer.Add(item = self.layerName,
192
flag = wx.EXPAND, proportion = 1)
194
reqDataSizer.Add(item = layerNameSizer,
195
flag = wx.TOP | wx.LEFT | wx.RIGHT | wx.EXPAND, border = 5)
197
self.ch_ws_sizer = wx.BoxSizer(wx.VERTICAL)
199
reqDataSizer.Add(item = self.ch_ws_sizer, proportion = 0,
200
flag = wx.TOP | wx.EXPAND, border = 5)
202
for ws in self.ws_panels.iterkeys():
203
reqDataSizer.Add(item = self.ws_panels[ws]['panel'], proportion = 1,
204
flag = wx.TOP | wx.LEFT | wx.RIGHT | wx.EXPAND, border = 5)
205
self.ws_panels[ws]['panel'].Hide()
207
dialogSizer.Add(item = self.reqDataPanel, proportion = 1,
210
self.reqDataPanel.SetSizer(reqDataSizer)
211
self.reqDataPanel.Hide()
214
self.btnsizer = wx.BoxSizer(orient = wx.HORIZONTAL)
216
self.btnsizer.Add(item = self.btn_close, proportion = 0,
217
flag = wx.ALL | wx.ALIGN_CENTER,
220
dialogSizer.Add(item = self.btnsizer, proportion = 0,
221
flag = wx.ALIGN_CENTER)
223
dialogSizer.Add(item = self.statusbar, proportion = 0)
225
self.SetSizer(dialogSizer)
228
self.SetMinSize((550, -1))
229
self.SetMaxSize((-1, self.GetBestSize()[1]))
232
def MakeAdvConnPane(self, pane):
233
"""Create advanced connection settings pane
235
self.usernameText = wx.StaticText(parent = pane,
236
id = wx.ID_ANY, label = _("Username:"))
237
self.username = wx.TextCtrl(parent = pane, id = wx.ID_ANY)
239
self.passwText = wx.StaticText(parent = pane,
240
id = wx.ID_ANY, label = _("Password:"))
241
self.password = wx.TextCtrl(parent = pane, id = wx.ID_ANY,
242
style = wx.TE_PASSWORD)
245
adv_conn_sizer = wx.BoxSizer(wx.VERTICAL)
247
usernameSizer = wx.BoxSizer(wx.HORIZONTAL)
249
usernameSizer.Add(item = self.usernameText,
250
flag = wx.ALIGN_CENTER_VERTICAL, border = 5)
252
usernameSizer.Add(item = self.username, proportion = 1,
253
flag = wx.EXPAND, border = 5)
255
adv_conn_sizer.Add(item = usernameSizer,
256
flag = wx.ALL | wx.EXPAND, border = 5)
258
passwSizer = wx.BoxSizer(wx.HORIZONTAL)
260
passwSizer.Add(item = self.passwText,
261
flag = wx.ALIGN_CENTER_VERTICAL, border = 5)
263
passwSizer.Add(item = self.password, proportion = 1,
264
flag = wx.EXPAND, border = 5)
266
adv_conn_sizer.Add(item = passwSizer,
267
flag = wx.ALL | wx.EXPAND, border = 5)
269
pane.SetSizer(adv_conn_sizer)
270
adv_conn_sizer.Fit(pane)
272
pane.SetSizer(adv_conn_sizer)
273
adv_conn_sizer.Fit(pane)
275
def OnSettingsSaving(self, name):
276
"""Check if required data are filled before setting save is performed.
278
server = self.server.GetValue().strip()
280
GMessage(parent = self,
281
message = _("No data source defined, settings are not saved."))
284
self.settsManager.SetDataToSave((server,
285
self.username.GetValue(),
286
self.password.GetValue()))
287
self.settsManager.SaveSettings(name)
289
def OnSettingsChanged(self, data):
290
"""Update widgets according to chosen settings"""
291
# data list: [server, username, password]
295
self.server.SetValue(data[0])
297
self.username.SetValue(data[1])
298
self.password.SetValue(data[2])
300
if data[1] or data[2]:
301
self.adv_conn.Expand()
303
self.adv_conn.Collapse(True)
305
def OnClose(self, event):
309
if not self.IsModal():
313
def _getCapFiles(self):
315
for v in self.ws_panels.itervalues():
316
ws_cap_files[v['panel'].GetWebService()] = v['panel'].GetCapFile()
320
def OnServer(self, event):
321
"""Server settings edited
323
value = event.GetString()
325
self.btn_connect.Enable(True)
327
self.btn_connect.Enable(False)
329
def OnOutputLayerName(self, event):
330
"""Update layer name to web service panel
332
lname = event.GetString()
333
lname = lname.encode('ascii', 'replace')
335
for v in self.ws_panels.itervalues():
336
v['panel'].SetOutputLayerName(lname.strip())
338
def OnConnect(self, event):
339
"""Connect to the server
341
server = self.server.GetValue().strip()
343
self.ch_ws_sizer.Clear(deleteWindows = True)
345
if self.active_ws_panel is not None:
346
self.reqDataPanel.Hide()
347
for btn in self.run_btns:
349
self.active_ws_panel = None
354
self.statusbar.SetStatusText(_("Connecting to <%s>..." % self.server.GetValue().strip()))
356
# number of panels already connected
357
self.finished_panels_num = 0
358
for ws in self.ws_panels.iterkeys():
359
self.ws_panels[ws]['panel'].ConnectToServer(url = server,
360
username = self.username.GetValue(),
361
password = self.password.GetValue())
362
self.ws_panels[ws]['panel'].Hide()
364
def OnPanelCapParsed(self, error_msg):
365
"""Called when panel has downloaded and parsed capabilities file.
367
# how many web service panels are finished
368
self.finished_panels_num += 1
371
self.error_msgs += '\n' + error_msg
373
# if all are finished, show panels, which succeeded in connection
374
if self.finished_panels_num == len(self.ws_panels):
375
self.UpdateDialogAfterConnection()
377
# show error dialog only if connections to all web services were unsuccessful
378
if not self._getConnectedWS() and self.error_msgs:
379
GError(self.error_msgs, parent = self)
385
def _getConnectedWS(self):
387
:return: list of found web services on server (identified as keys in self.ws_panels)
390
for ws, data in self.ws_panels.iteritems():
391
if data['panel'].IsConnected():
396
def UpdateDialogAfterConnection(self):
397
"""Update dialog after all web service panels downloaded and parsed capabilities data.
400
conn_ws = self._getConnectedWS()
403
avail_ws[ws] = self.ws_panels[ws]
405
self.web_service_sel = []
408
# at least one web service found on server
409
if len(avail_ws) > 0:
410
self.reqDataPanel.Show()
411
self.rb_order = ['WMS_1.1.1', 'WMS_1.3.0', 'WMTS', 'OnEarth']
413
for ws in self.rb_order:
416
self.web_service_sel.append(ws)
417
self.rb_choices.append(avail_ws[ws]['label'])
419
self.choose_ws_rb = wx.RadioBox(parent = self.reqDataPanel, id = wx.ID_ANY,
420
label = _("Available web services"),
421
pos = wx.DefaultPosition, choices = self.rb_choices,
422
majorDimension = 1, style = wx.RA_SPECIFY_ROWS)
424
self.Bind(wx.EVT_RADIOBOX, self.OnChooseWs, self.choose_ws_rb)
425
self.ch_ws_sizer.Add(item = self.choose_ws_rb,
426
flag = wx.TOP | wx.LEFT | wx.RIGHT | wx.EXPAND, border = 5)
427
self._showWsPanel(self.web_service_sel[self.choose_ws_rb.GetSelection()])
428
self.statusbar.SetStatusText(_("Connected to <%s>" % self.server.GetValue().strip()))
429
for btn in self.run_btns:
431
# no web service found on server
433
self.statusbar.SetStatusText(_("Unable to connect to <%s>" % self.server.GetValue().strip()))
434
for btn in self.run_btns:
436
self.reqDataPanel.Hide()
437
self.active_ws_panel = None
439
def OnChooseWs(self, event):
440
"""Show panel corresponding to selected web service.
442
choosen_r = event.GetInt()
443
self._showWsPanel(self.web_service_sel[choosen_r])
445
def _showWsPanel(self, ws):
448
if self.active_ws_panel is not None:
449
self.active_ws_panel.Hide()
451
self.active_ws_panel = self.ws_panels[ws]['panel']
452
self.active_ws_panel.Show()
453
self.SetMaxSize((-1, -1))
454
self.active_ws_panel.GetContainingSizer().Layout()
456
def OnAdvConnPaneChanged(self, event):
457
"""Collapse search module box
459
if self.adv_conn.IsExpanded():
460
self.adv_conn.SetLabel(self.infoCollapseLabelCol)
462
self.adv_conn.SetLabel(self.infoCollapseLabelExp)
465
self.SetMaxSize((-1, self.GetBestSize()[1]))
469
class AddWSDialog(WSDialogBase):
470
"""Dialog for adding web service layer."""
471
def __init__(self, parent, giface, id = wx.ID_ANY,
472
style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER, **kwargs):
474
WSDialogBase.__init__(self, parent, id = wx.ID_ANY,
475
style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER, **kwargs)
477
self.SetTitle(_("Add web service layer"))
481
self.btn_connect.SetDefault()
483
def _createWidgets(self):
485
WSDialogBase._createWidgets(self)
487
self.btn_add = wx.Button(parent = self, id = wx.ID_ANY, label = _("&Add layer"))
488
self.btn_add.SetToolTipString(_("Add selected web service layers as map layer into layer tree"))
489
self.btn_add.Enable(False)
491
self.run_btns.append(self.btn_add)
495
WSDialogBase._doLayout(self)
497
self.btnsizer.Add(item = self.btn_add, proportion = 0,
498
flag = wx.ALL | wx.ALIGN_CENTER,
502
self.btn_add.Bind(wx.EVT_BUTTON, self.OnAddLayer)
504
def UpdateDialogAfterConnection(self):
505
"""Connect to the server
507
WSDialogBase.UpdateDialogAfterConnection(self)
509
if self._getConnectedWS():
510
self.btn_add.SetDefault()
512
self.btn_connect.SetDefault()
514
def OnAddLayer(self, event):
515
"""Add web service layer.
518
if self.active_ws_panel is None:
521
lcmd = self.active_ws_panel.CreateCmd()
525
# TODO: It is not clear how to do GetOptData in giface
526
# knowing what GetOptData is doing might help
527
# (maybe Get... is not the right name)
528
# please fix giface if you know
530
# GetLayerTree -> GetLayerList
531
# AddLayer -> AddLayer (but tree ones returns some layer,
532
# giface ones nothing)
533
# GetLayerInfo -> Layer object can by used instead
534
# GetOptData -> unknown
535
ltree = self.giface.GetLayerTree()
537
active_ws = self.active_ws_panel.GetWebService()
538
if 'WMS' not in active_ws:
539
cap_file = self.active_ws_panel.GetCapFile()
540
cmd_cap_file = grass.tempfile()
541
shutil.copyfile(cap_file, cmd_cap_file)
542
lcmd.append('capfile=' + cmd_cap_file)
544
layer = ltree.AddLayer(ltype = 'wms',
545
lname = self.active_ws_panel.GetOutputLayerName(),
546
lchecked = True, lcmd = lcmd)
549
ws_cap_files = self._getCapFiles()
550
# create properties dialog
551
cmd_list = ltree.GetLayerInfo(layer,'cmd')
552
cmd = CmdToTuple(cmd_list)
554
prop_win = WSPropertiesDialog(parent = self.parent,
555
giface = self.giface,
558
ws_cap_files = ws_cap_files,
562
ltree.GetOptData(dcmd = None, layer = layer,
563
params = None, propwin = prop_win)
565
class WSPropertiesDialog(WSDialogBase):
566
"""Dialog for editing web service properties."""
567
def __init__(self, parent, giface, layer, ws_cap_files, cmd, id = wx.ID_ANY,
568
style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER, **kwargs):
570
:param giface: grass interface
571
:param layer: layer tree item
572
:param ws_cap_files: dict web service('WMS_1.1.1', 'WMS_1.3.0',
573
'WMTS', 'OnEarth') : cap file path cap files, which will be parsed
574
:param cmd: cmd to which dialog widgets will be initialized if
575
it is possible (cmp parameters exists in parsed web service cap_file)
578
WSDialogBase.__init__(self, parent, id = wx.ID_ANY,
579
style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER, **kwargs)
581
self.SetTitle(_("Web service layer properties"))
586
# after web service panels are connected, set dialog widgets
587
# according to cmd in this variable (if it is not None)
588
self.cmd_to_set = None
590
# store data needed for reverting
591
self.revert_ws_cap_files = {}
592
self.revert_cmd = cmd
594
ws_cap = self._getWSfromCmd(cmd)
595
for ws in self.ws_panels.iterkeys():
596
# cap file used in cmd will be deleted, thnaks to the dialogs destructor
597
if ws == ws_cap and cmd[1].has_key('capfile'):
598
self.revert_ws_cap_files[ws] = cmd[1]['capfile']
601
self.revert_ws_cap_files[ws] = grass.tempfile()
603
self._setRevertCapFiles(ws_cap_files)
605
self.LoadCapFiles(ws_cap_files = self.revert_ws_cap_files, cmd = cmd)
606
self.btn_ok.SetDefault()
609
for f in self.revert_ws_cap_files.itervalues():
612
def _setRevertCapFiles(self, ws_cap_files):
614
for ws, f in ws_cap_files.iteritems():
615
if os.path.isfile(ws_cap_files[ws]):
616
shutil.copyfile(f, self.revert_ws_cap_files[ws])
618
# delete file content
622
def _createWidgets(self):
624
WSDialogBase._createWidgets(self)
626
self.btn_apply = wx.Button(parent = self, id = wx.ID_ANY, label = _("&Apply"))
627
self.btn_apply.SetToolTipString(_("Apply changes"))
628
self.btn_apply.Enable(False)
629
self.run_btns.append(self.btn_apply)
631
self.btn_ok = wx.Button(parent = self, id = wx.ID_ANY, label = _("&OK"))
632
self.btn_ok.SetToolTipString(_("Apply changes and close dialog"))
633
self.btn_ok.Enable(False)
634
self.run_btns.append(self.btn_ok)
638
WSDialogBase._doLayout(self)
640
self.btnsizer.Add(item = self.btn_apply, proportion = 0,
641
flag = wx.ALL | wx.ALIGN_CENTER,
644
self.btnsizer.Add(item = self.btn_ok, proportion = 0,
645
flag = wx.ALL | wx.ALIGN_CENTER,
649
self.btn_apply.Bind(wx.EVT_BUTTON, self.OnApply)
650
self.btn_ok.Bind(wx.EVT_BUTTON, self.OnSave)
652
def LoadCapFiles(self, ws_cap_files, cmd):
653
"""Parse cap files and update dialog.
655
For parameters description, see the constructor.
657
self.ch_ws_sizer.Clear(deleteWindows = True)
659
self.cmd_to_set = cmd
661
self.finished_panels_num = 0
663
conn = self._getServerConnFromCmd(cmd)
665
self.server.SetValue(conn['url'])
666
self.password.SetValue(conn['password'])
667
self.username.SetValue(conn['username'])
669
self.layerName.SetValue(cmd[1]['map'])
671
for ws, data in self.ws_panels.iteritems():
674
if ws_cap_files.has_key(ws):
675
cap_file = ws_cap_files[ws]
677
data['panel'].ParseCapFile(url = conn['url'],
678
username = conn['password'],
679
password = conn['username'],
682
def _getServerConnFromCmd(self, cmd):
683
"""Get url/server/passwod from cmd tuple
685
conn = { 'url' : '', 'username' : '', 'password' : ''}
687
for k in conn.iterkeys():
688
if cmd[1].has_key(k):
693
"""Apply chosen values from widgets to web service layer."""
694
lcmd = self.active_ws_panel.CreateCmd()
698
active_ws = self.active_ws_panel.GetWebService()
699
if 'WMS' not in active_ws:
700
lcmd.append('capfile=' + self.revert_ws_cap_files[active_ws])
702
self.giface.GetLayerTree().GetOptData(dcmd = lcmd,
707
#TODO use just list or tuple
708
cmd = CmdToTuple(lcmd)
709
self.revert_cmd = cmd
710
self._setRevertCapFiles(self._getCapFiles())
712
self.giface.updateMap.emit()
714
def UpdateDialogAfterConnection(self):
715
"""Connect to the server
717
WSDialogBase.UpdateDialogAfterConnection(self)
718
if self._getConnectedWS():
719
self.btn_ok.SetDefault()
721
self.btn_connect.SetDefault()
723
def OnApply(self, event):
726
def OnSave(self, event):
730
def OnClose(self, event):
737
self.LoadCapFiles(cmd = self.revert_cmd,
738
ws_cap_files = self.revert_ws_cap_files)
740
def OnPanelCapParsed(self, error_msg):
741
"""Called when panel has downloaded and parsed capabilities file.
743
WSDialogBase.OnPanelCapParsed(self, error_msg)
745
if self.finished_panels_num == len(self.ws_panels):
747
self._updateWsPanelWidgetsByCmd(self.cmd_to_set)
748
self.cmd_to_set = None
750
def _updateWsPanelWidgetsByCmd(self, cmd):
751
"""Set values of widgets according to parameters in cmd.
754
ws = self._getWSfromCmd(cmd)
755
if self.ws_panels[ws]['panel'].IsConnected():
756
self.ws_panels[ws]['panel'].UpdateWidgetsByCmd(cmd)
757
self.choose_ws_rb.SetStringSelection(self.ws_panels[ws]['label'])
758
self._showWsPanel(ws)
760
def _getWSfromCmd(self, cmd):
761
driver = cmd[1]['driver']
762
ws = driver.split('_')[0]
765
ws += '_' + cmd[1]['wms_version']
768
class SaveWMSLayerDialog(wx.Dialog):
769
"""Dialog for saving web service layer into GRASS vector/raster layer.
772
Implement saving data in region of map display.
774
def __init__(self, parent, layer, giface):
776
wx.Dialog.__init__(self, parent = parent, title = ("Save web service layer as raster map"), id = wx.ID_ANY)
779
self._giface = giface
781
self.cmd = self.layer.GetCmd()
783
self.thread = CmdThread(self)
784
self.cmdStdErr = GStderr(self)
786
self._createWidgets()
788
def _createWidgets(self):
793
self.labels['output'] = wx.StaticText(parent = self, id = wx.ID_ANY, label = _("Name for output raster map:"))
795
self.params['output'] = Select(parent = self, type = 'raster', mapsets = [grass.gisenv()['MAPSET']],
796
size = globalvar.DIALOG_GSELECT_SIZE)
798
self.regionStBoxLabel = wx.StaticBox(parent = self, id = wx.ID_ANY,
799
label = " %s " % _("Export region"))
801
self.region_types_order = ['display', 'comp', 'named']
802
self.region_types = {}
803
self.region_types['display'] = wx.RadioButton(parent=self, label=_("Map display"),
805
self.region_types['comp'] = wx.RadioButton(parent=self, label=_("Computational region"))
806
self.region_types['named'] = wx.RadioButton(parent=self, label=_("Named region"))
807
self.region_types['display'].SetToolTipString(_("Extent and resolution"
808
" are based on Map Display geometry."))
809
self.region_types['comp'].SetToolTipString(_("Extent and resolution"
810
" are based on computational region."))
811
self.region_types['named'].SetToolTipString(_("Extent and resolution"
812
" are based on named region."))
813
self.region_types['display'].SetValue(True) # set default as map display
815
self.overwrite = wx.CheckBox(parent = self, id = wx.ID_ANY,
816
label = _("Overwrite existing raster map"))
818
self.named_reg_panel = wx.Panel(parent = self, id = wx.ID_ANY)
819
self.labels['region'] = wx.StaticText(parent = self.named_reg_panel, id = wx.ID_ANY,
820
label = _("Choose named region:"))
822
self.params['region'] = Select(parent = self.named_reg_panel, type = 'region',
823
size = globalvar.DIALOG_GSELECT_SIZE)
826
self.btn_close = wx.Button(parent = self, id = wx.ID_CLOSE)
827
self.btn_close.SetToolTipString(_("Close dialog"))
829
self.btn_ok = wx.Button(parent=self, id=wx.ID_OK, label=_("&Save layer"))
830
self.btn_ok.SetToolTipString(_("Save web service layer as raster map"))
833
self.statusbar = wx.StatusBar(parent = self, id = wx.ID_ANY)
839
self._border = wx.BoxSizer(wx.VERTICAL)
840
dialogSizer = wx.BoxSizer(wx.VERTICAL)
842
regionSizer = wx.BoxSizer(wx.HORIZONTAL)
844
dialogSizer.Add(item = self._addSelectSizer(title = self.labels['output'],
845
sel = self.params['output']))
847
regionSizer = wx.StaticBoxSizer(self.regionStBoxLabel, wx.VERTICAL)
849
regionTypeSizer = wx.BoxSizer(wx.HORIZONTAL)
850
for r_type in self.region_types_order:
851
regionTypeSizer.Add(item=self.region_types[r_type], flag=wx.RIGHT, border=8)
853
regionSizer.Add(item = regionTypeSizer)
855
self.named_reg_panel.SetSizer(self._addSelectSizer(title = self.labels['region'],
856
sel = self.params['region']))
857
regionSizer.Add(item = self.named_reg_panel)
858
self.named_reg_panel.Hide()
860
dialogSizer.Add(item = regionSizer, flag = wx.EXPAND)
862
dialogSizer.Add(item=self.overwrite, flag=wx.TOP, border=10)
865
self.btnsizer = wx.BoxSizer(orient = wx.HORIZONTAL)
867
self.btnsizer.Add(item = self.btn_close, proportion = 0,
868
flag = wx.ALL | wx.ALIGN_CENTER,
871
self.btnsizer.Add(item = self.btn_ok, proportion = 0,
872
flag = wx.ALL | wx.ALIGN_CENTER,
875
dialogSizer.Add(item = self.btnsizer, proportion = 0,
876
flag = wx.ALIGN_CENTER)
878
self._border.Add(item=dialogSizer, proportion=0,
879
flag=wx.ALL, border=5)
881
self._border.Add(item=self.statusbar, proportion=0)
883
self.SetSizer(self._border)
888
self.btn_close.Bind(wx.EVT_BUTTON, self.OnClose)
889
self.btn_ok.Bind(wx.EVT_BUTTON, self.OnSave)
891
self.Bind(EVT_CMD_DONE, self.OnCmdDone)
892
self.Bind(EVT_CMD_OUTPUT, self.OnCmdOutput)
894
for r_type in self.region_types_order:
895
self.Bind(wx.EVT_RADIOBUTTON, self.OnRegionType, self.region_types[r_type])
897
def _addSelectSizer(self, title, sel):
898
"""Helper layout function.
900
selSizer = wx.BoxSizer(orient = wx.VERTICAL)
902
selTitleSizer = wx.BoxSizer(wx.HORIZONTAL)
903
selTitleSizer.Add(item = title, proportion = 1,
904
flag = wx.LEFT | wx.TOP | wx.EXPAND, border = 5)
906
selSizer.Add(item = selTitleSizer, proportion = 0,
909
selSizer.Add(item = sel, proportion = 1,
910
flag = wx.EXPAND | wx.ALL| wx.ALIGN_CENTER_VERTICAL,
915
def OnClose(self, event):
918
if not self.IsModal():
922
def OnRegionType(self, event):
923
selected = event.GetEventObject()
924
if selected == self.region_types['named']:
925
self.named_reg_panel.Show()
927
self.named_reg_panel.Hide()
929
self._border.Layout()
932
def OnSave(self, event):
933
"""Import WMS raster data into GRASS as raster layer.
935
self.thread.abort(abortall = True)
936
currmapset = grass.gisenv()['MAPSET']
938
self.output = self.params['output'].GetValue().strip()
939
l_spl = self.output.strip().split("@")
944
msg = _('Missing output raster.')
946
elif len(l_spl) > 1 and \
947
l_spl[1] != currmapset:
948
msg = _('Output map can be added only to current mapset.')
950
elif not self.overwrite.IsChecked() and\
951
grass.find_file(self.output, 'cell', '.')['fullname']:
952
msg = _('Output map <%s> already exists' % self.output)
955
GMessage(parent = self,
959
self.output = l_spl[0]
963
region = self.params['region'].GetValue().strip()
964
reg_spl = region.strip().split("@")
968
reg_mapset = reg_spl[1]
970
if self.region_types['named'].GetValue():
971
if not grass.find_file(reg_spl[0], 'windows', reg_mapset)['fullname']:
972
msg = _('Region <%s> does not exist.' % self.params['region'].GetValue())
973
GWarning(parent=self,
977
# create r.in.wms command
978
cmd = ('r.in.wms', deepcopy(self.cmd[1]))
980
if cmd[1].has_key('map'):
983
cmd[1]['output'] = self.output
985
if self.overwrite.IsChecked():
986
cmd[1]['overwrite'] = True
988
env = os.environ.copy()
989
if self.region_types['named'].GetValue():
990
cmd[1]['region'] = region
991
elif self.region_types['display'].GetValue():
992
region = self._giface.GetMapWindow().GetMap().SetRegion()
993
env['GRASS_REGION'] = region
995
cmdList = CmdTupleToList(cmd)
996
self.currentPid = self.thread.GetId()
998
self.thread.RunCmd(cmdList, env=env, stderr=self.cmdStdErr)
1000
self.statusbar.SetStatusText(_("Downloading data..."))
1002
def OnCmdDone(self, event):
1003
"""When data are fetched.
1005
if event.pid != self.currentPid:
1009
self.statusbar.SetStatusText("")
1011
def _addLayer(self):
1012
"""Add layer into layer tree.
1014
llist = self._giface.GetLayerList()
1015
if len(llist.GetLayersByName(self.output)) == 0:
1016
cmd = ['d.rast', 'map=' + self.output]
1017
llist.AddLayer(ltype='raster',
1022
def OnCmdOutput(self, event):
1023
"""Handle cmd output according to debug level.
1025
if Debug.GetLevel() == 0:
1026
if event.type == 'error':
1027
msg = _('Unable to fetch data.\n')
1029
GWarning(parent = self,
1032
Debug.msg(1, event.text)