Пример #1
0
    def _do_layout(self):

        sizer = wx.BoxSizer(wx.VERTICAL)

        box = wx.GridBagSizer(hgap=3, vgap=3)

        rastText = ''
        for r in self.rasterList:
            rastText += '%s,' % r

        rastText = rastText.rstrip(',')

        txt = _("Select raster map(s) to profile:")
        label = wx.StaticText(parent=self, id=wx.ID_ANY, label=txt)
        box.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(0, 0))

        selection = Select(self,
                           id=wx.ID_ANY,
                           size=globalvar.DIALOG_GSELECT_SIZE,
                           type='cell',
                           multiple=True)
        selection.SetValue(rastText)
        selection.Bind(wx.EVT_TEXT, self.OnSelection)

        box.Add(item=selection, pos=(0, 1))

        sizer.Add(item=box, proportion=0, flag=wx.ALL, border=10)

        line = wx.StaticLine(parent=self,
                             id=wx.ID_ANY,
                             size=(20, -1),
                             style=wx.LI_HORIZONTAL)
        sizer.Add(item=line,
                  proportion=0,
                  flag=wx.GROW | wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT,
                  border=5)

        btnsizer = wx.StdDialogButtonSizer()

        btn = wx.Button(self, wx.ID_OK)
        btn.SetDefault()
        btnsizer.AddButton(btn)

        btn = wx.Button(self, wx.ID_CANCEL)
        btnsizer.AddButton(btn)
        btnsizer.Realize()

        sizer.Add(item=btnsizer,
                  proportion=0,
                  flag=wx.ALIGN_RIGHT | wx.ALL,
                  border=5)

        self.SetSizer(sizer)
        sizer.Fit(self)
Пример #2
0
class ExportCategoryRaster(wx.Dialog):

    def __init__(self, parent, title, rasterName=None, id=wx.ID_ANY,
                 style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER,
                 **kwargs):
        """Dialog for export of category raster.

        :param parent: window
        :param str rasterName name of vector layer for export
        :param title: window title
        """
        wx.Dialog.__init__(self, parent, id, title, style=style, **kwargs)

        self.rasterName = rasterName
        self.panel = wx.Panel(parent=self, id=wx.ID_ANY)

        self.btnCancel = Button(parent=self.panel, id=wx.ID_CANCEL)
        self.btnOK = Button(parent=self.panel, id=wx.ID_OK)
        self.btnOK.SetDefault()
        self.btnOK.Enable(False)
        self.btnOK.Bind(wx.EVT_BUTTON, self.OnOK)

        self.__layout()

        self.vectorNameCtrl.Bind(wx.EVT_TEXT, self.OnTextChanged)
        self.OnTextChanged(None)
        wx.CallAfter(self.vectorNameCtrl.SetFocus)

    def OnTextChanged(self, event):
        """Name of new vector map given.

        Enable/diable OK button.
        """
        file = self.vectorNameCtrl.GetValue()
        if len(file) > 0:
            self.btnOK.Enable(True)
        else:
            self.btnOK.Enable(False)

    def __layout(self):
        """Do layout"""
        sizer = wx.BoxSizer(wx.VERTICAL)

        dataSizer = wx.BoxSizer(wx.VERTICAL)

        dataSizer.Add(
            StaticText(
                parent=self.panel,
                id=wx.ID_ANY,
                label=_("Enter name of new vector map:")),
            proportion=0,
            flag=wx.ALL,
            border=3)
        self.vectorNameCtrl = Select(parent=self.panel, type='raster',
                                     mapsets=[grass.gisenv()['MAPSET']],
                                     size=globalvar.DIALOG_GSELECT_SIZE)
        if self.rasterName:
            self.vectorNameCtrl.SetValue(self.rasterName)
        dataSizer.Add(self.vectorNameCtrl,
                      proportion=0, flag=wx.ALL | wx.EXPAND, border=3)

        # buttons
        btnSizer = wx.StdDialogButtonSizer()
        btnSizer.AddButton(self.btnCancel)
        btnSizer.AddButton(self.btnOK)
        btnSizer.Realize()

        sizer.Add(dataSizer, proportion=1,
                  flag=wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border=5)

        sizer.Add(btnSizer, proportion=0,
                  flag=wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border=5)

        self.panel.SetSizer(sizer)
        sizer.Fit(self)

        self.SetMinSize(self.GetSize())

    def GetRasterName(self):
        """Returns vector name"""
        return self.vectorNameCtrl.GetValue()

    def OnOK(self, event):
        """Checks if map exists and can be overwritten."""
        overwrite = UserSettings.Get(
            group='cmd', key='overwrite', subkey='enabled')
        rast_name = self.GetRasterName()
        res = grass.find_file(rast_name, element='cell')
        if res['fullname'] and overwrite is False:
            qdlg = wx.MessageDialog(
                parent=self, message=_(
                    "Raster map <%s> already exists."
                    " Do you want to overwrite it?" %
                    rast_name), caption=_(
                    "Raster <%s> exists" %
                    rast_name), style=wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION | wx.CENTRE)
            if qdlg.ShowModal() == wx.ID_YES:
                event.Skip()
            qdlg.Destroy()
        else:
            event.Skip()
Пример #3
0
class ModelDataDialog(SimpleDialog):
    """Data item properties dialog"""

    def __init__(self, parent, shape, title=_("Data properties")):
        self.parent = parent
        self.shape = shape

        label, etype = self._getLabel()
        self.etype = etype
        SimpleDialog.__init__(self, parent, title)

        self.element = Select(
            parent=self.panel,
            type=self.shape.GetPrompt(),
            validator=SimpleValidator(
                callback=self.ValidatorCallback))
        if shape.GetValue():
            self.element.SetValue(shape.GetValue())

        self.Bind(wx.EVT_BUTTON, self.OnOK, self.btnOK)
        self.Bind(wx.EVT_BUTTON, self.OnCancel, self.btnCancel)
        if self.etype:
            self.typeSelect = ElementSelect(
                parent=self.panel,
                elements=[
                    'raster',
                    'raster_3d',
                    'vector'],
                size=globalvar.DIALOG_GSELECT_SIZE)
            self.typeSelect.Bind(wx.EVT_CHOICE, self.OnType)
            self.typeSelect.SetSelection(0)
            self.element.SetType('raster')

        if shape.GetValue():
            self.btnOK.Enable()

        self._layout()
        self.SetMinSize(self.GetSize())

    def _getLabel(self):
        etype = False
        prompt = self.shape.GetPrompt()
        if prompt == 'raster':
            label = _('Name of raster map:')
        elif prompt == 'vector':
            label = _('Name of vector map:')
        else:
            etype = True
            label = _('Name of element:')

        return label, etype

    def _layout(self):
        """Do layout"""
        if self.etype:
            self.dataSizer.Add(
                StaticText(
                    parent=self.panel,
                    id=wx.ID_ANY,
                    label=_("Type of element:")),
                proportion=0,
                flag=wx.ALL,
                border=1)
            self.dataSizer.Add(self.typeSelect,
                               proportion=0, flag=wx.ALL, border=1)
        self.dataSizer.Add(StaticText(parent=self.panel, id=wx.ID_ANY,
                                      label=_("Name of element:")),
                           proportion=0, flag=wx.ALL, border=1)
        self.dataSizer.Add(self.element, proportion=0,
                           flag=wx.EXPAND | wx.ALL, border=1)

        self.panel.SetSizer(self.sizer)
        self.sizer.Fit(self)

    def GetType(self):
        """Get element type"""
        if not self.etype:
            return
        return self.element.tcp.GetType()

    def OnType(self, event):
        """Select element type"""
        evalue = self.typeSelect.GetValue(event.GetString())
        self.element.SetType(evalue)

    def OnOK(self, event):
        """Ok pressed"""
        self.shape.SetValue(self.element.GetValue())
        if self.etype:
            elem = self.GetType()
            if elem == 'raster':
                self.shape.SetPrompt('raster')
            elif elem == 'vector':
                self.shape.SetPrompt('vector')
            elif elem == 'raster_3d':
                self.shape.SetPrompt('raster_3d')

        self.parent.canvas.Refresh()
        self.parent.SetStatusText('', 0)
        self.shape.SetPropDialog(None)

        if self.IsModal():
            event.Skip()
        else:
            self.Destroy()

    def OnCancel(self, event):
        """Cancel pressed"""
        self.shape.SetPropDialog(None)
        if self.IsModal():
            event.Skip()
        else:
            self.Destroy()
Пример #4
0
class AnalysesPanel(wx.Panel):
    def __init__(self, parent, giface, settings):
        wx.Panel.__init__(self, parent)
        self.giface = giface
        self.settings = settings

        mainSizer = wx.BoxSizer(wx.VERTICAL)
        if self.settings['analyses']['file']:
            path = self.settings['analyses']['file']
            initDir = os.path.dirname(path)
        else:
            path = initDir = ""
        self.contoursSelect = Select(self, size=(-1, -1), type='vector')
        self.contoursStepTextCtrl = wx.TextCtrl(self, size=(40, -1))
        self.contoursStepTextCtrl.SetToolTipString("Contour step")

        if 'contours' in self.settings['analyses'] and self.settings[
                'analyses']['contours']:
            self.contoursStepTextCtrl.SetValue(
                str(self.settings['analyses']['contours_step']))
            self.contoursSelect.SetValue(self.settings['analyses']['contours'])
        self.contoursSelect.Bind(wx.EVT_TEXT, self.OnAnalysesChange)
        self.contoursStepTextCtrl.Bind(wx.EVT_TEXT, self.OnAnalysesChange)

        self.selectAnalyses = filebrowse.FileBrowseButton(
            self,
            labelText="Analyses:",
            startDirectory=initDir,
            initialValue=path,
            changeCallback=lambda evt: self.SetAnalysesFile(evt.GetString()))
        if self.settings['analyses']['file']:
            self.selectAnalyses.SetValue(self.settings['analyses']['file'])

        newAnalyses = wx.Button(self, label="Create new file")
        newAnalyses.Bind(wx.EVT_BUTTON, lambda evt: self.CreateNewFile())

        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add(wx.StaticText(self, label="Contours:"),
                  proportion=0,
                  flag=wx.ALIGN_CENTER_VERTICAL | wx.RIGHT,
                  border=5)
        sizer.Add(self.contoursSelect,
                  proportion=1,
                  flag=wx.ALIGN_CENTER_VERTICAL | wx.RIGHT,
                  border=5)
        sizer.Add(self.contoursStepTextCtrl,
                  proportion=0,
                  flag=wx.ALIGN_CENTER_VERTICAL,
                  border=5)
        mainSizer.Add(sizer, flag=wx.EXPAND | wx.ALL, border=5)

        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add(self.selectAnalyses,
                  proportion=1,
                  flag=wx.ALIGN_CENTER_VERTICAL | wx.RIGHT,
                  border=5)
        mainSizer.Add(sizer, flag=wx.EXPAND | wx.ALL, border=5)

        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.AddStretchSpacer()
        sizer.Add(newAnalyses,
                  proportion=1,
                  flag=wx.ALIGN_CENTER_VERTICAL | wx.RIGHT,
                  border=5)
        mainSizer.Add(sizer,
                      flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
                      border=5)

        self.SetSizer(mainSizer)
        mainSizer.Fit(self)

    def SetAnalysesFile(self, path):
        self.settings['analyses']['file'] = path

    def OnAnalysesChange(self, event):
        self.settings['analyses']['contours'] = self.contoursSelect.GetValue()
        self.settings['analyses'][
            'contours_step'] = self.contoursStepTextCtrl.GetValue()

    def CreateNewFile(self):
        get_lib_path('g.gui.tangible')
        dlg = wx.FileDialog(self,
                            message="Create a new file with analyses",
                            wildcard="Python source (*.py)|*.py",
                            style=wx.SAVE | wx.FD_OVERWRITE_PROMPT)
        if dlg.ShowModal() == wx.ID_OK:
            path = dlg.GetPath()
            orig = os.path.join(get_lib_path('g.gui.tangible'),
                                'current_analyses.py')
            if not os.path.exists(orig):
                self.giface.WriteError(
                    "File with analyses not found: {}".format(orig))
            else:
                copyfile(orig, path)
                self.selectAnalyses.SetValue(path)
                self.settings['analyses']['file'] = path
        dlg.Destroy()
