GRASS Programmer's Manual  6.5.svn(2012)-r51648
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
gui_core/dialogs.py
Go to the documentation of this file.
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)