|
GRASS Programmer's Manual
6.5.svn(2012)-r51648
|
00001 """! 00002 @package gui_core.dialogs 00003 00004 @brief Various dialogs used in wxGUI. 00005 00006 List of classes: 00007 - dialogs::ElementDialog 00008 - dialogs::LocationDialog 00009 - dialogs::MapsetDialog 00010 - dialogs::NewVectorDialog 00011 - dialogs::SavedRegion 00012 - dialogs::DecorationDialog 00013 - dialogs::TextLayerDialog 00014 - dialogs::GroupDialog 00015 - dialogs::MapLayersDialog 00016 - dialogs::ImportDialog 00017 - dialogs::GdalImportDialog 00018 - dialogs::DxfImportDialog 00019 - dialogs::LayersList (used by MultiImport) 00020 - dialogs::SetOpacityDialog 00021 - dialogs::ImageSizeDialog 00022 00023 (C) 2008-2011 by the GRASS Development Team 00024 00025 This program is free software under the GNU General Public License 00026 (>=v2). Read the file COPYING that comes with GRASS for details. 00027 00028 @author Martin Landa <landa.martin gmail.com> 00029 @author Anna Kratochvilova <kratochanna gmail.com> (GroupDialog) 00030 """ 00031 00032 import os 00033 import sys 00034 import re 00035 from bisect import bisect 00036 00037 import wx 00038 import wx.lib.filebrowsebutton as filebrowse 00039 import wx.lib.mixins.listctrl as listmix 00040 00041 from grass.script import core as grass 00042 from grass.script import task as gtask 00043 00044 from core import globalvar 00045 from core.gcmd import GError, RunCommand, GMessage 00046 from gui_core.gselect import ElementSelect, LocationSelect, MapsetSelect, Select, GdalSelect 00047 from gui_core.forms import GUI 00048 from gui_core.widgets import SingleSymbolPanel, EVT_SYMBOL_SELECTION_CHANGED 00049 from core.utils import GetListOfMapsets, GetLayerNameFromCmd, GetValidLayerName 00050 from core.settings import UserSettings 00051 from core.debug import Debug 00052 00053 class ElementDialog(wx.Dialog): 00054 def __init__(self, parent, title, label, id = wx.ID_ANY, 00055 etype = False, style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER, 00056 **kwargs): 00057 """!General dialog to choose given element (location, mapset, vector map, etc.) 00058 00059 @param parent window 00060 @param title window title 00061 @param label element label 00062 @param etype show also ElementSelect 00063 """ 00064 wx.Dialog.__init__(self, parent, id, title, style = style, **kwargs) 00065 00066 self.etype = etype 00067 self.label = label 00068 00069 self.panel = wx.Panel(parent = self, id = wx.ID_ANY) 00070 00071 self.btnCancel = wx.Button(parent = self.panel, id = wx.ID_CANCEL) 00072 self.btnOK = wx.Button(parent = self.panel, id = wx.ID_OK) 00073 self.btnOK.SetDefault() 00074 self.btnOK.Enable(False) 00075 00076 if self.etype: 00077 self.typeSelect = ElementSelect(parent = self.panel, 00078 size = globalvar.DIALOG_GSELECT_SIZE) 00079 self.typeSelect.Bind(wx.EVT_CHOICE, self.OnType) 00080 00081 self.element = None # must be defined 00082 00083 self.__layout() 00084 00085 def PostInit(self): 00086 self.element.SetFocus() 00087 self.element.Bind(wx.EVT_TEXT, self.OnElement) 00088 00089 def OnType(self, event): 00090 """!Select element type""" 00091 if not self.etype: 00092 return 00093 evalue = self.typeSelect.GetValue(event.GetString()) 00094 self.element.SetType(evalue) 00095 00096 def OnElement(self, event): 00097 """!Name for vector map layer given""" 00098 if len(event.GetString()) > 0: 00099 self.btnOK.Enable(True) 00100 else: 00101 self.btnOK.Enable(False) 00102 00103 def __layout(self): 00104 """!Do layout""" 00105 self.sizer = wx.BoxSizer(wx.VERTICAL) 00106 00107 self.dataSizer = wx.BoxSizer(wx.VERTICAL) 00108 00109 if self.etype: 00110 self.dataSizer.Add(item = wx.StaticText(parent = self.panel, id = wx.ID_ANY, 00111 label = _("Type of element:")), 00112 proportion = 0, flag = wx.ALL, border = 1) 00113 self.dataSizer.Add(item = self.typeSelect, 00114 proportion = 0, flag = wx.ALL, border = 1) 00115 00116 self.dataSizer.Add(item = wx.StaticText(parent = self.panel, id = wx.ID_ANY, 00117 label = self.label), 00118 proportion = 0, flag = wx.ALL, border = 1) 00119 00120 # buttons 00121 btnSizer = wx.StdDialogButtonSizer() 00122 btnSizer.AddButton(self.btnCancel) 00123 btnSizer.AddButton(self.btnOK) 00124 btnSizer.Realize() 00125 00126 self.sizer.Add(item = self.dataSizer, proportion = 1, 00127 flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border = 5) 00128 00129 self.sizer.Add(item = btnSizer, proportion = 0, 00130 flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border = 5) 00131 00132 def GetElement(self): 00133 """!Return (mapName, overwrite)""" 00134 return self.element.GetValue() 00135 00136 def GetType(self): 00137 """!Get element type""" 00138 return self.element.tcp.GetType() 00139 00140 class LocationDialog(ElementDialog): 00141 """!Dialog used to select location""" 00142 def __init__(self, parent, title = _("Select GRASS location and mapset"), id = wx.ID_ANY): 00143 ElementDialog.__init__(self, parent, title, label = _("Name of GRASS location:")) 00144 00145 self.element = LocationSelect(parent = self.panel, id = wx.ID_ANY, 00146 size = globalvar.DIALOG_GSELECT_SIZE) 00147 00148 self.element1 = MapsetSelect(parent = self.panel, id = wx.ID_ANY, 00149 size = globalvar.DIALOG_GSELECT_SIZE, 00150 setItems = False, skipCurrent = True) 00151 00152 self.PostInit() 00153 00154 self._layout() 00155 self.SetMinSize(self.GetSize()) 00156 00157 def _layout(self): 00158 """!Do layout""" 00159 self.dataSizer.Add(self.element, proportion = 0, 00160 flag = wx.EXPAND | wx.ALL, border = 1) 00161 00162 self.dataSizer.Add(wx.StaticText(parent = self.panel, id = wx.ID_ANY, 00163 label = _("Name of mapset:")), proportion = 0, 00164 flag = wx.EXPAND | wx.ALL, border = 1) 00165 00166 self.dataSizer.Add(self.element1, proportion = 0, 00167 flag = wx.EXPAND | wx.ALL, border = 1) 00168 00169 self.panel.SetSizer(self.sizer) 00170 self.sizer.Fit(self) 00171 00172 def OnElement(self, event): 00173 """!Select mapset given location name""" 00174 location = event.GetString() 00175 00176 if location: 00177 dbase = grass.gisenv()['GISDBASE'] 00178 self.element1.UpdateItems(dbase = dbase, location = location) 00179 self.element1.SetSelection(0) 00180 mapset = self.element1.GetStringSelection() 00181 00182 if location and mapset: 00183 self.btnOK.Enable(True) 00184 else: 00185 self.btnOK.Enable(False) 00186 00187 def GetValues(self): 00188 """!Get location, mapset""" 00189 return (self.GetElement(), self.element1.GetStringSelection()) 00190 00191 class MapsetDialog(ElementDialog): 00192 """!Dialog used to select mapset""" 00193 def __init__(self, parent, title = _("Select mapset in GRASS location"), 00194 location = None, id = wx.ID_ANY): 00195 ElementDialog.__init__(self, parent, title, label = _("Name of mapset:")) 00196 if location: 00197 self.SetTitle(self.GetTitle() + ' <%s>' % location) 00198 else: 00199 self.SetTitle(self.GetTitle() + ' <%s>' % grass.gisenv()['LOCATION_NAME']) 00200 00201 self.element = MapsetSelect(parent = self.panel, id = wx.ID_ANY, skipCurrent = True, 00202 size = globalvar.DIALOG_GSELECT_SIZE) 00203 00204 self.PostInit() 00205 00206 self.__Layout() 00207 self.SetMinSize(self.GetSize()) 00208 00209 def __Layout(self): 00210 """!Do layout""" 00211 self.dataSizer.Add(self.element, proportion = 0, 00212 flag = wx.EXPAND | wx.ALL, border = 1) 00213 00214 self.panel.SetSizer(self.sizer) 00215 self.sizer.Fit(self) 00216 00217 def GetMapset(self): 00218 return self.GetElement() 00219 00220 class NewVectorDialog(ElementDialog): 00221 def __init__(self, parent, id = wx.ID_ANY, title = _('Create new vector map'), 00222 disableAdd = False, disableTable = False, 00223 style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER, *kwargs): 00224 """!Dialog for creating new vector map 00225 00226 @param parent parent window 00227 @param id window id 00228 @param title window title 00229 @param disableAdd disable 'add layer' checkbox 00230 @param disableTable disable 'create table' checkbox 00231 @param style window style 00232 @param kwargs other argumentes for ElementDialog 00233 00234 @return dialog instance 00235 """ 00236 ElementDialog.__init__(self, parent, title, label = _("Name for new vector map:")) 00237 00238 self.element = Select(parent = self.panel, id = wx.ID_ANY, size = globalvar.DIALOG_GSELECT_SIZE, 00239 type = 'vector', mapsets = [grass.gisenv()['MAPSET'],]) 00240 00241 self.table = wx.CheckBox(parent = self.panel, id = wx.ID_ANY, 00242 label = _("Create attribute table")) 00243 self.table.SetValue(True) 00244 if disableTable: 00245 self.table.Enable(False) 00246 00247 self.keycol = wx.TextCtrl(parent = self.panel, id = wx.ID_ANY, 00248 size = globalvar.DIALOG_SPIN_SIZE) 00249 self.keycol.SetValue(UserSettings.Get(group = 'atm', key = 'keycolumn', subkey = 'value')) 00250 if disableTable: 00251 self.keycol.Enable(False) 00252 00253 self.addbox = wx.CheckBox(parent = self.panel, 00254 label = _('Add created map into layer tree'), style = wx.NO_BORDER) 00255 if disableAdd: 00256 self.addbox.SetValue(True) 00257 self.addbox.Enable(False) 00258 else: 00259 self.addbox.SetValue(UserSettings.Get(group = 'cmd', key = 'addNewLayer', subkey = 'enabled')) 00260 00261 self.table.Bind(wx.EVT_CHECKBOX, self.OnTable) 00262 00263 self.PostInit() 00264 00265 self._layout() 00266 self.SetMinSize(self.GetSize()) 00267 00268 def OnMapName(self, event): 00269 """!Name for vector map layer given""" 00270 self.OnElement(event) 00271 00272 def OnTable(self, event): 00273 self.keycol.Enable(event.IsChecked()) 00274 00275 def _layout(self): 00276 """!Do layout""" 00277 self.dataSizer.Add(self.element, proportion = 0, 00278 flag = wx.EXPAND | wx.ALL, border = 1) 00279 00280 self.dataSizer.Add(self.table, proportion = 0, 00281 flag = wx.EXPAND | wx.ALL, border = 1) 00282 00283 keySizer = wx.BoxSizer(wx.HORIZONTAL) 00284 keySizer.Add(item = wx.StaticText(parent = self.panel, label = _("Key column:")), 00285 proportion = 0, 00286 flag = wx.ALIGN_CENTER_VERTICAL) 00287 keySizer.AddSpacer(10) 00288 keySizer.Add(item = self.keycol, proportion = 0, 00289 flag = wx.ALIGN_RIGHT) 00290 self.dataSizer.Add(item = keySizer, proportion = 1, 00291 flag = wx.EXPAND | wx.ALL, border = 1) 00292 00293 self.dataSizer.AddSpacer(5) 00294 00295 self.dataSizer.Add(item = self.addbox, proportion = 0, 00296 flag = wx.EXPAND | wx.ALL, border = 1) 00297 00298 self.panel.SetSizer(self.sizer) 00299 self.sizer.Fit(self) 00300 00301 def GetName(self, full = False): 00302 """!Get name of vector map to be created 00303 00304 @param full True to get fully qualified name 00305 """ 00306 name = self.GetElement() 00307 if full: 00308 if '@' in name: 00309 return name 00310 else: 00311 return name + '@' + grass.gisenv()['MAPSET'] 00312 00313 return name.split('@', 1)[0] 00314 00315 def GetKey(self): 00316 """!Get key column name""" 00317 return self.keycol.GetValue() 00318 00319 def IsChecked(self, key): 00320 """!Get dialog properties 00321 00322 @param key window key ('add', 'table') 00323 00324 @return True/False 00325 @return None on error 00326 """ 00327 if key == 'add': 00328 return self.addbox.IsChecked() 00329 elif key == 'table': 00330 return self.table.IsChecked() 00331 00332 return None 00333 00334 def CreateNewVector(parent, cmd, title = _('Create new vector map'), 00335 exceptMap = None, log = None, disableAdd = False, disableTable = False): 00336 """!Create new vector map layer 00337 00338 @param cmd (prog, **kwargs) 00339 @param title window title 00340 @param exceptMap list of maps to be excepted 00341 @param log 00342 @param disableAdd disable 'add layer' checkbox 00343 @param disableTable disable 'create table' checkbox 00344 00345 @return dialog instance 00346 @return None on error 00347 """ 00348 dlg = NewVectorDialog(parent, title = title, 00349 disableAdd = disableAdd, disableTable = disableTable) 00350 00351 if dlg.ShowModal() != wx.ID_OK: 00352 dlg.Destroy() 00353 return None 00354 00355 outmap = dlg.GetName() 00356 key = dlg.GetKey() 00357 if outmap == exceptMap: 00358 GError(parent = parent, 00359 message = _("Unable to create vector map <%s>.") % outmap) 00360 dlg.Destroy() 00361 return None 00362 if dlg.table.IsEnabled() and not key: 00363 GError(parent = parent, 00364 message = _("Invalid or empty key column.\n" 00365 "Unable to create vector map <%s>.") % outmap) 00366 dlg.Destroy() 00367 return 00368 00369 if outmap == '': # should not happen 00370 dlg.Destroy() 00371 return None 00372 00373 # update cmd -> output name defined 00374 cmd[1][cmd[2]] = outmap 00375 00376 listOfVectors = grass.list_grouped('vect')[grass.gisenv()['MAPSET']] 00377 00378 overwrite = False 00379 if not UserSettings.Get(group = 'cmd', key = 'overwrite', subkey = 'enabled') and \ 00380 outmap in listOfVectors: 00381 dlgOw = wx.MessageDialog(parent, message = _("Vector map <%s> already exists " 00382 "in the current mapset. " 00383 "Do you want to overwrite it?") % outmap, 00384 caption = _("Overwrite?"), 00385 style = wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION) 00386 if dlgOw.ShowModal() == wx.ID_YES: 00387 overwrite = True 00388 else: 00389 dlgOw.Destroy() 00390 dlg.Destroy() 00391 return None 00392 00393 if UserSettings.Get(group = 'cmd', key = 'overwrite', subkey = 'enabled'): 00394 overwrite = True 00395 00396 ret = RunCommand(prog = cmd[0], 00397 parent = parent, 00398 overwrite = overwrite, 00399 **cmd[1]) 00400 if ret != 0: 00401 dlg.Destroy() 00402 return None 00403 00404 # create attribute table 00405 if dlg.table.IsEnabled() and dlg.table.IsChecked(): 00406 sql = 'CREATE TABLE %s (%s INTEGER)' % (outmap, key) 00407 00408 RunCommand('db.connect', 00409 flags = 'c') 00410 00411 Debug.msg(1, "SQL: %s" % sql) 00412 RunCommand('db.execute', 00413 quiet = True, 00414 parent = parent, 00415 input = '-', 00416 stdin = sql) 00417 00418 RunCommand('v.db.connect', 00419 quiet = True, 00420 parent = parent, 00421 map = outmap, 00422 table = outmap, 00423 key = key, 00424 layer = '1') 00425 00426 # return fully qualified map name 00427 if '@' not in outmap: 00428 outmap += '@' + grass.gisenv()['MAPSET'] 00429 00430 if log: 00431 log.WriteLog(_("New vector map <%s> created") % outmap) 00432 00433 return dlg 00434 00435 class SavedRegion(wx.Dialog): 00436 def __init__(self, parent, id = wx.ID_ANY, title = "", loadsave = 'load', 00437 **kwargs): 00438 """!Loading and saving of display extents to saved region file 00439 00440 @param loadsave load or save region? 00441 """ 00442 wx.Dialog.__init__(self, parent, id, title, **kwargs) 00443 00444 self.loadsave = loadsave 00445 self.wind = '' 00446 00447 sizer = wx.BoxSizer(wx.VERTICAL) 00448 00449 box = wx.BoxSizer(wx.HORIZONTAL) 00450 label = wx.StaticText(parent = self, id = wx.ID_ANY) 00451 box.Add(item = label, proportion = 0, flag = wx.ALIGN_CENTRE | wx.ALL, border = 5) 00452 if loadsave == 'load': 00453 label.SetLabel(_("Load region:")) 00454 selection = Select(parent = self, id = wx.ID_ANY, size = globalvar.DIALOG_GSELECT_SIZE, 00455 type = 'windows') 00456 elif loadsave == 'save': 00457 label.SetLabel(_("Save region:")) 00458 selection = Select(parent = self, id = wx.ID_ANY, size = globalvar.DIALOG_GSELECT_SIZE, 00459 type = 'windows', mapsets = [grass.gisenv()['MAPSET']]) 00460 00461 box.Add(item = selection, proportion = 0, flag = wx.ALIGN_CENTRE | wx.ALL, border = 5) 00462 selection.SetFocus() 00463 selection.Bind(wx.EVT_TEXT, self.OnRegion) 00464 00465 sizer.Add(item = box, proportion = 0, flag = wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 00466 border = 5) 00467 00468 line = wx.StaticLine(parent = self, id = wx.ID_ANY, size = (20, -1), style = wx.LI_HORIZONTAL) 00469 sizer.Add(item = line, proportion = 0, 00470 flag = wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, border = 5) 00471 00472 btnsizer = wx.StdDialogButtonSizer() 00473 00474 btn = wx.Button(parent = self, id = wx.ID_OK) 00475 btn.SetDefault() 00476 btnsizer.AddButton(btn) 00477 00478 btn = wx.Button(parent = self, id = wx.ID_CANCEL) 00479 btnsizer.AddButton(btn) 00480 btnsizer.Realize() 00481 00482 sizer.Add(item = btnsizer, proportion = 0, flag = wx.ALIGN_RIGHT | wx.ALL, border = 5) 00483 00484 self.SetSizer(sizer) 00485 sizer.Fit(self) 00486 self.Layout() 00487 00488 def OnRegion(self, event): 00489 self.wind = event.GetString() 00490 00491 class DecorationDialog(wx.Dialog): 00492 """ 00493 Controls setting options and displaying/hiding map overlay decorations 00494 """ 00495 def __init__(self, parent, ovlId, title, cmd, name = None, 00496 pos = wx.DefaultPosition, size = wx.DefaultSize, style = wx.DEFAULT_DIALOG_STYLE, 00497 checktxt = '', ctrltxt = ''): 00498 00499 wx.Dialog.__init__(self, parent, wx.ID_ANY, title, pos, size, style) 00500 00501 self.ovlId = ovlId # PseudoDC id 00502 self.cmd = cmd 00503 self.name = name # overlay name 00504 self.parent = parent # MapFrame 00505 00506 sizer = wx.BoxSizer(wx.VERTICAL) 00507 00508 box = wx.BoxSizer(wx.HORIZONTAL) 00509 self.chkbox = wx.CheckBox(parent = self, id = wx.ID_ANY, label = checktxt) 00510 if self.parent.Map.GetOverlay(self.ovlId) is None: 00511 self.chkbox.SetValue(True) 00512 else: 00513 self.chkbox.SetValue(self.parent.MapWindow.overlays[self.ovlId]['layer'].IsActive()) 00514 box.Add(item = self.chkbox, proportion = 0, 00515 flag = wx.ALIGN_CENTRE|wx.ALL, border = 5) 00516 sizer.Add(item = box, proportion = 0, 00517 flag = wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, border = 5) 00518 00519 box = wx.BoxSizer(wx.HORIZONTAL) 00520 optnbtn = wx.Button(parent = self, id = wx.ID_ANY, label = _("Set options")) 00521 box.Add(item = optnbtn, proportion = 0, flag = wx.ALIGN_CENTRE|wx.ALL, border = 5) 00522 sizer.Add(item = box, proportion = 0, 00523 flag = wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, border = 5) 00524 if self.name == 'legend': 00525 box = wx.BoxSizer(wx.HORIZONTAL) 00526 resize = wx.ToggleButton(parent = self, id = wx.ID_ANY, label = _("Set size and position")) 00527 resize.SetToolTipString(_("Click and drag on the map display to set legend" 00528 " size and position and then press OK")) 00529 resize.SetName('resize') 00530 if self.parent.IsPaneShown('3d'): 00531 resize.Disable() 00532 box.Add(item = resize, proportion = 0, flag = wx.ALIGN_CENTRE|wx.ALL, border = 5) 00533 sizer.Add(item = box, proportion = 0, 00534 flag = wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, border = 5) 00535 00536 box = wx.BoxSizer(wx.HORIZONTAL) 00537 label = wx.StaticText(parent = self, id = wx.ID_ANY, 00538 label = _("Drag %s with mouse in pointer mode to position.\n" 00539 "Double-click to change options." % ctrltxt)) 00540 if self.name == 'legend': 00541 label.SetLabel(label.GetLabel() + _('\nDefine raster map name for legend in ' 00542 'properties dialog.')) 00543 box.Add(item = label, proportion = 0, 00544 flag = wx.ALIGN_CENTRE|wx.ALL, border = 5) 00545 sizer.Add(item = box, proportion = 0, 00546 flag = wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, border = 5) 00547 00548 line = wx.StaticLine(parent = self, id = wx.ID_ANY, size = (20,-1), style = wx.LI_HORIZONTAL) 00549 sizer.Add(item = line, proportion = 0, 00550 flag = wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, border = 5) 00551 00552 # buttons 00553 btnsizer = wx.StdDialogButtonSizer() 00554 00555 self.btnOK = wx.Button(parent = self, id = wx.ID_OK) 00556 self.btnOK.SetDefault() 00557 if self.name == 'legend': 00558 self.btnOK.Enable(False) 00559 btnsizer.AddButton(self.btnOK) 00560 00561 btnCancel = wx.Button(parent = self, id = wx.ID_CANCEL) 00562 btnsizer.AddButton(btnCancel) 00563 btnsizer.Realize() 00564 00565 sizer.Add(item = btnsizer, proportion = 0, 00566 flag = wx.EXPAND | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border = 5) 00567 00568 # 00569 # bindings 00570 # 00571 self.Bind(wx.EVT_BUTTON, self.OnOptions, optnbtn) 00572 if self.name == 'legend': 00573 self.Bind(wx.EVT_TOGGLEBUTTON, self.OnResize, resize) 00574 self.Bind(wx.EVT_BUTTON, self.OnCancel, btnCancel) 00575 self.Bind(wx.EVT_BUTTON, self.OnOK, self.btnOK) 00576 00577 self.SetSizer(sizer) 00578 sizer.Fit(self) 00579 00580 # create overlay if doesn't exist 00581 self._createOverlay() 00582 00583 if len(self.parent.MapWindow.overlays[self.ovlId]['cmd']) > 1: 00584 if name == 'legend': 00585 mapName, found = GetLayerNameFromCmd(self.parent.MapWindow.overlays[self.ovlId]['cmd']) 00586 if found: 00587 # enable 'OK' button 00588 self.btnOK.Enable() 00589 # set title 00590 self.SetTitle(_('Legend of raster map <%s>') % \ 00591 mapName) 00592 00593 00594 def _createOverlay(self): 00595 """!Creates overlay""" 00596 if not self.parent.Map.GetOverlay(self.ovlId): 00597 self.newOverlay = self.parent.Map.AddOverlay(id = self.ovlId, type = self.name, 00598 command = self.cmd, 00599 l_active = False, l_render = False, l_hidden = True) 00600 prop = { 'layer' : self.newOverlay, 00601 'params' : None, 00602 'propwin' : None, 00603 'cmd' : self.cmd, 00604 'coords': (0, 0), 00605 'pdcType': 'image' } 00606 self.parent.MapWindow2D.overlays[self.ovlId] = prop 00607 if self.parent.MapWindow3D: 00608 self.parent.MapWindow3D.overlays[self.ovlId] = prop 00609 00610 else: 00611 if self.parent.MapWindow.overlays[self.ovlId]['propwin'] == None: 00612 return 00613 00614 self.parent.MapWindow.overlays[self.ovlId]['propwin'].get_dcmd = self.GetOptData 00615 00616 00617 def OnOptions(self, event): 00618 """!Sets option for decoration map overlays 00619 """ 00620 if self.parent.MapWindow.overlays[self.ovlId]['propwin'] is None: 00621 # build properties dialog 00622 GUI(parent = self.parent).ParseCommand(cmd = self.cmd, 00623 completed = (self.GetOptData, self.name, '')) 00624 00625 else: 00626 if self.parent.MapWindow.overlays[self.ovlId]['propwin'].IsShown(): 00627 self.parent.MapWindow.overlays[self.ovlId]['propwin'].SetFocus() 00628 else: 00629 self.parent.MapWindow.overlays[self.ovlId]['propwin'].Show() 00630 00631 def OnResize(self, event): 00632 if self.FindWindowByName('resize').GetValue(): 00633 self.parent.MapWindow.SetCursor(self.parent.cursors["cross"]) 00634 self.parent.MapWindow.mouse['use'] = 'legend' 00635 self.parent.MapWindow.mouse['box'] = 'box' 00636 self.parent.MapWindow.pen = wx.Pen(colour = 'Black', width = 2, style = wx.SHORT_DASH) 00637 else: 00638 self.parent.MapWindow.SetCursor(self.parent.cursors["default"]) 00639 self.parent.MapWindow.mouse['use'] = 'pointer' 00640 00641 def OnCancel(self, event): 00642 """!Cancel dialog""" 00643 if self.name == 'legend' and self.FindWindowByName('resize').GetValue(): 00644 self.FindWindowByName('resize').SetValue(False) 00645 self.OnResize(None) 00646 00647 self.parent.dialogs['barscale'] = None 00648 00649 if event and hasattr(self, 'newOverlay'): 00650 self.parent.Map.DeleteOverlay(self.newOverlay) 00651 00652 self.Destroy() 00653 00654 def OnOK(self, event): 00655 """!Button 'OK' pressed""" 00656 # enable or disable overlay 00657 self.parent.Map.GetOverlay(self.ovlId).SetActive(self.chkbox.IsChecked()) 00658 00659 # update map 00660 if self.parent.IsPaneShown('3d'): 00661 self.parent.MapWindow.UpdateOverlays() 00662 00663 self.parent.MapWindow.UpdateMap() 00664 00665 # close dialog 00666 self.OnCancel(None) 00667 00668 def GetOptData(self, dcmd, layer, params, propwin): 00669 """!Process decoration layer data""" 00670 # update layer data 00671 if params: 00672 self.parent.MapWindow.overlays[self.ovlId]['params'] = params 00673 if dcmd: 00674 self.parent.MapWindow.overlays[self.ovlId]['cmd'] = dcmd 00675 self.parent.MapWindow.overlays[self.ovlId]['propwin'] = propwin 00676 00677 # change parameters for item in layers list in render.Map 00678 # "Use mouse..." (-m) flag causes GUI freeze and is pointless here, trac #119 00679 00680 try: 00681 self.parent.MapWindow.overlays[self.ovlId]['cmd'].remove('-m') 00682 except ValueError: 00683 pass 00684 00685 self.parent.Map.ChangeOverlay(id = self.ovlId, type = self.name, 00686 command = self.parent.MapWindow.overlays[self.ovlId]['cmd'], 00687 l_active = self.parent.MapWindow.overlays[self.ovlId]['layer'].IsActive(), 00688 l_render = False, l_hidden = True) 00689 if self.name == 'legend': 00690 if params and not self.btnOK.IsEnabled(): 00691 self.btnOK.Enable() 00692 00693 class TextLayerDialog(wx.Dialog): 00694 """ 00695 Controls setting options and displaying/hiding map overlay decorations 00696 """ 00697 00698 def __init__(self, parent, ovlId, title, name = 'text', 00699 pos = wx.DefaultPosition, size = wx.DefaultSize, style = wx.DEFAULT_DIALOG_STYLE): 00700 00701 wx.Dialog.__init__(self, parent, wx.ID_ANY, title, pos, size, style) 00702 from wx.lib.expando import ExpandoTextCtrl, EVT_ETC_LAYOUT_NEEDED 00703 00704 self.ovlId = ovlId 00705 self.parent = parent 00706 00707 if self.ovlId in self.parent.MapWindow.textdict.keys(): 00708 self.currText = self.parent.MapWindow.textdict[self.ovlId]['text'] 00709 self.currFont = self.parent.MapWindow.textdict[self.ovlId]['font'] 00710 self.currClr = self.parent.MapWindow.textdict[self.ovlId]['color'] 00711 self.currRot = self.parent.MapWindow.textdict[self.ovlId]['rotation'] 00712 self.currCoords = self.parent.MapWindow.textdict[self.ovlId]['coords'] 00713 self.currBB = self.parent.MapWindow.textdict[self.ovlId]['bbox'] 00714 else: 00715 self.currClr = wx.BLACK 00716 self.currText = '' 00717 self.currFont = self.GetFont() 00718 self.currRot = 0.0 00719 self.currCoords = [10, 10, 10, 10] 00720 self.currBB = wx.Rect() 00721 00722 self.sizer = wx.BoxSizer(wx.VERTICAL) 00723 box = wx.GridBagSizer(vgap = 5, hgap = 5) 00724 00725 # show/hide 00726 self.chkbox = wx.CheckBox(parent = self, id = wx.ID_ANY, 00727 label = _('Show text object')) 00728 if self.parent.Map.GetOverlay(self.ovlId) is None: 00729 self.chkbox.SetValue(True) 00730 else: 00731 self.chkbox.SetValue(self.parent.MapWindow.overlays[self.ovlId]['layer'].IsActive()) 00732 box.Add(item = self.chkbox, span = (1,2), 00733 flag = wx.ALIGN_LEFT|wx.ALL, border = 5, 00734 pos = (0, 0)) 00735 00736 # text entry 00737 label = wx.StaticText(parent = self, id = wx.ID_ANY, label = _("Enter text:")) 00738 box.Add(item = label, 00739 flag = wx.ALIGN_CENTER_VERTICAL, 00740 pos = (1, 0)) 00741 00742 self.textentry = ExpandoTextCtrl(parent = self, id = wx.ID_ANY, value = "", size = (300,-1)) 00743 self.textentry.SetFont(self.currFont) 00744 self.textentry.SetForegroundColour(self.currClr) 00745 self.textentry.SetValue(self.currText) 00746 # get rid of unneeded scrollbar when text box first opened 00747 self.textentry.SetClientSize((300,-1)) 00748 00749 box.Add(item = self.textentry, 00750 pos = (1, 1)) 00751 00752 # rotation 00753 label = wx.StaticText(parent = self, id = wx.ID_ANY, label = _("Rotation:")) 00754 box.Add(item = label, 00755 flag = wx.ALIGN_CENTER_VERTICAL, 00756 pos = (2, 0)) 00757 self.rotation = wx.SpinCtrl(parent = self, id = wx.ID_ANY, value = "", pos = (30, 50), 00758 size = (75,-1), style = wx.SP_ARROW_KEYS) 00759 self.rotation.SetRange(-360, 360) 00760 self.rotation.SetValue(int(self.currRot)) 00761 box.Add(item = self.rotation, 00762 flag = wx.ALIGN_RIGHT, 00763 pos = (2, 1)) 00764 00765 # font 00766 fontbtn = wx.Button(parent = self, id = wx.ID_ANY, label = _("Set font")) 00767 box.Add(item = fontbtn, 00768 flag = wx.ALIGN_RIGHT, 00769 pos = (3, 1)) 00770 00771 self.sizer.Add(item = box, proportion = 1, 00772 flag = wx.ALL, border = 10) 00773 00774 # note 00775 box = wx.BoxSizer(wx.HORIZONTAL) 00776 label = wx.StaticText(parent = self, id = wx.ID_ANY, 00777 label = _("Drag text with mouse in pointer mode " 00778 "to position.\nDouble-click to change options")) 00779 box.Add(item = label, proportion = 0, 00780 flag = wx.ALIGN_CENTRE | wx.ALL, border = 5) 00781 self.sizer.Add(item = box, proportion = 0, 00782 flag = wx.EXPAND | wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER | wx.ALL, border = 5) 00783 00784 line = wx.StaticLine(parent = self, id = wx.ID_ANY, 00785 size = (20,-1), style = wx.LI_HORIZONTAL) 00786 self.sizer.Add(item = line, proportion = 0, 00787 flag = wx.EXPAND | wx.ALIGN_CENTRE | wx.ALL, border = 5) 00788 00789 btnsizer = wx.StdDialogButtonSizer() 00790 00791 btn = wx.Button(parent = self, id = wx.ID_OK) 00792 btn.SetDefault() 00793 btnsizer.AddButton(btn) 00794 00795 btn = wx.Button(parent = self, id = wx.ID_CANCEL) 00796 btnsizer.AddButton(btn) 00797 btnsizer.Realize() 00798 00799 self.sizer.Add(item = btnsizer, proportion = 0, 00800 flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border = 5) 00801 00802 self.SetSizer(self.sizer) 00803 self.sizer.Fit(self) 00804 00805 # bindings 00806 self.Bind(EVT_ETC_LAYOUT_NEEDED, self.OnRefit, self.textentry) 00807 self.Bind(wx.EVT_BUTTON, self.OnSelectFont, fontbtn) 00808 self.Bind(wx.EVT_TEXT, self.OnText, self.textentry) 00809 self.Bind(wx.EVT_SPINCTRL, self.OnRotation, self.rotation) 00810 00811 def OnRefit(self, event): 00812 """!Resize text entry to match text""" 00813 self.sizer.Fit(self) 00814 00815 def OnText(self, event): 00816 """!Change text string""" 00817 self.currText = event.GetString() 00818 00819 def OnRotation(self, event): 00820 """!Change rotation""" 00821 self.currRot = event.GetInt() 00822 00823 event.Skip() 00824 00825 def OnSelectFont(self, event): 00826 """!Change font""" 00827 data = wx.FontData() 00828 data.EnableEffects(True) 00829 data.SetColour(self.currClr) # set colour 00830 data.SetInitialFont(self.currFont) 00831 00832 dlg = wx.FontDialog(self, data) 00833 00834 if dlg.ShowModal() == wx.ID_OK: 00835 data = dlg.GetFontData() 00836 self.currFont = data.GetChosenFont() 00837 self.currClr = data.GetColour() 00838 00839 self.textentry.SetFont(self.currFont) 00840 self.textentry.SetForegroundColour(self.currClr) 00841 00842 self.Layout() 00843 00844 dlg.Destroy() 00845 00846 def GetValues(self): 00847 """!Get text properties""" 00848 return { 'text' : self.currText, 00849 'font' : self.currFont, 00850 'color' : self.currClr, 00851 'rotation' : self.currRot, 00852 'coords' : self.currCoords, 00853 'active' : self.chkbox.IsChecked() } 00854 00855 class GroupDialog(wx.Dialog): 00856 """!Dialog for creating/editing groups""" 00857 def __init__(self, parent = None, defaultGroup = None, 00858 title = _("Create or edit imagery groups"), 00859 style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER, **kwargs): 00860 00861 wx.Dialog.__init__(self, parent = parent, id = wx.ID_ANY, title = title, 00862 style = style, **kwargs) 00863 00864 self.parent = parent 00865 self.defaultGroup = defaultGroup 00866 self.currentGroup = self.defaultGroup 00867 self.groupChanged = False 00868 00869 self.bodySizer = self._createDialogBody() 00870 00871 # buttons 00872 btnOk = wx.Button(parent = self, id = wx.ID_OK) 00873 btnApply = wx.Button(parent = self, id = wx.ID_APPLY) 00874 btnClose = wx.Button(parent = self, id = wx.ID_CANCEL) 00875 00876 btnOk.SetToolTipString(_("Apply changes to selected group and close dialog")) 00877 btnApply.SetToolTipString(_("Apply changes to selected group")) 00878 btnClose.SetToolTipString(_("Close dialog, changes are not applied")) 00879 00880 btnOk.SetDefault() 00881 00882 # sizers & do layout 00883 # btnSizer = wx.BoxSizer(wx.HORIZONTAL) 00884 # btnSizer.Add(item = btnClose, proportion = 0, 00885 # flag = wx.RIGHT | wx.ALIGN_RIGHT | wx.EXPAND, border = 5) 00886 # btnSizer.Add(item = btnApply, proportion = 0, 00887 # flag = wx.LEFT, border = 5) 00888 btnSizer = wx.StdDialogButtonSizer() 00889 btnSizer.AddButton(btnOk) 00890 btnSizer.AddButton(btnApply) 00891 btnSizer.AddButton(btnClose) 00892 btnSizer.Realize() 00893 00894 mainSizer = wx.BoxSizer(wx.VERTICAL) 00895 mainSizer.Add(item = self.bodySizer, proportion = 1, 00896 flag = wx.EXPAND | wx.LEFT | wx.RIGHT, border = 10) 00897 mainSizer.Add(item = wx.StaticLine(parent = self, id = wx.ID_ANY, 00898 style = wx.LI_HORIZONTAL), proportion = 0, 00899 flag = wx.EXPAND | wx.LEFT | wx.RIGHT, border = 10) 00900 00901 mainSizer.Add(item = btnSizer, proportion = 0, 00902 flag = wx.ALL | wx.ALIGN_RIGHT, border = 10) 00903 00904 self.SetSizer(mainSizer) 00905 mainSizer.Fit(self) 00906 00907 btnOk.Bind(wx.EVT_BUTTON, self.OnOk) 00908 btnApply.Bind(wx.EVT_BUTTON, self.OnApply) 00909 btnClose.Bind(wx.EVT_BUTTON, self.OnClose) 00910 00911 # set dialog min size 00912 self.SetMinSize(self.GetSize()) 00913 00914 def _createDialogBody(self): 00915 bodySizer = wx.BoxSizer(wx.VERTICAL) 00916 00917 # group selection 00918 bodySizer.Add(item = wx.StaticText(parent = self, id = wx.ID_ANY, 00919 label = _("Select the group you want to edit or " 00920 "enter name of new group:")), 00921 flag = wx.ALIGN_CENTER_VERTICAL | wx.TOP, border = 10) 00922 self.groupSelect = Select(parent = self, type = 'group', 00923 mapsets = [grass.gisenv()['MAPSET']], 00924 size = globalvar.DIALOG_GSELECT_SIZE) # searchpath? 00925 00926 bodySizer.Add(item = self.groupSelect, flag = wx.TOP | wx.EXPAND, border = 5) 00927 00928 bodySizer.AddSpacer(10) 00929 # layers in group 00930 bodySizer.Add(item = wx.StaticText(parent = self, label = _("Layers in selected group:")), 00931 flag = wx.ALIGN_CENTER_VERTICAL | wx.BOTTOM, border = 5) 00932 00933 gridSizer = wx.GridBagSizer(vgap = 5, hgap = 5) 00934 gridSizer.AddGrowableCol(0) 00935 00936 self.layerBox = wx.ListBox(parent = self, id = wx.ID_ANY, size = (-1, 150), 00937 style = wx.LB_MULTIPLE | wx.LB_NEEDED_SB) 00938 00939 gridSizer.Add(item = self.layerBox, pos = (0, 0), span = (2, 1), flag = wx.EXPAND) 00940 00941 self.addLayer = wx.Button(self, id = wx.ID_ADD) 00942 self.addLayer.SetToolTipString(_("Select map layers and add them to the list.")) 00943 gridSizer.Add(item = self.addLayer, pos = (0, 1), flag = wx.EXPAND) 00944 00945 self.removeLayer = wx.Button(self, id = wx.ID_REMOVE) 00946 self.removeLayer.SetToolTipString(_("Remove selected layer(s) from list.")) 00947 gridSizer.Add(item = self.removeLayer, pos = (1, 1)) 00948 00949 bodySizer.Add(item = gridSizer, proportion = 1, flag = wx.EXPAND) 00950 00951 self.infoLabel = wx.StaticText(parent = self, id = wx.ID_ANY) 00952 bodySizer.Add(item = self.infoLabel, 00953 flag = wx.ALIGN_CENTER_VERTICAL | wx.TOP | wx.BOTTOM, border = 5) 00954 00955 self.subGroup = wx.CheckBox(parent = self, id = wx.ID_ANY, 00956 label = _("Define also sub-group (same name as group)")) 00957 bodySizer.Add(item = self.subGroup, flag = wx.BOTTOM | wx.EXPAND, border = 5) 00958 00959 # bindings 00960 self.groupSelect.GetTextCtrl().Bind(wx.EVT_TEXT, self.OnGroupSelected) 00961 self.addLayer.Bind(wx.EVT_BUTTON, self.OnAddLayer) 00962 self.removeLayer.Bind(wx.EVT_BUTTON, self.OnRemoveLayer) 00963 00964 if self.defaultGroup: 00965 self.groupSelect.SetValue(self.defaultGroup) 00966 00967 return bodySizer 00968 00969 def OnAddLayer(self, event): 00970 """!Add new layer to listbox""" 00971 dlg = MapLayersDialog(parent = self, title = _("Add selected map layers into group"), 00972 mapType = 'raster', selectAll = False, 00973 fullyQualified = True, showFullyQualified = False) 00974 if dlg.ShowModal() != wx.ID_OK: 00975 dlg.Destroy() 00976 return 00977 00978 layers = dlg.GetMapLayers() 00979 for layer in layers: 00980 if layer not in self.GetLayers(): 00981 self.layerBox.Append(layer) 00982 self.groupChanged = True 00983 00984 00985 def OnRemoveLayer(self, event): 00986 """!Remove layer from listbox""" 00987 while self.layerBox.GetSelections(): 00988 sel = self.layerBox.GetSelections()[0] 00989 self.layerBox.Delete(sel) 00990 self.groupChanged = True 00991 00992 def GetLayers(self): 00993 """!Get layers""" 00994 return self.layerBox.GetItems() 00995 00996 def OnGroupSelected(self, event): 00997 """!Text changed in group selector""" 00998 # callAfter must be called to close popup before other actions 00999 wx.CallAfter(self.GroupSelected) 01000 01001 def GroupSelected(self): 01002 """!Group was selected, check if changes were apllied""" 01003 group = self.GetSelectedGroup() 01004 if self.groupChanged: 01005 dlg = wx.MessageDialog(self, message = _("Group <%s> was changed, " 01006 "do you want to apply changes?") % self.currentGroup, 01007 caption = _("Unapplied changes"), 01008 style = wx.YES_NO | wx.ICON_QUESTION | wx.YES_DEFAULT) 01009 if dlg.ShowModal() == wx.ID_YES: 01010 self.ApplyChanges(showResult = True) 01011 01012 dlg.Destroy() 01013 01014 01015 01016 groups = self.GetExistGroups() 01017 if group in groups: 01018 self.ShowGroupLayers(self.GetGroupLayers(group)) 01019 01020 self.currentGroup = group 01021 self.groupChanged = False 01022 01023 self.ClearNotification() 01024 01025 def ShowGroupLayers(self, mapList): 01026 """!Show map layers in currently selected group""" 01027 self.layerBox.Set(mapList) 01028 01029 01030 def EditGroup(self, group): 01031 """!Edit selected group""" 01032 layersNew = self.GetLayers() 01033 layersOld = self.GetGroupLayers(group) 01034 01035 add = [] 01036 remove = [] 01037 for layerNew in layersNew: 01038 if layerNew not in layersOld: 01039 add.append(layerNew) 01040 01041 for layerOld in layersOld: 01042 if layerOld not in layersNew: 01043 remove.append(layerOld) 01044 01045 kwargs = {} 01046 if self.subGroup.IsChecked(): 01047 kwargs['subgroup'] = group 01048 01049 ret = None 01050 if remove: 01051 ret = RunCommand('i.group', 01052 parent = self, 01053 group = group, 01054 flags = 'r', 01055 input = ','.join(remove), 01056 **kwargs) 01057 01058 if add: 01059 ret = RunCommand('i.group', 01060 parent = self, 01061 group = group, 01062 input = ','.join(add), 01063 **kwargs) 01064 01065 return ret 01066 01067 def CreateNewGroup(self, group): 01068 """!Create new group""" 01069 layers = self.GetLayers() 01070 01071 kwargs = {} 01072 if self.subGroup.IsChecked(): 01073 kwargs['subgroup'] = group 01074 01075 return RunCommand('i.group', 01076 parent = self, 01077 group = group, 01078 input = layers, 01079 **kwargs) 01080 01081 def GetExistGroups(self): 01082 """!Returns existing groups in current mapset""" 01083 return grass.list_grouped('group')[grass.gisenv()['MAPSET']] 01084 01085 def ShowResult(self, group, returnCode, create): 01086 """!Show if operation was successfull.""" 01087 group += '@' + grass.gisenv()['MAPSET'] 01088 if returnCode is None: 01089 label = _("No changes to apply in group <%s>.") % group 01090 elif returnCode == 0: 01091 if create: 01092 label = _("Group <%s> was successfully created.") % group 01093 else: 01094 label = _("Group <%s> was successfully changed.") % group 01095 else: 01096 if create: 01097 label = _("Creating of new group <%s> failed.") % group 01098 else: 01099 label = _("Changing of group <%s> failed.") % group 01100 01101 self.infoLabel.SetLabel(label) 01102 wx.FutureCall(4000, self.ClearNotification) 01103 01104 def GetSelectedGroup(self): 01105 """!Return currently selected group (without mapset)""" 01106 return self.groupSelect.GetValue().split('@')[0] 01107 01108 def GetGroupLayers(self, group): 01109 """!Get layers in group""" 01110 res = RunCommand('i.group', 01111 parent = self, 01112 flags = 'g', 01113 group = group, 01114 read = True).strip() 01115 if res.split('\n')[0]: 01116 return res.split('\n') 01117 return [] 01118 01119 def ClearNotification(self): 01120 """!Clear notification string""" 01121 self.infoLabel.SetLabel("") 01122 01123 def ApplyChanges(self, showResult): 01124 """!Create or edit group""" 01125 group = self.currentGroup 01126 if not group: 01127 GMessage(parent = self, 01128 message = _("No group selected.")) 01129 return False 01130 01131 groups = self.GetExistGroups() 01132 if group in groups: 01133 ret = self.EditGroup(group) 01134 self.ShowResult(group = group, returnCode = ret, create = False) 01135 01136 else: 01137 ret = self.CreateNewGroup(group) 01138 self.ShowResult(group = group, returnCode = ret, create = True) 01139 01140 self.groupChanged = False 01141 01142 return True 01143 01144 def OnApply(self, event): 01145 """!Apply changes""" 01146 self.ApplyChanges(showResult = True) 01147 01148 def OnOk(self, event): 01149 """!Apply changes and close dialog""" 01150 if self.ApplyChanges(showResult = False): 01151 self.OnClose(event) 01152 01153 def OnClose(self, event): 01154 """!Close dialog""" 01155 if not self.IsModal(): 01156 self.Destroy() 01157 event.Skip() 01158 01159 class MapLayersDialog(wx.Dialog): 01160 def __init__(self, parent, title, modeler = False, 01161 mapType = None, selectAll = True, fullyQualified = True, showFullyQualified = True, 01162 style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER, **kwargs): 01163 """!Dialog for selecting map layers (raster, vector) 01164 01165 Valid mapType values: 01166 - raster 01167 - raster3d 01168 - vector 01169 01170 @param mapType type of map (if None: raster, vector, 3d raster, if one only: selects it and disables selection) 01171 @param selectAll all/none maps should be selected by default 01172 @param fullyQualified True if dialog should return full map names by default 01173 @param showFullyQualified True to show 'fullyQualified' checkbox, otherwise hide it 01174 """ 01175 wx.Dialog.__init__(self, parent = parent, id = wx.ID_ANY, title = title, 01176 style = style, **kwargs) 01177 01178 self.parent = parent # GMFrame or ? 01179 self.mapType = mapType 01180 self.selectAll = selectAll 01181 01182 # dialog body 01183 self.bodySizer = self._createDialogBody() 01184 # update list of layer to be loaded 01185 self.map_layers = [] # list of map layers (full list type/mapset) 01186 self.LoadMapLayers(self.GetLayerType(cmd = True), 01187 self.mapset.GetStringSelection()) 01188 01189 self.fullyQualified = wx.CheckBox(parent = self, id = wx.ID_ANY, 01190 label = _("Use fully-qualified map names")) 01191 self.fullyQualified.SetValue(fullyQualified) 01192 self.fullyQualified.Show(showFullyQualified) 01193 01194 self.dseries = None 01195 if modeler: 01196 self.dseries = wx.CheckBox(parent = self, id = wx.ID_ANY, 01197 label = _("Dynamic series (%s)") % 'g.mlist') 01198 self.dseries.SetValue(False) 01199 01200 # buttons 01201 btnCancel = wx.Button(parent = self, id = wx.ID_CANCEL) 01202 btnOk = wx.Button(parent = self, id = wx.ID_OK) 01203 btnOk.SetDefault() 01204 01205 # sizers & do layout 01206 btnSizer = wx.StdDialogButtonSizer() 01207 btnSizer.AddButton(btnCancel) 01208 btnSizer.AddButton(btnOk) 01209 btnSizer.Realize() 01210 01211 mainSizer = wx.BoxSizer(wx.VERTICAL) 01212 mainSizer.Add(item = self.bodySizer, proportion = 1, 01213 flag = wx.EXPAND | wx.ALL, border = 5) 01214 mainSizer.Add(item = self.fullyQualified, proportion = 0, 01215 flag = wx.EXPAND | wx.LEFT | wx.RIGHT, border = 5) 01216 if self.dseries: 01217 mainSizer.Add(item = self.dseries, proportion = 0, 01218 flag = wx.EXPAND | wx.LEFT | wx.RIGHT, border = 5) 01219 01220 mainSizer.Add(item = btnSizer, proportion = 0, 01221 flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border = 5) 01222 01223 self.SetSizer(mainSizer) 01224 mainSizer.Fit(self) 01225 01226 # set dialog min size 01227 self.SetMinSize(self.GetSize()) 01228 01229 def _createDialogBody(self): 01230 bodySizer = wx.GridBagSizer(vgap = 3, hgap = 3) 01231 bodySizer.AddGrowableCol(1) 01232 bodySizer.AddGrowableRow(3) 01233 01234 # layer type 01235 bodySizer.Add(item = wx.StaticText(parent = self, label = _("Map type:")), 01236 flag = wx.ALIGN_CENTER_VERTICAL, 01237 pos = (0,0)) 01238 01239 self.layerType = wx.Choice(parent = self, id = wx.ID_ANY, 01240 choices = [_('raster'), _('3D raster'), _('vector')], size = (100,-1)) 01241 01242 if self.mapType: 01243 if self.mapType == 'raster': 01244 self.layerType.SetSelection(0) 01245 elif self.mapType == 'raster3d': 01246 self.layerType.SetSelection(1) 01247 elif self.mapType == 'vector': 01248 self.layerType.SetSelection(2) 01249 self.layerType.Disable() 01250 else: 01251 self.layerType.SetSelection(0) 01252 01253 bodySizer.Add(item = self.layerType, 01254 pos = (0,1)) 01255 01256 # select toggle 01257 self.toggle = wx.CheckBox(parent = self, id = wx.ID_ANY, 01258 label = _("Select toggle")) 01259 self.toggle.SetValue(self.selectAll) 01260 bodySizer.Add(item = self.toggle, 01261 flag = wx.ALIGN_CENTER_VERTICAL, 01262 pos = (0,2)) 01263 01264 # mapset filter 01265 bodySizer.Add(item = wx.StaticText(parent = self, label = _("Mapset:")), 01266 flag = wx.ALIGN_CENTER_VERTICAL, 01267 pos = (1,0)) 01268 01269 self.mapset = MapsetSelect(parent = self, searchPath = True) 01270 self.mapset.SetStringSelection(grass.gisenv()['MAPSET']) 01271 bodySizer.Add(item = self.mapset, 01272 pos = (1,1), span = (1, 2)) 01273 01274 # map name filter 01275 bodySizer.Add(item = wx.StaticText(parent = self, label = _("Pattern:")), 01276 flag = wx.ALIGN_CENTER_VERTICAL, 01277 pos = (2,0)) 01278 01279 self.filter = wx.TextCtrl(parent = self, id = wx.ID_ANY, 01280 value = "", 01281 size = (250,-1)) 01282 bodySizer.Add(item = self.filter, 01283 flag = wx.EXPAND, 01284 pos = (2,1), span = (1, 2)) 01285 01286 # layer list 01287 bodySizer.Add(item = wx.StaticText(parent = self, label = _("List of maps:")), 01288 flag = wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_TOP, 01289 pos = (3,0)) 01290 self.layers = wx.CheckListBox(parent = self, id = wx.ID_ANY, 01291 size = (250, 100), 01292 choices = []) 01293 bodySizer.Add(item = self.layers, 01294 flag = wx.EXPAND, 01295 pos = (3,1), span = (1, 2)) 01296 01297 # bindings 01298 self.layerType.Bind(wx.EVT_CHOICE, self.OnChangeParams) 01299 self.mapset.Bind(wx.EVT_COMBOBOX, self.OnChangeParams) 01300 self.layers.Bind(wx.EVT_RIGHT_DOWN, self.OnMenu) 01301 self.filter.Bind(wx.EVT_TEXT, self.OnFilter) 01302 self.toggle.Bind(wx.EVT_CHECKBOX, self.OnToggle) 01303 01304 return bodySizer 01305 01306 def LoadMapLayers(self, type, mapset): 01307 """!Load list of map layers 01308 01309 @param type layer type ('raster' or 'vector') 01310 @param mapset mapset name 01311 """ 01312 self.map_layers = grass.mlist_grouped(type = type)[mapset] 01313 self.layers.Set(self.map_layers) 01314 01315 # check all items by default 01316 for item in range(self.layers.GetCount()): 01317 01318 self.layers.Check(item, check = self.selectAll) 01319 01320 def OnChangeParams(self, event): 01321 """!Filter parameters changed by user""" 01322 # update list of layer to be loaded 01323 self.LoadMapLayers(self.GetLayerType(cmd = True), 01324 self.mapset.GetStringSelection()) 01325 01326 event.Skip() 01327 01328 def OnMenu(self, event): 01329 """!Table description area, context menu""" 01330 if not hasattr(self, "popupID1"): 01331 self.popupDataID1 = wx.NewId() 01332 self.popupDataID2 = wx.NewId() 01333 self.popupDataID3 = wx.NewId() 01334 01335 self.Bind(wx.EVT_MENU, self.OnSelectAll, id = self.popupDataID1) 01336 self.Bind(wx.EVT_MENU, self.OnSelectInvert, id = self.popupDataID2) 01337 self.Bind(wx.EVT_MENU, self.OnDeselectAll, id = self.popupDataID3) 01338 01339 # generate popup-menu 01340 menu = wx.Menu() 01341 menu.Append(self.popupDataID1, _("Select all")) 01342 menu.Append(self.popupDataID2, _("Invert selection")) 01343 menu.Append(self.popupDataID3, _("Deselect all")) 01344 01345 self.PopupMenu(menu) 01346 menu.Destroy() 01347 01348 def OnSelectAll(self, event): 01349 """!Select all map layer from list""" 01350 for item in range(self.layers.GetCount()): 01351 self.layers.Check(item, True) 01352 01353 def OnSelectInvert(self, event): 01354 """!Invert current selection""" 01355 for item in range(self.layers.GetCount()): 01356 if self.layers.IsChecked(item): 01357 self.layers.Check(item, False) 01358 else: 01359 self.layers.Check(item, True) 01360 01361 def OnDeselectAll(self, event): 01362 """!Select all map layer from list""" 01363 for item in range(self.layers.GetCount()): 01364 self.layers.Check(item, False) 01365 01366 def OnFilter(self, event): 01367 """!Apply filter for map names""" 01368 if len(event.GetString()) == 0: 01369 self.layers.Set(self.map_layers) 01370 return 01371 01372 list = [] 01373 for layer in self.map_layers: 01374 try: 01375 if re.compile('^' + event.GetString()).search(layer): 01376 list.append(layer) 01377 except: 01378 pass 01379 01380 self.layers.Set(list) 01381 self.OnSelectAll(None) 01382 01383 event.Skip() 01384 01385 def OnToggle(self, event): 01386 """!Select toggle (check or uncheck all layers)""" 01387 check = event.Checked() 01388 for item in range(self.layers.GetCount()): 01389 self.layers.Check(item, check) 01390 01391 event.Skip() 01392 01393 def GetMapLayers(self): 01394 """!Return list of checked map layers""" 01395 layerNames = [] 01396 for indx in self.layers.GetSelections(): 01397 # layers.append(self.layers.GetStringSelec(indx)) 01398 pass 01399 01400 fullyQualified = self.fullyQualified.IsChecked() 01401 mapset = self.mapset.GetStringSelection() 01402 for item in range(self.layers.GetCount()): 01403 if not self.layers.IsChecked(item): 01404 continue 01405 if fullyQualified: 01406 layerNames.append(self.layers.GetString(item) + '@' + mapset) 01407 else: 01408 layerNames.append(self.layers.GetString(item)) 01409 01410 return layerNames 01411 01412 def GetLayerType(self, cmd = False): 01413 """!Get selected layer type 01414 01415 @param cmd True for g.mlist 01416 """ 01417 if not cmd: 01418 return self.layerType.GetStringSelection() 01419 01420 sel = self.layerType.GetSelection() 01421 if sel == 0: 01422 ltype = 'rast' 01423 elif sel == 1: 01424 ltype = 'rast3d' 01425 else: 01426 ltype = 'vect' 01427 01428 return ltype 01429 01430 def GetDSeries(self): 01431 """!Used by modeler only 01432 01433 @return g.mlist command 01434 """ 01435 if not self.dseries or not self.dseries.IsChecked(): 01436 return '' 01437 01438 cond = 'map in `g.mlist type=%s ' % self.GetLayerType(cmd = True) 01439 patt = self.filter.GetValue() 01440 if patt: 01441 cond += 'pattern=%s ' % patt 01442 cond += 'mapset=%s`' % self.mapset.GetStringSelection() 01443 01444 return cond 01445 01446 class ImportDialog(wx.Dialog): 01447 """!Dialog for bulk import of various data (base class)""" 01448 def __init__(self, parent, itype, 01449 id = wx.ID_ANY, title = _("Multiple import"), 01450 style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER): 01451 self.parent = parent # GMFrame 01452 self.importType = itype 01453 self.options = dict() # list of options 01454 01455 self.commandId = -1 # id of running command 01456 01457 wx.Dialog.__init__(self, parent, id, title, style = style, 01458 name = "MultiImportDialog") 01459 01460 self.panel = wx.Panel(parent = self, id = wx.ID_ANY) 01461 01462 self.layerBox = wx.StaticBox(parent = self.panel, id = wx.ID_ANY, 01463 label = _(" List of %s layers ") % self.importType.upper()) 01464 01465 # 01466 # list of layers 01467 # 01468 columns = [_('Layer id'), 01469 _('Layer name'), 01470 _('Name for GRASS map (editable)')] 01471 self.list = LayersList(parent = self.panel, columns = columns) 01472 self.list.LoadData() 01473 01474 self.optionBox = wx.StaticBox(parent = self.panel, id = wx.ID_ANY, 01475 label = "%s" % _("Options")) 01476 01477 cmd = self._getCommand() 01478 task = gtask.parse_interface(cmd) 01479 for f in task.get_options()['flags']: 01480 name = f.get('name', '') 01481 desc = f.get('label', '') 01482 if not desc: 01483 desc = f.get('description', '') 01484 if not name and not desc: 01485 continue 01486 if cmd == 'r.in.gdal' and name not in ('o', 'e', 'l', 'k'): 01487 continue 01488 elif cmd == 'r.external' and name not in ('o', 'e', 'r', 'h', 'v'): 01489 continue 01490 elif cmd == 'v.in.ogr' and name not in ('c', 'z', 't', 'o', 'r', 'e', 'w'): 01491 continue 01492 elif cmd == 'v.external' and name not in ('b'): 01493 continue 01494 elif cmd == 'v.in.dxf' and name not in ('e', 't', 'b', 'f', 'i'): 01495 continue 01496 self.options[name] = wx.CheckBox(parent = self.panel, id = wx.ID_ANY, 01497 label = desc) 01498 01499 if not self.options: 01500 self.optionBox.Hide() 01501 01502 self.overwrite = wx.CheckBox(parent = self.panel, id = wx.ID_ANY, 01503 label = _("Allow output files to overwrite existing files")) 01504 self.overwrite.SetValue(UserSettings.Get(group = 'cmd', key = 'overwrite', subkey = 'enabled')) 01505 01506 self.add = wx.CheckBox(parent = self.panel, id = wx.ID_ANY) 01507 01508 # 01509 # buttons 01510 # 01511 # cancel 01512 self.btn_cancel = wx.Button(parent = self.panel, id = wx.ID_CANCEL) 01513 self.btn_cancel.SetToolTipString(_("Close dialog")) 01514 self.btn_cancel.Bind(wx.EVT_BUTTON, self.OnCancel) 01515 # run 01516 self.btn_run = wx.Button(parent = self.panel, id = wx.ID_OK, label = _("&Import")) 01517 self.btn_run.SetToolTipString(_("Import selected layers")) 01518 self.btn_run.SetDefault() 01519 self.btn_run.Enable(False) 01520 self.btn_run.Bind(wx.EVT_BUTTON, self.OnRun) 01521 # run command dialog 01522 self.btn_cmd = wx.Button(parent = self.panel, id = wx.ID_ANY, 01523 label = _("Command dialog")) 01524 self.btn_cmd.Bind(wx.EVT_BUTTON, self.OnCmdDialog) 01525 01526 def doLayout(self): 01527 """!Do layout""" 01528 dialogSizer = wx.BoxSizer(wx.VERTICAL) 01529 01530 # dsn input 01531 dialogSizer.Add(item = self.dsnInput, proportion = 0, 01532 flag = wx.EXPAND) 01533 01534 # 01535 # list of DXF layers 01536 # 01537 layerSizer = wx.StaticBoxSizer(self.layerBox, wx.HORIZONTAL) 01538 01539 layerSizer.Add(item = self.list, proportion = 1, 01540 flag = wx.ALL | wx.EXPAND, border = 5) 01541 01542 dialogSizer.Add(item = layerSizer, proportion = 1, 01543 flag = wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border = 5) 01544 01545 # options 01546 if self.optionBox.IsShown(): 01547 optionSizer = wx.StaticBoxSizer(self.optionBox, wx.VERTICAL) 01548 for key in self.options.keys(): 01549 optionSizer.Add(item = self.options[key], proportion = 0) 01550 01551 dialogSizer.Add(item = optionSizer, proportion = 0, 01552 flag = wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border = 5) 01553 01554 dialogSizer.Add(item = self.overwrite, proportion = 0, 01555 flag = wx.LEFT | wx.RIGHT | wx.BOTTOM, border = 5) 01556 01557 dialogSizer.Add(item = self.add, proportion = 0, 01558 flag = wx.LEFT | wx.RIGHT | wx.BOTTOM, border = 5) 01559 01560 # 01561 # buttons 01562 # 01563 btnsizer = wx.BoxSizer(orient = wx.HORIZONTAL) 01564 01565 btnsizer.Add(item = self.btn_cmd, proportion = 0, 01566 flag = wx.RIGHT | wx.ALIGN_CENTER, 01567 border = 10) 01568 01569 btnsizer.Add(item = self.btn_cancel, proportion = 0, 01570 flag = wx.LEFT | wx.RIGHT | wx.ALIGN_CENTER, 01571 border = 10) 01572 01573 btnsizer.Add(item = self.btn_run, proportion = 0, 01574 flag = wx.RIGHT | wx.ALIGN_CENTER, 01575 border = 10) 01576 01577 dialogSizer.Add(item = btnsizer, proportion = 0, 01578 flag = wx.ALIGN_CENTER_VERTICAL | wx.BOTTOM | wx.ALIGN_RIGHT, 01579 border = 10) 01580 01581 # dialogSizer.SetSizeHints(self.panel) 01582 self.panel.SetAutoLayout(True) 01583 self.panel.SetSizer(dialogSizer) 01584 dialogSizer.Fit(self.panel) 01585 01586 # auto-layout seems not work here - FIXME 01587 size = wx.Size(globalvar.DIALOG_GSELECT_SIZE[0] + 225, 550) 01588 self.SetMinSize(size) 01589 self.SetSize((size.width, size.height + 100)) 01590 # width = self.GetSize()[0] 01591 # self.list.SetColumnWidth(col = 1, width = width / 2 - 50) 01592 self.Layout() 01593 01594 def _getCommand(self): 01595 """!Get command""" 01596 return '' 01597 01598 def OnCancel(self, event = None): 01599 """!Close dialog""" 01600 self.Close() 01601 01602 def OnRun(self, event): 01603 """!Import/Link data (each layes as separate vector map)""" 01604 pass 01605 01606 def OnCmdDialog(self, event): 01607 """!Show command dialog""" 01608 pass 01609 01610 def AddLayers(self, returncode, cmd = None): 01611 """!Add imported/linked layers into layer tree""" 01612 if not self.add.IsChecked() or returncode != 0: 01613 return 01614 01615 self.commandId += 1 01616 maptree = self.parent.curr_page.maptree 01617 01618 layer, output = self.list.GetLayers()[self.commandId] 01619 01620 if '@' not in output: 01621 name = output + '@' + grass.gisenv()['MAPSET'] 01622 else: 01623 name = output 01624 01625 # add imported layers into layer tree 01626 if self.importType == 'gdal': 01627 cmd = ['d.rast', 01628 'map=%s' % name] 01629 if UserSettings.Get(group = 'cmd', key = 'rasterOverlay', subkey = 'enabled'): 01630 cmd.append('-o') 01631 01632 item = maptree.AddLayer(ltype = 'raster', 01633 lname = name, lchecked = False, 01634 lcmd = cmd, multiple = False) 01635 else: 01636 item = maptree.AddLayer(ltype = 'vector', 01637 lname = name, lchecked = False, 01638 lcmd = ['d.vect', 01639 'map=%s' % name], 01640 multiple = False) 01641 01642 maptree.mapdisplay.MapWindow.ZoomToMap() 01643 01644 def OnAbort(self, event): 01645 """!Abort running import 01646 01647 @todo not yet implemented 01648 """ 01649 pass 01650 01651 class GdalImportDialog(ImportDialog): 01652 def __init__(self, parent, ogr = False, link = False): 01653 """!Dialog for bulk import of various raster/vector data 01654 01655 @param parent parent window 01656 @param ogr True for OGR (vector) otherwise GDAL (raster) 01657 @param link True for linking data otherwise importing data 01658 """ 01659 self.link = link 01660 self.ogr = ogr 01661 01662 if ogr: 01663 ImportDialog.__init__(self, parent, itype = 'ogr') 01664 if link: 01665 self.SetTitle(_("Link external vector data")) 01666 else: 01667 self.SetTitle(_("Import vector data")) 01668 else: 01669 ImportDialog.__init__(self, parent, itype = 'gdal') 01670 if link: 01671 self.SetTitle(_("Link external raster data")) 01672 else: 01673 self.SetTitle(_("Import raster data")) 01674 01675 self.dsnInput = GdalSelect(parent = self, panel = self.panel, 01676 ogr = ogr, link = link) 01677 01678 if link: 01679 self.add.SetLabel(_("Add linked layers into layer tree")) 01680 else: 01681 self.add.SetLabel(_("Add imported layers into layer tree")) 01682 01683 self.add.SetValue(UserSettings.Get(group = 'cmd', key = 'addNewLayer', subkey = 'enabled')) 01684 01685 if link: 01686 self.btn_run.SetLabel(_("&Link")) 01687 self.btn_run.SetToolTipString(_("Link selected layers")) 01688 if ogr: 01689 self.btn_cmd.SetToolTipString(_('Open %s dialog') % 'v.external') 01690 else: 01691 self.btn_cmd.SetToolTipString(_('Open %s dialog') % 'r.external') 01692 else: 01693 self.btn_run.SetLabel(_("&Import")) 01694 self.btn_run.SetToolTipString(_("Import selected layers")) 01695 if ogr: 01696 self.btn_cmd.SetToolTipString(_('Open %s dialog') % 'v.in.ogr') 01697 else: 01698 self.btn_cmd.SetToolTipString(_('Open %s dialog') % 'r.in.gdal') 01699 01700 self.doLayout() 01701 01702 def OnRun(self, event): 01703 """!Import/Link data (each layes as separate vector map)""" 01704 self.commandId = -1 01705 data = self.list.GetLayers() 01706 if not data: 01707 GMessage(_("No layers selected. Operation canceled."), 01708 parent = self) 01709 return 01710 01711 dsn = self.dsnInput.GetDsn() 01712 ext = self.dsnInput.GetFormatExt() 01713 01714 # determine data driver for PostGIS links 01715 popOGR = False 01716 if self.importType == 'ogr' and \ 01717 self.dsnInput.GetType() == 'db' and \ 01718 self.dsnInput.GetFormat() == 'PostgreSQL' and \ 01719 'GRASS_VECTOR_OGR' not in os.environ: 01720 popOGR = True 01721 os.environ['GRASS_VECTOR_OGR'] = '1' 01722 01723 for layer, output in data: 01724 if self.importType == 'ogr': 01725 if ext and layer.rfind(ext) > -1: 01726 layer = layer.replace('.' + ext, '') 01727 if self.link: 01728 cmd = ['v.external', 01729 'dsn=%s' % dsn, 01730 'output=%s' % output, 01731 'layer=%s' % layer] 01732 else: 01733 cmd = ['v.in.ogr', 01734 'dsn=%s' % dsn, 01735 'layer=%s' % layer, 01736 'output=%s' % output] 01737 else: # gdal 01738 if self.dsnInput.GetType() == 'dir': 01739 idsn = os.path.join(dsn, layer) 01740 else: 01741 idsn = dsn 01742 01743 if self.link: 01744 cmd = ['r.external', 01745 'input=%s' % idsn, 01746 'output=%s' % output] 01747 else: 01748 cmd = ['r.in.gdal', 01749 'input=%s' % idsn, 01750 'output=%s' % output] 01751 01752 if self.overwrite.IsChecked(): 01753 cmd.append('--overwrite') 01754 01755 for key in self.options.keys(): 01756 if self.options[key].IsChecked(): 01757 cmd.append('-%s' % key) 01758 01759 if UserSettings.Get(group = 'cmd', key = 'overwrite', subkey = 'enabled') and \ 01760 '--overwrite' not in cmd: 01761 cmd.append('--overwrite') 01762 01763 # run in Layer Manager 01764 self.parent.goutput.RunCmd(cmd, switchPage = True, 01765 onDone = self.AddLayers) 01766 01767 if popOGR: 01768 os.environ.pop('GRASS_VECTOR_OGR') 01769 01770 def _getCommand(self): 01771 """!Get command""" 01772 if self.link: 01773 if self.ogr: 01774 return 'v.external' 01775 else: 01776 return 'r.external' 01777 else: 01778 if self.ogr: 01779 return 'v.in.ogr' 01780 else: 01781 return 'r.in.gdal' 01782 01783 return '' 01784 01785 def OnCmdDialog(self, event): 01786 """!Show command dialog""" 01787 name = self._getCommand() 01788 GUI(parent = self, modal = False).ParseCommand(cmd = [name]) 01789 01790 class DxfImportDialog(ImportDialog): 01791 """!Dialog for bulk import of DXF layers""" 01792 def __init__(self, parent): 01793 ImportDialog.__init__(self, parent, itype = 'dxf', 01794 title = _("Import DXF layers")) 01795 01796 self.dsnInput = filebrowse.FileBrowseButton(parent = self.panel, id = wx.ID_ANY, 01797 size = globalvar.DIALOG_GSELECT_SIZE, labelText = '', 01798 dialogTitle = _('Choose DXF file to import'), 01799 buttonText = _('Browse'), 01800 startDirectory = os.getcwd(), fileMode = 0, 01801 changeCallback = self.OnSetDsn, 01802 fileMask = "DXF File (*.dxf)|*.dxf") 01803 01804 self.add.SetLabel(_("Add imported layers into layer tree")) 01805 01806 self.add.SetValue(UserSettings.Get(group = 'cmd', key = 'addNewLayer', subkey = 'enabled')) 01807 01808 self.doLayout() 01809 01810 def _getCommand(self): 01811 """!Get command""" 01812 return 'v.in.dxf' 01813 01814 def OnRun(self, event): 01815 """!Import/Link data (each layes as separate vector map)""" 01816 data = self.list.GetLayers() 01817 01818 # hide dialog 01819 self.Hide() 01820 01821 inputDxf = self.dsnInput.GetValue() 01822 01823 for layer, output in data: 01824 cmd = ['v.in.dxf', 01825 'input=%s' % inputDxf, 01826 'layers=%s' % layer, 01827 'output=%s' % output] 01828 01829 for key in self.options.keys(): 01830 if self.options[key].IsChecked(): 01831 cmd.append('-%s' % key) 01832 01833 if self.overwrite.IsChecked() or \ 01834 UserSettings.Get(group = 'cmd', key = 'overwrite', subkey = 'enabled'): 01835 cmd.append('--overwrite') 01836 01837 # run in Layer Manager 01838 self.parent.goutput.RunCmd(cmd, switchPage = True, 01839 onDone = self.AddLayers) 01840 01841 self.OnCancel() 01842 01843 def OnSetDsn(self, event): 01844 """!Input DXF file defined, update list of layer widget""" 01845 path = event.GetString() 01846 if not path: 01847 return 01848 01849 data = list() 01850 ret = RunCommand('v.in.dxf', 01851 quiet = True, 01852 parent = self, 01853 read = True, 01854 flags = 'l', 01855 input = path) 01856 if not ret: 01857 self.list.LoadData() 01858 self.btn_run.Enable(False) 01859 return 01860 01861 for line in ret.splitlines(): 01862 layerId = line.split(':')[0].split(' ')[1] 01863 layerName = line.split(':')[1].strip() 01864 grassName = GetValidLayerName(layerName) 01865 data.append((layerId, layerName.strip(), grassName.strip())) 01866 01867 self.list.LoadData(data) 01868 if len(data) > 0: 01869 self.btn_run.Enable(True) 01870 else: 01871 self.btn_run.Enable(False) 01872 01873 def OnCmdDialog(self, event): 01874 """!Show command dialog""" 01875 GUI(parent = self, modal = True).ParseCommand(cmd = ['v.in.dxf']) 01876 01877 class LayersList(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin, 01878 listmix.CheckListCtrlMixin, listmix.TextEditMixin): 01879 """!List of layers to be imported (dxf, shp...)""" 01880 def __init__(self, parent, columns, log = None): 01881 self.parent = parent 01882 01883 wx.ListCtrl.__init__(self, parent, wx.ID_ANY, 01884 style = wx.LC_REPORT) 01885 listmix.CheckListCtrlMixin.__init__(self) 01886 self.log = log 01887 01888 # setup mixins 01889 listmix.ListCtrlAutoWidthMixin.__init__(self) 01890 listmix.TextEditMixin.__init__(self) 01891 01892 for i in range(len(columns)): 01893 self.InsertColumn(i, columns[i]) 01894 01895 if len(columns) == 3: 01896 width = (65, 200) 01897 else: 01898 width = (65, 180, 110) 01899 01900 for i in range(len(width)): 01901 self.SetColumnWidth(col = i, width = width[i]) 01902 01903 self.Bind(wx.EVT_COMMAND_RIGHT_CLICK, self.OnPopupMenu) #wxMSW 01904 self.Bind(wx.EVT_RIGHT_UP, self.OnPopupMenu) #wxGTK 01905 01906 def LoadData(self, data = None): 01907 """!Load data into list""" 01908 self.DeleteAllItems() 01909 if data is None: 01910 return 01911 01912 for item in data: 01913 index = self.InsertStringItem(sys.maxint, str(item[0])) 01914 for i in range(1, len(item)): 01915 self.SetStringItem(index, i, "%s" % str(item[i])) 01916 01917 # check by default only on one item 01918 if len(data) == 1: 01919 self.CheckItem(index, True) 01920 01921 def OnPopupMenu(self, event): 01922 """!Show popup menu""" 01923 if self.GetItemCount() < 1: 01924 return 01925 01926 if not hasattr(self, "popupDataID1"): 01927 self.popupDataID1 = wx.NewId() 01928 self.popupDataID2 = wx.NewId() 01929 01930 self.Bind(wx.EVT_MENU, self.OnSelectAll, id = self.popupDataID1) 01931 self.Bind(wx.EVT_MENU, self.OnSelectNone, id = self.popupDataID2) 01932 01933 # generate popup-menu 01934 menu = wx.Menu() 01935 menu.Append(self.popupDataID1, _("Select all")) 01936 menu.Append(self.popupDataID2, _("Deselect all")) 01937 01938 self.PopupMenu(menu) 01939 menu.Destroy() 01940 01941 def OnSelectAll(self, event): 01942 """!Select all items""" 01943 item = -1 01944 01945 while True: 01946 item = self.GetNextItem(item) 01947 if item == -1: 01948 break 01949 self.CheckItem(item, True) 01950 01951 event.Skip() 01952 01953 def OnSelectNone(self, event): 01954 """!Deselect items""" 01955 item = -1 01956 01957 while True: 01958 item = self.GetNextItem(item, wx.LIST_STATE_SELECTED) 01959 if item == -1: 01960 break 01961 self.CheckItem(item, False) 01962 01963 event.Skip() 01964 01965 def OnLeftDown(self, event): 01966 """!Allow editing only output name 01967 01968 Code taken from TextEditMixin class. 01969 """ 01970 x, y = event.GetPosition() 01971 01972 colLocs = [0] 01973 loc = 0 01974 for n in range(self.GetColumnCount()): 01975 loc = loc + self.GetColumnWidth(n) 01976 colLocs.append(loc) 01977 01978 col = bisect(colLocs, x + self.GetScrollPos(wx.HORIZONTAL)) - 1 01979 01980 if col == self.GetColumnCount() - 1: 01981 listmix.TextEditMixin.OnLeftDown(self, event) 01982 else: 01983 event.Skip() 01984 01985 def GetLayers(self): 01986 """!Get list of layers (layer name, output name)""" 01987 data = [] 01988 item = -1 01989 while True: 01990 item = self.GetNextItem(item) 01991 if item == -1: 01992 break 01993 if not self.IsChecked(item): 01994 continue 01995 # layer / output name 01996 data.append((self.GetItem(item, 1).GetText(), 01997 self.GetItem(item, self.GetColumnCount() - 1).GetText())) 01998 01999 return data 02000 02001 class SetOpacityDialog(wx.Dialog): 02002 """!Set opacity of map layers""" 02003 def __init__(self, parent, id = wx.ID_ANY, title = _("Set Map Layer Opacity"), 02004 size = wx.DefaultSize, pos = wx.DefaultPosition, 02005 style = wx.DEFAULT_DIALOG_STYLE, opacity = 100): 02006 02007 self.parent = parent # GMFrame 02008 self.opacity = opacity # current opacity 02009 02010 super(SetOpacityDialog, self).__init__(parent, id = id, pos = pos, 02011 size = size, style = style, title = title) 02012 02013 panel = wx.Panel(parent = self, id = wx.ID_ANY) 02014 02015 sizer = wx.BoxSizer(wx.VERTICAL) 02016 02017 box = wx.GridBagSizer(vgap = 5, hgap = 5) 02018 self.value = wx.Slider(panel, id = wx.ID_ANY, value = self.opacity, 02019 style = wx.SL_HORIZONTAL | wx.SL_AUTOTICKS | \ 02020 wx.SL_TOP | wx.SL_LABELS, 02021 minValue = 0, maxValue = 100, 02022 size = (350, -1)) 02023 02024 box.Add(item = self.value, 02025 flag = wx.ALIGN_CENTRE, pos = (0, 0), span = (1, 2)) 02026 box.Add(item = wx.StaticText(parent = panel, id = wx.ID_ANY, 02027 label = _("transparent")), 02028 pos = (1, 0)) 02029 box.Add(item = wx.StaticText(parent = panel, id = wx.ID_ANY, 02030 label = _("opaque")), 02031 flag = wx.ALIGN_RIGHT, 02032 pos = (1, 1)) 02033 02034 sizer.Add(item = box, proportion = 0, 02035 flag = wx.EXPAND | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border = 5) 02036 02037 line = wx.StaticLine(parent = panel, id = wx.ID_ANY, 02038 style = wx.LI_HORIZONTAL) 02039 sizer.Add(item = line, proportion = 0, 02040 flag = wx.EXPAND | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border = 5) 02041 02042 # buttons 02043 btnsizer = wx.StdDialogButtonSizer() 02044 02045 btnOK = wx.Button(parent = panel, id = wx.ID_OK) 02046 btnOK.SetDefault() 02047 btnsizer.AddButton(btnOK) 02048 02049 btnCancel = wx.Button(parent = panel, id = wx.ID_CANCEL) 02050 btnsizer.AddButton(btnCancel) 02051 btnsizer.Realize() 02052 02053 sizer.Add(item = btnsizer, proportion = 0, 02054 flag = wx.EXPAND | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border = 5) 02055 02056 panel.SetSizer(sizer) 02057 sizer.Fit(panel) 02058 02059 self.SetSize(self.GetBestSize()) 02060 02061 self.Layout() 02062 02063 def GetOpacity(self): 02064 """!Button 'OK' pressed""" 02065 # return opacity value 02066 opacity = float(self.value.GetValue()) / 100 02067 return opacity 02068 02069 def GetImageHandlers(image): 02070 """!Get list of supported image handlers""" 02071 lext = list() 02072 ltype = list() 02073 for h in image.GetHandlers(): 02074 lext.append(h.GetExtension()) 02075 02076 filetype = '' 02077 if 'png' in lext: 02078 filetype += "PNG file (*.png)|*.png|" 02079 ltype.append({ 'type' : wx.BITMAP_TYPE_PNG, 02080 'ext' : 'png' }) 02081 filetype += "BMP file (*.bmp)|*.bmp|" 02082 ltype.append({ 'type' : wx.BITMAP_TYPE_BMP, 02083 'ext' : 'bmp' }) 02084 if 'gif' in lext: 02085 filetype += "GIF file (*.gif)|*.gif|" 02086 ltype.append({ 'type' : wx.BITMAP_TYPE_GIF, 02087 'ext' : 'gif' }) 02088 02089 if 'jpg' in lext: 02090 filetype += "JPG file (*.jpg)|*.jpg|" 02091 ltype.append({ 'type' : wx.BITMAP_TYPE_JPEG, 02092 'ext' : 'jpg' }) 02093 02094 if 'pcx' in lext: 02095 filetype += "PCX file (*.pcx)|*.pcx|" 02096 ltype.append({ 'type' : wx.BITMAP_TYPE_PCX, 02097 'ext' : 'pcx' }) 02098 02099 if 'pnm' in lext: 02100 filetype += "PNM file (*.pnm)|*.pnm|" 02101 ltype.append({ 'type' : wx.BITMAP_TYPE_PNM, 02102 'ext' : 'pnm' }) 02103 02104 if 'tif' in lext: 02105 filetype += "TIF file (*.tif)|*.tif|" 02106 ltype.append({ 'type' : wx.BITMAP_TYPE_TIF, 02107 'ext' : 'tif' }) 02108 02109 if 'xpm' in lext: 02110 filetype += "XPM file (*.xpm)|*.xpm" 02111 ltype.append({ 'type' : wx.BITMAP_TYPE_XPM, 02112 'ext' : 'xpm' }) 02113 02114 return filetype, ltype 02115 02116 class ImageSizeDialog(wx.Dialog): 02117 """!Set size for saved graphic file""" 02118 def __init__(self, parent, id = wx.ID_ANY, title = _("Set image size"), 02119 style = wx.DEFAULT_DIALOG_STYLE, **kwargs): 02120 self.parent = parent 02121 02122 wx.Dialog.__init__(self, parent, id = id, style = style, title = title, **kwargs) 02123 02124 self.panel = wx.Panel(parent = self, id = wx.ID_ANY) 02125 02126 self.box = wx.StaticBox(parent = self.panel, id = wx.ID_ANY, 02127 label = ' % s' % _("Image size")) 02128 02129 size = self.parent.GetWindow().GetClientSize() 02130 self.width = wx.SpinCtrl(parent = self.panel, id = wx.ID_ANY, 02131 style = wx.SP_ARROW_KEYS) 02132 self.width.SetRange(20, 1e6) 02133 self.width.SetValue(size.width) 02134 wx.CallAfter(self.width.SetFocus) 02135 self.height = wx.SpinCtrl(parent = self.panel, id = wx.ID_ANY, 02136 style = wx.SP_ARROW_KEYS) 02137 self.height.SetRange(20, 1e6) 02138 self.height.SetValue(size.height) 02139 self.template = wx.Choice(parent = self.panel, id = wx.ID_ANY, 02140 size = (125, -1), 02141 choices = [ "", 02142 "640x480", 02143 "800x600", 02144 "1024x768", 02145 "1280x960", 02146 "1600x1200", 02147 "1920x1440" ]) 02148 02149 self.btnOK = wx.Button(parent = self.panel, id = wx.ID_OK) 02150 self.btnOK.SetDefault() 02151 self.btnCancel = wx.Button(parent = self.panel, id = wx.ID_CANCEL) 02152 02153 self.template.Bind(wx.EVT_CHOICE, self.OnTemplate) 02154 02155 self._layout() 02156 self.SetSize(self.GetBestSize()) 02157 02158 def _layout(self): 02159 """!Do layout""" 02160 sizer = wx.BoxSizer(wx.VERTICAL) 02161 02162 # body 02163 box = wx.StaticBoxSizer(self.box, wx.HORIZONTAL) 02164 fbox = wx.FlexGridSizer(cols = 2, vgap = 5, hgap = 5) 02165 fbox.Add(item = wx.StaticText(parent = self.panel, id = wx.ID_ANY, 02166 label = _("Width:")), 02167 flag = wx.ALIGN_CENTER_VERTICAL) 02168 fbox.Add(item = self.width) 02169 fbox.Add(item = wx.StaticText(parent = self.panel, id = wx.ID_ANY, 02170 label = _("Height:")), 02171 flag = wx.ALIGN_CENTER_VERTICAL) 02172 fbox.Add(item = self.height) 02173 fbox.Add(item = wx.StaticText(parent = self.panel, id = wx.ID_ANY, 02174 label = _("Template:")), 02175 flag = wx.ALIGN_CENTER_VERTICAL) 02176 fbox.Add(item = self.template) 02177 02178 box.Add(item = fbox, proportion = 1, 02179 flag = wx.EXPAND | wx.ALL, border = 5) 02180 sizer.Add(item = box, proportion = 1, 02181 flag = wx.EXPAND | wx.ALL, border = 3) 02182 02183 # buttons 02184 btnsizer = wx.StdDialogButtonSizer() 02185 btnsizer.AddButton(self.btnOK) 02186 btnsizer.AddButton(self.btnCancel) 02187 btnsizer.Realize() 02188 02189 sizer.Add(item = btnsizer, proportion = 0, 02190 flag = wx.EXPAND | wx.ALIGN_RIGHT | wx.ALL, border = 5) 02191 02192 self.panel.SetSizer(sizer) 02193 sizer.Fit(self.panel) 02194 self.Layout() 02195 02196 def GetValues(self): 02197 """!Get width/height values""" 02198 return self.width.GetValue(), self.height.GetValue() 02199 02200 def OnTemplate(self, event): 02201 """!Template selected""" 02202 sel = event.GetString() 02203 if not sel: 02204 width, height = self.parent.GetWindow().GetClientSize() 02205 else: 02206 width, height = map(int, sel.split('x')) 02207 self.width.SetValue(width) 02208 self.height.SetValue(height) 02209 02210 class SymbolDialog(wx.Dialog): 02211 """!Dialog for GRASS symbols selection. 02212 02213 Dialog is called in gui_core::forms module. 02214 """ 02215 def __init__(self, parent, symbolPath, currentSymbol = None, title = _("Symbols")): 02216 """!Dialog constructor. 02217 02218 It is assumed that symbolPath contains folders with symbols. 02219 02220 @param parent dialog parent 02221 @param symbolPath absolute path to symbols 02222 @param currentSymbol currently selected symbol (e.g. 'basic/x') 02223 @param title dialog title 02224 """ 02225 wx.Dialog.__init__(self, parent = parent, title = title, id = wx.ID_ANY) 02226 02227 self.symbolPath = symbolPath 02228 self.currentSymbol = currentSymbol # default basic/x 02229 self.selected = None 02230 self.selectedDir = None 02231 02232 self._layout() 02233 02234 def _layout(self): 02235 mainPanel = wx.Panel(self, id = wx.ID_ANY) 02236 mainSizer = wx.BoxSizer(wx.VERTICAL) 02237 vSizer = wx.BoxSizer( wx.VERTICAL) 02238 fgSizer = wx.FlexGridSizer(rows = 2, vgap = 5, hgap = 5) 02239 self.folderChoice = wx.Choice(mainPanel, id = wx.ID_ANY, choices = os.listdir(self.symbolPath)) 02240 self.folderChoice.Bind(wx.EVT_CHOICE, self.OnFolderSelect) 02241 02242 fgSizer.Add(item = wx.StaticText(mainPanel, id = wx.ID_ANY, label = _("Symbol directory:")), 02243 proportion = 0, 02244 flag = wx.ALIGN_CENTER_VERTICAL) 02245 02246 fgSizer.Add(item = self.folderChoice, proportion = 0, 02247 flag = wx.ALIGN_CENTER, border = 0) 02248 02249 self.infoLabel = wx.StaticText(mainPanel, id = wx.ID_ANY) 02250 fgSizer.Add(wx.StaticText(mainPanel, id = wx.ID_ANY, label = _("Symbol name:")), 02251 flag = wx.ALIGN_CENTRE_VERTICAL) 02252 fgSizer.Add(self.infoLabel, proportion = 0, 02253 flag = wx.ALIGN_CENTRE_VERTICAL) 02254 vSizer.Add(fgSizer, proportion = 0, flag = wx.ALL, border = 5) 02255 02256 self.panels = self._createSymbolPanels(mainPanel) 02257 for panel in self.panels: 02258 vSizer.Add(panel, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5) 02259 panel.Bind(EVT_SYMBOL_SELECTION_CHANGED, self.SelectionChanged) 02260 02261 mainSizer.Add(vSizer, proportion = 1, flag = wx.ALL| wx.EXPAND, border = 5) 02262 self.btnCancel = wx.Button(parent = mainPanel, id = wx.ID_CANCEL) 02263 self.btnOK = wx.Button(parent = mainPanel, id = wx.ID_OK) 02264 self.btnOK.SetDefault() 02265 self.btnOK.Enable(False) 02266 02267 # buttons 02268 btnSizer = wx.StdDialogButtonSizer() 02269 btnSizer.AddButton(self.btnCancel) 02270 btnSizer.AddButton(self.btnOK) 02271 btnSizer.Realize() 02272 mainSizer.Add(item = btnSizer, proportion = 0, 02273 flag = wx.EXPAND | wx.ALL, border = 5) 02274 02275 # show panel with the largest number of images and fit size 02276 count = [] 02277 for folder in os.listdir(self.symbolPath): 02278 count.append(len(os.listdir(os.path.join(self.symbolPath, folder)))) 02279 02280 index = count.index(max(count)) 02281 self.folderChoice.SetSelection(index) 02282 self.OnFolderSelect(None) 02283 self.infoLabel.Show() 02284 02285 mainPanel.SetSizerAndFit(mainSizer) 02286 self.SetSize(self.GetBestSize()) 02287 02288 # show currently selected symbol 02289 if self.currentSymbol: 02290 # set directory 02291 self.selectedDir, self.selected = os.path.split(self.currentSymbol) 02292 self.folderChoice.SetStringSelection(self.selectedDir) 02293 # select symbol 02294 panelIdx = self.folderChoice.GetSelection() 02295 for panel in self.symbolPanels[panelIdx]: 02296 if panel.GetName() == self.selected: 02297 panel.Select() 02298 else: 02299 self.folderChoice.SetSelection(0) 02300 02301 self.OnFolderSelect(None) 02302 02303 def _createSymbolPanels(self, parent): 02304 """!Creates multiple panels with symbols. 02305 02306 Panels are shown/hidden according to selected folder.""" 02307 folders = os.listdir(self.symbolPath) 02308 02309 panels = [] 02310 self.symbolPanels = [] 02311 maxImages = 0 02312 02313 for folder in folders: 02314 panel = wx.Panel(parent, style = wx.BORDER_RAISED) 02315 sizer = wx.GridSizer(cols = 6, vgap = 3, hgap = 3) 02316 images = self._getSymbols(path = os.path.join(self.symbolPath, folder)) 02317 02318 symbolPanels = [] 02319 for img in images: 02320 iP = SingleSymbolPanel(parent = panel, symbolPath = img) 02321 sizer.Add(item = iP, proportion = 0, flag = wx.ALIGN_CENTER) 02322 symbolPanels.append(iP) 02323 02324 panel.SetSizerAndFit(sizer) 02325 panel.Hide() 02326 panels.append(panel) 02327 self.symbolPanels.append(symbolPanels) 02328 02329 return panels 02330 02331 def _getSymbols(self, path): 02332 # we assume that images are in subfolders (1 level only) 02333 imageList = [] 02334 for image in os.listdir(path): 02335 imageList.append(os.path.join(path, image)) 02336 02337 return sorted(imageList) 02338 02339 def OnFolderSelect(self, event): 02340 """!Selected folder with symbols changed.""" 02341 idx = self.folderChoice.GetSelection() 02342 for i in range(len(self.panels)): 02343 sizer = self.panels[i].GetContainingSizer() 02344 sizer.Show(self.panels[i], i == idx, recursive = True) 02345 sizer.Layout() 02346 02347 if self.selectedDir == self.folderChoice.GetStringSelection(): 02348 self.btnOK.Enable() 02349 self.infoLabel.SetLabel(self.selected) 02350 else: 02351 self.btnOK.Disable() 02352 self.infoLabel.SetLabel('') 02353 02354 def SelectionChanged(self, event): 02355 """!Selected symbol changed.""" 02356 if event.doubleClick: 02357 self.EndModal(wx.ID_OK) 02358 # deselect all 02359 for i in range(len(self.panels)): 02360 for panel in self.symbolPanels[i]: 02361 if panel.GetName() != event.name: 02362 panel.Deselect() 02363 02364 self.btnOK.Enable() 02365 02366 self.selected = event.name 02367 self.selectedDir = self.folderChoice.GetStringSelection() 02368 02369 self.infoLabel.SetLabel(event.name) 02370 02371 def GetSelectedSymbol(self, fullPath = False): 02372 """!Returns currently selected symbol. 02373 02374 @param fullPath true to return absolute path to symbol, 02375 otherwise returns e.g. 'basic/x' 02376 """ 02377 if fullPath: 02378 return os.path.join(self.symbolPath, self.selectedDir, self.selected) 02379 02380 return os.path.join(self.selectedDir, self.selected)