Пример #5
0
class ScanningPanel(wx.Panel):
    def __init__(self, parent, giface, settings):
        wx.Panel.__init__(self, parent)
        self.giface = giface
        self.settings = settings
        self.scan = self.settings['scan']

        self.settingsChanged = Signal('ScanningPanel.settingsChanged')

        mainSizer = wx.BoxSizer(wx.VERTICAL)
        hSizer = wx.BoxSizer(wx.HORIZONTAL)

        # create widgets
        self.scan_name_ctrl = wx.TextCtrl(self, value='scan')
        # widgets for model
        self.elevInput = Select(self, size=(-1, -1), type='raster')
        self.regionInput = Select(self, size=(-1, -1), type='region')
        self.zexag = wx.TextCtrl(self)
        self.numscans = wx.SpinCtrl(self, min=1, max=5, initial=1)
        self.rotate = wx.SpinCtrl(self, min=0, max=360, initial=180)
        self.smooth = wx.TextCtrl(self)
        self.resolution = wx.TextCtrl(self)
        self.trim = {}
        for each in 'tbnsew':
            self.trim[each] = wx.TextCtrl(self, size=(40, -1))
        self.trim_tolerance = wx.TextCtrl(self)
        self.interpolate = wx.CheckBox(
            self, label="Use interpolation instead of binning")
        self.equalize = wx.CheckBox(self,
                                    label="Use equalized color table for scan")

        self.elevInput.SetValue(self.scan['elevation'])
        self.regionInput.SetValue(self.scan['region'])
        self.zexag.SetValue(str(self.scan['zexag']))
        self.rotate.SetValue(self.scan['rotation_angle'])
        self.numscans.SetValue(self.scan['numscans'])
        self.interpolate.SetValue(self.scan['interpolate'])
        for i, each in enumerate('nsewtb'):
            self.trim[each].SetValue(self.scan['trim_nsewtb'].split(',')[i])
        self.equalize.SetValue(self.scan['equalize'])
        self.smooth.SetValue(str(self.scan['smooth']))
        self.resolution.SetValue(str(self.scan['resolution']))
        self.trim_tolerance.SetValue(str(self.scan['trim_tolerance']))

        # layout
        mainSizer.Add(hSizer, flag=wx.EXPAND)
        hSizer = wx.BoxSizer(wx.HORIZONTAL)
        hSizer.Add(wx.StaticText(self, label="Name of scanned raster:"),
                   flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL,
                   border=3)
        hSizer.Add(self.scan_name_ctrl,
                   proportion=1,
                   flag=wx.EXPAND | wx.ALL,
                   border=5)
        mainSizer.Add(hSizer, flag=wx.EXPAND)
        # model parameters
        hSizer = wx.BoxSizer(wx.HORIZONTAL)
        hSizer.Add(wx.StaticText(self, label="Reference DEM:"),
                   flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL,
                   border=3)
        hSizer.Add(self.elevInput,
                   proportion=1,
                   flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL,
                   border=3)
        mainSizer.Add(hSizer, flag=wx.EXPAND)
        # region
        hSizer = wx.BoxSizer(wx.HORIZONTAL)
        hSizer.Add(wx.StaticText(self, label="Reference region:"),
                   flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL,
                   border=3)
        hSizer.Add(self.regionInput,
                   proportion=1,
                   flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL,
                   border=3)
        mainSizer.Add(hSizer, flag=wx.EXPAND)
        hSizer = wx.BoxSizer(wx.HORIZONTAL)
        hSizer.Add(wx.StaticText(self, label="Z-exaggeration:"),
                   proportion=1,
                   flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL,
                   border=3)
        hSizer.Add(self.zexag,
                   flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL,
                   border=3)
        mainSizer.Add(hSizer, flag=wx.EXPAND)
        # number of scans
        hSizer = wx.BoxSizer(wx.HORIZONTAL)
        hSizer.Add(wx.StaticText(self, label="Number of scans:"),
                   proportion=1,
                   flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL,
                   border=3)
        hSizer.Add(self.numscans,
                   flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL,
                   border=3)
        mainSizer.Add(hSizer, flag=wx.EXPAND)
        hSizer = wx.BoxSizer(wx.HORIZONTAL)
        hSizer.Add(wx.StaticText(self, label="Rotation angle:"),
                   proportion=1,
                   flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL,
                   border=3)
        hSizer.Add(self.rotate,
                   flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL,
                   border=3)
        mainSizer.Add(hSizer, flag=wx.EXPAND)
        # smooth
        hSizer = wx.BoxSizer(wx.HORIZONTAL)
        hSizer.Add(wx.StaticText(self, label="Smooth value:"),
                   proportion=1,
                   flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL,
                   border=3)
        hSizer.Add(self.smooth,
                   flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL,
                   border=3)
        mainSizer.Add(hSizer, flag=wx.EXPAND)
        # resolution
        hSizer = wx.BoxSizer(wx.HORIZONTAL)
        hSizer.Add(wx.StaticText(self, label="Resolution [mm]:"),
                   proportion=1,
                   flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL,
                   border=3)
        hSizer.Add(self.resolution,
                   flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL,
                   border=3)
        mainSizer.Add(hSizer, flag=wx.EXPAND)
        hSizer = wx.BoxSizer(wx.HORIZONTAL)
        hSizer.Add(wx.StaticText(self,
                                 label="Limit scan vertically T, B [cm]:"),
                   proportion=1,
                   flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL,
                   border=3)
        for each in 'tb':
            hSizer.Add(self.trim[each],
                       flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL,
                       border=3)
        mainSizer.Add(hSizer, flag=wx.EXPAND)
        hSizer = wx.BoxSizer(wx.HORIZONTAL)
        hSizer.Add(wx.StaticText(self, label="Trim scan N, S, E, W [cm]:"),
                   proportion=1,
                   flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL,
                   border=3)
        for each in 'nsew':
            hSizer.Add(self.trim[each],
                       flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL,
                       border=3)
        mainSizer.Add(hSizer, flag=wx.EXPAND)
        hSizer = wx.BoxSizer(wx.HORIZONTAL)
        hSizer.Add(wx.StaticText(self, label="Trim tolerance [0-1]:"),
                   proportion=1,
                   flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL,
                   border=3)
        hSizer.Add(self.trim_tolerance,
                   flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL,
                   border=3)
        mainSizer.Add(hSizer, flag=wx.EXPAND)
        hSizer = wx.BoxSizer(wx.HORIZONTAL)
        hSizer.Add(self.interpolate,
                   flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL,
                   border=3)
        mainSizer.Add(hSizer, flag=wx.EXPAND)
        hSizer = wx.BoxSizer(wx.HORIZONTAL)
        hSizer.Add(self.equalize,
                   flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL,
                   border=3)
        mainSizer.Add(hSizer, flag=wx.EXPAND)

        self.SetSizer(mainSizer)
        mainSizer.Fit(self)

        self.BindModelProperties()

    def BindModelProperties(self):
        self.scan_name_ctrl.Bind(wx.EVT_TEXT, self.OnModelProperties)
        # model parameters
        self.elevInput.Bind(wx.EVT_TEXT, self.OnModelProperties)
        self.regionInput.Bind(wx.EVT_TEXT, self.OnModelProperties)
        self.zexag.Bind(wx.EVT_TEXT, self.OnModelProperties)
        self.rotate.Bind(wx.EVT_SPINCTRL, self.OnModelProperties)
        self.rotate.Bind(wx.EVT_TEXT, self.OnModelProperties)
        self.numscans.Bind(wx.EVT_SPINCTRL, self.OnModelProperties)
        self.numscans.Bind(wx.EVT_TEXT, self.OnModelProperties)
        self.interpolate.Bind(wx.EVT_CHECKBOX, self.OnModelProperties)
        self.equalize.Bind(wx.EVT_CHECKBOX, self.OnModelProperties)
        self.smooth.Bind(wx.EVT_TEXT, self.OnModelProperties)
        self.resolution.Bind(wx.EVT_TEXT, self.OnModelProperties)
        self.trim_tolerance.Bind(wx.EVT_TEXT, self.OnModelProperties)
        for each in 'nsewtb':
            self.trim[each].Bind(wx.EVT_TEXT, self.OnModelProperties)

    def OnModelProperties(self, event):
        self.scan['scan_name'] = self.scan_name_ctrl.GetValue()
        self.scan['elevation'] = self.elevInput.GetValue()
        self.scan['region'] = self.regionInput.GetValue()
        self.scan['rotation_angle'] = self.rotate.GetValue()
        self.scan['numscans'] = self.numscans.GetValue()
        self.scan['interpolate'] = self.interpolate.IsChecked()
        self.scan['equalize'] = self.equalize.IsChecked()
        self.scan['smooth'] = self.smooth.GetValue()
        self.scan['resolution'] = self.resolution.GetValue()
        self.scan['trim_tolerance'] = self.trim_tolerance.GetValue()

        try:
            self.scan['zexag'] = float(self.zexag.GetValue())
            nsewtb_list = []
            for each in 'nsewtb':
                nsewtb_list.append(self.trim[each].GetValue())
            self.scan['trim_nsewtb'] = ','.join(nsewtb_list)
        except ValueError:
            pass
        self.settingsChanged.emit()
Пример #6
0
class MapCalcFrame(wx.Frame):
    """Mapcalc Frame class. Calculator-style window to create and run
    r(3).mapcalc statements.
    """
    def __init__(self,
                 parent,
                 giface,
                 cmd,
                 id=wx.ID_ANY,
                 style=wx.DEFAULT_FRAME_STYLE | wx.RESIZE_BORDER,
                 **kwargs):
        self.parent = parent
        self._giface = giface

        if self.parent:
            self.log = self.parent.GetLogWindow()
        else:
            self.log = None

        # grass command
        self.cmd = cmd

        if self.cmd == 'r.mapcalc':
            self.rast3d = False
            title = _('GRASS GIS Raster Map Calculator')
        if self.cmd == 'r3.mapcalc':
            self.rast3d = True
            title = _('GRASS GIS 3D Raster Map Calculator')

        wx.Frame.__init__(self, parent, id=id, title=title, **kwargs)
        self.SetIcon(
            wx.Icon(os.path.join(globalvar.ICONDIR, 'grass.ico'),
                    wx.BITMAP_TYPE_ICO))

        self.panel = wx.Panel(parent=self, id=wx.ID_ANY)
        self.CreateStatusBar()

        #
        # variables
        #
        self.heading = _('mapcalc statement')
        self.funct_dict = {
            'abs(x)': 'abs()',
            'acos(x)': 'acos()',
            'asin(x)': 'asin()',
            'atan(x)': 'atan()',
            'atan(x,y)': 'atan( , )',
            'cos(x)': 'cos()',
            'double(x)': 'double()',
            'eval([x,y,...,]z)': 'eval()',
            'exp(x)': 'exp()',
            'exp(x,y)': 'exp( , )',
            'float(x)': 'float()',
            'graph(x,x1,y1[x2,y2..])': 'graph( , , )',
            'if(x)': 'if()',
            'if(x,a)': 'if( , )',
            'if(x,a,b)': 'if( , , )',
            'if(x,a,b,c)': 'if( , , , )',
            'int(x)': 'int()',
            'isnull(x)': 'isnull()',
            'log(x)': 'log(',
            'log(x,b)': 'log( , )',
            'max(x,y[,z...])': 'max( , )',
            'median(x,y[,z...])': 'median( , )',
            'min(x,y[,z...])': 'min( , )',
            'mode(x,y[,z...])': 'mode( , )',
            'nmax(x,y[,z...])': 'nmax( , )',
            'nmedian(x,y[,z...])': 'nmedian( , )',
            'nmin(x,y[,z...])': 'nmin( , )',
            'nmode(x,y[,z...])': 'nmode( , )',
            'not(x)': 'not()',
            'pow(x,y)': 'pow( , )',
            'rand(a,b)': 'rand( , )',
            'round(x)': 'round()',
            'round(x,y)': 'round( , )',
            'round(x,y,z)': 'round( , , )',
            'sin(x)': 'sin()',
            'sqrt(x)': 'sqrt()',
            'tan(x)': 'tan()',
            'xor(x,y)': 'xor( , )',
            'row()': 'row()',
            'col()': 'col()',
            'nrows()': 'nrows()',
            'ncols()': 'ncols()',
            'x()': 'x()',
            'y()': 'y()',
            'ewres()': 'ewres()',
            'nsres()': 'nsres()',
            'area()': 'area()',
            'null()': 'null()'
        }

        if self.rast3d:
            self.funct_dict['z()'] = 'z()'
            self.funct_dict['tbres()'] = 'tbres()'
            element = 'raster_3d'
        else:
            element = 'cell'

        # characters which can be in raster map name but the map name must be
        # then quoted
        self.charactersToQuote = '+-&!<>%~?^|'
        # stores last typed map name in Select widget to distinguish typing
        # from selection
        self.lastMapName = ''

        self.operatorBox = StaticBox(parent=self.panel,
                                     id=wx.ID_ANY,
                                     label=" %s " % _('Operators'))
        self.outputBox = StaticBox(parent=self.panel,
                                   id=wx.ID_ANY,
                                   label=" %s " % _('Output'))
        self.operandBox = StaticBox(parent=self.panel,
                                    id=wx.ID_ANY,
                                    label=" %s " % _('Operands'))
        self.expressBox = StaticBox(parent=self.panel,
                                    id=wx.ID_ANY,
                                    label=" %s " % _('Expression'))

        #
        # Buttons
        #
        self.btn_clear = ClearButton(parent=self.panel)
        self.btn_help = Button(parent=self.panel, id=wx.ID_HELP)
        self.btn_run = Button(parent=self.panel, id=wx.ID_ANY, label=_("&Run"))
        self.btn_run.SetDefault()
        self.btn_close = CloseButton(parent=self.panel)
        self.btn_save = Button(parent=self.panel, id=wx.ID_SAVE)
        self.btn_save.SetToolTip(_('Save expression to file'))
        self.btn_load = Button(parent=self.panel,
                               id=wx.ID_ANY,
                               label=_("&Load"))
        self.btn_load.SetToolTip(_('Load expression from file'))
        self.btn_copy = Button(parent=self.panel,
                               id=wx.ID_ANY,
                               label=_("Copy"))
        self.btn_copy.SetToolTip(
            _("Copy the current command string to the clipboard"))

        self.btn = dict()
        self.btn['pow'] = Button(parent=self.panel, id=wx.ID_ANY, label="^")
        self.btn['pow'].SetToolTip(_('exponent'))
        self.btn['div'] = Button(parent=self.panel, id=wx.ID_ANY, label="/")
        self.btn['div'].SetToolTip(_('divide'))
        self.btn['add'] = Button(parent=self.panel, id=wx.ID_ANY, label="+")
        self.btn['add'].SetToolTip(_('add'))
        self.btn['minus'] = Button(parent=self.panel, id=wx.ID_ANY, label="-")
        self.btn['minus'].SetToolTip(_('subtract'))
        self.btn['mod'] = Button(parent=self.panel, id=wx.ID_ANY, label="%")
        self.btn['mod'].SetToolTip(_('modulus'))
        self.btn['mult'] = Button(parent=self.panel, id=wx.ID_ANY, label="*")
        self.btn['mult'].SetToolTip(_('multiply'))

        self.btn['parenl'] = Button(parent=self.panel, id=wx.ID_ANY, label="(")
        self.btn['parenr'] = Button(parent=self.panel, id=wx.ID_ANY, label=")")
        self.btn['lshift'] = Button(parent=self.panel,
                                    id=wx.ID_ANY,
                                    label="<<")
        self.btn['lshift'].SetToolTip(_('left shift'))
        self.btn['rshift'] = Button(parent=self.panel,
                                    id=wx.ID_ANY,
                                    label=">>")
        self.btn['rshift'].SetToolTip(_('right shift'))
        self.btn['rshiftu'] = Button(parent=self.panel,
                                     id=wx.ID_ANY,
                                     label=">>>")
        self.btn['rshiftu'].SetToolTip(_('right shift (unsigned)'))
        self.btn['gt'] = Button(parent=self.panel, id=wx.ID_ANY, label=">")
        self.btn['gt'].SetToolTip(_('greater than'))
        self.btn['gteq'] = Button(parent=self.panel, id=wx.ID_ANY, label=">=")
        self.btn['gteq'].SetToolTip(_('greater than or equal to'))
        self.btn['lt'] = Button(parent=self.panel, id=wx.ID_ANY, label="<")
        self.btn['lt'].SetToolTip(_('less than'))
        self.btn['lteq'] = Button(parent=self.panel, id=wx.ID_ANY, label="<=")
        self.btn['lteq'].SetToolTip(_('less than or equal to'))
        self.btn['eq'] = Button(parent=self.panel, id=wx.ID_ANY, label="==")
        self.btn['eq'].SetToolTip(_('equal to'))
        self.btn['noteq'] = Button(parent=self.panel, id=wx.ID_ANY, label="!=")
        self.btn['noteq'].SetToolTip(_('not equal to'))

        self.btn['compl'] = Button(parent=self.panel, id=wx.ID_ANY, label="~")
        self.btn['compl'].SetToolTip(_('one\'s complement'))
        self.btn['not'] = Button(parent=self.panel, id=wx.ID_ANY, label="!")
        self.btn['not'].SetToolTip(_('NOT'))
        self.btn['andbit'] = Button(parent=self.panel,
                                    id=wx.ID_ANY,
                                    label='&&')
        self.btn['andbit'].SetToolTip(_('bitwise AND'))
        self.btn['orbit'] = Button(parent=self.panel, id=wx.ID_ANY, label="|")
        self.btn['orbit'].SetToolTip(_('bitwise OR'))
        self.btn['and'] = Button(parent=self.panel, id=wx.ID_ANY, label="&&&&")
        self.btn['and'].SetToolTip(_('logical AND'))
        self.btn['andnull'] = Button(parent=self.panel,
                                     id=wx.ID_ANY,
                                     label="&&&&&&")
        self.btn['andnull'].SetToolTip(_('logical AND (ignores NULLs)'))
        self.btn['or'] = Button(parent=self.panel, id=wx.ID_ANY, label="||")
        self.btn['or'].SetToolTip(_('logical OR'))
        self.btn['ornull'] = Button(parent=self.panel,
                                    id=wx.ID_ANY,
                                    label="|||")
        self.btn['ornull'].SetToolTip(_('logical OR (ignores NULLs)'))
        self.btn['cond'] = Button(parent=self.panel,
                                  id=wx.ID_ANY,
                                  label="a ? b : c")
        self.btn['cond'].SetToolTip(_('conditional'))

        #
        # Text area
        #
        self.text_mcalc = TextCtrl(parent=self.panel,
                                   id=wx.ID_ANY,
                                   size=(-1, 100),
                                   style=wx.TE_MULTILINE)
        wx.CallAfter(self.text_mcalc.SetFocus)

        #
        # Map and function insertion text and ComboBoxes
        self.newmaplabel = StaticText(parent=self.panel, id=wx.ID_ANY)
        if self.rast3d:
            self.newmaplabel.SetLabel(
                _('Name for new 3D raster map to create'))
        else:
            self.newmaplabel.SetLabel(_('Name for new raster map to create'))
        # As we can write only to current mapset, names should not be fully qualified
        # to not confuse end user about writing in other mapset
        self.newmaptxt = Select(parent=self.panel,
                                id=wx.ID_ANY,
                                size=(250, -1),
                                type=element,
                                multiple=False,
                                fullyQualified=False)
        self.mapsellabel = StaticText(parent=self.panel, id=wx.ID_ANY)
        if self.rast3d:
            self.mapsellabel.SetLabel(_('Insert existing 3D raster map'))
        else:
            self.mapsellabel.SetLabel(_('Insert existing raster map'))
        self.mapselect = Select(parent=self.panel,
                                id=wx.ID_ANY,
                                size=(250, -1),
                                type=element,
                                multiple=False)
        self.functlabel = StaticText(parent=self.panel,
                                     id=wx.ID_ANY,
                                     label=_('Insert mapcalc function'))
        self.function = wx.ComboBox(parent=self.panel,
                                    id=wx.ID_ANY,
                                    size=(250, -1),
                                    choices=sorted(self.funct_dict.keys()),
                                    style=wx.CB_DROPDOWN | wx.CB_READONLY
                                    | wx.TE_PROCESS_ENTER)

        self.overwrite = wx.CheckBox(
            parent=self.panel,
            id=wx.ID_ANY,
            label=_("Allow output files to overwrite existing files"))
        self.overwrite.SetValue(
            UserSettings.Get(group='cmd', key='overwrite', subkey='enabled'))

        self.randomSeed = wx.CheckBox(
            parent=self.panel, label=_("Generate random seed for rand()"))
        self.randomSeedStaticText = StaticText(parent=self.panel,
                                               label=_("Seed:"))
        self.randomSeedText = TextCtrl(parent=self.panel,
                                       size=(100, -1),
                                       validator=IntegerValidator())
        self.randomSeedText.SetToolTip(_("Integer seed for rand() function"))
        self.randomSeed.SetValue(True)
        self.randomSeedStaticText.Disable()
        self.randomSeedText.Disable()

        self.addbox = wx.CheckBox(
            parent=self.panel,
            label=_('Add created raster map into layer tree'),
            style=wx.NO_BORDER)
        self.addbox.SetValue(
            UserSettings.Get(group='cmd', key='addNewLayer', subkey='enabled'))
        if not self.parent or self.parent.GetName() != 'LayerManager':
            self.addbox.Hide()

        #
        # Bindings
        #
        for btn in self.btn.keys():
            self.btn[btn].Bind(wx.EVT_BUTTON, self.AddMark)

        self.btn_close.Bind(wx.EVT_BUTTON, self.OnClose)
        self.btn_clear.Bind(wx.EVT_BUTTON, self.OnClear)
        self.btn_run.Bind(wx.EVT_BUTTON, self.OnMCalcRun)
        self.btn_help.Bind(wx.EVT_BUTTON, self.OnHelp)
        self.btn_save.Bind(wx.EVT_BUTTON, self.OnSaveExpression)
        self.btn_load.Bind(wx.EVT_BUTTON, self.OnLoadExpression)
        self.btn_copy.Bind(wx.EVT_BUTTON, self.OnCopyCommand)

        self.mapselect.Bind(wx.EVT_TEXT, self.OnSelect)
        self.function.Bind(wx.EVT_COMBOBOX, self._return_funct)
        self.function.Bind(wx.EVT_TEXT_ENTER, self.OnSelect)
        self.newmaptxt.Bind(wx.EVT_TEXT, self.OnUpdateStatusBar)
        self.text_mcalc.Bind(wx.EVT_TEXT, self.OnUpdateStatusBar)
        self.overwrite.Bind(wx.EVT_CHECKBOX, self.OnUpdateStatusBar)
        self.randomSeed.Bind(wx.EVT_CHECKBOX, self.OnUpdateStatusBar)
        self.randomSeed.Bind(wx.EVT_CHECKBOX, self.OnSeedFlag)
        self.randomSeedText.Bind(wx.EVT_TEXT, self.OnUpdateStatusBar)

        # bind closing to ESC
        self.Bind(wx.EVT_MENU, self.OnClose, id=wx.ID_CANCEL)
        accelTableList = [(wx.ACCEL_NORMAL, wx.WXK_ESCAPE, wx.ID_CANCEL)]
        accelTable = wx.AcceleratorTable(accelTableList)
        self.SetAcceleratorTable(accelTable)

        self._layout()

        self.SetMinSize(self.panel.GetBestSize())
        # workaround for http://trac.wxwidgets.org/ticket/13628
        self.SetSize(self.panel.GetBestSize())

    def _return_funct(self, event):
        i = event.GetString()
        self._addSomething(self.funct_dict[i])

        # reset
        win = self.FindWindowById(event.GetId())
        win.SetValue('')

    def _layout(self):
        sizer = wx.BoxSizer(wx.VERTICAL)

        controlSizer = wx.BoxSizer(wx.HORIZONTAL)
        operatorSizer = wx.StaticBoxSizer(self.operatorBox, wx.HORIZONTAL)
        outOpeSizer = wx.BoxSizer(wx.VERTICAL)

        buttonSizer1 = wx.GridBagSizer(5, 1)
        buttonSizer1.Add(self.btn['add'], pos=(0, 0))
        buttonSizer1.Add(self.btn['minus'], pos=(0, 1))
        buttonSizer1.Add(self.btn['mod'], pos=(5, 0))
        buttonSizer1.Add(self.btn['mult'], pos=(1, 0))
        buttonSizer1.Add(self.btn['div'], pos=(1, 1))
        buttonSizer1.Add(self.btn['pow'], pos=(5, 1))
        buttonSizer1.Add(self.btn['gt'], pos=(2, 0))
        buttonSizer1.Add(self.btn['gteq'], pos=(2, 1))
        buttonSizer1.Add(self.btn['eq'], pos=(4, 0))
        buttonSizer1.Add(self.btn['lt'], pos=(3, 0))
        buttonSizer1.Add(self.btn['lteq'], pos=(3, 1))
        buttonSizer1.Add(self.btn['noteq'], pos=(4, 1))

        buttonSizer2 = wx.GridBagSizer(5, 1)
        buttonSizer2.Add(self.btn['and'], pos=(0, 0))
        buttonSizer2.Add(self.btn['andbit'], pos=(1, 0))
        buttonSizer2.Add(self.btn['andnull'], pos=(2, 0))
        buttonSizer2.Add(self.btn['or'], pos=(0, 1))
        buttonSizer2.Add(self.btn['orbit'], pos=(1, 1))
        buttonSizer2.Add(self.btn['ornull'], pos=(2, 1))
        buttonSizer2.Add(self.btn['lshift'], pos=(3, 0))
        buttonSizer2.Add(self.btn['rshift'], pos=(3, 1))
        buttonSizer2.Add(self.btn['rshiftu'], pos=(4, 0))
        buttonSizer2.Add(self.btn['cond'], pos=(5, 0))
        buttonSizer2.Add(self.btn['compl'], pos=(5, 1))
        buttonSizer2.Add(self.btn['not'], pos=(4, 1))

        outputSizer = wx.StaticBoxSizer(self.outputBox, wx.VERTICAL)
        outputSizer.Add(self.newmaplabel,
                        flag=wx.ALIGN_CENTER | wx.TOP,
                        border=5)
        outputSizer.Add(self.newmaptxt, flag=wx.EXPAND | wx.ALL, border=5)

        operandSizer = wx.StaticBoxSizer(self.operandBox, wx.HORIZONTAL)

        buttonSizer3 = wx.GridBagSizer(7, 1)
        buttonSizer3.Add(self.functlabel,
                         pos=(0, 0),
                         span=(1, 2),
                         flag=wx.ALIGN_CENTER | wx.EXPAND)
        buttonSizer3.Add(self.function, pos=(1, 0), span=(1, 2))
        buttonSizer3.Add(self.mapsellabel,
                         pos=(2, 0),
                         span=(1, 2),
                         flag=wx.ALIGN_CENTER)
        buttonSizer3.Add(self.mapselect, pos=(3, 0), span=(1, 2))
        threebutton = wx.GridBagSizer(1, 2)
        threebutton.Add(self.btn['parenl'],
                        pos=(0, 0),
                        span=(1, 1),
                        flag=wx.ALIGN_LEFT)
        threebutton.Add(self.btn['parenr'],
                        pos=(0, 1),
                        span=(1, 1),
                        flag=wx.ALIGN_CENTER)
        threebutton.Add(self.btn_clear,
                        pos=(0, 2),
                        span=(1, 1),
                        flag=wx.ALIGN_RIGHT)
        buttonSizer3.Add(threebutton,
                         pos=(4, 0),
                         span=(1, 1),
                         flag=wx.ALIGN_CENTER)

        buttonSizer4 = wx.BoxSizer(wx.HORIZONTAL)
        buttonSizer4.Add(self.btn_load, flag=wx.ALL, border=5)
        buttonSizer4.Add(self.btn_save, flag=wx.ALL, border=5)
        buttonSizer4.Add(self.btn_copy, flag=wx.ALL, border=5)
        buttonSizer4.AddSpacer(30)
        buttonSizer4.Add(self.btn_help, flag=wx.ALL, border=5)
        buttonSizer4.Add(self.btn_run, flag=wx.ALL, border=5)
        buttonSizer4.Add(self.btn_close, flag=wx.ALL, border=5)

        operatorSizer.Add(buttonSizer1,
                          proportion=0,
                          flag=wx.ALL | wx.EXPAND,
                          border=5)
        operatorSizer.Add(buttonSizer2,
                          proportion=0,
                          flag=wx.TOP | wx.BOTTOM | wx.RIGHT | wx.EXPAND,
                          border=5)

        operandSizer.Add(buttonSizer3, proportion=0, flag=wx.ALL, border=5)

        controlSizer.Add(operatorSizer,
                         proportion=1,
                         flag=wx.RIGHT | wx.EXPAND,
                         border=5)
        outOpeSizer.Add(outputSizer, proportion=0, flag=wx.EXPAND)
        outOpeSizer.Add(operandSizer,
                        proportion=1,
                        flag=wx.EXPAND | wx.TOP,
                        border=5)
        controlSizer.Add(outOpeSizer, proportion=0, flag=wx.EXPAND)

        expressSizer = wx.StaticBoxSizer(self.expressBox, wx.HORIZONTAL)
        expressSizer.Add(self.text_mcalc, proportion=1, flag=wx.EXPAND)

        sizer.Add(controlSizer,
                  proportion=0,
                  flag=wx.EXPAND | wx.ALL,
                  border=5)
        sizer.Add(expressSizer,
                  proportion=1,
                  flag=wx.EXPAND | wx.LEFT | wx.RIGHT,
                  border=5)
        sizer.Add(buttonSizer4,
                  proportion=0,
                  flag=wx.ALIGN_RIGHT | wx.ALL,
                  border=3)

        randomSizer = wx.BoxSizer(wx.HORIZONTAL)
        randomSizer.Add(self.randomSeed,
                        proportion=0,
                        flag=wx.RIGHT | wx.ALIGN_CENTER_VERTICAL,
                        border=20)
        randomSizer.Add(self.randomSeedStaticText,
                        proportion=0,
                        flag=wx.RIGHT | wx.ALIGN_CENTER_VERTICAL,
                        border=5)
        randomSizer.Add(self.randomSeedText, proportion=0)
        sizer.Add(randomSizer, proportion=0, flag=wx.LEFT | wx.RIGHT, border=5)

        sizer.Add(self.overwrite,
                  proportion=0,
                  flag=wx.LEFT | wx.RIGHT,
                  border=5)
        if self.addbox.IsShown():
            sizer.Add(self.addbox,
                      proportion=0,
                      flag=wx.LEFT | wx.RIGHT,
                      border=5)

        self.panel.SetAutoLayout(True)
        self.panel.SetSizer(sizer)
        sizer.Fit(self.panel)

        self.Layout()

    def AddMark(self, event):
        """Sends operators to insertion method
        """
        if event.GetId() == self.btn['compl'].GetId():
            mark = "~"
        elif event.GetId() == self.btn['not'].GetId():
            mark = "!"
        elif event.GetId() == self.btn['pow'].GetId():
            mark = "^"
        elif event.GetId() == self.btn['div'].GetId():
            mark = "/"
        elif event.GetId() == self.btn['add'].GetId():
            mark = "+"
        elif event.GetId() == self.btn['minus'].GetId():
            mark = "-"
        elif event.GetId() == self.btn['mod'].GetId():
            mark = "%"
        elif event.GetId() == self.btn['mult'].GetId():
            mark = "*"
        elif event.GetId() == self.btn['lshift'].GetId():
            mark = "<<"
        elif event.GetId() == self.btn['rshift'].GetId():
            mark = ">>"
        elif event.GetId() == self.btn['rshiftu'].GetId():
            mark = ">>>"
        elif event.GetId() == self.btn['gt'].GetId():
            mark = ">"
        elif event.GetId() == self.btn['gteq'].GetId():
            mark = ">="
        elif event.GetId() == self.btn['lt'].GetId():
            mark = "<"
        elif event.GetId() == self.btn['lteq'].GetId():
            mark = "<="
        elif event.GetId() == self.btn['eq'].GetId():
            mark = "=="
        elif event.GetId() == self.btn['noteq'].GetId():
            mark = "!="
        elif event.GetId() == self.btn['andbit'].GetId():
            mark = "&"
        elif event.GetId() == self.btn['orbit'].GetId():
            mark = "|"
        elif event.GetId() == self.btn['or'].GetId():
            mark = "||"
        elif event.GetId() == self.btn['ornull'].GetId():
            mark = "|||"
        elif event.GetId() == self.btn['and'].GetId():
            mark = "&&"
        elif event.GetId() == self.btn['andnull'].GetId():
            mark = "&&&"
        elif event.GetId() == self.btn['cond'].GetId():
            mark = " ? : "
        elif event.GetId() == self.btn['parenl'].GetId():
            mark = "("
        elif event.GetId() == self.btn['parenr'].GetId():
            mark = ")"
        self._addSomething(mark)

    # unused
    # def OnSelectTextEvt(self, event):
    #     """Checks if user is typing or the event was emited by map selection.
    #     Prevents from changing focus.
    #     """
    #     item = self.mapselect.GetValue().strip()
    #     if not (abs(len(item) - len(self.lastMapName)) == 1 and \
    #         self.lastMapName in item or item in self.lastMapName):
    #         self.OnSelect(event)

    #     self.lastMapName = item

    def OnSelect(self, event):
        """Gets raster map or function selection and send it to
        insertion method.

        Checks for characters which can be in raster map name but
        the raster map name must be then quoted.
        """
        win = self.FindWindowById(event.GetId())
        item = win.GetValue().strip()
        if any((char in item) for char in self.charactersToQuote):
            item = '"' + item + '"'
        self._addSomething(item)

        win.ChangeValue('')  # reset
        # Map selector likes to keep focus. Set it back to expression input area
        wx.CallAfter(self.text_mcalc.SetFocus)

    def OnUpdateStatusBar(self, event):
        """Update statusbar text"""
        command = self._getCommand()
        self.SetStatusText(command)
        event.Skip()

    def OnSeedFlag(self, event):
        checked = self.randomSeed.IsChecked()
        self.randomSeedText.Enable(not checked)
        self.randomSeedStaticText.Enable(not checked)

        event.Skip()

    def _getCommand(self):
        """Returns entire command as string."""
        expr = self.text_mcalc.GetValue().strip().replace("\n", " ")
        cmd = 'r.mapcalc'
        if self.rast3d:
            cmd = 'r3.mapcalc'
        overwrite = ''
        if self.overwrite.IsChecked():
            overwrite = ' --overwrite'
        seed_flag = seed = ''
        if re.search(pattern="rand *\(.+\)", string=expr):
            if self.randomSeed.IsChecked():
                seed_flag = ' -s'
            else:
                seed = " seed={val}".format(
                    val=self.randomSeedText.GetValue().strip())

        return ('{cmd} expression="{new} = {expr}"{seed}{seed_flag}{overwrite}'
                .format(cmd=cmd,
                        expr=expr,
                        new=self.newmaptxt.GetValue(),
                        seed_flag=seed_flag,
                        seed=seed,
                        overwrite=overwrite))

    def _addSomething(self, what):
        """Inserts operators, map names, and functions into text area
        """
        mcalcstr = self.text_mcalc.GetValue()
        position = self.text_mcalc.GetInsertionPoint()

        newmcalcstr = mcalcstr[:position]

        position_offset = 0
        try:
            if newmcalcstr[-1] != ' ':
                newmcalcstr += ' '
                position_offset += 1
        except:
            pass

        newmcalcstr += what

        # Do not add extra space if there is already one
        try:
            if newmcalcstr[-1] != ' ' and mcalcstr[position] != ' ':
                newmcalcstr += ' '
        except:
            newmcalcstr += ' '

        newmcalcstr += mcalcstr[position:]

        self.text_mcalc.SetValue(newmcalcstr)
        if len(what) > 0:
            match = re.search(pattern="\(.*\)", string=what)
            if match:
                position_offset += match.start() + 1
            else:
                position_offset += len(what)
                try:
                    if newmcalcstr[position + position_offset] == ' ':
                        position_offset += 1
                except:
                    pass

        self.text_mcalc.SetInsertionPoint(position + position_offset)
        self.text_mcalc.Update()
        self.text_mcalc.SetFocus()

    def OnMCalcRun(self, event):
        """Builds and runs r.mapcalc statement
        """
        name = self.newmaptxt.GetValue().strip()
        if not name:
            GError(parent=self,
                   message=_("You must enter the name of "
                             "a new raster map to create."))
            return

        if not (name[0] == '"' and name[-1] == '"') and any(
            (char in name) for char in self.charactersToQuote):
            name = '"' + name + '"'

        expr = self.text_mcalc.GetValue().strip().replace("\n", " ")
        if not expr:
            GError(parent=self,
                   message=_("You must enter an expression "
                             "to create a new raster map."))
            return

        seed_flag = seed = None
        if re.search(pattern="rand *\(.+\)", string=expr):
            if self.randomSeed.IsChecked():
                seed_flag = '-s'
            else:
                seed = self.randomSeedText.GetValue().strip()
        if self.log:
            cmd = [self.cmd]
            if seed_flag:
                cmd.append('-s')
            if seed:
                cmd.append("seed={val}".format(val=seed))
            if self.overwrite.IsChecked():
                cmd.append('--overwrite')
            cmd.append(str('expression=%s = %s' % (name, expr)))

            self.log.RunCmd(cmd, onDone=self.OnDone)
            self.parent.Raise()
        else:
            if self.overwrite.IsChecked():
                overwrite = True
            else:
                overwrite = False
            params = dict(expression="%s=%s" % (name, expr),
                          overwrite=overwrite)
            if seed_flag:
                params['flags'] = 's'
            if seed:
                params['seed'] = seed

            RunCommand(self.cmd, **params)

    def OnDone(self, event):
        """Add create map to the layer tree

        Sends the mapCreated signal from the grass interface.
        """
        if event.returncode != 0:
            return
        name = self.newmaptxt.GetValue().strip(
            ' "') + '@' + grass.gisenv()['MAPSET']
        ltype = 'raster'
        if self.rast3d:
            ltype = 'raster_3d'
        self._giface.mapCreated.emit(name=name,
                                     ltype=ltype,
                                     add=self.addbox.IsChecked())
        gisenv = grass.gisenv()
        self._giface.grassdbChanged.emit(grassdb=gisenv['GISDBASE'],
                                         location=gisenv['LOCATION_NAME'],
                                         mapset=gisenv['MAPSET'],
                                         action='new',
                                         map=name.split('@')[0],
                                         element=ltype)

    def OnSaveExpression(self, event):
        """Saves expression to file
        """
        mctxt = self.newmaptxt.GetValue() + ' = ' + self.text_mcalc.GetValue(
        ) + os.linesep

        # dialog
        dlg = wx.FileDialog(
            parent=self,
            message=_("Choose a file name to save the expression"),
            wildcard=_("Expression file (*)|*"),
            style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT)
        if dlg.ShowModal() == wx.ID_OK:
            path = dlg.GetPath()
            if not path:
                dlg.Destroy()
                return

            try:
                fobj = open(path, 'w')
                fobj.write(mctxt)
            finally:
                fobj.close()

        dlg.Destroy()

    def OnLoadExpression(self, event):
        """Load expression from file
        """
        dlg = wx.FileDialog(
            parent=self,
            message=_("Choose a file name to load the expression"),
            wildcard=_("Expression file (*)|*"),
            style=wx.FD_OPEN)
        if dlg.ShowModal() == wx.ID_OK:
            path = dlg.GetPath()
            if not path:
                dlg.Destroy()
                return

            try:
                fobj = open(path, 'r')
                mctxt = fobj.read()
            finally:
                fobj.close()

            try:
                result, exp = mctxt.split('=', 1)
            except ValueError:
                result = ''
                exp = mctxt

            self.newmaptxt.SetValue(result.strip())
            self.text_mcalc.SetValue(exp.strip())
            self.text_mcalc.SetFocus()
            self.text_mcalc.SetInsertionPointEnd()

        dlg.Destroy()

    def OnCopyCommand(self, event):
        command = self._getCommand()
        cmddata = wx.TextDataObject()
        cmddata.SetText(command)
        if wx.TheClipboard.Open():
            wx.TheClipboard.SetData(cmddata)
            wx.TheClipboard.Close()
            self.SetStatusText(
                _("'{cmd}' copied to clipboard").format(cmd=command))

    def OnClear(self, event):
        """Clears text area
        """
        self.text_mcalc.SetValue('')

    def OnHelp(self, event):
        """Launches r.mapcalc help
        """
        RunCommand('g.manual', parent=self, entry=self.cmd)

    def OnClose(self, event):
        """Close window"""
        self.Destroy()
Пример #7
0
class ModelDataDialog(ElementDialog):
    """!Data item properties dialog"""
    def __init__(self,
                 parent,
                 shape,
                 id=wx.ID_ANY,
                 title=_("Data properties"),
                 style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER):
        self.parent = parent
        self.shape = shape

        label, etype = self._getLabel()
        ElementDialog.__init__(self, parent, title, label=label, etype=etype)

        self.element = Select(parent=self.panel)
        self.element.SetValue(shape.GetValue())

        self.Bind(wx.EVT_BUTTON, self.OnOK, self.btnOK)
        self.Bind(wx.EVT_BUTTON, self.OnCancel, self.btnCancel)

        self.PostInit()

        if shape.GetValue():
            self.btnOK.Enable()

        self._layout()
        self.SetMinSize(self.GetSize())

    def _getLabel(self):
        etype = False
        prompt = self.shape.GetPrompt()
        if prompt == 'raster':
            label = _('Name of raster map:')
        elif prompt == 'vector':
            label = _('Name of vector map:')
        else:
            etype = True
            label = _('Name of element:')

        return label, etype

    def _layout(self):
        """!Do layout"""
        self.dataSizer.Add(self.element,
                           proportion=0,
                           flag=wx.EXPAND | wx.ALL,
                           border=1)

        self.panel.SetSizer(self.sizer)
        self.sizer.Fit(self)

    def OnOK(self, event):
        """!Ok pressed"""
        self.shape.SetValue(self.GetElement())
        if self.etype:
            elem = self.GetType()
            if elem == 'rast':
                self.shape.SetPrompt('raster')
            elif elem == 'vect':
                self.shape.SetPrompt('raster')

        self.parent.canvas.Refresh()
        self.parent.SetStatusText('', 0)
        self.shape.SetPropDialog(None)

        if self.IsModal():
            event.Skip()
        else:
            self.Destroy()

    def OnCancel(self, event):
        """!Cancel pressed"""
        self.shape.SetPropDialog(None)
        if self.IsModal():
            event.Skip()
        else:
            self.Destroy()
Пример #8
0
class OutputPanel(wx.Panel):
    def __init__(self, parent, giface, settings):
        wx.Panel.__init__(self, parent)
        self.giface = giface
        self.settings = settings
        self.settingsChanged = Signal('OutputPanel.settingsChanged')

        if 'output' not in self.settings:
            self.settings['output'] = {}
            self.settings['output']['scan'] = 'scan'
            self.settings['output']['PLY'] = False
            self.settings['output']['PLY_file'] = ''
            self.settings['output']['color'] = False
            self.settings['output']['color_name'] = ''
            self.settings['output']['blender'] = False
            self.settings['output']['blender_path'] = ''

        if self.settings['output']['PLY_file']:
            initDir = os.path.dirname(self.settings['output']['PLY_file'])
        else:
            initDir = ""

        # scan
        self.scan_name = wx.TextCtrl(self)
        self.scan_name.SetValue(self.settings['output']['scan'])
        self.scan_name.Bind(wx.EVT_TEXT, self.OnChange)
        bmp = get_show_layer_icon()
        self.addScan = wx.BitmapButton(self,
                                       bitmap=bmp,
                                       size=(bmp.GetWidth() + 12,
                                             bmp.GetHeight() + 8))
        self.addScan.Bind(wx.EVT_BUTTON, lambda evt: self._addLayer('scan'))

        # color
        self.ifColor = wx.CheckBox(
            self, label=_("Save color rasters (with postfixes _r, _g, _b):"))
        self.ifColor.SetValue(self.settings['output']['color'])
        self.ifColor.Bind(wx.EVT_CHECKBOX, self.OnChange)
        self.exportColor = Select(self, size=(-1, -1), type='raster')
        self.exportColor.SetValue(self.settings['output']['color_name'])
        self.exportColor.Bind(wx.EVT_TEXT, self.OnChange)
        bmp = get_show_layer_icon()
        self.addColor = wx.BitmapButton(self,
                                        bitmap=bmp,
                                        size=(bmp.GetWidth() + 12,
                                              bmp.GetHeight() + 8))
        self.addColor.Bind(wx.EVT_BUTTON, lambda evt: self._addLayer('color'))
        # Blender
        self.ifBlender = wx.CheckBox(self, label='')
        self.ifBlender.SetValue(self.settings['output']['blender'])
        self.ifBlender.Bind(wx.EVT_CHECKBOX, self.OnChange)
        initDirBlender = ''
        if self.settings['output']['blender_path']:
            initDirBlender = self.settings['output']['blender_path']
        self.blenderPath = filebrowse.DirBrowseButton(
            self,
            labelText="Export folder for Blender coupling:",
            startDirectory=initDirBlender,
            newDirectory=True,
            changeCallback=self.OnChange)

        # PLY
        self.ifPLY = wx.CheckBox(self, label="")
        self.ifPLY.SetValue(self.settings['output']['PLY'])
        self.ifPLY.Bind(wx.EVT_CHECKBOX, self.OnChange)
        self.exportPLY = filebrowse.FileBrowseButton(
            self,
            labelText="Export PLY:",
            fileMode=wx.FD_SAVE,
            startDirectory=initDir,
            initialValue=self.settings['output']['PLY_file'],
            changeCallback=self.OnChange)
        # must be called after all widgets are created
        self.blenderPath.SetValue(initDirBlender)

        mainSizer = wx.BoxSizer(wx.VERTICAL)
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add(wx.StaticText(self, label="Name of scanned raster:"),
                  flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL,
                  border=5)
        sizer.Add(self.scan_name,
                  proportion=1,
                  flag=wx.EXPAND | wx.ALL,
                  border=5)
        sizer.Add(self.addScan,
                  proportion=0,
                  flag=wx.EXPAND | wx.RIGHT | wx.TOP | wx.BOTTOM,
                  border=5)
        mainSizer.Add(sizer, flag=wx.EXPAND | wx.ALL, border=5)
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add(self.ifColor, flag=wx.ALIGN_CENTER_VERTICAL, border=5)
        sizer.Add(self.exportColor,
                  proportion=1,
                  flag=wx.ALIGN_CENTER_VERTICAL,
                  border=5)
        sizer.Add(self.addColor,
                  proportion=0,
                  flag=wx.EXPAND | wx.ALL,
                  border=5)
        mainSizer.Add(sizer, flag=wx.EXPAND | wx.ALL, border=5)
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add(self.ifBlender,
                  flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL | wx.LEFT,
                  border=3)
        sizer.Add(self.blenderPath,
                  flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL,
                  proportion=1,
                  border=0)
        mainSizer.Add(sizer, flag=wx.EXPAND | wx.ALL, border=5)
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add(self.ifPLY,
                  flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL | wx.LEFT,
                  border=3)
        sizer.Add(self.exportPLY,
                  flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL,
                  proportion=1,
                  border=0)
        mainSizer.Add(sizer, flag=wx.EXPAND | wx.ALL, border=5)
        self.SetSizer(mainSizer)
        mainSizer.Fit(self)

    def OnChange(self, event):
        self.settings['output']['scan'] = self.scan_name.GetValue()
        self.settings['output']['color'] = self.ifColor.IsChecked()
        self.settings['output']['color_name'] = self.exportColor.GetValue()
        self.settings['output']['blender'] = self.ifBlender.IsChecked()
        self.settings['output']['blender_path'] = self.blenderPath.GetValue()
        self.settings['output']['PLY'] = self.ifPLY.IsChecked()
        self.settings['output']['PLY_file'] = self.exportPLY.GetValue()
        self.settingsChanged.emit()

    def _addLayer(self, ltype):
        if not self.giface.GetLayerTree():
            return
        ll = self.giface.GetLayerList()
        if ltype == 'scan':
            raster = self.scan_name.GetValue()
            if not raster:
                return
            cmd = ['d.rast', 'map=' + raster]
            ll.AddLayer('raster', name=raster, checked=True, cmd=cmd)
        elif ltype == 'color':
            name = self.exportColor.GetValue()
            if not name:
                return
            cmd = [
                'd.rgb', 'red={m}'.format(m=name + '_r'),
                'green={m}'.format(m=name + '_g'),
                'blue={m}'.format(m=name + '_b'), '-n'
            ]
            ll.AddLayer('rgb', name=name, checked=True, cmd=cmd)
Пример #9
0
class DrawingPanel(wx.Panel):
    def __init__(self, parent, giface, settings):
        wx.Panel.__init__(self, parent)
        self.giface = giface
        self.settings = settings
        self.settingsChanged = Signal('ScanningPanel.settingsChanged')

        if 'drawing' not in self.settings:
            self.settings['drawing'] = {}
            self.settings['drawing']['active'] = False
            self.settings['drawing']['name'] = ''
            self.settings['drawing']['type'] = 'point'
            self.settings['drawing']['append'] = False
            self.settings['drawing']['appendName'] = ''
            self.settings['drawing']['threshold'] = 760

        mainSizer = wx.BoxSizer(wx.VERTICAL)
        self.ifDraw = wx.CheckBox(self, label=_("Draw vector:"))
        self.ifDraw.SetValue(self.settings['drawing']['active'])
        self.ifDraw.Bind(wx.EVT_CHECKBOX, self.OnDrawChange)
        self.ifDraw.Bind(wx.EVT_CHECKBOX, self.OnEnableDrawing)
        self.draw_vector = Select(self, size=(-1, -1), type='vector')
        self.draw_vector.SetValue(self.settings['drawing']['name'])
        self.draw_vector.Bind(wx.EVT_TEXT, self.OnDrawChange)
        self.draw_type = wx.RadioBox(parent=self,
                                     label="Vector type",
                                     choices=['point', 'line', 'area'])
        {'point': 0, 'line': 1, 'area': 2}[self.settings['drawing']['type']]
        self.draw_type.SetSelection({
            'point': 0,
            'line': 1,
            'area': 2
        }[self.settings['drawing']['type']])
        self.draw_type.Bind(wx.EVT_RADIOBOX, self.OnDrawChange)
        self.threshold = wx.SpinCtrl(
            parent=self,
            min=0,
            max=765,
            initial=int(self.settings['drawing']['threshold']))
        self.threshold.SetValue(int(self.settings['drawing']['threshold']))
        self.threshold.Bind(wx.EVT_SPINCTRL, self.OnDrawChange)
        self.append = wx.CheckBox(parent=self, label="Append vector")
        self.append.SetValue(self.settings['drawing']['append'])
        self.append.Bind(wx.EVT_CHECKBOX, self.OnDrawChange)
        self.appendName = Select(self, size=(-1, -1), type='vector')
        self.appendName.SetValue(self.settings['drawing']['appendName'])
        self.appendName.Bind(wx.EVT_TEXT, self.OnDrawChange)
        self.clearBtn = wx.Button(parent=self, label="Clear")
        self.clearBtn.Bind(wx.EVT_BUTTON,
                           lambda evt: self._newAppendedVector(evt))

        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add(self.ifDraw, flag=wx.ALIGN_CENTER_VERTICAL, border=5)
        sizer.Add(self.draw_vector,
                  proportion=1,
                  flag=wx.ALIGN_CENTER_VERTICAL,
                  border=5)
        mainSizer.Add(sizer, flag=wx.EXPAND | wx.ALL, border=5)
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add(self.draw_type,
                  proportion=1,
                  flag=wx.ALIGN_CENTER_VERTICAL,
                  border=5)
        mainSizer.Add(sizer, flag=wx.EXPAND | wx.ALL, border=5)
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add(wx.StaticText(self, label='Brightness threshold:'),
                  proportion=0,
                  flag=wx.ALIGN_CENTER_VERTICAL,
                  border=5)
        sizer.Add(self.threshold,
                  proportion=1,
                  flag=wx.ALIGN_CENTER_VERTICAL,
                  border=5)
        mainSizer.Add(sizer, flag=wx.EXPAND | wx.ALL, border=5)
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add(self.append,
                  proportion=0,
                  flag=wx.ALIGN_CENTER_VERTICAL,
                  border=5)
        sizer.Add(self.appendName,
                  proportion=1,
                  flag=wx.ALIGN_CENTER_VERTICAL,
                  border=5)
        sizer.Add(self.clearBtn, flag=wx.ALIGN_CENTER_VERTICAL, border=5)
        mainSizer.Add(sizer, flag=wx.EXPAND | wx.ALL, border=5)
        self.SetSizer(mainSizer)
        mainSizer.Fit(self)
        self.EnableDrawing(self.ifDraw.IsChecked())

    def OnDrawChange(self, event):
        self.settings['drawing']['active'] = self.ifDraw.GetValue()
        self.settings['drawing']['name'] = self.draw_vector.GetValue().split(
            '@')[0]
        self.settings['drawing']['appendName'] = self.appendName.GetValue(
        ).split('@')[0]
        self.settings['drawing']['type'] = ['point', 'line', 'area'
                                            ][self.draw_type.GetSelection()]
        self.settings['drawing']['append'] = self.append.IsChecked()
        self.settings['drawing']['threshold'] = self.threshold.GetValue()
        event.Skip()
        self.settingsChanged.emit()

    def OnEnableDrawing(self, event):
        self.EnableDrawing(self.ifDraw.IsChecked())
        event.Skip()

    def EnableDrawing(self, enable):
        self.draw_vector.Enable(enable)
        self.appendName.Enable(enable)
        self.draw_type.Enable(enable)
        self.append.Enable(enable)
        self.threshold.Enable(enable)
        self.clearBtn.Enable(enable)

    def appendVector(self):
        if not self.settings['drawing']['append']:
            return
        ff = gscript.find_file(self.settings['drawing']['appendName'],
                               element='vector',
                               mapset=gscript.gisenv()['MAPSET'])
        if not (ff and ff['fullname']):
            self._newAppendedVector()
        gscript.run_command('v.patch',
                            input=self.settings['drawing']['name'],
                            output=self.settings['drawing']['appendName'],
                            flags='a',
                            overwrite=True,
                            quiet=True)

    def _newAppendedVector(self, event=None):
        gscript.run_command('v.edit',
                            tool='create',
                            map=self.settings['drawing']['appendName'],
                            overwrite=True,
                            quiet=True)
Пример #10
0
class ColorInteractionPanel(wx.Panel):
    def __init__(self, parent, giface, settings, scaniface):
        wx.Panel.__init__(self, parent)
        self.group = None
        self.segment = 'segment'
        self.segment_clump = 'segment_clump'
        self.signature = 'signature'
        self.classification = 'classification'
        self.filtered_classification = 'fclassification'
        self.reject = 'reject'
        self.output = 'objects'

        self.hasSuperpixels = gscript.find_program('i.superpixels.slic', '--help')

        self.env = None
        self.giface = giface
        self.parent = parent
        self.settings = settings
        self.scaniface = scaniface
        self.settingsChanged = Signal('ColorInteractionPanel.settingsChanged')

        if 'color' not in self.settings:
            self.settings['color'] = {}
            self.settings['color']['active'] = False
            self.settings['color']['name'] = ''
            self.settings['color']['training'] = ''

        self.hide = []
        self.ifColor = wx.CheckBox(self, label=_("Save color rasters:"))
        self.ifColor.SetValue(self.settings['color']['active'])
        self.ifColor.Bind(wx.EVT_CHECKBOX, self.OnChange)
        self.exportColor = Select(self, size=(-1, -1), type='raster')
        self.exportColor.SetValue(self.settings['color']['name'])
        self.exportColor.Bind(wx.EVT_TEXT, self.OnChange)
        self.hide.append(self.exportColor)
        if self.settings['color']['name']:
            self.group = self.settings['color']['name']

        self.trainingAreas = Select(self, size=(-1, -1), type='raster')
        self.trainingAreas.SetValue(self.settings['color']['training'])
        self.trainingAreas.Bind(wx.EVT_TEXT, self.OnChange)
        labelTraining = wx.StaticText(self, label=_("Training areas:"))
        self.hide.append(self.trainingAreas)
        self.hide.append(labelTraining)
        calibrateBtn = wx.Button(self, label=_("Calibrate"))
        calibrateBtn.Bind(wx.EVT_BUTTON, self.OnCalibration)
        self.hide.append(calibrateBtn)

        analyzeBtn = wx.Button(self, label=_("Scan and process"))
        analyzeBtn.Bind(wx.EVT_BUTTON, self.OnAnalysis)
        self.hide.append(analyzeBtn)

        self.mainSizer = wx.BoxSizer(wx.VERTICAL)
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add(self.ifColor, flag=wx.ALIGN_CENTER_VERTICAL, border=5)
        sizer.Add(self.exportColor, proportion=1, flag=wx.ALIGN_CENTER_VERTICAL, border=5)
        self.mainSizer.Add(sizer, flag=wx.EXPAND | wx.ALL, border=5)
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add(labelTraining, flag=wx.ALIGN_CENTER_VERTICAL, border=5)
        sizer.Add(self.trainingAreas, proportion=1, flag=wx.ALIGN_CENTER_VERTICAL, border=5)
        sizer.Add(calibrateBtn, flag=wx.ALIGN_CENTER_VERTICAL, border=5)
        self.mainSizer.Add(sizer, flag=wx.EXPAND | wx.ALL, border=5)
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.AddStretchSpacer()
        sizer.Add(analyzeBtn, flag=wx.ALIGN_CENTER_VERTICAL, border=5)
        self.mainSizer.Add(sizer, flag=wx.EXPAND | wx.ALL, border=5)
        self.SetSizer(self.mainSizer)
        self.mainSizer.Fit(self)

        self._enable()

    def OnChange(self, event):
        self.settings['color']['training'] = self.trainingAreas.GetValue()
        self.settings['color']['active'] = self.ifColor.IsChecked()
        self.settings['color']['name'] = self.exportColor.GetValue()
        self.group = self.settings['color']['name']
        self._enable()

    def _enable(self):
        for each in self.hide:
            each.Enable(self.ifColor.IsChecked())

    def _defineEnvironment(self):
        try:
            gscript.read_command('i.group', flags='g', group=self.group, subgroup=self.group, env=self.env)
        except CalledModuleError:
            gscript.run_command('i.group', group=self.group, subgroup=self.group,
                                input=[self.group + '_' + ext for ext in 'r', 'g', 'b'], env=self.env)
        maps = gscript.read_command('i.group', flags='g', group=self.group, subgroup=self.group).strip()
        if maps:
            self.env = get_environment(raster=maps.splitlines()[0])

    def OnAnalysis(self, event):
        self._defineEnvironment()
        self.Run(self.Analyze)

    def OnCalibration(self, event):
        self._defineEnvironment()
        training = self.trainingAreas.GetValue()
        if not training:
            return
        self.Run(self.Calibrate)

    def Run(self, func):
        ll = self.giface.GetLayerList()
        checked = []
        for l in ll:
            if ll.IsLayerChecked(l):
                checked.append(l.cmd)
                ll.CheckLayer(l, False)
        wx.Yield()

        if not self.scaniface.IsScanning():
            self.scaniface.Scan(continuous=False)
            self.scaniface.process.wait()
            self.scaniface.process = None
            self.scaniface.status.SetLabel("Done.")
            self.Done(func, checked)
        elif self.scaniface.pause:
            pass
        else:
            wx.CallLater(3000, self.Done, func, checked)

    def Done(self, func, checked):
        func()
        ll = self.giface.GetLayerList()
        for l in ll:
            if l.cmd in checked:
                ll.CheckLayer(l, True)

    def Calibrate(self):
        gscript.run_command('i.gensigset', trainingmap=self.settings['color']['training'], group=self.group,
                            subgroup=self.group, signaturefile=self.signature, env=self.env, overwrite=True)  # we need here overwrite=True

    def Analyze(self):
        if self.hasSuperpixels:
            gscript.run_command('i.superpixels.slic', group=self.group, output=self.segment, compactness=2,
                                minsize=50, env=self.env)
        else:
            gscript.run_command('i.segment', group=self.group, output=self.segment, threshold=0.3, minsize=50, env=self.env)
            gscript.run_command('r.clump', input=self.segment, output=self.segment_clump, env=self.env)

        gscript.run_command('i.smap', group=self.group, subgroup=self.group, signaturefile=self.signature,
                            output=self.classification, goodness=self.reject, env=self.env)
        percentile = float(gscript.parse_command('r.univar', flags='ge', map=self.reject, env=self.env)['percentile_90'])
        gscript.mapcalc('{new} = if({classif} < {thres}, {classif}, null())'.format(new=self.filtered_classification,
                                                                                    classif=self.classification, thres=percentile), env=self.env)
        segments = self.segment if self.hasSuperpixels else self.segment_clump
        gscript.run_command('r.stats.quantile', base=segments, cover=self.filtered_classification, output=self.output, env=self.env)
class AnalysesPanel(wx.Panel):
    def __init__(self, parent, giface, settings, scaniface):
        wx.Panel.__init__(self, parent)
        self.giface = giface
        self.settings = settings
        self.scaniface = scaniface
        self.settingsChanged = Signal('AnalysesPanel.settingsChanged')

        mainSizer = wx.BoxSizer(wx.VERTICAL)
        if self.settings['analyses']['file']:
            path = self.settings['analyses']['file']
            initDir = os.path.dirname(path)
        else:
            path = initDir = ""

        topoBox = wx.StaticBox(self, label='  Topographic analyses ')
        topoSizer = wx.StaticBoxSizer(topoBox, wx.VERTICAL)
        self.contoursSelect = Select(self, size=(-1, -1), type='vector')
        self.contoursStepTextCtrl = wx.TextCtrl(self, size=(40, -1))
        self.contoursStepTextCtrl.SetToolTipString("Contour step")

        if 'contours' in self.settings['analyses'] and self.settings['analyses']['contours']:
            self.contoursStepTextCtrl.SetValue(str(self.settings['analyses']['contours_step']))
            self.contoursSelect.SetValue(self.settings['analyses']['contours'])

        bmp = get_show_layer_icon()
        self.addContours = wx.BitmapButton(self, bitmap=bmp, size=(bmp.GetWidth() + 12, bmp.GetHeight() + 8))
        self.addContours.Bind(wx.EVT_BUTTON, self._addContourLayer)

        self.contoursSelect.Bind(wx.EVT_TEXT, self.OnAnalysesChange)
        self.contoursStepTextCtrl.Bind(wx.EVT_TEXT, self.OnAnalysesChange)

        fileBox = wx.StaticBox(self, label='  Python file with analyses to run ')
        fileSizer = wx.StaticBoxSizer(fileBox, wx.VERTICAL)
        self.selectAnalyses = filebrowse.FileBrowseButton(self, labelText="File path:", fileMask="Python file (*.py)|*.py",
                                                          startDirectory=initDir, initialValue=path,
                                                          changeCallback=lambda evt: self.SetAnalysesFile(evt.GetString()))
        if self.settings['analyses']['file']:
            self.selectAnalyses.SetValue(self.settings['analyses']['file'])

        newAnalyses = wx.Button(self, label="Create new file with predefined analyses")
        newAnalyses.Bind(wx.EVT_BUTTON, lambda evt: self.CreateNewFile())
        self.selectAnalyses.Bind(wx.EVT_TEXT, self.OnAnalysesChange)

        if 'color_training' not in self.settings['analyses']:
            self.settings['analyses']['color_training'] = ''

        colorBox = wx.StaticBox(self, label='  Color calibration for classification  ')
        colorSizer = wx.StaticBoxSizer(colorBox, wx.VERTICAL)
        self.trainingAreas = Select(self, size=(-1, -1), type='raster')
        self.trainingAreas.SetValue(self.settings['analyses']['color_training'])
        self.trainingAreas.Bind(wx.EVT_TEXT, self.OnAnalysesChange)
        calibrateBtn = wx.Button(self, label="Calibrate")
        calibrateBtn.Bind(wx.EVT_BUTTON, self.OnColorCalibration)

        bmp = get_show_layer_icon()
        addLayerBtn = wx.BitmapButton(self, bitmap=bmp, size=(bmp.GetWidth()+12, bmp.GetHeight()+8))
        addLayerBtn.SetToolTipString("Add layer to display")
        addLayerBtn.Bind(wx.EVT_BUTTON, self._addCalibLayer)

        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add(wx.StaticText(self, label="Contour map name:"), proportion=0, flag=wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, border=5)
        sizer.Add(self.contoursSelect, proportion=4, flag=wx.ALIGN_CENTER_VERTICAL, border=5)
        sizer.Add(self.addContours, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, border=5)
        sizer.Add(wx.StaticText(self, label="Interval:"), proportion=0, flag=wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, border=5)
        sizer.Add(self.contoursStepTextCtrl, proportion=1, flag=wx.ALIGN_CENTER_VERTICAL, border=5)
        topoSizer.Add(sizer, flag=wx.EXPAND | wx.ALL, border=5)
        mainSizer.Add(topoSizer, flag=wx.EXPAND | wx.ALL, border=5)

        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add(self.selectAnalyses, proportion=1, flag=wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, border=5)
        fileSizer.Add(sizer, flag=wx.EXPAND | wx.ALL, border=5)

        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.AddStretchSpacer()
        sizer.Add(newAnalyses, proportion=1, flag=wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, border=5)
        fileSizer.Add(sizer, flag=wx.EXPAND | wx.ALL, border=5)
        mainSizer.Add(fileSizer, flag=wx.EXPAND | wx.ALL, border=5)

        # color training
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add(wx.StaticText(self, label="Raster with training areas:"), proportion=0, flag=wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, border=5)
        sizer.Add(self.trainingAreas, proportion=1, flag=wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, border=1)
        sizer.Add(addLayerBtn, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, border=5)
        sizer.Add(calibrateBtn, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL)
        colorSizer.Add(sizer, flag=wx.EXPAND | wx.ALL, border=5)
        mainSizer.Add(colorSizer, flag=wx.EXPAND | wx.ALL, border=5)

        self.SetSizer(mainSizer)
        mainSizer.Fit(self)

    def SetAnalysesFile(self, path):
        self.settings['analyses']['file'] = path

    def OnAnalysesChange(self, event):
        self.settings['analyses']['contours'] = self.contoursSelect.GetValue()
        self.settings['analyses']['contours_step'] = self.contoursStepTextCtrl.GetValue()
        self.settings['analyses']['file'] = self.selectAnalyses.GetValue()
        self.settings['analyses']['color_training'] = self.trainingAreas.GetValue()
        self.settingsChanged.emit()

    def CreateNewFile(self):
        get_lib_path('g.gui.tangible')
        dlg = wx.FileDialog(self, message="Create a new file with analyses",
                            wildcard="Python source (*.py)|*.py",
                            style=wx.SAVE | wx.FD_OVERWRITE_PROMPT)
        if dlg.ShowModal() == wx.ID_OK:
            path = dlg.GetPath()
            orig = os.path.join(get_lib_path('g.gui.tangible'), 'current_analyses.py')
            if not os.path.exists(orig):
                self.giface.WriteError("File with analyses not found: {}".format(orig))
            else:
                copyfile(orig, path)
                self.selectAnalyses.SetValue(path)
                self.settings['analyses']['file'] = path
        dlg.Destroy()

    def OnColorCalibration(self, event):
        if self.scaniface.IsScanning():
            dlg = wx.MessageDialog(self, 'In order to calibrate, please stop scanning process first.',
                                   'Stop scanning',
                                   wx.OK | wx.ICON_WARNING)
            dlg.ShowModal()
            dlg.Destroy()
            return

        training = self.trainingAreas.GetValue()
        if not training:
            return
        if self.settings['output']['color'] and self.settings['output']['color_name']:
            self.group = self.settings['output']['color_name']
        else:
            self.group = None
            dlg = wx.MessageDialog(self, "In order to calibrate colors, please specify name of output color raster in 'Output' tab.",
                                   'Need color output',
                                   wx.OK | wx.ICON_WARNING)
            dlg.ShowModal()
            dlg.Destroy()
            return

        self.CalibrateColor()

    def CalibrateColor(self):
        ll = self.giface.GetLayerList()
        checked = []
        for l in ll:
            if ll.IsLayerChecked(l):
                checked.append(l.cmd)
                ll.CheckLayer(l, False)
        wx.Yield()

        self.scaniface.Scan(continuous=False)
        self.scaniface.process.wait()
        self.scaniface.process = None
        self.scaniface.status.SetLabel("Done.")

        self._defineEnvironment()

        self._calibrateColor()
        # check the layers back to previous state
        ll = self.giface.GetLayerList()
        for l in ll:
            if l.cmd in checked:
                ll.CheckLayer(l, True)

    def _calibrateColor(self):
        gscript.run_command('i.gensigset', trainingmap=self.settings['analyses']['color_training'], group=self.group,
                            subgroup=self.group, signaturefile='signature', env=self.env, overwrite=True)  # we need here overwrite=True

    def _defineEnvironment(self):
        self.env = None
        maps = gscript.read_command('i.group', flags='g', group=self.group, subgroup=self.group, quiet=True).strip()
        if maps:
            self.env = get_environment(raster=maps.splitlines()[0])

    def _addCalibLayer(self, event):
        ll = self.giface.GetLayerList()
        raster = self.trainingAreas.GetValue()
        if not raster:
            return
        cmd = ['d.rast', 'map=' + raster]
        ll.AddLayer('raster', name=raster, checked=True, cmd=cmd)

    def _addContourLayer(self, event):
        ll = self.giface.GetLayerList()
        vector = self.contoursSelect.GetValue()
        if not vector:
            return
        cmd = ['d.vect', 'map=' + vector]
        ll.AddLayer('vector', name=vector, checked=True, cmd=cmd)
class ScanningPanel(wx.Panel):
    def __init__(self, parent, giface, settings, scaniface):
        wx.Panel.__init__(self, parent)
        self.giface = giface
        self.settings = settings
        self.scaniface = scaniface
        if 'scan' not in self.settings:
            self.settings['scan'] = {}
            self.settings['scan']['elevation'] = ''
            self.settings['scan']['region'] = ''
            self.settings['scan']['zexag'] = 1
            self.settings['scan']['smooth'] = 8
            self.settings['scan']['numscans'] = 1
            self.settings['scan']['rotation_angle'] = 180
            self.settings['scan']['resolution'] = 2
            self.settings['scan']['trim_nsewtb'] = '30,30,30,30,50,150'
            self.settings['scan']['interpolate'] = False
            self.settings['scan']['trim_tolerance'] = ''
            self.settings['scan']['resolution'] = 2

        self.scan = self.settings['scan']

        self.settingsChanged = Signal('ScanningPanel.settingsChanged')

        mainSizer = wx.BoxSizer(wx.VERTICAL)
        # define static boxes before all widgets are defined
        georefBox = wx.StaticBox(self, label='  Georeferencing  ')
        georefSizer = wx.StaticBoxSizer(georefBox, wx.VERTICAL)
        geomBox = wx.StaticBox(self, label='  Scan geometry  ')
        geomSizer = wx.StaticBoxSizer(geomBox, wx.VERTICAL)
        demBox = wx.StaticBox(self, label=' DEM quality ')
        demSizer = wx.StaticBoxSizer(demBox, wx.VERTICAL)

        # create widgets
        self.btnCalibrateTilt = wx.Button(self, label="Calibration 1")
        self.btnCalibrateTilt.SetToolTipString('Calibrate to remove tilt of the scanner and to set suitable distance from the scanner')
        self.btnCalibrateExtent = wx.Button(self, label="Calibration 2")
        self.btnCalibrateExtent.SetToolTipString('Calibrate to identify the extent and position of the scanned object')

        # widgets for model
        self.elevInput = Select(self, size=(-1, -1), type='raster')
        self.elevInput.SetToolTipString('Raster from which we take the georeferencing information')
        self.regionInput = Select(self, size=(-1, -1), type='region')
        self.regionInput.SetToolTipString('Saved region from which we take the georeferencing information')
        self.zexag = wx.TextCtrl(self)
        self.zexag.SetToolTipString('Set vertical exaggeration of the physical model')
        self.numscans = wx.SpinCtrl(self, min=1, max=5, initial=1)
        self.numscans.SetToolTipString('Set number of scans to integrate')
        self.rotate = wx.SpinCtrl(self, min=0, max=360, initial=180)
        self.rotate.SetToolTipString('Set angle of rotation of the sensor around Z axis (typically 180 degrees)')
        self.smooth = wx.TextCtrl(self)
        self.smooth.SetToolTipString('Set smoothing of the DEM (typically between 7 to 12, higher value means more smoothing)')
        self.resolution = wx.TextCtrl(self)
        self.resolution.SetToolTipString('Raster resolution in mm of the ungeoreferenced scan')
        self.trim = {}
        for each in 'tbnsew':
            self.trim[each] = wx.TextCtrl(self, size=(40, -1))
            if each in 'tb':
                self.trim[each].SetToolTipString('Distance from the scanner')
            else:
                self.trim[each].SetToolTipString('Distance from the center of scanning to the scanning boundary')
        self.trim_tolerance = wx.TextCtrl(self)
        self.trim_tolerance.SetToolTipString('Automatic trimming of the edges for rectangular models')
        self.interpolate = wx.CheckBox(self, label="Use interpolation instead of binning")
        self.interpolate.SetToolTipString('Interpolation avoids gaps in the scan, but takes longer')

        self.elevInput.SetValue(self.scan['elevation'])
        self.regionInput.SetValue(self.scan['region'])
        self.zexag.SetValue(str(self.scan['zexag']))
        self.rotate.SetValue(self.scan['rotation_angle'])
        self.numscans.SetValue(self.scan['numscans'])
        self.interpolate.SetValue(self.scan['interpolate'])
        for i, each in enumerate('nsewtb'):
            self.trim[each].SetValue(self.scan['trim_nsewtb'].split(',')[i])
        self.smooth.SetValue(str(self.scan['smooth']))
        self.resolution.SetValue(str(self.scan['resolution']))
        self.trim_tolerance.SetValue(str(self.scan['trim_tolerance']))

        # layout
        #
        # Geometry box
        #
        # rotation
        hSizer = wx.BoxSizer(wx.HORIZONTAL)
        hSizer.Add(wx.StaticText(self, label="Rotation angle:"), proportion=1, flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=5)
        hSizer.Add(self.rotate, flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=5)
        geomSizer.Add(hSizer, flag=wx.EXPAND)
        # trimming
        hSizer = wx.BoxSizer(wx.HORIZONTAL)
        hSizer.Add(wx.StaticText(self, label="Trim vertically [cm]:"), proportion=1, flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=5)
        for each in 'tb':
            hSizer.Add(wx.StaticText(self, label=each.upper() + ':'), flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=2)
            hSizer.Add(self.trim[each], flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=2)
        hSizer.Add(self.btnCalibrateTilt, flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=2)
        geomSizer.Add(hSizer, flag=wx.EXPAND)
        hSizer = wx.BoxSizer(wx.HORIZONTAL)
        hSizer.Add(wx.StaticText(self, label="Trim horizontally [cm]:"), proportion=1, flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=5)
        for each in 'nsew':
            hSizer.Add(wx.StaticText(self, label=each.upper() + ':'), flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=3)
            hSizer.Add(self.trim[each], flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=2)
        hSizer.Add(self.btnCalibrateExtent, flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=2)
        geomSizer.Add(hSizer, flag=wx.EXPAND)
        # automatic trim
        hSizer = wx.BoxSizer(wx.HORIZONTAL)
        hSizer.Add(wx.StaticText(self, label="Trim tolerance [0-1]:"), proportion=1, flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=5)
        hSizer.Add(self.trim_tolerance, flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=5)
        geomSizer.Add(hSizer, flag=wx.EXPAND)
        mainSizer.Add(geomSizer, flag=wx.EXPAND|wx.ALL, border=10)

        hSizer2 = wx.BoxSizer(wx.HORIZONTAL)
        #
        # Georeferencing box
        #
        # model parameters
        hSizer = wx.BoxSizer(wx.HORIZONTAL)
        hSizer.Add(wx.StaticText(self, label="Reference DEM:"), flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=5)
        hSizer.Add(self.elevInput, proportion=1, flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=5)
        georefSizer.Add(hSizer, flag=wx.EXPAND)
        # region
        hSizer = wx.BoxSizer(wx.HORIZONTAL)
        hSizer.Add(wx.StaticText(self, label="Reference region:"), flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=5)
        hSizer.Add(self.regionInput, proportion=1, flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=5)
        georefSizer.Add(hSizer, flag=wx.EXPAND)
        hSizer = wx.BoxSizer(wx.HORIZONTAL)
        hSizer.Add(wx.StaticText(self, label="Z-exaggeration:"), proportion=1, flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=5)
        hSizer.Add(self.zexag, flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=5)
        georefSizer.Add(hSizer, flag=wx.EXPAND)
        hSizer2.Add(georefSizer, proportion=1, flag=wx.EXPAND|wx.RIGHT, border=10)

        #
        # DEM properties box
        #
        # number of scans
        hSizer = wx.BoxSizer(wx.HORIZONTAL)
        hSizer.Add(wx.StaticText(self, label="Number of scans:"), proportion=1, flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=5)
        hSizer.Add(self.numscans, flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=5)
        demSizer.Add(hSizer, flag=wx.EXPAND)

        # smooth
        hSizer = wx.BoxSizer(wx.HORIZONTAL)
        hSizer.Add(wx.StaticText(self, label="Smooth value:"), proportion=1, flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=5)
        hSizer.Add(self.smooth, flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=5)
        demSizer.Add(hSizer, flag=wx.EXPAND)
        # resolution
        hSizer = wx.BoxSizer(wx.HORIZONTAL)
        hSizer.Add(wx.StaticText(self, label="Resolution [mm]:"), proportion=1, flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=5)
        hSizer.Add(self.resolution, flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=5)
        demSizer.Add(hSizer, flag=wx.EXPAND)

        hSizer = wx.BoxSizer(wx.HORIZONTAL)
        hSizer.Add(self.interpolate, flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=5)
        demSizer.Add(hSizer, flag=wx.EXPAND)

        hSizer2.Add(demSizer, proportion=1, flag=wx.EXPAND)
        mainSizer.Add(hSizer2, flag=wx.EXPAND|wx.LEFT|wx.RIGHT|wx.BOTTOM, border=10)

        self.SetSizer(mainSizer)
        mainSizer.Fit(self)

        self.BindModelProperties()

    def BindModelProperties(self):
        self.btnCalibrateTilt.Bind(wx.EVT_BUTTON, self.scaniface.Calibrate)
        self.btnCalibrateExtent.Bind(wx.EVT_BUTTON, self.scaniface.CalibrateModelBBox)

        # model parameters
        self.elevInput.Bind(wx.EVT_TEXT, self.OnModelProperties)
        self.regionInput.Bind(wx.EVT_TEXT, self.OnModelProperties)
        self.zexag.Bind(wx.EVT_TEXT, self.OnModelProperties)
        self.rotate.Bind(wx.EVT_SPINCTRL, self.OnModelProperties)
        self.rotate.Bind(wx.EVT_TEXT, self.OnModelProperties)
        self.numscans.Bind(wx.EVT_SPINCTRL, self.OnModelProperties)
        self.numscans.Bind(wx.EVT_TEXT, self.OnModelProperties)
        self.interpolate.Bind(wx.EVT_CHECKBOX, self.OnModelProperties)
        self.smooth.Bind(wx.EVT_TEXT, self.OnModelProperties)
        self.resolution.Bind(wx.EVT_TEXT, self.OnModelProperties)
        self.trim_tolerance.Bind(wx.EVT_TEXT, self.OnModelProperties)
        for each in 'nsewtb':
            self.trim[each].Bind(wx.EVT_TEXT, self.OnModelProperties)

    def OnModelProperties(self, event):
        self.scan['elevation'] = self.elevInput.GetValue()
        self.scan['region'] = self.regionInput.GetValue()
        self.scan['rotation_angle'] = self.rotate.GetValue()
        self.scan['numscans'] = self.numscans.GetValue()
        self.scan['interpolate'] = self.interpolate.IsChecked()
        self.scan['smooth'] = self.smooth.GetValue()
        self.scan['resolution'] = self.resolution.GetValue()
        trim_tol = self.trim_tolerance.GetValue()
        self.scan['trim_tolerance'] = float(trim_tol) if trim_tol else trim_tol

        try:
            self.scan['zexag'] = float(self.zexag.GetValue())
            nsewtb_list = []
            for each in 'nsewtb':
                nsewtb_list.append(self.trim[each].GetValue())
            self.scan['trim_nsewtb'] = ','.join(nsewtb_list)
        except ValueError:
            pass
        self.settingsChanged.emit()