Example #1
0
    def __init__(self, parent, title=_("Class manager"), id=wx.ID_ANY):
        """
        Does post init and layout.

        :param parent: gui parent
        :param title: dialog window title
        :param id: wx id
        """
        wx.Dialog.__init__(self, parent=parent, title=title, id=id)

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

        mainSizer = wx.BoxSizer(wx.VERTICAL)
        box = StaticBox(panel, id=wx.ID_ANY,
                        label=" %s " % _("Classes"))
        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
        gridSizer = wx.GridBagSizer(hgap=5, vgap=5)
        self.catList = CategoryListCtrl(panel, mapwindow=parent,
                                        stats_data=parent.stats_data)
        addButton = Button(panel, id=wx.ID_ADD)
        deleteButton = Button(panel, id=wx.ID_DELETE)

        gridSizer.Add(
            self.catList, pos=(
                0, 0), span=(
                3, 1), flag=wx.EXPAND)
        gridSizer.Add(addButton, pos=(0, 1), flag=wx.EXPAND)
        gridSizer.Add(deleteButton, pos=(1, 1), flag=wx.EXPAND)

        gridSizer.AddGrowableCol(0)
        gridSizer.AddGrowableRow(2)
        sizer.Add(
            gridSizer,
            proportion=1,
            flag=wx.EXPAND | wx.ALL,
            border=5)
        mainSizer.Add(
            sizer,
            proportion=1,
            flag=wx.EXPAND | wx.ALL,
            border=5)

        btnSizer = wx.BoxSizer(wx.HORIZONTAL)
        closeButton = Button(panel, id=wx.ID_CLOSE)
        btnSizer.Add(wx.Size(-1, -1), proportion=1, flag=wx.EXPAND)
        btnSizer.Add(closeButton, proportion=0, flag=wx.ALIGN_RIGHT)
        mainSizer.Add(
            btnSizer,
            proportion=0,
            flag=wx.EXPAND | wx.ALL,
            border=5)

        addButton.Bind(wx.EVT_BUTTON, self.OnAddCategory)
        deleteButton.Bind(wx.EVT_BUTTON, self.OnDeleteCategory)
        closeButton.Bind(wx.EVT_BUTTON, self.OnClose)
        self.Bind(wx.EVT_CLOSE, self.OnClose)

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

        self.SetSize((400, 250))

        self.Layout()
Example #2
0
class SbMask:
    """Button to show whether mask is activated and remove mask with
    left mouse click
    """

    def __init__(self, parent, giface):
        self.name = "mask"
        self.mask_layer = "MASK"
        self.parent = parent
        self.giface = giface
        self.widget = Button(
            parent=parent, id=wx.ID_ANY, label=_(self.mask_layer), style=wx.NO_BORDER
        )
        self.widget.Bind(wx.EVT_BUTTON, self.OnRemoveMask)
        self.widget.SetForegroundColour(wx.Colour(255, 0, 0))
        self.widget.SetToolTip(tip=_("Left mouse click to remove the MASK"))
        self.giface.currentMapsetChanged.connect(self.Refresh)
        self.giface.grassdbChanged.connect(self._dbChanged)
        self.Refresh()

    def _dbChanged(self, map=None, newname=None):
        if map == self.mask_layer or newname == self.mask_layer:
            self.Refresh()
            self.giface.updateMap.emit()

    def Show(self):
        """Invokes showing of underlying widget.

        In derived classes it can do what is appropriate for it,
        e.g. showing text on statusbar (only).
        """
        self.widget.Show()

    def Hide(self):
        self.widget.Hide()

    def SetValue(self, value):
        self.widget.SetValue(value)

    def GetValue(self):
        return self.widget.GetValue()

    def GetWidget(self):
        """Returns underlying widget.

        :return: widget or None if doesn't exist
        """
        return self.widget

    def Refresh(self):
        """Show mask in the statusbar if mask file found"""
        if gs.find_file(
            name=self.mask_layer, element="cell", mapset=gs.gisenv()["MAPSET"]
        )["name"]:
            self.Show()
        else:
            self.Hide()

    def OnRemoveMask(self, event):
        dlg = wx.MessageDialog(
            self.parent,
            message=_("Are you sure that you want to remove the MASK?"),
            caption=_("Remove MASK"),
            style=wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION,
        )
        if dlg.ShowModal() != wx.ID_YES:
            dlg.Destroy()
            return
        RunCommand("r.mask", flags="r")
        gisenv = gs.gisenv()
        self.giface.grassdbChanged.emit(
            grassdb=gisenv["GISDBASE"],
            location=gisenv["LOCATION_NAME"],
            mapset=gisenv["MAPSET"],
            map=self.mask_layer,
            action="delete",
            element="raster",
        )
Example #3
0
class SQLBuilder(wx.Frame):
    """SQLBuider class
    Base class for classes, which builds SQL statements.
    """

    def __init__(self, parent, title, vectmap, modeChoices=[], id=wx.ID_ANY,
                 layer=1):
        wx.Frame.__init__(self, parent, id, title)

        self.SetIcon(wx.Icon(os.path.join(globalvar.ICONDIR, 'grass_sql.ico'),
                             wx.BITMAP_TYPE_ICO))

        self.parent = parent

        # variables
        self.vectmap = vectmap  # fullname
        if "@" not in self.vectmap:
            self.vectmap = grass.find_file(
                self.vectmap, element='vector')['fullname']
            if not self.vectmap:
                grass.fatal(_("Vector map <%s> not found") % vectmap)
        self.mapname, self.mapset = self.vectmap.split("@", 1)

        # db info
        self.layer = layer
        self.dbInfo = VectorDBInfo(self.vectmap)
        self.tablename = self.dbInfo.GetTable(self.layer)

        self.driver, self.database = self.dbInfo.GetDbSettings(self.layer)

        self.colvalues = []     # array with unique values in selected column

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

        # statusbar
        self.statusbar = self.CreateStatusBar(number=1)

        self._doLayout(modeChoices)

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

        self.SetMinSize((400, 600))
        self.SetClientSize(self.panel.GetSize())
        self.CenterOnParent()

    def _doLayout(self, modeChoices, showDbInfo=False):
        """Do dialog layout"""

        self.pagesizer = wx.BoxSizer(wx.VERTICAL)

        # dbInfo
        if showDbInfo:
            databasebox = StaticBox(parent=self.panel, id=wx.ID_ANY,
                                    label=" %s " % _("Database connection"))
            databaseboxsizer = wx.StaticBoxSizer(databasebox, wx.VERTICAL)
            databaseboxsizer.Add(
                CreateDbInfoDesc(
                    self.panel,
                    self.dbInfo,
                    layer=self.layer),
                proportion=1,
                flag=wx.EXPAND | wx.ALL,
                border=3)

        #
        # text areas
        #
        # sql box
        sqlbox = StaticBox(parent=self.panel, id=wx.ID_ANY,
                           label=" %s " % _("Query"))
        sqlboxsizer = wx.StaticBoxSizer(sqlbox, wx.VERTICAL)

        self.text_sql = TextCtrl(parent=self.panel, id=wx.ID_ANY,
                                    value='', size=(-1, 50),
                                    style=wx.TE_MULTILINE)

        self.text_sql.SetInsertionPointEnd()
        wx.CallAfter(self.text_sql.SetFocus)

        sqlboxsizer.Add(self.text_sql, flag=wx.EXPAND)

        #
        # buttons
        #
        self.btn_clear = Button(parent=self.panel, id=wx.ID_CLEAR)
        self.btn_clear.SetToolTip(_("Set SQL statement to default"))
        self.btn_apply = Button(parent=self.panel, id=wx.ID_APPLY)
        self.btn_apply.SetToolTip(_("Apply SQL statement"))
        self.btn_close = Button(parent=self.panel, id=wx.ID_CLOSE)
        self.btn_close.SetToolTip(_("Close the dialog"))

        self.btn_logic = {'is': ['=', ],
                          'isnot': ['!=', ],
                          'like': ['LIKE', ],
                          'gt': ['>', ],
                          'ge': ['>=', ],
                          'lt': ['<', ],
                          'le': ['<=', ],
                          'or': ['OR', ],
                          'not': ['NOT', ],
                          'and': ['AND', ],
                          'brac': ['()', ],
                          'prc': ['%', ]}

        self.btn_logicpanel = wx.Panel(parent=self.panel, id=wx.ID_ANY)
        for key, value in six.iteritems(self.btn_logic):
            btn = Button(parent=self.btn_logicpanel, id=wx.ID_ANY,
                            label=value[0])
            self.btn_logic[key].append(btn.GetId())

        self.buttonsizer = wx.FlexGridSizer(cols=4, hgap=5, vgap=5)
        self.buttonsizer.Add(self.btn_clear)
        self.buttonsizer.Add(self.btn_apply)
        self.buttonsizer.Add(self.btn_close)

        btn_logicsizer = wx.GridBagSizer(5, 5)
        btn_logicsizer.Add(
            self.FindWindowById(
                self.btn_logic['is'][1]), pos=(
                0, 0))
        btn_logicsizer.Add(
            self.FindWindowById(
                self.btn_logic['isnot'][1]), pos=(
                1, 0))
        btn_logicsizer.Add(
            self.FindWindowById(
                self.btn_logic['like'][1]), pos=(
                2, 0))

        btn_logicsizer.Add(
            self.FindWindowById(
                self.btn_logic['gt'][1]), pos=(
                0, 1))
        btn_logicsizer.Add(
            self.FindWindowById(
                self.btn_logic['ge'][1]), pos=(
                1, 1))
        btn_logicsizer.Add(
            self.FindWindowById(
                self.btn_logic['or'][1]), pos=(
                2, 1))

        btn_logicsizer.Add(
            self.FindWindowById(
                self.btn_logic['lt'][1]), pos=(
                0, 2))
        btn_logicsizer.Add(
            self.FindWindowById(
                self.btn_logic['le'][1]), pos=(
                1, 2))
        btn_logicsizer.Add(
            self.FindWindowById(
                self.btn_logic['not'][1]), pos=(
                2, 2))

        btn_logicsizer.Add(
            self.FindWindowById(
                self.btn_logic['brac'][1]), pos=(
                0, 3))
        btn_logicsizer.Add(
            self.FindWindowById(
                self.btn_logic['prc'][1]), pos=(
                1, 3))
        btn_logicsizer.Add(
            self.FindWindowById(
                self.btn_logic['and'][1]), pos=(
                2, 3))

        self.btn_logicpanel.SetSizer(btn_logicsizer)

        #
        # list boxes (columns, values)
        #
        self.hsizer = wx.BoxSizer(wx.HORIZONTAL)

        columnsbox = StaticBox(parent=self.panel, id=wx.ID_ANY,
                               label=" %s " % _("Columns"))
        columnsizer = wx.StaticBoxSizer(columnsbox, wx.VERTICAL)
        self.list_columns = wx.ListBox(
            parent=self.panel,
            id=wx.ID_ANY,
            choices=self.dbInfo.GetColumns(
                self.tablename),
            style=wx.LB_MULTIPLE)
        columnsizer.Add(self.list_columns, proportion=1,
                        flag=wx.EXPAND)

        if modeChoices:
            modesizer = wx.BoxSizer(wx.VERTICAL)

            self.mode = wx.RadioBox(parent=self.panel, id=wx.ID_ANY,
                                    label=" %s " % _("Interactive insertion"),
                                    choices=modeChoices,
                                    style=wx.RA_SPECIFY_COLS,
                                    majorDimension=1)

            self.mode.SetSelection(1)  # default 'values'
            modesizer.Add(self.mode, proportion=1,
                          flag=wx.ALIGN_CENTER_HORIZONTAL | wx.EXPAND, border=5)

        # self.list_columns.SetMinSize((-1,130))
        # self.list_values.SetMinSize((-1,100))

        self.valuespanel = wx.Panel(parent=self.panel, id=wx.ID_ANY)
        valuesbox = StaticBox(parent=self.valuespanel, id=wx.ID_ANY,
                              label=" %s " % _("Values"))
        valuesizer = wx.StaticBoxSizer(valuesbox, wx.VERTICAL)
        self.list_values = wx.ListBox(parent=self.valuespanel, id=wx.ID_ANY,
                                      choices=self.colvalues,
                                      style=wx.LB_MULTIPLE)
        valuesizer.Add(self.list_values, proportion=1,
                       flag=wx.EXPAND)
        self.valuespanel.SetSizer(valuesizer)

        self.btn_unique = Button(parent=self.valuespanel, id=wx.ID_ANY,
                                    label=_("Get all values"))
        self.btn_unique.Enable(False)
        self.btn_uniquesample = Button(
            parent=self.valuespanel,
            id=wx.ID_ANY,
            label=_("Get sample"))
        self.btn_uniquesample.SetToolTip(
            _("Get first 256 unique values as sample"))
        self.btn_uniquesample.Enable(False)

        buttonsizer3 = wx.BoxSizer(wx.HORIZONTAL)
        buttonsizer3.Add(self.btn_uniquesample, proportion=0,
                         flag=wx.ALIGN_CENTER_HORIZONTAL | wx.RIGHT, border=5)
        buttonsizer3.Add(self.btn_unique, proportion=0,
                         flag=wx.ALIGN_CENTER_HORIZONTAL)

        valuesizer.Add(buttonsizer3, proportion=0,
                       flag=wx.TOP, border=5)

        # go to
        gotosizer = wx.BoxSizer(wx.HORIZONTAL)
        self.goto = TextCtrl(
            parent=self.valuespanel,
            id=wx.ID_ANY,
            style=wx.TE_PROCESS_ENTER)
        gotosizer.Add(StaticText(parent=self.valuespanel, id=wx.ID_ANY,
                                 label=_("Go to:")), proportion=0,
                      flag=wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, border=5)
        gotosizer.Add(self.goto, proportion=1,
                      flag=wx.EXPAND)
        valuesizer.Add(gotosizer, proportion=0,
                       flag=wx.ALL | wx.EXPAND, border=5)

        self.hsizer.Add(columnsizer, proportion=1,
                        flag=wx.EXPAND)
        self.hsizer.Add(self.valuespanel, proportion=1,
                        flag=wx.EXPAND)

        self.close_onapply = wx.CheckBox(parent=self.panel, id=wx.ID_ANY,
                                         label=_("Close dialog on apply"))
        self.close_onapply.SetValue(True)

        if showDbInfo:
            self.pagesizer.Add(databaseboxsizer,
                               flag=wx.ALL | wx.EXPAND, border=5)
        if modeChoices:
            self.pagesizer.Add(
                modesizer,
                proportion=0,
                flag=wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND,
                border=5)
        self.pagesizer.Add(
            self.hsizer,
            proportion=1,
            flag=wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND,
            border=5)
        # self.pagesizer.Add(self.btn_uniqe,0,wx.ALIGN_LEFT|wx.TOP,border=5)
        # self.pagesizer.Add(self.btn_uniqesample,0,wx.ALIGN_LEFT|wx.TOP,border=5)
        self.pagesizer.Add(self.btn_logicpanel, proportion=0,
                           flag=wx.ALIGN_CENTER_HORIZONTAL)
        self.pagesizer.Add(sqlboxsizer, proportion=0,
                           flag=wx.EXPAND | wx.LEFT | wx.RIGHT, border=5)
        self.pagesizer.Add(self.buttonsizer, proportion=0,
                           flag=wx.ALIGN_RIGHT | wx.ALL, border=5)
        self.pagesizer.Add(
            self.close_onapply,
            proportion=0,
            flag=wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND,
            border=5)

        #
        # bindings
        #
        if modeChoices:
            self.mode.Bind(wx.EVT_RADIOBOX, self.OnMode)
        # self.text_sql.Bind(wx.EVT_ACTIVATE, self.OnTextSqlActivate)TODO

        self.btn_unique.Bind(wx.EVT_BUTTON, self.OnUniqueValues)
        self.btn_uniquesample.Bind(wx.EVT_BUTTON, self.OnSampleValues)

        for key, value in six.iteritems(self.btn_logic):
            self.FindWindowById(value[1]).Bind(wx.EVT_BUTTON, self.OnAddMark)

        self.btn_close.Bind(wx.EVT_BUTTON, self.OnClose)
        self.btn_clear.Bind(wx.EVT_BUTTON, self.OnClear)
        self.btn_apply.Bind(wx.EVT_BUTTON, self.OnApply)

        self.list_columns.Bind(wx.EVT_LISTBOX, self.OnAddColumn)
        self.list_values.Bind(wx.EVT_LISTBOX, self.OnAddValue)
        self.goto.Bind(wx.EVT_TEXT, self.OnGoTo)
        self.goto.Bind(wx.EVT_TEXT_ENTER, self.OnAddValue)

    def OnUniqueValues(self, event, justsample=False):
        """Get unique values"""
        vals = []
        try:
            idx = self.list_columns.GetSelections()[0]
            column = self.list_columns.GetString(idx)
        except:
            self.list_values.Clear()
            return

        self.list_values.Clear()

        sql = "SELECT DISTINCT {column} FROM {table} ORDER BY {column}".format(
            column=column, table=self.tablename)
        if justsample:
            sql += " LIMIT {}".format(255)
        data = grass.db_select(
            sql=sql,
            database=self.database,
            driver=self.driver,
            sep='{_sep_}')
        if not data:
            return

        desc = self.dbInfo.GetTableDesc(
            self.dbInfo.GetTable(self.layer))[column]

        i = 0
        items = []
        for item in data: # sorted(set(map(lambda x: desc['ctype'](x[0]), data))):
            if desc['type'] not in ('character', 'text'):
                items.append(str(item[0]))
            else:
                items.append(u"'{}'".format(GetUnicodeValue(item[0])))
            i += 1

        self.list_values.AppendItems(items)

    def OnSampleValues(self, event):
        """Get sample values"""
        self.OnUniqueValues(None, True)

    def OnAddColumn(self, event):
        """Add column name to the query"""
        idx = self.list_columns.GetSelections()
        for i in idx:
            column = self.list_columns.GetString(i)
            self._add(element='column', value=column)

        if not self.btn_uniquesample.IsEnabled():
            self.btn_uniquesample.Enable(True)
            self.btn_unique.Enable(True)

    def OnAddValue(self, event):
        """Add value"""
        selection = self.list_values.GetSelections()
        if not selection:
            event.Skip()
            return

        idx = selection[0]
        value = self.list_values.GetString(idx)
        idx = self.list_columns.GetSelections()[0]
        column = self.list_columns.GetString(idx)

        ctype = self.dbInfo.GetTableDesc(
            self.dbInfo.GetTable(
                self.layer))[column]['type']

        self._add(element='value', value=value)

    def OnGoTo(self, event):
        # clear all previous selections
        for item in self.list_values.GetSelections():
            self.list_values.Deselect(item)

        gotoText = event.GetString()
        lenLimit = len(gotoText)
        found = idx = 0
        string = False
        for item in self.list_values.GetItems():
            if idx == 0 and item.startswith("'"):
                string = True
            if string:
                item = item[1:-1] # strip "'"
            if item[:lenLimit] == gotoText:
                found = idx
                break
            idx += 1

        if found > 0:
            self.list_values.SetSelection(found)

    def OnAddMark(self, event):
        """Add mark"""
        mark = None
        if self.btn_logicpanel and \
           self.btn_logicpanel.IsShown():
            btns = self.btn_logic
        elif self.btn_arithmeticpanel and \
                self.btn_arithmeticpanel.IsShown():
            btns = self.btn_arithmetic

        for key, value in six.iteritems(btns):
            if event.GetId() == value[1]:
                mark = value[0]
                break

        self._add(element='mark', value=mark)

    def GetSQLStatement(self):
        """Return SQL statement"""
        return self.text_sql.GetValue().strip().replace("\n", " ")

    def OnClose(self, event):
        self.Destroy()
        event.Skip()
Example #4
0
class HelpPanel(wx.Panel):
    def __init__(self,
                 parent,
                 command="index",
                 text=None,
                 skipDescription=False,
                 **kwargs):
        self.command = command
        wx.Panel.__init__(self, parent=parent, id=wx.ID_ANY)

        self.content = HelpWindow(self, command, text, skipDescription)

        self.btnNext = Button(parent=self, id=wx.ID_ANY, label=_("&Next"))
        self.btnNext.Enable(False)
        self.btnPrev = Button(parent=self, id=wx.ID_ANY, label=_("&Previous"))
        self.btnPrev.Enable(False)

        self.btnNext.Bind(wx.EVT_BUTTON, self.OnNext)
        self.btnPrev.Bind(wx.EVT_BUTTON, self.OnPrev)

        self._layout()

    def _layout(self):
        """Do layout"""
        sizer = wx.BoxSizer(wx.VERTICAL)
        btnSizer = wx.BoxSizer(wx.HORIZONTAL)

        btnSizer.Add(self.btnPrev, proportion=0, flag=wx.ALL, border=5)
        btnSizer.Add(wx.Size(1, 1), proportion=1)
        btnSizer.Add(self.btnNext, proportion=0, flag=wx.ALL, border=5)

        sizer.Add(self.content, proportion=1, flag=wx.EXPAND)
        sizer.Add(btnSizer, proportion=0, flag=wx.EXPAND)

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

    def LoadPage(self, path=None):
        """Load page"""
        if not path:
            path = self.GetFile()
        self.content.history.append(path)
        self.content.LoadPage(path)

    def GetFile(self):
        """Get HTML file"""
        fMan = os.path.join(self.content.fspath, self.command + ".html")
        if os.path.isfile(fMan):
            return fMan

        # check also addons
        faMan = os.path.join(os.getenv('GRASS_ADDON_BASE'), "docs", "html",
                             self.command + ".html")
        if os.getenv('GRASS_ADDON_BASE') and \
                os.path.isfile(faMan):
            return faMan

        return None

    def IsLoaded(self):
        return self.content.loaded

    def OnHistory(self):
        """Update buttons"""
        nH = len(self.content.history)
        iH = self.content.historyIdx
        if iH == nH - 1:
            self.btnNext.Enable(False)
        elif iH > -1:
            self.btnNext.Enable(True)
        if iH < 1:
            self.btnPrev.Enable(False)
        else:
            self.btnPrev.Enable(True)

    def OnNext(self, event):
        """Load next page"""
        self.content.historyIdx += 1
        idx = self.content.historyIdx
        path = self.content.history[idx]
        self.content.LoadPage(path)
        self.OnHistory()

        event.Skip()

    def OnPrev(self, event):
        """Load previous page"""
        self.content.historyIdx -= 1
        idx = self.content.historyIdx
        path = self.content.history[idx]
        self.content.LoadPage(path)
        self.OnHistory()

        event.Skip()
Example #5
0
class InstallExtensionWindow(wx.Frame):
    def __init__(
            self,
            parent,
            giface,
            id=wx.ID_ANY,
            title=_("Fetch & install extension from GRASS Addons"),
            **kwargs,
    ):
        self.parent = parent
        self._giface = giface
        self.options = dict()  # list of options

        wx.Frame.__init__(self, parent=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.repoBox = StaticBox(
        #     parent=self.panel, id=wx.ID_ANY, label=" %s " %
        #     _("Repository (leave empty to use the official one)"))
        self.treeBox = StaticBox(
            parent=self.panel,
            id=wx.ID_ANY,
            label=" %s " % _("List of extensions - double-click to install"),
        )

        # self.repo = TextCtrl(parent=self.panel, id=wx.ID_ANY)

        # modelBuilder loads data into tree model
        self.modelBuilder = ExtensionTreeModelBuilder()
        # tree view displays model data
        self.tree = CTreeView(parent=self.panel,
                              model=self.modelBuilder.GetModel())

        self.search = SearchCtrl(self.panel)
        self.search.SetDescriptiveText(_("Search"))
        self.search.ShowCancelButton(True)
        # load data in different thread
        self.thread = gThread()

        self.optionBox = StaticBox(parent=self.panel,
                                   id=wx.ID_ANY,
                                   label=" %s " % _("Options"))
        task = gtask.parse_interface("g.extension")
        ignoreFlags = ["l", "c", "g", "a", "f", "t", "help", "quiet"]
        if sys.platform == "win32":
            ignoreFlags.append("d")
            ignoreFlags.append("i")

        for f in task.get_options()["flags"]:
            name = f.get("name", "")
            desc = f.get("label", "")
            if not desc:
                desc = f.get("description", "")
            if not name and not desc:
                continue
            if name in ignoreFlags:
                continue
            self.options[name] = wx.CheckBox(parent=self.panel,
                                             id=wx.ID_ANY,
                                             label=desc)
        # defaultUrl = ''  # default/official one will be used when option empty
        # self.repo.SetValue(
        #     task.get_param(
        #         value='url').get(
        #         'default',
        #         defaultUrl))

        self.statusbar = self.CreateStatusBar(number=1)

        # self.btnFetch = Button(parent=self.panel, id=wx.ID_ANY,
        #                        label=_("&Fetch"))
        # self.btnFetch.SetToolTip(_("Fetch list of available tools "
        #                            "from GRASS Addons repository"))
        self.btnClose = Button(parent=self.panel, id=wx.ID_CLOSE)
        self.btnInstall = Button(parent=self.panel,
                                 id=wx.ID_ANY,
                                 label=_("&Install"))
        self.btnInstall.SetToolTip(_("Install selected add-ons GRASS tool"))
        self.btnInstall.Enable(False)
        self.btnHelp = Button(parent=self.panel, id=wx.ID_HELP)
        self.btnHelp.SetToolTip(_("Show g.extension manual page"))

        self.btnClose.Bind(wx.EVT_BUTTON, lambda evt: self.Close())
        # self.btnFetch.Bind(wx.EVT_BUTTON, self.OnFetch)
        self.btnInstall.Bind(wx.EVT_BUTTON, self.OnInstall)
        self.btnHelp.Bind(wx.EVT_BUTTON, self.OnHelp)
        self.search.Bind(wx.EVT_TEXT, lambda evt: self.Filter(evt.GetString()))
        self.search.Bind(wx.EVT_SEARCHCTRL_CANCEL_BTN,
                         lambda evt: self.Filter(""))
        self.tree.selectionChanged.connect(self.OnItemSelected)
        self.tree.itemActivated.connect(self.OnItemActivated)
        self.tree.contextMenu.connect(self.OnContextMenu)

        wx.CallAfter(self._fetch)

        self._layout()

    def _layout(self):
        """Do layout"""
        sizer = wx.BoxSizer(wx.VERTICAL)
        # repoSizer = wx.StaticBoxSizer(self.repoBox, wx.VERTICAL)
        # repo1Sizer = wx.BoxSizer(wx.HORIZONTAL)
        # repo1Sizer.Add(self.repo, proportion=1,
        #                flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=1)
        # repo1Sizer.Add(self.btnFetch, proportion=0,
        #                flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=1)
        # repoSizer.Add(repo1Sizer,
        #               flag=wx.EXPAND)

        sizer.Add(self.search, proportion=0, flag=wx.EXPAND | wx.ALL, border=3)

        treeSizer = wx.StaticBoxSizer(self.treeBox, wx.HORIZONTAL)
        treeSizer.Add(self.tree,
                      proportion=1,
                      flag=wx.ALL | wx.EXPAND,
                      border=1)

        # options
        optionSizer = wx.StaticBoxSizer(self.optionBox, wx.VERTICAL)
        for key in self.options.keys():
            optionSizer.Add(self.options[key], proportion=0)

        btnSizer = wx.BoxSizer(wx.HORIZONTAL)
        btnSizer.Add(self.btnHelp, proportion=0)
        btnSizer.AddStretchSpacer()
        btnSizer.Add(self.btnClose, proportion=0, flag=wx.RIGHT, border=5)
        btnSizer.Add(self.btnInstall, proportion=0)

        # sizer.Add(repoSizer, proportion=0,
        #           flag=wx.ALL | wx.EXPAND, border=3)
        sizer.Add(
            treeSizer,
            proportion=1,
            flag=wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND,
            border=3,
        )
        sizer.Add(
            optionSizer,
            proportion=0,
            flag=wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND,
            border=3,
        )
        sizer.Add(btnSizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)

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

        self.Layout()

    def _getCmd(self):
        item = self.tree.GetSelected()
        if not item or "command" not in item[0].data:
            GError(_("Extension not defined"), parent=self)
            return

        name = item[0].data["command"]

        flags = list()
        for key in self.options.keys():
            if self.options[key].IsChecked():
                if len(key) == 1:
                    flags.append("-%s" % key)
                else:
                    flags.append("--%s" % key)

        # 'url=' + self.repo.GetValue().strip()]
        return ["g.extension"] + flags + ["extension={}".format(name)]

    def OnFetch(self, event):
        """Fetch list of available extensions"""
        self._fetch()

    def _fetch(self):
        """Fetch list of available extensions"""
        wx.BeginBusyCursor()
        self.SetStatusText(
            _("Fetching list of tools from GRASS-Addons (be patient)..."), 0)
        try:
            self.thread.Run(
                callable=self.modelBuilder.Load,
                url="",  # self.repo.GetValue().strip(),
                ondone=lambda event: self._fetchDone(),
            )
        except GException as error:
            self._fetchDone()
            GError(str(error), parent=self, showTraceback=False)

    def _fetchDone(self):
        self.tree.RefreshItems()
        nitems = len(self.modelBuilder.GetModel().SearchNodes(key="command",
                                                              value="*"))
        self.SetStatusText(_("%d extensions loaded") % nitems, 0)
        wx.EndBusyCursor()

    def Filter(self, text):
        model = self.modelBuilder.GetModel()
        if text:
            model = model.Filtered(key=["command", "keywords", "description"],
                                   value=text)
            self.tree.SetModel(model)
            self.tree.ExpandAll()
        else:
            self.tree.SetModel(model)

    def OnContextMenu(self, node):
        if not hasattr(self, "popupID"):
            self.popupID = dict()
            for key in ("install", "help"):
                self.popupID[key] = NewId()

        data = node.data
        if data and "command" in data:
            self.popupMenu = Menu()
            self.popupMenu.Append(self.popupID["install"], _("Install"))
            self.Bind(wx.EVT_MENU, self.OnInstall, id=self.popupID["install"])
            self.popupMenu.AppendSeparator()
            self.popupMenu.Append(self.popupID["help"], _("Show manual page"))
            self.Bind(wx.EVT_MENU, self.OnItemHelp, id=self.popupID["help"])

            self.PopupMenu(self.popupMenu)
            self.popupMenu.Destroy()

    def OnItemActivated(self, node):
        data = node.data
        if data and "command" in data:
            self.OnInstall(event=None)

    def OnInstall(self, event):
        """Install selected extension"""
        log = self.parent.GetLogWindow()
        cmd = self._getCmd()
        if cmd:
            log.RunCmd(cmd, onDone=self.OnDone)

    def OnDone(self, event):
        if event.returncode == 0:
            if not os.getenv("GRASS_ADDON_BASE"):
                SetAddOnPath(key="BASE")

            globalvar.UpdateGRASSAddOnCommands()
            toolboxesOutdated()

    def OnItemHelp(self, event):
        item = self.tree.GetSelected()
        if not item or "command" not in item[0].data:
            return

        self._giface.Help(entry=item[0].data["command"], online=True)

    def OnHelp(self, event):
        self._giface.Help(entry="g.extension")

    def OnItemSelected(self, node):
        """Item selected"""
        data = node.data
        if data is None:
            self.SetStatusText("", 0)
            self.btnInstall.Enable(False)
        else:
            self.SetStatusText(data.get("description", ""), 0)
            self.btnInstall.Enable(True)
Example #6
0
class DataCatalogFrame(wx.Frame):
    """Frame for testing purposes only."""

    def __init__(self, parent, giface=None):
        wx.Frame.__init__(self, parent=parent,
                          title=_('GRASS GIS Data Catalog'))
        self.SetName("DataCatalog")
        self.SetIcon(
            wx.Icon(
                os.path.join(
                    ICONDIR,
                    'grass.ico'),
                wx.BITMAP_TYPE_ICO))

        self._giface = giface
        self.panel = wx.Panel(self)

        self.toolbar = DataCatalogToolbar(parent=self)
        # workaround for http://trac.wxwidgets.org/ticket/13888
        if sys.platform != 'darwin':
            self.SetToolBar(self.toolbar)

        # tree
        self.tree = DataCatalogTree(parent=self.panel, giface=self._giface)
        self.tree.InitTreeItems()
        self.tree.ExpandCurrentMapset()
        self.tree.changeMapset.connect(lambda mapset:
                                       self.ChangeLocationMapset(location=None,
                                                                 mapset=mapset))
        self.tree.changeLocation.connect(lambda mapset, location:
                                         self.ChangeLocationMapset(location=location,
                                                                   mapset=mapset))

        # buttons
        self.btnClose = Button(parent=self.panel, id=wx.ID_CLOSE)
        self.btnClose.SetToolTip(_("Close GRASS GIS Data Catalog"))
        self.btnClose.SetDefault()

        # events
        self.btnClose.Bind(wx.EVT_BUTTON, self.OnCloseWindow)
        self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)

        self._layout()

    def _layout(self):
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.tree, proportion=1, flag=wx.EXPAND)

        btnSizer = wx.BoxSizer(wx.HORIZONTAL)
        btnSizer.AddStretchSpacer()
        btnSizer.Add(self.btnClose)

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

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

        self.SetMinSize((400, 500))

    def OnCloseWindow(self, event):
        """Cancel button pressed"""
        if not isinstance(event, wx.CloseEvent):
            self.Destroy()

        event.Skip()

    def OnReloadTree(self, event):
        """Reload whole tree"""
        self.tree.ReloadTreeItems()
        self.tree.ExpandCurrentMapset()

    def OnReloadCurrentMapset(self, event):
        """Reload current mapset tree only"""
        self.tree.ReloadCurrentMapset()

    def SetRestriction(self, restrict):
        """Allow editing other mapsets or restrict editing to current mapset"""
        self.tree.SetRestriction(restrict)

    def ChangeLocationMapset(self, mapset, location=None):
        """Change mapset or location"""
        if location:
            if RunCommand('g.mapset', parent=self,
                          location=location,
                          mapset=mapset) == 0:
                GMessage(parent=self,
                         message=_("Current location is <%(loc)s>.\n"
                                   "Current mapset is <%(mapset)s>.") %
                         {'loc': location, 'mapset': mapset})
        else:
            if RunCommand('g.mapset',
                          parent=self,
                          mapset=mapset) == 0:
                GMessage(parent=self,
                         message=_("Current mapset is <%s>.") % mapset)

    def Filter(self, text):
        self.tree.Filter(text=text)
Example #7
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 = _("Raster Map Calculator")
        if self.cmd == "r3.mapcalc":
            self.rast3d = True
            title = _("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 emitted 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()
Example #8
0
class WSPropertiesDialog(WSDialogBase):
    """Dialog for editing web service properties."""
    def __init__(
        self,
        parent,
        giface,
        layer,
        ws_cap_files,
        cmd,
        id=wx.ID_ANY,
        style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER,
        **kwargs,
    ):
        """
        :param giface: grass interface
        :param layer: layer tree item
        :param ws_cap_files: dict web service('WMS_1.1.1', 'WMS_1.3.0',
        'WMTS', 'OnEarth') : cap file path cap files, which will be parsed
        :param cmd: cmd to which dialog widgets will be initialized if
        it is possible (cmp parameters exists in parsed web service cap_file)
        """

        WSDialogBase.__init__(
            self,
            parent,
            id=wx.ID_ANY,
            style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER,
            **kwargs,
        )

        self.SetTitle(_("Web service layer properties"))

        self.layer = layer
        self.giface = giface

        # after web service panels are connected, set dialog widgets
        # according to cmd in this variable (if it is not None)
        self.cmd_to_set = None

        # store data needed for reverting
        self.revert_ws_cap_files = {}
        self.revert_cmd = cmd

        ws_cap = self._getWSfromCmd(cmd)
        for ws in six.iterkeys(self.ws_panels):
            # cap file used in cmd will be deleted, thnaks to the dialogs
            # destructor
            if ws == ws_cap and "capfile" in cmd[1]:
                self.revert_ws_cap_files[ws] = cmd[1]["capfile"]
                del ws_cap_files[ws]
            else:
                self.revert_ws_cap_files[ws] = grass.tempfile()

        self._setRevertCapFiles(ws_cap_files)

        self.LoadCapFiles(ws_cap_files=self.revert_ws_cap_files, cmd=cmd)
        self.btn_ok.SetDefault()

    def __del__(self):
        for f in six.itervalues(self.revert_ws_cap_files):
            grass.try_remove(f)

    def _setRevertCapFiles(self, ws_cap_files):

        for ws, f in six.iteritems(ws_cap_files):
            if os.path.isfile(ws_cap_files[ws]):
                shutil.copyfile(f, self.revert_ws_cap_files[ws])
            else:
                # delete file content
                f_o = open(f, "w")
                f_o.close()

    def _createWidgets(self):

        WSDialogBase._createWidgets(self)

        self.btn_apply = Button(parent=self, id=wx.ID_ANY, label=_("&Apply"))
        self.btn_apply.SetToolTip(_("Apply changes"))
        self.btn_apply.Enable(False)
        self.run_btns.append(self.btn_apply)

        self.btn_ok = Button(parent=self, id=wx.ID_ANY, label=_("&OK"))
        self.btn_ok.SetToolTip(_("Apply changes and close dialog"))
        self.btn_ok.Enable(False)
        self.run_btns.append(self.btn_ok)

    def _doLayout(self):

        WSDialogBase._doLayout(self)

        self.btnsizer.Add(self.btn_apply,
                          proportion=0,
                          flag=wx.ALL | wx.ALIGN_CENTER,
                          border=10)

        self.btnsizer.Add(self.btn_ok,
                          proportion=0,
                          flag=wx.ALL | wx.ALIGN_CENTER,
                          border=10)

        # bindings
        self.btn_apply.Bind(wx.EVT_BUTTON, self.OnApply)
        self.btn_ok.Bind(wx.EVT_BUTTON, self.OnSave)

    def LoadCapFiles(self, ws_cap_files, cmd):
        """Parse cap files and update dialog.

        For parameters description, see the constructor.
        """
        self.ch_ws_sizer.Clear(True)

        self.cmd_to_set = cmd

        self.finished_panels_num = 0

        conn = self._getServerConnFromCmd(cmd)

        self.server.SetValue(conn["url"])
        self.password.SetValue(conn["password"])
        self.username.SetValue(conn["username"])

        self.layerName.SetValue(cmd[1]["map"])

        for ws, data in six.iteritems(self.ws_panels):
            cap_file = None

            if ws in ws_cap_files:
                cap_file = ws_cap_files[ws]

            data["panel"].ParseCapFile(
                url=conn["url"],
                username=conn["password"],
                password=conn["username"],
                cap_file=cap_file,
            )

    def _getServerConnFromCmd(self, cmd):
        """Get url/server/passwod from cmd tuple"""
        conn = {"url": "", "username": "", "password": ""}

        for k in six.iterkeys(conn):
            if k in cmd[1]:
                conn[k] = cmd[1][k]
        return conn

    def _apply(self):
        """Apply chosen values from widgets to web service layer."""
        lcmd = self.active_ws_panel.CreateCmd()
        if not lcmd:
            return

        active_ws = self.active_ws_panel.GetWebService()
        if "WMS" not in active_ws:
            lcmd.append("capfile=" + self.revert_ws_cap_files[active_ws])

        self.giface.GetLayerTree().GetOptData(dcmd=lcmd,
                                              layer=self.layer,
                                              params=True,
                                              propwin=self)

        # TODO use just list or tuple
        cmd = cmdlist_to_tuple(lcmd)
        self.revert_cmd = cmd
        self._setRevertCapFiles(self._getCapFiles())

        self.giface.updateMap.emit()

    def UpdateDialogAfterConnection(self):
        """Connect to the server"""
        WSDialogBase.UpdateDialogAfterConnection(self)
        if self._getConnectedWS():
            self.btn_ok.SetDefault()
        else:
            self.btn_connect.SetDefault()

    def OnApply(self, event):
        self._apply()

    def OnSave(self, event):
        self._apply()
        self._close()

    def OnClose(self, event):
        """Close dialog"""
        self._close()

    def _close(self):
        """Hide dialog"""
        self.Hide()
        self.LoadCapFiles(cmd=self.revert_cmd,
                          ws_cap_files=self.revert_ws_cap_files)

    def OnPanelCapParsed(self, error_msg):
        """Called when panel has downloaded and parsed capabilities file."""
        WSDialogBase.OnPanelCapParsed(self, error_msg)

        if self.finished_panels_num == len(self.ws_panels):
            if self.cmd_to_set:
                self._updateWsPanelWidgetsByCmd(self.cmd_to_set)
                self.cmd_to_set = None

    def _updateWsPanelWidgetsByCmd(self, cmd):
        """Set values of  widgets according to parameters in cmd."""

        ws = self._getWSfromCmd(cmd)
        if self.ws_panels[ws]["panel"].IsConnected():
            self.choose_ws_rb.SetStringSelection(self.ws_panels[ws]["label"])
            self._showWsPanel(ws)
            self.ws_panels[ws]["panel"].UpdateWidgetsByCmd(cmd)

    def _getWSfromCmd(self, cmd):
        driver = cmd[1]["driver"]
        ws = driver.split("_")[0]

        if ws == "WMS":
            ws += "_" + cmd[1]["wms_version"]
        return ws
Example #9
0
class SaveWMSLayerDialog(wx.Dialog):
    """Dialog for saving web service layer into GRASS vector/raster layer.

    .. todo::
        Implement saving data in region of map display.
    """
    def __init__(self, parent, layer, giface):

        wx.Dialog.__init__(
            self,
            parent=parent,
            title=("Save web service layer as raster map"),
            id=wx.ID_ANY,
        )

        self.layer = layer
        self._giface = giface

        self.cmd = self.layer.GetCmd()

        self.thread = CmdThread(self)
        self.cmdStdErr = GStderr(self)

        self._createWidgets()

    def _createWidgets(self):

        self.labels = {}
        self.params = {}

        self.labels["output"] = StaticText(
            parent=self, id=wx.ID_ANY, label=_("Name for output raster map:"))

        self.params["output"] = Select(
            parent=self,
            type="raster",
            mapsets=[grass.gisenv()["MAPSET"]],
            size=globalvar.DIALOG_GSELECT_SIZE,
        )

        self.regionStBoxLabel = StaticBox(parent=self,
                                          id=wx.ID_ANY,
                                          label=" %s " % _("Export region"))

        self.region_types_order = ["display", "comp", "named"]
        self.region_types = {}
        self.region_types["display"] = RadioButton(parent=self,
                                                   label=_("Map display"),
                                                   style=wx.RB_GROUP)
        self.region_types["comp"] = RadioButton(
            parent=self, label=_("Computational region"))
        self.region_types["named"] = RadioButton(parent=self,
                                                 label=_("Named region"))
        self.region_types["display"].SetToolTip(
            _("Extent and resolution"
              " are based on Map Display geometry."))
        self.region_types["comp"].SetToolTip(
            _("Extent and resolution"
              " are based on computational region."))
        self.region_types["named"].SetToolTip(
            _("Extent and resolution"
              " are based on named region."))
        self.region_types["display"].SetValue(
            True)  # set default as map display

        self.overwrite = wx.CheckBox(parent=self,
                                     id=wx.ID_ANY,
                                     label=_("Overwrite existing raster map"))

        self.named_reg_panel = wx.Panel(parent=self, id=wx.ID_ANY)
        self.labels["region"] = StaticText(parent=self.named_reg_panel,
                                           id=wx.ID_ANY,
                                           label=_("Choose named region:"))

        self.params["region"] = Select(
            parent=self.named_reg_panel,
            type="region",
            size=globalvar.DIALOG_GSELECT_SIZE,
        )

        # buttons
        self.btn_close = Button(parent=self, id=wx.ID_CLOSE)
        self.SetEscapeId(self.btn_close.GetId())
        self.btn_close.SetToolTip(_("Close dialog"))

        self.btn_ok = Button(parent=self, label=_("&Save layer"))
        self.btn_ok.SetToolTip(_("Save web service layer as raster map"))

        # statusbar
        self.statusbar = wx.StatusBar(parent=self, id=wx.ID_ANY)

        self._layout()

    def _layout(self):

        self._border = wx.BoxSizer(wx.VERTICAL)
        dialogSizer = wx.BoxSizer(wx.VERTICAL)

        regionSizer = wx.BoxSizer(wx.HORIZONTAL)

        dialogSizer.Add(
            self._addSelectSizer(title=self.labels["output"],
                                 sel=self.params["output"]))

        regionSizer = wx.StaticBoxSizer(self.regionStBoxLabel, wx.VERTICAL)

        regionTypeSizer = wx.BoxSizer(wx.HORIZONTAL)
        for r_type in self.region_types_order:
            regionTypeSizer.Add(self.region_types[r_type],
                                flag=wx.RIGHT,
                                border=8)

        regionSizer.Add(regionTypeSizer)

        self.named_reg_panel.SetSizer(
            self._addSelectSizer(title=self.labels["region"],
                                 sel=self.params["region"]))
        regionSizer.Add(self.named_reg_panel)
        self.named_reg_panel.Hide()

        dialogSizer.Add(regionSizer, flag=wx.EXPAND)

        dialogSizer.Add(self.overwrite, flag=wx.TOP, border=10)

        # buttons
        self.btnsizer = wx.BoxSizer(orient=wx.HORIZONTAL)

        self.btnsizer.Add(self.btn_close,
                          proportion=0,
                          flag=wx.ALL | wx.ALIGN_CENTER,
                          border=10)

        self.btnsizer.Add(self.btn_ok,
                          proportion=0,
                          flag=wx.ALL | wx.ALIGN_CENTER,
                          border=10)

        dialogSizer.Add(self.btnsizer, proportion=0, flag=wx.ALIGN_CENTER)

        self._border.Add(dialogSizer, proportion=0, flag=wx.ALL, border=5)

        self._border.Add(self.statusbar, proportion=0)

        self.SetSizer(self._border)
        self.Layout()
        self.Fit()

        # bindings
        self.btn_ok.Bind(wx.EVT_BUTTON, self.OnSave)

        self.Bind(EVT_CMD_DONE, self.OnCmdDone)
        self.Bind(EVT_CMD_OUTPUT, self.OnCmdOutput)

        for r_type in self.region_types_order:
            self.Bind(wx.EVT_RADIOBUTTON, self.OnRegionType,
                      self.region_types[r_type])

    def _addSelectSizer(self, title, sel):
        """Helper layout function."""
        selSizer = wx.BoxSizer(orient=wx.VERTICAL)

        selTitleSizer = wx.BoxSizer(wx.HORIZONTAL)
        selTitleSizer.Add(title,
                          proportion=1,
                          flag=wx.LEFT | wx.TOP | wx.EXPAND,
                          border=5)

        selSizer.Add(selTitleSizer, proportion=0, flag=wx.EXPAND)

        selSizer.Add(
            sel,
            proportion=1,
            flag=wx.EXPAND | wx.ALL,
            border=5,
        )

        return selSizer

    def OnRegionType(self, event):
        selected = event.GetEventObject()
        if selected == self.region_types["named"]:
            self.named_reg_panel.Show()
        else:
            self.named_reg_panel.Hide()

        self._border.Layout()
        self.Fit()

    def OnSave(self, event):
        """Import WMS raster data into GRASS as raster layer."""
        self.thread.abort(abortall=True)
        currmapset = grass.gisenv()["MAPSET"]

        self.output = self.params["output"].GetValue().strip()
        l_spl = self.output.strip().split("@")

        # check output layer
        msg = None
        if not self.output:
            msg = _("Missing output raster.")

        elif len(l_spl) > 1 and l_spl[1] != currmapset:
            msg = _("Output map can be added only to current mapset.")

        elif (not self.overwrite.IsChecked()
              and grass.find_file(self.output, "cell", ".")["fullname"]):
            msg = _("Output map <%s> already exists" % self.output)

        if msg:
            GMessage(parent=self, message=msg)
            return

        self.output = l_spl[0]

        # check region
        region = self.params["region"].GetValue().strip()
        reg_spl = region.strip().split("@")

        reg_mapset = "."
        if len(reg_spl) > 1:
            reg_mapset = reg_spl[1]

        if self.region_types["named"].GetValue():
            if not grass.find_file(reg_spl[0], "windows",
                                   reg_mapset)["fullname"]:
                msg = _("Region <%s> does not exist." %
                        self.params["region"].GetValue())
                GWarning(parent=self, message=msg)
                return

        # create r.in.wms command
        cmd = ("r.in.wms", deepcopy(self.cmd[1]))

        if "map" in cmd[1]:
            del cmd[1]["map"]

        cmd[1]["output"] = self.output

        if self.overwrite.IsChecked():
            cmd[1]["overwrite"] = True

        env = os.environ.copy()
        if self.region_types["named"].GetValue():
            cmd[1]["region"] = region
        elif self.region_types["display"].GetValue():
            region = self._giface.GetMapWindow().GetMap().SetRegion()
            env["GRASS_REGION"] = region

        cmdList = cmdtuple_to_list(cmd)
        self.currentPid = self.thread.GetId()

        self.thread.RunCmd(cmdList, env=env, stderr=self.cmdStdErr)

        self.statusbar.SetStatusText(_("Downloading data..."))

    def OnCmdDone(self, event):
        """When data are fetched."""
        if event.pid != self.currentPid:
            return

        self._addLayer()
        self.statusbar.SetStatusText("")

    def _addLayer(self):
        """Add layer into layer tree."""
        llist = self._giface.GetLayerList()
        if len(llist.GetLayersByName(self.output)) == 0:
            cmd = ["d.rast", "map=" + self.output]
            llist.AddLayer(ltype="raster",
                           name=self.output,
                           cmd=cmd,
                           checked=True)

    def OnCmdOutput(self, event):
        """Handle cmd output according to debug level."""
        if Debug.GetLevel() == 0:
            if event.type == "error":
                msg = _("Unable to fetch data.\n")
                msg += event.text
                GWarning(parent=self, message=msg)
        else:
            Debug.msg(1, event.text)
Example #10
0
class WSDialogBase(wx.Dialog):
    """Base class for web service dialogs."""
    def __init__(
        self,
        parent,
        id=wx.ID_ANY,
        style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER,
        **kwargs,
    ):

        wx.Dialog.__init__(self, parent, id, style=style, **kwargs)

        self.parent = parent

        # contains panel for every web service on server
        self.ws_panels = {
            "WMS_1.1.1": {
                "panel": None,
                "label": "WMS 1.1.1"
            },
            "WMS_1.3.0": {
                "panel": None,
                "label": "WMS 1.3.0"
            },
            "WMTS": {
                "panel": None,
                "label": "WMTS"
            },
            "OnEarth": {
                "panel": None,
                "label": "OnEarth"
            },
        }

        # TODO: should be in file
        self.default_servers = {
            "OSM-WMS": [
                "https://ows.terrestris.de/osm/service?",
                "",
                "",
            ],
            "NASA GIBS WMTS": [
                "http://gibs.earthdata.nasa.gov/wmts/epsg4326/best/wmts.cgi",
                "",
                "",
            ],
            "tiles.maps.eox.at (Sentinel-2)": [
                "https://tiles.maps.eox.at/wms",
                "",
                "",
            ],
        }

        # holds reference to web service panel which is showed
        self.active_ws_panel = None

        # buttons which are disabled when the dialog is not connected
        self.run_btns = []

        # stores error messages for GError dialog showed when all web service
        # connections were unsuccessful
        self.error_msgs = ""

        self._createWidgets()
        self._doLayout()

    def _createWidgets(self):

        settingsFile = os.path.join(GetSettingsPath(), "wxWS")

        self.settsManager = WSManageSettingsWidget(
            parent=self,
            settingsFile=settingsFile,
            default_servers=self.default_servers)

        self.settingsBox = StaticBox(parent=self,
                                     id=wx.ID_ANY,
                                     label=_(" Server settings "))

        self.serverText = StaticText(parent=self,
                                     id=wx.ID_ANY,
                                     label=_("Server:"))
        self.server = TextCtrl(parent=self, id=wx.ID_ANY)

        self.btn_connect = Button(parent=self,
                                  id=wx.ID_ANY,
                                  label=_("&Connect"))
        self.btn_connect.SetToolTip(_("Connect to the server"))
        if not self.server.GetValue():
            self.btn_connect.Enable(False)

        self.infoCollapseLabelExp = _("Show advanced connection settings")
        self.infoCollapseLabelCol = _("Hide advanced connection settings")

        self.adv_conn = wx.CollapsiblePane(
            parent=self,
            label=self.infoCollapseLabelExp,
            style=wx.CP_DEFAULT_STYLE | wx.CP_NO_TLW_RESIZE | wx.EXPAND,
        )

        self.MakeAdvConnPane(pane=self.adv_conn.GetPane())
        self.adv_conn.Collapse(True)
        self.Bind(wx.EVT_COLLAPSIBLEPANE_CHANGED, self.OnAdvConnPaneChanged,
                  self.adv_conn)

        self.reqDataPanel = wx.Panel(parent=self, id=wx.ID_ANY)

        self.layerNameBox = StaticBox(parent=self.reqDataPanel,
                                      id=wx.ID_ANY,
                                      label=_(" Layer Manager Settings "))

        self.layerNameText = StaticText(parent=self.reqDataPanel,
                                        id=wx.ID_ANY,
                                        label=_("Output layer name:"))
        self.layerName = TextCtrl(parent=self.reqDataPanel, id=wx.ID_ANY)

        for ws in six.iterkeys(self.ws_panels):
            # set class WSPanel argument layerNameTxtCtrl
            self.ws_panels[ws]["panel"] = WSPanel(parent=self.reqDataPanel,
                                                  web_service=ws)
            self.ws_panels[ws]["panel"].capParsed.connect(
                self.OnPanelCapParsed)
            self.ws_panels[ws]["panel"].layerSelected.connect(
                self.OnLayerSelected)

        # buttons
        self.btn_close = Button(parent=self, id=wx.ID_CLOSE)
        self.btn_close.SetToolTip(_("Close dialog"))

        # statusbar
        self.statusbar = wx.StatusBar(parent=self, id=wx.ID_ANY)

        # bindings
        self.btn_close.Bind(wx.EVT_BUTTON, self.OnClose)
        self.Bind(wx.EVT_CLOSE, self.OnClose)
        self.btn_connect.Bind(wx.EVT_BUTTON, self.OnConnect)

        self.server.Bind(wx.EVT_TEXT, self.OnServer)
        self.layerName.Bind(wx.EVT_TEXT, self.OnOutputLayerName)

        self.settsManager.settingsChanged.connect(self.OnSettingsChanged)
        self.settsManager.settingsSaving.connect(self.OnSettingsSaving)

    def OnLayerSelected(self, title):
        self.layerName.SetValue(title)

    def _doLayout(self):

        dialogSizer = wx.BoxSizer(wx.VERTICAL)

        dialogSizer.Add(
            self.settsManager,
            proportion=0,
            flag=wx.EXPAND | wx.TOP | wx.LEFT | wx.RIGHT,
            border=5,
        )

        # connectin settings
        settingsSizer = wx.StaticBoxSizer(self.settingsBox, wx.VERTICAL)

        serverSizer = wx.FlexGridSizer(cols=3, vgap=5, hgap=5)

        serverSizer.Add(self.serverText, flag=wx.ALIGN_CENTER_VERTICAL)
        serverSizer.AddGrowableCol(1)
        serverSizer.Add(self.server, flag=wx.EXPAND | wx.ALL)

        serverSizer.Add(self.btn_connect)

        settingsSizer.Add(serverSizer,
                          proportion=0,
                          flag=wx.EXPAND | wx.LEFT | wx.RIGHT,
                          border=5)

        settingsSizer.Add(self.adv_conn, flag=wx.ALL | wx.EXPAND, border=5)

        dialogSizer.Add(
            settingsSizer,
            proportion=0,
            flag=wx.EXPAND | wx.TOP | wx.LEFT | wx.RIGHT,
            border=5,
        )

        # layer name, parsed capabilities

        reqDataSizer = wx.BoxSizer(wx.VERTICAL)

        layerNameSizer = wx.StaticBoxSizer(self.layerNameBox, wx.HORIZONTAL)

        layerNameSizer.Add(self.layerNameText,
                           flag=wx.ALIGN_CENTER_VERTICAL | wx.ALL,
                           border=5)

        layerNameSizer.Add(self.layerName, flag=wx.EXPAND, proportion=1)

        reqDataSizer.Add(layerNameSizer,
                         flag=wx.TOP | wx.LEFT | wx.RIGHT | wx.EXPAND,
                         border=5)

        self.ch_ws_sizer = wx.BoxSizer(wx.VERTICAL)

        reqDataSizer.Add(self.ch_ws_sizer,
                         proportion=0,
                         flag=wx.TOP | wx.EXPAND,
                         border=5)

        for ws in six.iterkeys(self.ws_panels):
            reqDataSizer.Add(
                self.ws_panels[ws]["panel"],
                proportion=1,
                flag=wx.TOP | wx.LEFT | wx.RIGHT | wx.EXPAND,
                border=5,
            )
            self.ws_panels[ws]["panel"].Hide()

        dialogSizer.Add(self.reqDataPanel, proportion=1, flag=wx.EXPAND)

        self.reqDataPanel.SetSizer(reqDataSizer)
        self.reqDataPanel.Hide()

        # buttons
        self.btnsizer = wx.BoxSizer(orient=wx.HORIZONTAL)

        self.btnsizer.Add(self.btn_close,
                          proportion=0,
                          flag=wx.ALL | wx.ALIGN_CENTER,
                          border=10)

        dialogSizer.Add(self.btnsizer, proportion=0, flag=wx.ALIGN_CENTER)

        # expand wxWidget wx.StatusBar
        statusbarSizer = wx.BoxSizer(wx.HORIZONTAL)
        statusbarSizer.Add(self.statusbar, proportion=1, flag=wx.EXPAND)
        dialogSizer.Add(statusbarSizer, proportion=0, flag=wx.EXPAND)

        self.SetSizer(dialogSizer)
        self.Layout()

        self.SetMinSize((550, -1))
        self.SetMaxSize((-1, self.GetBestSize()[1]))
        self.Fit()

    def MakeAdvConnPane(self, pane):
        """Create advanced connection settings pane"""
        self.usernameText = StaticText(parent=pane,
                                       id=wx.ID_ANY,
                                       label=_("Username:"******"Password:"******"""Check if required data are filled before setting save is performed."""
        server = self.server.GetValue().strip()
        if not server:
            GMessage(
                parent=self,
                message=_("No data source defined, settings are not saved."),
            )
            return

        self.settsManager.SetDataToSave(
            (server, self.username.GetValue(), self.password.GetValue()))
        self.settsManager.SaveSettings(name)

    def OnSettingsChanged(self, data):
        """Update widgets according to chosen settings"""
        # data list: [server, username, password]
        if len(data) < 3:
            return

        self.server.SetValue(data[0])

        self.username.SetValue(data[1])
        self.password.SetValue(data[2])

        if data[1] or data[2]:
            self.adv_conn.Expand()
        else:
            self.adv_conn.Collapse(True)

        # clear content of the wxWidget wx.TextCtrl (Output layer
        # name:), based on changing default server selection in the
        # wxWidget wx.Choice
        if len(self.layerName.GetValue()) > 0:
            self.layerName.Clear()

    def OnClose(self, event):
        """Close the dialog"""
        """Close dialog"""
        if not self.IsModal():
            self.Destroy()
        event.Skip()

    def _getCapFiles(self):
        ws_cap_files = {}
        for v in six.itervalues(self.ws_panels):
            ws_cap_files[v["panel"].GetWebService()] = v["panel"].GetCapFile()

        return ws_cap_files

    def OnServer(self, event):
        """Server settings edited"""
        value = event.GetString()
        if value:
            self.btn_connect.Enable(True)
        else:
            self.btn_connect.Enable(False)

        # clear content of the wxWidget wx.TextCtrl (Output Layer
        # name:), based on changing content of the wxWidget
        # wx.TextCtrl (Server:)
        self.layerName.Clear()

    def OnOutputLayerName(self, event):
        """Update layer name to web service panel"""
        lname = event.GetString()
        for v in six.itervalues(self.ws_panels):
            v["panel"].SetOutputLayerName(lname.strip())

    def OnConnect(self, event):
        """Connect to the server"""
        server = self.server.GetValue().strip()

        self.ch_ws_sizer.Clear(True)

        if self.active_ws_panel is not None:
            self.reqDataPanel.Hide()
            for btn in self.run_btns:
                btn.Enable(False)
            self.active_ws_panel = None

            self.Layout()
            self.Fit()

        self.statusbar.SetStatusText(
            _("Connecting to <%s>..." % self.server.GetValue().strip()))

        # number of panels already connected
        self.finished_panels_num = 0
        for ws in six.iterkeys(self.ws_panels):
            self.ws_panels[ws]["panel"].ConnectToServer(
                url=server,
                username=self.username.GetValue(),
                password=self.password.GetValue(),
            )
            self.ws_panels[ws]["panel"].Hide()

    def OnPanelCapParsed(self, error_msg):
        """Called when panel has downloaded and parsed capabilities file."""
        # how many web service panels are finished
        self.finished_panels_num += 1

        if error_msg:
            self.error_msgs += "\n" + error_msg

        # if all are finished, show panels, which succeeded in connection
        if self.finished_panels_num == len(self.ws_panels):
            self.UpdateDialogAfterConnection()

            # show error dialog only if connections to all web services were
            # unsuccessful
            if not self._getConnectedWS() and self.error_msgs:
                GError(self.error_msgs, parent=self)
            self.error_msgs = ""

            self.Layout()
            self.Fit()

    def _getConnectedWS(self):
        """
        :return: list of found web services on server (identified as keys in self.ws_panels)
        """
        conn_ws = []
        for ws, data in six.iteritems(self.ws_panels):
            if data["panel"].IsConnected():
                conn_ws.append(ws)

        return conn_ws

    def UpdateDialogAfterConnection(self):
        """Update dialog after all web service panels downloaded and parsed capabilities data."""
        avail_ws = {}
        conn_ws = self._getConnectedWS()

        for ws in conn_ws:
            avail_ws[ws] = self.ws_panels[ws]

        self.web_service_sel = []
        self.rb_choices = []

        # at least one web service found on server
        if len(avail_ws) > 0:
            self.reqDataPanel.Show()
            self.rb_order = ["WMS_1.1.1", "WMS_1.3.0", "WMTS", "OnEarth"]

            for ws in self.rb_order:

                if ws in avail_ws:
                    self.web_service_sel.append(ws)
                    self.rb_choices.append(avail_ws[ws]["label"])

            self.choose_ws_rb = wx.RadioBox(
                parent=self.reqDataPanel,
                id=wx.ID_ANY,
                label=_("Available web services"),
                pos=wx.DefaultPosition,
                choices=self.rb_choices,
                majorDimension=1,
                style=wx.RA_SPECIFY_ROWS,
            )

            self.Bind(wx.EVT_RADIOBOX, self.OnChooseWs, self.choose_ws_rb)
            self.ch_ws_sizer.Add(
                self.choose_ws_rb,
                flag=wx.TOP | wx.LEFT | wx.RIGHT | wx.EXPAND,
                border=5,
            )
            self._showWsPanel(
                self.web_service_sel[self.choose_ws_rb.GetSelection()])
            self.statusbar.SetStatusText(
                _("Connected to <%s>" % self.server.GetValue().strip()))
            for btn in self.run_btns:
                btn.Enable(True)
        # no web service found on server
        else:
            self.statusbar.SetStatusText(
                _("Unable to connect to <%s>" %
                  self.server.GetValue().strip()))
            for btn in self.run_btns:
                btn.Enable(False)
            self.reqDataPanel.Hide()
            self.active_ws_panel = None

    def OnChooseWs(self, event):
        """Show panel corresponding to selected web service."""
        chosen_r = event.GetInt()
        self._showWsPanel(self.web_service_sel[chosen_r])

    def _showWsPanel(self, ws):
        """Helper function"""
        if self.active_ws_panel is not None:
            self.active_ws_panel.Hide()

        self.active_ws_panel = self.ws_panels[ws]["panel"]
        if not self.active_ws_panel.IsShown():
            self.active_ws_panel.Show()
            self.SetMaxSize((-1, -1))
            self.active_ws_panel.GetContainingSizer().Layout()

    def OnAdvConnPaneChanged(self, event):
        """Collapse search module box"""
        if self.adv_conn.IsExpanded():
            self.adv_conn.SetLabel(self.infoCollapseLabelCol)
        else:
            self.adv_conn.SetLabel(self.infoCollapseLabelExp)

        self.Layout()
        self.SetMaxSize((-1, self.GetBestSize()[1]))
        self.SendSizeEvent()
        self.Fit()
Example #11
0
class AddWSDialog(WSDialogBase):
    """Dialog for adding web service layer."""
    def __init__(
        self,
        parent,
        giface,
        id=wx.ID_ANY,
        style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER,
        **kwargs,
    ):

        WSDialogBase.__init__(
            self,
            parent,
            id=wx.ID_ANY,
            style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER,
            **kwargs,
        )

        self.SetTitle(_("Add web service layer"))

        self.parent = parent
        self.giface = giface
        self.btn_connect.SetDefault()

    def _createWidgets(self):

        WSDialogBase._createWidgets(self)

        self.btn_add = Button(parent=self, id=wx.ID_ANY, label=_("&Add layer"))
        self.btn_add.SetToolTip(
            _("Add selected web service layers as map layer into layer tree"))
        self.btn_add.Enable(False)

        self.run_btns.append(self.btn_add)

    def _doLayout(self):

        WSDialogBase._doLayout(self)

        self.btnsizer.Add(self.btn_add,
                          proportion=0,
                          flag=wx.ALL | wx.ALIGN_CENTER,
                          border=10)

        # bindings
        self.btn_add.Bind(wx.EVT_BUTTON, self.OnAddLayer)

    def UpdateDialogAfterConnection(self):
        """Connect to the server"""
        WSDialogBase.UpdateDialogAfterConnection(self)

        if self._getConnectedWS():
            self.btn_add.SetDefault()
        else:
            self.btn_connect.SetDefault()

    def OnAddLayer(self, event):
        """Add web service layer."""
        # add layer
        if self.active_ws_panel is None:
            return

        lcmd = self.active_ws_panel.CreateCmd()
        if not lcmd:
            return None

        # TODO: It is not clear how to do GetOptData in giface
        # knowing what GetOptData is doing might help
        # (maybe Get... is not the right name)
        # please fix giface if you know
        # tree -> giface
        # GetLayerTree -> GetLayerList
        # AddLayer -> AddLayer (but tree ones returns some layer,
        # giface ones nothing)
        # GetLayerInfo -> Layer object can by used instead
        # GetOptData -> unknown
        ltree = self.giface.GetLayerTree()

        active_ws = self.active_ws_panel.GetWebService()
        if "WMS" not in active_ws:
            cap_file = self.active_ws_panel.GetCapFile()
            cmd_cap_file = grass.tempfile()
            shutil.copyfile(cap_file, cmd_cap_file)
            lcmd.append("capfile=" + cmd_cap_file)

        layer = ltree.AddLayer(
            ltype="wms",
            lname=self.active_ws_panel.GetOutputLayerName(),
            lchecked=True,
            lcmd=lcmd,
        )

        ws_cap_files = self._getCapFiles()
        # create properties dialog
        cmd_list = ltree.GetLayerInfo(layer, "cmd")
        cmd = cmdlist_to_tuple(cmd_list)

        prop_win = WSPropertiesDialog(
            parent=self.parent,
            giface=self.giface,
            id=wx.ID_ANY,
            layer=layer,
            ws_cap_files=ws_cap_files,
            cmd=cmd,
        )

        prop_win.Hide()
        ltree.GetOptData(dcmd=None, layer=layer, params=None, propwin=prop_win)
Example #12
0
class VectorCleaningFrame(wx.Frame):
    def __init__(self,
                 parent,
                 id=wx.ID_ANY,
                 title=_('Set up vector cleaning tools'),
                 style=wx.DEFAULT_FRAME_STYLE | wx.RESIZE_BORDER,
                 **kwargs):
        """
        Dialog for interactively defining vector cleaning tools
        """
        wx.Frame.__init__(self, parent, id, title, style=style, **kwargs)

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

        # grass command
        self.cmd = 'v.clean'

        # statusbar
        self.CreateStatusBar()

        # icon
        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)

        # input map to clean
        self.inmap = ''

        # cleaned output map
        self.outmap = ''

        self.ftype = ''

        # cleaning tools
        self.toolslines = {}

        self.tool_desc_list = [
            _('break lines/boundaries'),
            _('remove duplicates'),
            _('remove dangles'),
            _('change boundary dangles to lines'),
            _('remove bridges'),
            _('change bridges to lines'),
            _('snap lines/boundaries'),
            _('remove duplicate area centroids'),
            _('break polygons'),
            _('prune lines/boundaries'),
            _('remove small areas'),
            _('remove lines/boundaries of zero length'),
            _('remove small angles at nodes')
        ]

        self.tool_list = [
            'break', 'rmdupl', 'rmdangle', 'chdangle', 'rmbridge', 'chbridge',
            'snap', 'rmdac', 'bpol', 'prune', 'rmarea', 'rmline', 'rmsa'
        ]

        self.ftype = ['point', 'line', 'boundary', 'centroid', 'area', 'face']

        self.n_ftypes = len(self.ftype)

        self.tools_string = ''
        self.thresh_string = ''
        self.ftype_string = ''

        self.SetStatusText(_("Set up vector cleaning tools"))
        self.elem = 'vector'
        self.ctlabel = _('Choose cleaning tools and set thresholds')

        # top controls
        self.inmaplabel = StaticText(parent=self.panel,
                                     id=wx.ID_ANY,
                                     label=_('Select input vector map:'))
        self.selectionInput = Select(parent=self.panel,
                                     id=wx.ID_ANY,
                                     size=globalvar.DIALOG_GSELECT_SIZE,
                                     type='vector')
        self.ftype_check = {}
        ftypeBox = StaticBox(parent=self.panel,
                             id=wx.ID_ANY,
                             label=_(' Feature type: '))
        self.ftypeSizer = wx.StaticBoxSizer(ftypeBox, wx.HORIZONTAL)

        self.outmaplabel = StaticText(parent=self.panel,
                                      id=wx.ID_ANY,
                                      label=_('Select output vector map:'))
        self.selectionOutput = Select(parent=self.panel,
                                      id=wx.ID_ANY,
                                      size=globalvar.DIALOG_GSELECT_SIZE,
                                      mapsets=[
                                          grass.gisenv()['MAPSET'],
                                      ],
                                      fullyQualified=False,
                                      type='vector')

        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'))

        # cleaning tools
        self.ct_label = StaticText(parent=self.panel,
                                   id=wx.ID_ANY,
                                   label=self.ctlabel)

        self.ct_panel = self._toolsPanel()

        # buttons to manage cleaning tools
        self.btn_add = Button(parent=self.panel, id=wx.ID_ADD)
        self.btn_remove = Button(parent=self.panel, id=wx.ID_REMOVE)
        self.btn_moveup = Button(parent=self.panel, id=wx.ID_UP)
        self.btn_movedown = Button(parent=self.panel, id=wx.ID_DOWN)

        # add one tool as default
        self.AddTool()
        self.selected = -1

        # Buttons
        self.btn_close = Button(parent=self.panel, id=wx.ID_CLOSE)
        self.btn_run = Button(parent=self.panel, id=wx.ID_ANY, label=_("&Run"))
        self.btn_run.SetDefault()
        self.btn_clipboard = Button(parent=self.panel, id=wx.ID_COPY)
        self.btn_clipboard.SetToolTip(
            _("Copy the current command string to the clipboard (Ctrl+C)"))
        self.btn_help = Button(parent=self.panel, id=wx.ID_HELP)

        # bindings
        self.btn_close.Bind(wx.EVT_BUTTON, self.OnClose)
        self.btn_run.Bind(wx.EVT_BUTTON, self.OnCleaningRun)
        self.btn_clipboard.Bind(wx.EVT_BUTTON, self.OnCopy)
        self.btn_help.Bind(wx.EVT_BUTTON, self.OnHelp)

        self.btn_add.Bind(wx.EVT_BUTTON, self.OnAddTool)
        self.btn_remove.Bind(wx.EVT_BUTTON, self.OnClearTool)
        self.btn_moveup.Bind(wx.EVT_BUTTON, self.OnMoveToolUp)
        self.btn_movedown.Bind(wx.EVT_BUTTON, self.OnMoveToolDown)

        # layout
        self._layout()

        self.SetMinSize(self.GetBestSize())

        self.CentreOnScreen()

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

        #
        # input output
        #
        inSizer = wx.GridBagSizer(hgap=5, vgap=5)

        inSizer.Add(self.inmaplabel,
                    pos=(0, 0),
                    flag=wx.ALIGN_CENTER_VERTICAL | wx.ALL | wx.EXPAND,
                    border=1)
        inSizer.Add(self.selectionInput,
                    pos=(1, 0),
                    flag=wx.ALIGN_CENTER_VERTICAL | wx.ALL | wx.EXPAND,
                    border=1)

        self.ftype_check = [
            wx.CheckBox(parent=self.panel, id=wx.ID_ANY, label=_('point')),
            wx.CheckBox(parent=self.panel, id=wx.ID_ANY, label=_('line')),
            wx.CheckBox(parent=self.panel, id=wx.ID_ANY, label=_('boundary')),
            wx.CheckBox(parent=self.panel, id=wx.ID_ANY, label=_('centroid')),
            wx.CheckBox(parent=self.panel, id=wx.ID_ANY, label=_('area')),
            wx.CheckBox(parent=self.panel, id=wx.ID_ANY, label=_('face'))
        ]

        typeoptSizer = wx.BoxSizer(wx.HORIZONTAL)
        for num in range(0, self.n_ftypes):
            type_box = self.ftype_check[num]
            if self.ftype[num] in ('point', 'line', 'area'):
                type_box.SetValue(True)
            typeoptSizer.Add(type_box, flag=wx.ALIGN_LEFT, border=1)

        self.ftypeSizer.Add(typeoptSizer,
                            flag=wx.ALIGN_CENTER_VERTICAL | wx.ALL,
                            border=2)

        outSizer = wx.GridBagSizer(hgap=5, vgap=5)

        outSizer.Add(self.outmaplabel,
                     pos=(0, 0),
                     flag=wx.ALIGN_CENTER_VERTICAL | wx.ALL | wx.EXPAND,
                     border=1)
        outSizer.Add(self.selectionOutput,
                     pos=(1, 0),
                     flag=wx.ALIGN_CENTER_VERTICAL | wx.ALL | wx.EXPAND,
                     border=1)
        replaceSizer = wx.BoxSizer(wx.HORIZONTAL)
        replaceSizer.Add(self.overwrite,
                         proportion=1,
                         flag=wx.ALL | wx.EXPAND,
                         border=1)

        outSizer.Add(replaceSizer,
                     pos=(2, 0),
                     flag=wx.ALL | wx.EXPAND,
                     border=1)

        #
        # tools selection
        #
        bodySizer = wx.GridBagSizer(hgap=5, vgap=5)

        bodySizer.Add(self.ct_label,
                      pos=(0, 0),
                      span=(1, 2),
                      flag=wx.ALL,
                      border=5)

        bodySizer.Add(self.ct_panel, pos=(1, 0), span=(1, 2))

        manageBoxSizer = wx.GridBagSizer(hgap=10, vgap=1)
        # start with row 1 for nicer layout
        manageBoxSizer.Add(self.btn_add,
                           pos=(1, 0),
                           border=2,
                           flag=wx.ALL | wx.EXPAND)
        manageBoxSizer.Add(self.btn_remove,
                           pos=(2, 0),
                           border=2,
                           flag=wx.ALL | wx.EXPAND)
        manageBoxSizer.Add(self.btn_moveup,
                           pos=(3, 0),
                           border=2,
                           flag=wx.ALL | wx.EXPAND)
        manageBoxSizer.Add(self.btn_movedown,
                           pos=(4, 0),
                           border=2,
                           flag=wx.ALL | wx.EXPAND)

        bodySizer.Add(manageBoxSizer,
                      pos=(1, 2),
                      flag=wx.EXPAND | wx.LEFT | wx.RIGHT,
                      border=5)

        bodySizer.AddGrowableCol(2)

        #
        # standard buttons
        #
        btnSizer = wx.BoxSizer(wx.HORIZONTAL)
        btnSizer.Add(self.btn_close, flag=wx.LEFT | wx.RIGHT, border=5)
        btnSizer.Add(self.btn_run, flag=wx.LEFT | wx.RIGHT, border=5)
        btnSizer.Add(self.btn_clipboard, flag=wx.LEFT | wx.RIGHT, border=5)
        btnSizer.Add(self.btn_help, flag=wx.LEFT | wx.RIGHT, border=5)

        #
        # put it all together
        #
        sizer.Add(inSizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)

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

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

        sizer.Add(wx.StaticLine(parent=self,
                                id=wx.ID_ANY,
                                style=wx.LI_HORIZONTAL),
                  proportion=0,
                  flag=wx.EXPAND | wx.ALL,
                  border=5)

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

        sizer.Add(wx.StaticLine(parent=self,
                                id=wx.ID_ANY,
                                style=wx.LI_HORIZONTAL),
                  proportion=0,
                  flag=wx.EXPAND | wx.ALL,
                  border=5)

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

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

        self.Layout()

    def _toolsPanel(self):
        ct_panel = scrolled.ScrolledPanel(parent=self.panel,
                                          id=wx.ID_ANY,
                                          size=(500, 240),
                                          style=wx.SUNKEN_BORDER)

        self.ct_sizer = wx.GridBagSizer(vgap=2, hgap=4)

        ct_panel.SetSizer(self.ct_sizer)
        ct_panel.SetAutoLayout(True)

        return ct_panel

    def OnAddTool(self, event):
        """Add tool button pressed"""
        self.AddTool()

    def AddTool(self):
        snum = len(self.toolslines.keys())
        num = snum + 1
        # tool
        tool_cbox = wx.ComboBox(parent=self.ct_panel,
                                id=1000 + num,
                                size=(300, -1),
                                choices=self.tool_desc_list,
                                style=wx.CB_DROPDOWN | wx.CB_READONLY
                                | wx.TE_PROCESS_ENTER)
        self.Bind(wx.EVT_COMBOBOX, self.OnSetTool, tool_cbox)
        # threshold
        txt_ctrl = TextCtrl(parent=self.ct_panel,
                            id=2000 + num,
                            value='0.00',
                            size=(100, -1),
                            style=wx.TE_NOHIDESEL)
        self.Bind(wx.EVT_TEXT, self.OnThreshValue, txt_ctrl)

        # select with tool number
        select = wx.CheckBox(parent=self.ct_panel,
                             id=num,
                             label=str(num) + '.')
        select.SetValue(False)
        self.Bind(wx.EVT_CHECKBOX, self.OnSelect, select)

        # start with row 1 and col 1 for nicer layout
        self.ct_sizer.Add(select,
                          pos=(num, 1),
                          flag=wx.ALIGN_CENTER | wx.RIGHT)
        self.ct_sizer.Add(tool_cbox,
                          pos=(num, 2),
                          flag=wx.ALIGN_CENTER | wx.RIGHT,
                          border=5)
        self.ct_sizer.Add(txt_ctrl,
                          pos=(num, 3),
                          flag=wx.ALIGN_CENTER | wx.RIGHT,
                          border=5)

        self.toolslines[num] = {'tool_desc': '', 'tool': '', 'thresh': '0.00'}

        self.ct_panel.Layout()
        self.ct_panel.SetupScrolling()

    def OnClearTool(self, event):
        """Remove tool button pressed"""
        id = self.selected

        if id > 0:
            self.FindWindowById(id + 1000).SetValue('')
            self.toolslines[id]['tool_desc'] = ''
            self.toolslines[id]['tool'] = ''
            self.SetStatusText(
                _("%s. cleaning tool removed, will be ignored") % id)
        else:
            self.SetStatusText(_("Please select a cleaning tool to remove"))

    def OnMoveToolUp(self, event):
        """Move up tool button pressed"""
        id = self.selected

        if id > 1:
            id_up = id - 1
            this_toolline = self.toolslines[id]
            up_toolline = self.toolslines[id_up]

            self.FindWindowById(id_up).SetValue(True)
            self.FindWindowById(id_up + 1000).SetValue(
                this_toolline['tool_desc'])
            self.FindWindowById(id_up + 2000).SetValue(this_toolline['thresh'])
            self.toolslines[id_up] = this_toolline

            self.FindWindowById(id).SetValue(False)
            self.FindWindowById(id + 1000).SetValue(up_toolline['tool_desc'])
            self.FindWindowById(id + 2000).SetValue(up_toolline['thresh'])
            self.toolslines[id] = up_toolline
            self.selected = id_up
            self.SetStatusText(_("%s. cleaning tool moved up") % id)
        elif id == 1:
            self.SetStatusText(_("1. cleaning tool can not be moved up "))
        elif id == -1:
            self.SetStatusText(_("Please select a cleaning tool to move up"))

    def OnMoveToolDown(self, event):
        """Move down tool button pressed"""
        id = self.selected
        snum = len(self.toolslines.keys())

        if id > 0 and id < snum:
            id_down = id + 1
            this_toolline = self.toolslines[id]
            down_toolline = self.toolslines[id_down]

            self.FindWindowById(id_down).SetValue(True)
            self.FindWindowById(id_down + 1000).SetValue(
                this_toolline['tool_desc'])
            self.FindWindowById(id_down + 2000).SetValue(
                this_toolline['thresh'])
            self.toolslines[id_down] = this_toolline

            self.FindWindowById(id).SetValue(False)
            self.FindWindowById(id + 1000).SetValue(down_toolline['tool_desc'])
            self.FindWindowById(id + 2000).SetValue(down_toolline['thresh'])
            self.toolslines[id] = down_toolline
            self.selected = id_down
            self.SetStatusText(_("%s. cleaning tool moved down") % id)
        elif id == snum:
            self.SetStatusText(_("Last cleaning tool can not be moved down "))
        elif id == -1:
            self.SetStatusText(_("Please select a cleaning tool to move down"))

    def OnSetTool(self, event):
        """Tool was defined"""
        id = event.GetId()
        tool_no = id - 1000
        num = self.FindWindowById(id).GetCurrentSelection()

        self.toolslines[tool_no]['tool_desc'] = self.tool_desc_list[num]
        self.toolslines[tool_no]['tool'] = self.tool_list[num]

        self.SetStatusText(
            str(tool_no) + '. ' + _("cleaning tool: '%s'") %
            (self.tool_list[num]))

    def OnThreshValue(self, event):
        """Threshold value was entered"""
        id = event.GetId()
        num = id - 2000
        self.toolslines[num]['thresh'] = self.FindWindowById(id).GetValue()

        self.SetStatusText(
            _("Threshold for %(num)s. tool '%(tool)s': %(thresh)s") % {
                'num': num,
                'tool': self.toolslines[num]['tool'],
                'thresh': self.toolslines[num]['thresh']
            })

    def OnSelect(self, event):
        """Tool was selected"""
        id = event.GetId()

        if self.selected > -1 and self.selected != id:
            win = self.FindWindowById(self.selected)
            win.SetValue(False)

        if self.selected != id:
            self.selected = id
        else:
            self.selected = -1

    def OnDone(self, event):
        """Command done"""
        self.SetStatusText('')

    def OnCleaningRun(self, event):
        """Builds options and runs v.clean
        """
        self.GetCmdStrings()

        err = list()
        for p, name in ((self.inmap, _('Name of input vector map')),
                        (self.outmap, _('Name for output vector map')),
                        (self.tools_string, _('Tools')), (self.thresh_string,
                                                          _('Threshold'))):
            if not p:
                err.append(_("'%s' not defined") % name)
        if err:
            GError(_("Some parameters not defined. Operation "
                     "canceled.\n\n%s") % '\n'.join(err),
                   parent=self)
            return

        self.SetStatusText(_("Executing selected cleaning operations..."))
        snum = len(self.toolslines.keys())

        if self.log:
            cmd = [
                self.cmd,
                'input=%s' % self.inmap,
                'output=%s' % self.outmap,
                'tool=%s' % self.tools_string,
                'thres=%s' % self.thresh_string
            ]
            if self.ftype_string:
                cmd.append('type=%s' % self.ftype_string)
            if self.overwrite.IsChecked():
                cmd.append('--overwrite')

            self.log.RunCmd(cmd, onDone=self.OnDone)
            self.parent.Raise()
        else:
            if self.overwrite.IsChecked():
                overwrite = True
            else:
                overwrite = False

            RunCommand(self.cmd,
                       input=self.inmap,
                       output=self.outmap,
                       type=self.ftype_string,
                       tool=self.tools_string,
                       thresh=self.thresh_string,
                       overwrite=overwrite)

    def OnClose(self, event):
        self.Destroy()

    def OnHelp(self, event):
        """Show GRASS manual page"""
        RunCommand('g.manual', quiet=True, parent=self, entry=self.cmd)

    def OnCopy(self, event):
        """Copy the command"""
        cmddata = wx.TextDataObject()
        # get tool and thresh strings
        self.GetCmdStrings()
        cmdstring = '%s' % (self.cmd)
        # list -> string
        cmdstring += ' input=%s output=%s type=%s tool=%s thres=%s' % (
            self.inmap, self.outmap, self.ftype_string, self.tools_string,
            self.thresh_string)
        if self.overwrite.IsChecked():
            cmdstring += ' --overwrite'

        cmddata.SetText(cmdstring)
        if wx.TheClipboard.Open():
            wx.TheClipboard.SetData(cmddata)
            wx.TheClipboard.Close()
            self.SetStatusText(
                _("Vector cleaning command copied to clipboard"))

    def GetCmdStrings(self):
        self.tools_string = ''
        self.thresh_string = ''
        self.ftype_string = ''
        # feature types
        first = 1
        for num in range(0, self.n_ftypes - 1):
            if self.ftype_check[num].IsChecked():
                if first:
                    self.ftype_string = '%s' % self.ftype[num]
                    first = 0
                else:
                    self.ftype_string += ',%s' % self.ftype[num]

        # cleaning tools
        first = 1
        snum = len(self.toolslines.keys())
        for num in range(1, snum + 1):
            if self.toolslines[num]['tool']:
                if first:
                    self.tools_string = '%s' % self.toolslines[num]['tool']
                    self.thresh_string = '%s' % self.toolslines[num]['thresh']
                    first = 0
                else:
                    self.tools_string += ',%s' % self.toolslines[num]['tool']
                    self.thresh_string += ',%s' % self.toolslines[num]['thresh']

        self.inmap = self.selectionInput.GetValue()
        self.outmap = self.selectionOutput.GetValue()
Example #13
0
class IClassExportAreasDialog(wx.Dialog):
    def __init__(self,
                 parent,
                 vectorName=None,
                 title=_("Export training areas"),
                 id=wx.ID_ANY,
                 style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER,
                 **kwargs):
        """Dialog for export of training areas to vector layer

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

        self.vectorName = vectorName
        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 = gselect.Select(
            parent=self.panel,
            type='vector',
            mapsets=[grass.gisenv()['MAPSET']],
            size=globalvar.DIALOG_GSELECT_SIZE)
        if self.vectorName:
            self.vectorNameCtrl.SetValue(self.vectorName)
        dataSizer.Add(self.vectorNameCtrl,
                      proportion=0,
                      flag=wx.ALL | wx.EXPAND,
                      border=3)
        self.withTableCtrl = CheckBox(parent=self.panel,
                                      id=wx.ID_ANY,
                                      label=_("Export attribute table"))
        self.withTableCtrl.SetValue(True)
        self.withTableCtrl.SetToolTip(
            _("Export attribute table containing"
              " computed statistical data"))

        dataSizer.Add(self.withTableCtrl, proportion=0, flag=wx.ALL, 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 GetVectorName(self):
        """Returns vector name"""
        return self.vectorNameCtrl.GetValue()

    def WithTable(self):
        """Returns true if attribute table should be exported too"""
        return self.withTableCtrl.IsChecked()

    def OnOK(self, event):
        """Checks if map exists and can be overwritten."""
        overwrite = UserSettings.Get(group='cmd',
                                     key='overwrite',
                                     subkey='enabled')
        vName = self.GetVectorName()
        res = grass.find_file(vName, element='vector')
        if res['fullname'] and overwrite is False:
            qdlg = wx.MessageDialog(
                parent=self,
                message=_("Vector map <%s> already exists."
                          " Do you want to overwrite it?" % vName),
                caption=_("Vector <%s> exists" % vName),
                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()
Example #14
0
class IClassGroupDialog(SimpleDialog):
    """Dialog for imagery group selection"""
    def __init__(self,
                 parent,
                 group=None,
                 subgroup=None,
                 title=_("Select imagery group"),
                 id=wx.ID_ANY):
        """
        Does post init and layout.

        :param parent: gui parent
        :param title: dialog window title
        :param id: wx id
        """
        SimpleDialog.__init__(self, parent, title)

        self.use_subg = True

        self.groupSelect = gselect.Select(
            parent=self.panel,
            type='group',
            mapsets=[grass.gisenv()['MAPSET']],
            size=globalvar.DIALOG_GSELECT_SIZE,
            validator=SimpleValidator(callback=self.ValidatorCallback))

        # TODO use when subgroup will be optional
        # self.subg_chbox = wx.CheckBox(parent = self.panel, id = wx.ID_ANY,
        #                              label = _("Use subgroup"))
        self.subGroupSelect = gselect.SubGroupSelect(parent=self.panel)

        self.groupSelect.SetFocus()
        if group:
            self.groupSelect.SetValue(group)
            self.GroupSelected()
        if subgroup:
            self.subGroupSelect.SetValue(subgroup)

        self.editGroup = Button(parent=self.panel,
                                id=wx.ID_ANY,
                                label=_("Create/edit group..."))

        self.editGroup.Bind(wx.EVT_BUTTON, self.OnEditGroup)
        self.groupSelect.GetTextCtrl().Bind(
            wx.EVT_TEXT, lambda event: wx.CallAfter(self.GroupSelected))

        self.warning = _("Name of imagery group is missing.")
        self._layout()
        self.SetMinSize(self.GetSize())

    def _layout(self):
        """Do layout"""
        self.dataSizer.Add(StaticText(self.panel,
                                      id=wx.ID_ANY,
                                      label=_("Name of imagery group:")),
                           proportion=0,
                           flag=wx.EXPAND | wx.BOTTOM | wx.LEFT | wx.RIGHT,
                           border=5)
        self.dataSizer.Add(self.groupSelect,
                           proportion=0,
                           flag=wx.EXPAND | wx.ALL,
                           border=5)

        # TODO use when subgroup will be optional
        # self.dataSizer.Add(self.subg_chbox, proportion = 0,
        # flag = wx.EXPAND | wx.TOP | wx.LEFT | wx.RIGHT, border = 5)

        self.dataSizer.Add(StaticText(self.panel,
                                      id=wx.ID_ANY,
                                      label=_("Name of imagery subgroup:")),
                           proportion=0,
                           flag=wx.EXPAND | wx.EXPAND | wx.BOTTOM | wx.LEFT
                           | wx.RIGHT,
                           border=5)
        self.dataSizer.Add(self.subGroupSelect,
                           proportion=0,
                           flag=wx.EXPAND | wx.ALL,
                           border=5)

        self.dataSizer.Add(self.editGroup, proportion=0, flag=wx.ALL, border=5)

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

        # TODO use when subgroup will be optional
        # self.subg_panel.Show(False)
        #self.subg_chbox.Bind(wx.EVT_CHECKBOX, self.OnSubgChbox)

    def OnSubgChbox(self, event):
        self.use_subg = self.subg_chbox.GetValue()

        if self.use_subg:
            self.subg_panel.Show()
            # self.SubGroupSelected()
        else:
            self.subg_panel.Hide()
            # self.GroupSelected()
        self.SetMinSize(self.GetBestSize())
        self.Layout()

    def GetData(self):
        """Returns selected group and subgroup"""

        if self.use_subg:
            ret = (self.groupSelect.GetValue(), self.subGroupSelect.GetValue())
        else:
            ret = (self.groupSelect.GetValue(), None)

        return ret

    def OnEditGroup(self, event):
        """Launch edit group dialog"""
        g, s = self.GetData()
        dlg = GroupDialog(parent=self, defaultGroup=g, defaultSubgroup=s)

        dlg.ShowModal()
        gr, s = dlg.GetSelectedGroup()
        if gr in dlg.GetExistGroups():
            self.groupSelect.SetValue(gr)
            self.GroupSelected()
            wx.CallAfter(self.subGroupSelect.SetValue, s)
        dlg.Destroy()

    def GroupSelected(self):
        group = self.GetSelectedGroup()
        self.subGroupSelect.Insert(group)

    def GetSelectedGroup(self):
        """Return currently selected group (without mapset)"""
        return self.groupSelect.GetValue().split('@')[0]

    def GetGroupBandsErr(self, parent):
        """Get list of raster bands which are in the soubgroup of group with both having same name.
           If the group does not exists or it does not contain any bands in subgoup with same name,
           error dialog is shown.
        """
        gr, s = self.GetData()

        group = grass.find_file(name=gr, element='group')

        bands = []
        g = group['name']

        if g:
            if self.use_subg:
                if s == '':
                    GError(_("Please choose a subgroup."), parent=parent)
                    return bands
                if s not in self.GetSubgroups(g):
                    GError(_("Subgroup <%s> not found in group <%s>") % (s, g),
                           parent=parent)
                    return bands

            bands = self.GetGroupBands(g, s)
            if not bands:
                if self.use_subg:
                    GError(_("No data found in subgroup <%s> of group <%s>.\n"
                             ".") % (s, g),
                           parent=parent)

                else:
                    GError(_("No data found in group <%s>.\n"
                             ".") % g,
                           parent=parent)
        else:
            GError(_("Group <%s> not found") % gr, parent=parent)

        return bands

    def GetGroupBands(self, group, subgroup):
        """Get list of raster bands which are in the soubgroup of group with both having same name."""

        kwargs = {}
        if subgroup:
            kwargs['subgroup'] = subgroup

        res = RunCommand('i.group',
                         flags='g',
                         group=group,
                         read=True,
                         **kwargs).strip()
        bands = None
        if res.split('\n')[0]:
            bands = res.split('\n')

        return bands

    def GetSubgroups(self, group):
        return RunCommand('i.group', group=group, read=True,
                          flags='sg').splitlines()
Example #15
0
class ModelLoopDialog(ModelItemDialog):
    """Loop properties dialog"""
    def __init__(
        self,
        parent,
        shape,
        id=wx.ID_ANY,
        title=_("Loop properties"),
        style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER,
        **kwargs,
    ):
        ModelItemDialog.__init__(self,
                                 parent,
                                 shape,
                                 title,
                                 style=style,
                                 **kwargs)

        self.listBox = StaticBox(parent=self.panel,
                                 id=wx.ID_ANY,
                                 label=" %s " % _("List of items in loop"))

        self.btnSeries = Button(parent=self.panel,
                                id=wx.ID_ANY,
                                label=_("Series"))
        self.btnSeries.SetToolTip(
            _("Define map series as condition for the loop"))
        self.btnSeries.Bind(wx.EVT_BUTTON, self.OnSeries)

        self._layout()
        self.SetMinSize(self.GetSize())
        self.SetSize((500, 400))

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

        condSizer = wx.StaticBoxSizer(self.condBox, wx.HORIZONTAL)
        condSizer.Add(self.condText, proportion=1, flag=wx.ALL, border=3)
        condSizer.Add(self.btnSeries, proportion=0, flag=wx.EXPAND)

        listSizer = wx.StaticBoxSizer(self.listBox, wx.VERTICAL)
        listSizer.Add(self.itemList,
                      proportion=1,
                      flag=wx.EXPAND | wx.ALL,
                      border=3)

        btnSizer = wx.StdDialogButtonSizer()
        btnSizer.AddButton(self.btnCancel)
        btnSizer.AddButton(self.btnOk)
        btnSizer.Realize()

        sizer.Add(condSizer, proportion=0, flag=wx.EXPAND | wx.ALL, border=3)
        sizer.Add(listSizer,
                  proportion=1,
                  flag=wx.EXPAND | wx.LEFT | wx.RIGHT,
                  border=3)
        sizer.Add(btnSizer,
                  proportion=0,
                  flag=wx.EXPAND | wx.ALL | wx.ALIGN_CENTER,
                  border=5)

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

        self.Layout()

    def GetItems(self):
        """Get list of selected actions"""
        return self.itemList.GetItems()

    def OnSeries(self, event):
        """Define map series as condition"""
        dialog = MapLayersDialogForModeler(parent=self,
                                           title=_("Define series of maps"))
        if dialog.ShowModal() != wx.ID_OK:
            dialog.Destroy()
            return

        cond = dialog.GetDSeries()
        if not cond:
            cond = "map in {}".format(list(map(str, dialog.GetMapLayers())))

        self.condText.SetValue(cond)

        dialog.Destroy()
Example #16
0
class GRASSStartup(wx.Frame):
    exit_success = 0
    # 2 is file not found from python interpreter
    exit_user_requested = 5

    """GRASS start-up screen"""

    def __init__(self, parent=None, id=wx.ID_ANY,
                 style=wx.DEFAULT_FRAME_STYLE):

        #
        # GRASS variables
        #
        self.gisbase = os.getenv("GISBASE")
        self.grassrc = self._readGisRC()
        self.gisdbase = self.GetRCValue("GISDBASE")

        #
        # list of locations/mapsets
        #
        self.listOfLocations = []
        self.listOfMapsets = []
        self.listOfMapsetsSelectable = []

        wx.Frame.__init__(self, parent=parent, id=id, style=style)

        self.locale = wx.Locale(language=wx.LANGUAGE_DEFAULT)

        # scroll panel was used here but not properly and is probably not need
        # as long as it is not high too much
        self.panel = wx.Panel(parent=self, id=wx.ID_ANY)

        # i18N

        #
        # graphical elements
        #
        # image
        try:
            if os.getenv('ISISROOT'):
                name = os.path.join(
                    globalvar.GUIDIR,
                    "images",
                    "startup_banner_isis.png")
            else:
                name = os.path.join(
                    globalvar.GUIDIR, "images", "startup_banner.png")
            self.hbitmap = wx.StaticBitmap(self.panel, wx.ID_ANY,
                                           wx.Bitmap(name=name,
                                                     type=wx.BITMAP_TYPE_PNG))
        except:
            self.hbitmap = wx.StaticBitmap(
                self.panel, wx.ID_ANY, wx.BitmapFromImage(
                    wx.EmptyImage(530, 150)))

        # labels
        # crashes when LOCATION doesn't exist
        # get version & revision
        versionFile = open(os.path.join(globalvar.ETCDIR, "VERSIONNUMBER"))
        versionLine = versionFile.readline().rstrip('\n')
        versionFile.close()
        try:
            grassVersion, grassRevision = versionLine.split(' ', 1)
            if grassVersion.endswith('svn'):
                grassRevisionStr = ' (%s)' % grassRevision
            else:
                grassRevisionStr = ''
        except ValueError:
            grassVersion = versionLine
            grassRevisionStr = ''

        self.gisdbase_box = StaticBox(
            parent=self.panel, id=wx.ID_ANY, label=" %s " %
            _("1. Select GRASS GIS database directory"))
        self.location_box = StaticBox(
            parent=self.panel, id=wx.ID_ANY, label=" %s " %
            _("2. Select GRASS Location"))
        self.mapset_box = StaticBox(
            parent=self.panel, id=wx.ID_ANY, label=" %s " %
            _("3. Select GRASS Mapset"))

        self.lmessage = StaticText(parent=self.panel)
        # It is not clear if all wx versions supports color, so try-except.
        # The color itself may not be correct for all platforms/system settings
        # but in http://xoomer.virgilio.it/infinity77/wxPython/Widgets/wx.SystemSettings.html
        # there is no 'warning' color.
        try:
            self.lmessage.SetForegroundColour(wx.Colour(255, 0, 0))
        except AttributeError:
            pass

        self.gisdbase_panel = wx.Panel(parent=self.panel)
        self.location_panel = wx.Panel(parent=self.panel)
        self.mapset_panel = wx.Panel(parent=self.panel)

        self.ldbase = StaticText(
            parent=self.gisdbase_panel, id=wx.ID_ANY,
            label=_("GRASS GIS database directory contains Locations."))

        self.llocation = StaticWrapText(
            parent=self.location_panel, id=wx.ID_ANY,
            label=_("All data in one Location is in the same "
                    " coordinate reference system (projection)."
                    " One Location can be one project."
                    " Location contains Mapsets."),
            style=wx.ALIGN_LEFT)

        self.lmapset = StaticWrapText(
            parent=self.mapset_panel, id=wx.ID_ANY,
            label=_("Mapset contains GIS data related"
                    " to one project, task within one project,"
                    " subregion or user."),
            style=wx.ALIGN_LEFT)

        try:
            for label in [self.ldbase, self.llocation, self.lmapset]:
                label.SetForegroundColour(
                    wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT))
        except AttributeError:
            # for explanation of try-except see above
            pass

        # buttons
        self.bstart = Button(parent=self.panel, id=wx.ID_ANY,
                             label=_("Start &GRASS session"))
        self.bstart.SetDefault()
        self.bexit = Button(parent=self.panel, id=wx.ID_EXIT)
        self.bstart.SetMinSize((180, self.bexit.GetSize()[1]))
        self.bhelp = Button(parent=self.panel, id=wx.ID_HELP)
        self.bbrowse = Button(parent=self.gisdbase_panel, id=wx.ID_ANY,
                              label=_("&Browse"))
        self.bmapset = Button(parent=self.mapset_panel, id=wx.ID_ANY,
                              # GTC New mapset
                              label=_("&New"))
        self.bmapset.SetToolTip(_("Create a new Mapset in selected Location"))
        self.bwizard = Button(parent=self.location_panel, id=wx.ID_ANY,
                              # GTC New location
                              label=_("N&ew"))
        self.bwizard.SetToolTip(
            _(
                "Create a new location using location wizard."
                " After location is created successfully,"
                " GRASS session is started."))
        self.rename_location_button = Button(parent=self.location_panel, id=wx.ID_ANY,
                                             # GTC Rename location
                                             label=_("Ren&ame"))
        self.rename_location_button.SetToolTip(_("Rename selected location"))
        self.delete_location_button = Button(parent=self.location_panel, id=wx.ID_ANY,
                                             # GTC Delete location
                                             label=_("De&lete"))
        self.delete_location_button.SetToolTip(_("Delete selected location"))
        self.rename_mapset_button = Button(parent=self.mapset_panel, id=wx.ID_ANY,
                                           # GTC Rename mapset
                                           label=_("&Rename"))
        self.rename_mapset_button.SetToolTip(_("Rename selected mapset"))
        self.delete_mapset_button = Button(parent=self.mapset_panel, id=wx.ID_ANY,
                                           # GTC Delete mapset
                                           label=_("&Delete"))
        self.delete_mapset_button.SetToolTip(_("Delete selected mapset"))

        # textinputs
        self.tgisdbase = TextCtrl(
            parent=self.gisdbase_panel, id=wx.ID_ANY, value="", size=(
                300, -1), style=wx.TE_PROCESS_ENTER)

        # Locations
        self.lblocations = GListBox(parent=self.location_panel,
                                    id=wx.ID_ANY, size=(180, 200),
                                    choices=self.listOfLocations)
        self.lblocations.SetColumnWidth(0, 180)

        # TODO: sort; but keep PERMANENT on top of list
        # Mapsets
        self.lbmapsets = GListBox(parent=self.mapset_panel,
                                  id=wx.ID_ANY, size=(180, 200),
                                  choices=self.listOfMapsets)
        self.lbmapsets.SetColumnWidth(0, 180)

        # layout & properties, first do layout so everything is created
        self._do_layout()
        self._set_properties(grassVersion, grassRevisionStr)

        # events
        self.bbrowse.Bind(wx.EVT_BUTTON, self.OnBrowse)
        self.bstart.Bind(wx.EVT_BUTTON, self.OnStart)
        self.bexit.Bind(wx.EVT_BUTTON, self.OnExit)
        self.bhelp.Bind(wx.EVT_BUTTON, self.OnHelp)
        self.bmapset.Bind(wx.EVT_BUTTON, self.OnCreateMapset)
        self.bwizard.Bind(wx.EVT_BUTTON, self.OnWizard)

        self.rename_location_button.Bind(wx.EVT_BUTTON, self.RenameLocation)
        self.delete_location_button.Bind(wx.EVT_BUTTON, self.DeleteLocation)
        self.rename_mapset_button.Bind(wx.EVT_BUTTON, self.RenameMapset)
        self.delete_mapset_button.Bind(wx.EVT_BUTTON, self.DeleteMapset)

        self.lblocations.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnSelectLocation)
        self.lbmapsets.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnSelectMapset)
        self.lbmapsets.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnStart)
        self.tgisdbase.Bind(wx.EVT_TEXT_ENTER, self.OnSetDatabase)
        self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)

    def _set_properties(self, version, revision):
        """Set frame properties"""
        self.SetTitle(_("GRASS GIS %s startup%s") % (version, revision))
        self.SetIcon(wx.Icon(os.path.join(globalvar.ICONDIR, "grass.ico"),
                             wx.BITMAP_TYPE_ICO))

        self.bstart.SetForegroundColour(wx.Colour(35, 142, 35))
        self.bstart.SetToolTip(_("Enter GRASS session"))
        self.bstart.Enable(False)
        self.bmapset.Enable(False)
        # this all was originally a choice, perhaps just mapset needed
        self.rename_location_button.Enable(False)
        self.delete_location_button.Enable(False)
        self.rename_mapset_button.Enable(False)
        self.delete_mapset_button.Enable(False)

        # set database
        if not self.gisdbase:
            # sets an initial path for gisdbase if nothing in GISRC
            if os.path.isdir(os.getenv("HOME")):
                self.gisdbase = os.getenv("HOME")
            else:
                self.gisdbase = os.getcwd()
        try:
            self.tgisdbase.SetValue(self.gisdbase)
        except UnicodeDecodeError:
            wx.MessageBox(parent=self, caption=_("Error"),
                          message=_("Unable to set GRASS database. "
                                    "Check your locale settings."),
                          style=wx.OK | wx.ICON_ERROR | wx.CENTRE)

        self.OnSetDatabase(None)
        location = self.GetRCValue("LOCATION_NAME")
        if location == "<UNKNOWN>":
            return
        if not os.path.isdir(os.path.join(self.gisdbase, location)):
            location = None

        # list of locations
        self.UpdateLocations(self.gisdbase)
        try:
            self.lblocations.SetSelection(self.listOfLocations.index(location),
                                          force=True)
            self.lblocations.EnsureVisible(
                self.listOfLocations.index(location))
        except ValueError:
            sys.stderr.write(
                _("ERROR: Location <%s> not found\n") %
                self.GetRCValue("LOCATION_NAME"))
            if len(self.listOfLocations) > 0:
                self.lblocations.SetSelection(0, force=True)
                self.lblocations.EnsureVisible(0)
                location = self.listOfLocations[0]
            else:
                return

        # list of mapsets
        self.UpdateMapsets(os.path.join(self.gisdbase, location))
        mapset = self.GetRCValue("MAPSET")
        if mapset:
            try:
                self.lbmapsets.SetSelection(self.listOfMapsets.index(mapset),
                                            force=True)
                self.lbmapsets.EnsureVisible(self.listOfMapsets.index(mapset))
            except ValueError:
                sys.stderr.write(_("ERROR: Mapset <%s> not found\n") % mapset)
                self.lbmapsets.SetSelection(0, force=True)
                self.lbmapsets.EnsureVisible(0)

    def _do_layout(self):
        sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer = sizer  # for the layout call after changing message
        dbase_sizer = wx.BoxSizer(wx.HORIZONTAL)

        location_mapset_sizer = wx.BoxSizer(wx.HORIZONTAL)

        gisdbase_panel_sizer = wx.BoxSizer(wx.VERTICAL)
        gisdbase_boxsizer = wx.StaticBoxSizer(self.gisdbase_box, wx.VERTICAL)

        btns_sizer = wx.BoxSizer(wx.HORIZONTAL)

        self.gisdbase_panel.SetSizer(gisdbase_panel_sizer)

        # gis data directory

        gisdbase_boxsizer.Add(self.gisdbase_panel, proportion=1,
                              flag=wx.EXPAND | wx.ALL,
                              border=1)

        gisdbase_panel_sizer.Add(dbase_sizer, proportion=1,
                                 flag=wx.EXPAND | wx.ALL,
                                 border=1)
        gisdbase_panel_sizer.Add(self.ldbase, proportion=0,
                                 flag=wx.EXPAND | wx.ALL,
                                 border=1)

        dbase_sizer.Add(self.tgisdbase, proportion=1,
                        flag=wx.ALIGN_CENTER_VERTICAL | wx.ALL,
                        border=1)
        dbase_sizer.Add(self.bbrowse, proportion=0,
                        flag=wx.ALIGN_CENTER_VERTICAL | wx.ALL,
                        border=1)

        gisdbase_panel_sizer.Fit(self.gisdbase_panel)

        # location and mapset lists

        def layout_list_box(box, panel, list_box, buttons, description):
            panel_sizer = wx.BoxSizer(wx.VERTICAL)
            main_sizer = wx.BoxSizer(wx.HORIZONTAL)
            box_sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
            buttons_sizer = wx.BoxSizer(wx.VERTICAL)

            panel.SetSizer(panel_sizer)
            panel_sizer.Fit(panel)

            main_sizer.Add(list_box, proportion=1,
                           flag=wx.EXPAND | wx.ALL,
                           border=1)
            main_sizer.Add(buttons_sizer, proportion=0,
                           flag=wx.ALIGN_CENTER_HORIZONTAL | wx.ALL,
                           border=1)
            for button in buttons:
                buttons_sizer.Add(button, proportion=0,
                                  flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
                                  border=3)
            box_sizer.Add(panel, proportion=1,
                          flag=wx.EXPAND | wx.ALL,
                          border=1)
            panel_sizer.Add(main_sizer, proportion=1,
                            flag=wx.EXPAND | wx.ALL,
                            border=1)
            panel_sizer.Add(description, proportion=0,
                            flag=wx.EXPAND | wx.ALL,
                            border=1)
            return box_sizer

        location_boxsizer = layout_list_box(
            box=self.location_box,
            panel=self.location_panel,
            list_box=self.lblocations,
            buttons=[self.bwizard, self.rename_location_button,
                     self.delete_location_button],
            description=self.llocation)
        mapset_boxsizer = layout_list_box(
            box=self.mapset_box,
            panel=self.mapset_panel,
            list_box=self.lbmapsets,
            buttons=[self.bmapset, self.rename_mapset_button,
                     self.delete_mapset_button],
            description=self.lmapset)

        # location and mapset sizer
        location_mapset_sizer.Add(location_boxsizer, proportion=1,
                                  flag=wx.LEFT | wx.RIGHT | wx.EXPAND,
                                  border=3)
        location_mapset_sizer.Add(mapset_boxsizer, proportion=1,
                                  flag=wx.RIGHT | wx.EXPAND,
                                  border=3)

        # buttons
        btns_sizer.Add(self.bstart, proportion=0,
                       flag=wx.ALIGN_CENTER_HORIZONTAL |
                       wx.ALIGN_CENTER_VERTICAL |
                       wx.ALL,
                       border=5)
        btns_sizer.Add(self.bexit, proportion=0,
                       flag=wx.ALIGN_CENTER_HORIZONTAL |
                       wx.ALIGN_CENTER_VERTICAL |
                       wx.ALL,
                       border=5)
        btns_sizer.Add(self.bhelp, proportion=0,
                       flag=wx.ALIGN_CENTER_HORIZONTAL |
                       wx.ALIGN_CENTER_VERTICAL |
                       wx.ALL,
                       border=5)

        # main sizer
        sizer.Add(self.hbitmap,
                  proportion=0,
                  flag=wx.ALIGN_CENTER_VERTICAL |
                  wx.ALIGN_CENTER_HORIZONTAL |
                  wx.ALL,
                  border=3)  # image
        sizer.Add(gisdbase_boxsizer, proportion=0,
                  flag=wx.ALIGN_CENTER_HORIZONTAL |
                  wx.RIGHT | wx.LEFT | wx.TOP | wx.EXPAND,
                  border=3)  # GISDBASE setting

        # warning/error message
        sizer.Add(self.lmessage,
                  proportion=0,
                  flag=wx.ALIGN_CENTER_VERTICAL |
                  wx.ALIGN_LEFT | wx.ALL | wx.EXPAND, border=5)
        sizer.Add(location_mapset_sizer, proportion=1,
                  flag=wx.RIGHT | wx.LEFT | wx.EXPAND,
                  border=1)
        sizer.Add(btns_sizer, proportion=0,
                  flag=wx.ALIGN_CENTER_VERTICAL |
                  wx.ALIGN_CENTER_HORIZONTAL |
                  wx.RIGHT | wx.LEFT,
                  border=3)

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

    def _readGisRC(self):
        """Read variables from $HOME/.grass7/rc file
        """
        grassrc = {}

        gisrc = os.getenv("GISRC")

        if gisrc and os.path.isfile(gisrc):
            try:
                rc = open(gisrc, "r")
                for line in rc.readlines():
                    try:
                        key, val = line.split(":", 1)
                    except ValueError as e:
                        sys.stderr.write(
                            _('Invalid line in GISRC file (%s):%s\n' % (e, line)))
                    grassrc[key.strip()] = DecodeString(val.strip())
            finally:
                rc.close()

        return grassrc

    def _showWarning(self, text):
        """Displays a warning, hint or info message to the user.

        This function can be used for all kinds of messages except for
        error messages.

        .. note::
            There is no cleaning procedure. You should call _hideMessage when
            you know that there is everything correct now.
        """
        self.lmessage.SetLabel(text)
        self.lmessage.Wrap(self.GetClientSize()[0])
        self.sizer.Layout()

    def _showError(self, text):
        """Displays a error message to the user.

        This function should be used only when something serious and unexpected
        happens, otherwise _showWarning should be used.

        .. note::
            There is no cleaning procedure. You should call _hideMessage when
            you know that there is everything correct now.
        """
        self.lmessage.SetLabel(_("Error: {text}").format(text=text))
        self.lmessage.Wrap(self.GetClientSize()[0])
        self.sizer.Layout()

    def _hideMessage(self):
        """Clears/hides the error message."""
        # we do no hide widget
        # because we do not want the dialog to change the size
        self.lmessage.SetLabel("")
        self.sizer.Layout()

    def GetRCValue(self, value):
        """Return GRASS variable (read from GISRC)
        """
        if value in self.grassrc:
            return self.grassrc[value]
        else:
            return None

    def OnWizard(self, event):
        """Location wizard started"""
        from location_wizard.wizard import LocationWizard
        gWizard = LocationWizard(parent=self,
                                 grassdatabase=self.tgisdbase.GetValue())
        if gWizard.location is not None:
            self.tgisdbase.SetValue(gWizard.grassdatabase)
            self.OnSetDatabase(None)
            self.UpdateMapsets(os.path.join(self.gisdbase, gWizard.location))
            self.lblocations.SetSelection(
                self.listOfLocations.index(
                    gWizard.location))
            self.lbmapsets.SetSelection(0)
            self.SetLocation(self.gisdbase, gWizard.location, 'PERMANENT')
            if gWizard.georeffile:
                message = _("Do you want to import <%(name)s> to the newly created location?") % {
                    'name': gWizard.georeffile}
                dlg = wx.MessageDialog(parent=self, message=message, caption=_(
                    "Import data?"), style=wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION)
                dlg.CenterOnParent()
                if dlg.ShowModal() == wx.ID_YES:
                    self.ImportFile(gWizard.georeffile)
                dlg.Destroy()
            if gWizard.default_region:
                defineRegion = RegionDef(self, location=gWizard.location)
                defineRegion.CenterOnParent()
                defineRegion.ShowModal()
                defineRegion.Destroy()

            if gWizard.user_mapset:
                dlg = TextEntryDialog(
                    parent=self,
                    message=_("New mapset:"),
                    caption=_("Create new mapset"),
                    defaultValue=self._getDefaultMapsetName(),
                    validator=GenericValidator(
                        grass.legal_name,
                        self._nameValidationFailed
                    ),
                    style=wx.OK | wx.CANCEL | wx.HELP
                )
                help = dlg.FindWindowById(wx.ID_HELP)
                help.Bind(wx.EVT_BUTTON, self.OnHelp)
                if dlg.ShowModal() == wx.ID_OK:
                    mapsetName = dlg.GetValue()
                    self.CreateNewMapset(mapsetName)

    def ImportFile(self, filePath):
        """Tries to import file as vector or raster.

        If successfull sets default region from imported map.
        """
        RunCommand('db.connect', flags='c')
        mapName = os.path.splitext(os.path.basename(filePath))[0]
        vectors = RunCommand('v.in.ogr', input=filePath, flags='l',
                             read=True)

        wx.BeginBusyCursor()
        wx.Yield()
        if mapName in vectors:
            # vector detected
            returncode, error = RunCommand(
                'v.in.ogr', input=filePath, output=mapName, flags='e',
                getErrorMsg=True)
        else:
            returncode, error = RunCommand(
                'r.in.gdal', input=filePath, output=mapName, flags='e',
                getErrorMsg=True)
        wx.EndBusyCursor()

        if returncode != 0:
            GError(
                parent=self,
                message=_(
                    "Import of <%(name)s> failed.\n"
                    "Reason: %(msg)s") % ({
                        'name': filePath,
                        'msg': error}))
        else:
            GMessage(
                message=_(
                    "Data file <%(name)s> imported successfully. "
                    "The location's default region was set from this imported map.") % {
                    'name': filePath},
                parent=self)

    # the event can be refactored out by using lambda in bind
    def RenameMapset(self, event):
        """Rename selected mapset
        """
        location = self.listOfLocations[self.lblocations.GetSelection()]
        mapset = self.listOfMapsets[self.lbmapsets.GetSelection()]
        if mapset == 'PERMANENT':
            GMessage(
                parent=self, message=_(
                    'Mapset <PERMANENT> is required for valid GRASS location.\n\n'
                    'This mapset cannot be renamed.'))
            return

        dlg = TextEntryDialog(
            parent=self,
            message=_('Current name: %s\n\nEnter new name:') %
            mapset,
            caption=_('Rename selected mapset'),
            validator=GenericValidator(
                grass.legal_name,
                self._nameValidationFailed))

        if dlg.ShowModal() == wx.ID_OK:
            newmapset = dlg.GetValue()
            if newmapset == mapset:
                dlg.Destroy()
                return

            if newmapset in self.listOfMapsets:
                wx.MessageBox(
                    parent=self, caption=_('Message'), message=_(
                        'Unable to rename mapset.\n\n'
                        'Mapset <%s> already exists in location.') %
                    newmapset, style=wx.OK | wx.ICON_INFORMATION | wx.CENTRE)
            else:
                try:
                    os.rename(os.path.join(self.gisdbase, location, mapset),
                              os.path.join(self.gisdbase, location, newmapset))
                    self.OnSelectLocation(None)
                    self.lbmapsets.SetSelection(
                        self.listOfMapsets.index(newmapset))
                except Exception as e:
                    wx.MessageBox(
                        parent=self,
                        caption=_('Error'),
                        message=_('Unable to rename mapset.\n\n%s') %
                        e,
                        style=wx.OK | wx.ICON_ERROR | wx.CENTRE)

        dlg.Destroy()

    def RenameLocation(self, event):
        """Rename selected location
        """
        location = self.listOfLocations[self.lblocations.GetSelection()]

        dlg = TextEntryDialog(
            parent=self,
            message=_('Current name: %s\n\nEnter new name:') %
            location,
            caption=_('Rename selected location'),
            validator=GenericValidator(
                grass.legal_name,
                self._nameValidationFailed))

        if dlg.ShowModal() == wx.ID_OK:
            newlocation = dlg.GetValue()
            if newlocation == location:
                dlg.Destroy()
                return

            if newlocation in self.listOfLocations:
                wx.MessageBox(
                    parent=self, caption=_('Message'), message=_(
                        'Unable to rename location.\n\n'
                        'Location <%s> already exists in GRASS database.') %
                    newlocation, style=wx.OK | wx.ICON_INFORMATION | wx.CENTRE)
            else:
                try:
                    os.rename(os.path.join(self.gisdbase, location),
                              os.path.join(self.gisdbase, newlocation))
                    self.UpdateLocations(self.gisdbase)
                    self.lblocations.SetSelection(
                        self.listOfLocations.index(newlocation))
                    self.UpdateMapsets(newlocation)
                except Exception as e:
                    wx.MessageBox(
                        parent=self,
                        caption=_('Error'),
                        message=_('Unable to rename location.\n\n%s') %
                        e,
                        style=wx.OK | wx.ICON_ERROR | wx.CENTRE)

        dlg.Destroy()

    def DeleteMapset(self, event):
        """Delete selected mapset
        """
        location = self.listOfLocations[self.lblocations.GetSelection()]
        mapset = self.listOfMapsets[self.lbmapsets.GetSelection()]
        if mapset == 'PERMANENT':
            GMessage(
                parent=self, message=_(
                    'Mapset <PERMANENT> is required for valid GRASS location.\n\n'
                    'This mapset cannot be deleted.'))
            return

        dlg = wx.MessageDialog(
            parent=self,
            message=_(
                "Do you want to continue with deleting mapset <%(mapset)s> "
                "from location <%(location)s>?\n\n"
                "ALL MAPS included in this mapset will be "
                "PERMANENTLY DELETED!") %
            {'mapset': mapset, 'location': location},
            caption=_("Delete selected mapset"),
            style=wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)

        if dlg.ShowModal() == wx.ID_YES:
            try:
                shutil.rmtree(os.path.join(self.gisdbase, location, mapset))
                self.OnSelectLocation(None)
                self.lbmapsets.SetSelection(0)
            except:
                wx.MessageBox(message=_('Unable to delete mapset'))

        dlg.Destroy()

    def DeleteLocation(self, event):
        """
        Delete selected location
        """

        location = self.listOfLocations[self.lblocations.GetSelection()]

        dlg = wx.MessageDialog(
            parent=self,
            message=_(
                "Do you want to continue with deleting "
                "location <%s>?\n\n"
                "ALL MAPS included in this location will be "
                "PERMANENTLY DELETED!") %
            (location),
            caption=_("Delete selected location"),
            style=wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)

        if dlg.ShowModal() == wx.ID_YES:
            try:
                shutil.rmtree(os.path.join(self.gisdbase, location))
                self.UpdateLocations(self.gisdbase)
                self.lblocations.SetSelection(0)
                self.OnSelectLocation(None)
                self.lbmapsets.SetSelection(0)
            except:
                wx.MessageBox(message=_('Unable to delete location'))

        dlg.Destroy()

    def UpdateLocations(self, dbase):
        """Update list of locations"""
        try:
            self.listOfLocations = GetListOfLocations(dbase)
        except (UnicodeEncodeError, UnicodeDecodeError) as e:
            GError(parent=self,
                   message=_("Unicode error detected. "
                             "Check your locale settings. Details: {0}").format(e),
                   showTraceback=False)

        self.lblocations.Clear()
        self.lblocations.InsertItems(self.listOfLocations, 0)

        if len(self.listOfLocations) > 0:
            self._hideMessage()
            self.lblocations.SetSelection(0)
        else:
            self.lblocations.SetSelection(wx.NOT_FOUND)
            self._showWarning(_("No GRASS Location found in '%s'."
                                " Create a new Location or choose different"
                                " GRASS database directory.")
                              % self.gisdbase)

        return self.listOfLocations

    def UpdateMapsets(self, location):
        """Update list of mapsets"""
        self.FormerMapsetSelection = wx.NOT_FOUND  # for non-selectable item

        self.listOfMapsetsSelectable = list()
        self.listOfMapsets = GetListOfMapsets(self.gisdbase, location)

        self.lbmapsets.Clear()

        # disable mapset with denied permission
        locationName = os.path.basename(location)

        ret = RunCommand('g.mapset',
                         read=True,
                         flags='l',
                         location=locationName,
                         gisdbase=self.gisdbase)

        if ret:
            for line in ret.splitlines():
                self.listOfMapsetsSelectable += line.split(' ')
        else:
            RunCommand("g.gisenv",
                       set="GISDBASE=%s" % self.gisdbase)
            RunCommand("g.gisenv",
                       set="LOCATION_NAME=%s" % locationName)
            RunCommand("g.gisenv",
                       set="MAPSET=PERMANENT")
            # first run only
            self.listOfMapsetsSelectable = copy.copy(self.listOfMapsets)

        disabled = []
        idx = 0
        for mapset in self.listOfMapsets:
            if mapset not in self.listOfMapsetsSelectable or \
                    os.path.isfile(os.path.join(self.gisdbase,
                                                locationName,
                                                mapset, ".gislock")):
                disabled.append(idx)
            idx += 1

        self.lbmapsets.InsertItems(self.listOfMapsets, 0, disabled=disabled)

        return self.listOfMapsets

    def OnSelectLocation(self, event):
        """Location selected"""
        if event:
            self.lblocations.SetSelection(event.GetIndex())

        if self.lblocations.GetSelection() != wx.NOT_FOUND:
            self.UpdateMapsets(
                os.path.join(
                    self.gisdbase,
                    self.listOfLocations[
                        self.lblocations.GetSelection()]))
        else:
            self.listOfMapsets = []

        disabled = []
        idx = 0
        try:
            locationName = self.listOfLocations[
                self.lblocations.GetSelection()]
        except IndexError:
            locationName = ''

        for mapset in self.listOfMapsets:
            if mapset not in self.listOfMapsetsSelectable or \
                    os.path.isfile(os.path.join(self.gisdbase,
                                                locationName,
                                                mapset, ".gislock")):
                disabled.append(idx)
            idx += 1

        self.lbmapsets.Clear()
        self.lbmapsets.InsertItems(self.listOfMapsets, 0, disabled=disabled)

        if len(self.listOfMapsets) > 0:
            self.lbmapsets.SetSelection(0)
            if locationName:
                # enable start button when location and mapset is selected
                self.bstart.Enable()
                self.bstart.SetFocus()
                self.bmapset.Enable()
                # replacing disabled choice, perhaps just mapset needed
                self.rename_location_button.Enable()
                self.delete_location_button.Enable()
                self.rename_mapset_button.Enable()
                self.delete_mapset_button.Enable()
        else:
            self.lbmapsets.SetSelection(wx.NOT_FOUND)
            self.bstart.Enable(False)
            self.bmapset.Enable(False)
            # this all was originally a choice, perhaps just mapset needed
            self.rename_location_button.Enable(False)
            self.delete_location_button.Enable(False)
            self.rename_mapset_button.Enable(False)
            self.delete_mapset_button.Enable(False)

    def OnSelectMapset(self, event):
        """Mapset selected"""
        self.lbmapsets.SetSelection(event.GetIndex())

        if event.GetText() not in self.listOfMapsetsSelectable:
            self.lbmapsets.SetSelection(self.FormerMapsetSelection)
        else:
            self.FormerMapsetSelection = event.GetIndex()
            event.Skip()

    def OnSetDatabase(self, event):
        """Database set"""
        gisdbase = self.tgisdbase.GetValue()
        self._hideMessage()
        if not os.path.exists(gisdbase):
            self._showError(_("Path '%s' doesn't exist.") % gisdbase)
            return

        self.gisdbase = self.tgisdbase.GetValue()
        self.UpdateLocations(self.gisdbase)

        self.OnSelectLocation(None)

    def OnBrowse(self, event):
        """'Browse' button clicked"""
        if not event:
            defaultPath = os.getenv('HOME')
        else:
            defaultPath = ""

        dlg = wx.DirDialog(parent=self, message=_("Choose GIS Data Directory"),
                           defaultPath=defaultPath, style=wx.DD_DEFAULT_STYLE)

        if dlg.ShowModal() == wx.ID_OK:
            self.gisdbase = dlg.GetPath()
            self.tgisdbase.SetValue(self.gisdbase)
            self.OnSetDatabase(event)

        dlg.Destroy()

    def OnCreateMapset(self, event):
        """Create new mapset"""
        dlg = TextEntryDialog(
            parent=self,
            message=_('Enter name for new mapset:'),
            caption=_('Create new mapset'),
            defaultValue=self._getDefaultMapsetName(),
            validator=GenericValidator(
                grass.legal_name,
                self._nameValidationFailed))
        if dlg.ShowModal() == wx.ID_OK:
            mapset = dlg.GetValue()
            return self.CreateNewMapset(mapset=mapset)
        else:
            return False

    def CreateNewMapset(self, mapset):
        if mapset in self.listOfMapsets:
            GMessage(parent=self,
                     message=_("Mapset <%s> already exists.") % mapset)
            return False

        if mapset.lower() == 'ogr':
            dlg1 = wx.MessageDialog(
                parent=self,
                message=_(
                    "Mapset <%s> is reserved for direct "
                    "read access to OGR layers. Please consider to use "
                    "another name for your mapset.\n\n"
                    "Are you really sure that you want to create this mapset?") %
                mapset,
                caption=_("Reserved mapset name"),
                style=wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
            ret = dlg1.ShowModal()
            dlg1.Destroy()
            if ret == wx.ID_NO:
                dlg1.Destroy()
                return False

        try:
            self.gisdbase = self.tgisdbase.GetValue()
            location = self.listOfLocations[self.lblocations.GetSelection()]
            os.mkdir(os.path.join(self.gisdbase, location, mapset))
            # copy WIND file and its permissions from PERMANENT and set
            # permissions to u+rw,go+r
            shutil.copy(
                os.path.join(
                    self.gisdbase,
                    location,
                    'PERMANENT',
                    'WIND'),
                os.path.join(
                    self.gisdbase,
                    location,
                    mapset))
            # os.chmod(os.path.join(database,location,mapset,'WIND'), 0644)
            self.OnSelectLocation(None)
            self.lbmapsets.SetSelection(self.listOfMapsets.index(mapset))
            self.bstart.SetFocus()

            return True
        except Exception as e:
            GError(parent=self,
                   message=_("Unable to create new mapset: %s") % e,
                   showTraceback=False)
            return False

    def OnStart(self, event):
        """'Start GRASS' button clicked"""
        dbase = self.tgisdbase.GetValue()
        location = self.listOfLocations[self.lblocations.GetSelection()]
        mapset = self.listOfMapsets[self.lbmapsets.GetSelection()]

        lockfile = os.path.join(dbase, location, mapset, '.gislock')
        if os.path.isfile(lockfile):
            dlg = wx.MessageDialog(
                parent=self,
                message=_(
                    "GRASS is already running in selected mapset <%(mapset)s>\n"
                    "(file %(lock)s found).\n\n"
                    "Concurrent use not allowed.\n\n"
                    "Do you want to try to remove .gislock (note that you "
                    "need permission for this operation) and continue?") %
                {'mapset': mapset, 'lock': lockfile},
                caption=_("Lock file found"),
                style=wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION | wx.CENTRE)

            ret = dlg.ShowModal()
            dlg.Destroy()
            if ret == wx.ID_YES:
                dlg1 = wx.MessageDialog(
                    parent=self,
                    message=_(
                        "ARE YOU REALLY SURE?\n\n"
                        "If you really are running another GRASS session doing this "
                        "could corrupt your data. Have another look in the processor "
                        "manager just to be sure..."),
                    caption=_("Lock file found"),
                    style=wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION | wx.CENTRE)

                ret = dlg1.ShowModal()
                dlg1.Destroy()

                if ret == wx.ID_YES:
                    try:
                        os.remove(lockfile)
                    except IOError as e:
                        GError(_("Unable to remove '%(lock)s'.\n\n"
                                 "Details: %(reason)s") % {'lock': lockfile, 'reason': e})
                else:
                    return
            else:
                return
        self.SetLocation(dbase, location, mapset)
        self.ExitSuccessfully()

    def SetLocation(self, dbase, location, mapset):
        RunCommand("g.gisenv",
                   set="GISDBASE=%s" % dbase)
        RunCommand("g.gisenv",
                   set="LOCATION_NAME=%s" % location)
        RunCommand("g.gisenv",
                   set="MAPSET=%s" % mapset)

    def _getDefaultMapsetName(self):
        """Returns default name for mapset."""
        try:
            defaultName = getpass.getuser()
            # raise error if not ascii (not valid mapset name)
            defaultName.encode('ascii')
        except:  # whatever might go wrong
            defaultName = 'user'

        return defaultName

    def ExitSuccessfully(self):
        self.Destroy()
        sys.exit(self.exit_success)

    def OnExit(self, event):
        """'Exit' button clicked"""
        self.Destroy()
        sys.exit(self.exit_user_requested)

    def OnHelp(self, event):
        """'Help' button clicked"""

        # help text in lib/init/helptext.html
        RunCommand('g.manual', entry='helptext')

    def OnCloseWindow(self, event):
        """Close window event"""
        event.Skip()
        sys.exit(self.exit_user_requested)

    def _nameValidationFailed(self, ctrl):
        message = _(
            "Name <%(name)s> is not a valid name for location or mapset. "
            "Please use only ASCII characters excluding %(chars)s "
            "and space.") % {
            'name': ctrl.GetValue(),
            'chars': '/"\'@,=*~'}
        GError(parent=self, message=message, caption=_("Invalid name"))
Example #17
0
class SwipeMapDialog(wx.Dialog):
    """Dialog used to select maps.

    There are two modes - simple (only two raster maps),
    or two layer lists.
    """

    def __init__(self, parent, title=_("Select raster maps"),
                 first=None, second=None,
                 firstLayerList=None, secondLayerList=None):

        wx.Dialog.__init__(self, parent=parent, title=title,
                           style=wx.RESIZE_BORDER | wx.DEFAULT_DIALOG_STYLE)

        if firstLayerList is None:
            self._firstLayerList = LayerList()
        else:
            self._firstLayerList = copy.deepcopy(firstLayerList)
        if secondLayerList is None:
            self._secondLayerList = LayerList()
        else:
            self._secondLayerList = copy.deepcopy(secondLayerList)

        self._firstPanel = self._createSimplePanel()
        self._secondPanel = self._createAdvancedPanel()

        self.btnSwitch = Button(self)
        self.btnCancel = Button(self, id=wx.ID_CANCEL)
        self.btnApply = Button(self, id=wx.ID_APPLY)
        self.btnOK = Button(self, id=wx.ID_OK)
        self.btnOK.SetDefault()

        self.btnSwitch.Bind(wx.EVT_BUTTON, self.OnSwitchMode)
        self.btnApply.Bind(wx.EVT_BUTTON, lambda evt: self._apply())
        self.btnOK.Bind(wx.EVT_BUTTON, lambda evt: self._ok())
        self.btnCancel.Bind(wx.EVT_BUTTON, lambda evt: self.Close())
        self.Bind(wx.EVT_CLOSE, lambda evt: self.Hide())

        self.applyChanges = Signal('SwipeMapDialog.applyChanges')

        if first:
            self._firstRaster.SetValue(first)
        if second:
            self._secondRaster.SetValue(second)

        self._layout()

    def UnInit(self):
        self._firstLmgr.UnInit()
        self._secondLmgr.UnInit()

    def _layout(self):
        """Do layout"""
        mainSizer = wx.BoxSizer(wx.VERTICAL)
        self._switchSizer = wx.BoxSizer()
        self._switchSizer.Add(self._firstPanel, proportion=1,
                              flag=wx.EXPAND | wx.ALL, border=5)
        self._switchSizer.Add(self._secondPanel, proportion=1,
                              flag=wx.EXPAND | wx.ALL, border=5)
        mainSizer.Add(self._switchSizer, proportion=1,
                      flag=wx.EXPAND | wx.ALL)

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

        mainSizer.Add(self.btnSwitch, proportion=0,
                      flag=wx.ALL | wx.ALIGN_LEFT, border=5)
        mainSizer.Add(self.btnSizer, proportion=0,
                      flag=wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border=5)
        self.mainSizer = mainSizer
        self._switchMode(simple=True)
        self.SetSizer(mainSizer)
        mainSizer.Fit(self)

    def _createSimplePanel(self):
        panel = wx.Panel(self)
        sizer = wx.BoxSizer(wx.VERTICAL)

        self._firstRaster = gselect.Select(
            parent=panel,
            type='raster',
            size=globalvar.DIALOG_GSELECT_SIZE,
            validator=SimpleValidator(
                callback=self.ValidatorCallback))

        self._secondRaster = gselect.Select(
            parent=panel,
            type='raster',
            size=globalvar.DIALOG_GSELECT_SIZE,
            validator=SimpleValidator(
                callback=self.ValidatorCallback))
        sizer.Add(
            StaticText(
                panel,
                label=_("Name of top/left raster map:")),
            proportion=0,
            flag=wx.EXPAND | wx.ALL,
            border=5)
        sizer.Add(self._firstRaster, proportion=0,
                  flag=wx.EXPAND | wx.ALL, border=1)
        sizer.Add(
            StaticText(
                panel,
                label=_("Name of bottom/right raster map:")),
            proportion=0,
            flag=wx.EXPAND | wx.ALL,
            border=1)
        sizer.Add(self._secondRaster, proportion=0,
                  flag=wx.EXPAND | wx.ALL, border=1)

        self._firstRaster.SetFocus()

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

        return panel

    def _createAdvancedPanel(self):
        panel = wx.Panel(self)
        sizer = wx.BoxSizer(wx.HORIZONTAL)

        self._firstLmgr = SimpleLayerManager(
            parent=panel, layerList=self._firstLayerList,
            lmgrStyle=SIMPLE_LMGR_RASTER | SIMPLE_LMGR_RGB | SIMPLE_LMGR_VECTOR |
            SIMPLE_LMGR_TB_LEFT)
        self._secondLmgr = SimpleLayerManager(
            parent=panel, layerList=self._secondLayerList,
            lmgrStyle=SIMPLE_LMGR_RASTER | SIMPLE_LMGR_RGB | SIMPLE_LMGR_VECTOR |
            SIMPLE_LMGR_TB_RIGHT)
        sizer.Add(
            self._firstLmgr,
            proportion=1,
            flag=wx.EXPAND | wx.ALL,
            border=5)
        sizer.Add(
            self._secondLmgr,
            proportion=1,
            flag=wx.EXPAND | wx.ALL,
            border=5)
        panel.SetSizer(sizer)
        sizer.Fit(panel)

        return panel

    def _switchMode(self, simple):
        if simple:
            self._switchSizer.Show(self._firstPanel, show=True, recursive=True)
            self._switchSizer.Show(
                self._secondPanel, show=False, recursive=True)
            self.btnSwitch.SetLabel(_("Switch to advanced mode"))
            self.btnCancel.SetLabel(_("Cancel"))
        else:
            self._switchSizer.Show(
                self._firstPanel, show=False, recursive=True)
            self._switchSizer.Show(
                self._secondPanel, show=True, recursive=True)
            self.btnSwitch.SetLabel(_("Switch to simple mode"))
            self.btnCancel.SetLabel(_("Close"))

        self.Freeze()  # doesn't do anything (at least on Ubuntu)
        self.btnSizer.Show(self.btnApply, simple)
        self.btnSizer.Show(self.btnOK, simple)
        self.btnSizer.Layout()
        self._switchSizer.Layout()
        self.Fit()
        self.Thaw()

        self.applyChanges.emit()

    def OnSwitchMode(self, event):
        if self._switchSizer.IsShown(self._secondPanel):
            self._switchMode(simple=True)
        else:
            self._switchMode(simple=False)

    def ValidatorCallback(self, win):
        if self._switchSizer.IsShown(self._secondPanel):
            return

        if win == self._firstRaster.GetTextCtrl():
            GMessage(parent=self, message=_(
                "Name of the first map is missing."))
        else:
            GMessage(parent=self, message=_(
                "Name of the second map is missing."))

    def _ok(self):
        self._apply()
        self.Close()

    def _apply(self):
        # TODO check if not empty
        self.applyChanges.emit()

    def GetValues(self):
        """Get raster maps"""
        if self.IsSimpleMode():
            return (self._firstRaster.GetValue(),
                    self._secondRaster.GetValue())
        else:
            return (self._firstLayerList, self._secondLayerList)

    def IsSimpleMode(self):
        if self._switchSizer.IsShown(self._firstPanel):
            return True
        return False

    def GetFirstSimpleLmgr(self):
        return self._firstLmgr

    def GetSecondSimpleLmgr(self):
        return self._secondLmgr
Example #18
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 = Button(parent=self.panel, id=wx.ID_CLEAR)
        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.SetForegroundColour(wx.Colour(35, 142, 35))
        self.btn_run.SetDefault()
        self.btn_close = Button(parent=self.panel, id=wx.ID_CLOSE)
        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_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, 75),
                                   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.OnCopy)

        # self.mapselect.Bind(wx.EVT_TEXT, self.OnSelectTextEvt)
        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)

        self._layout()

        self.SetMinSize(self.GetBestSize())
        # workaround for http://trac.wxwidgets.org/ticket/13628
        self.SetSize(self.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.BOTTOM | wx.TOP,
                        border=5)
        outputSizer.Add(self.newmaptxt, flag=wx.EXPAND)

        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)
        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.TOP | wx.BOTTOM | wx.RIGHT,
                         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())

    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 OnCopy(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()
Example #19
0
class ImportDialog(wx.Dialog):
    """Dialog for bulk import of various data (base class)"""

    def __init__(self, parent, giface, itype,
                 id=wx.ID_ANY, title=_("Multiple import"),
                 style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER):
        self.parent = parent    # GMFrame
        self._giface = giface  # used to add layers
        self.importType = itype
        self.options = dict()   # list of options
        self.options_par = dict()

        self.commandId = -1  # id of running command

        wx.Dialog.__init__(self, parent, id, title, style=style,
                           name="MultiImportDialog")

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

        self.layerBox = StaticBox(parent=self.panel, id=wx.ID_ANY)
        if self.importType == 'gdal':
            label = _("List of raster layers")
        elif self.importType == 'ogr':
            label = _("List of vector layers")
        else:
            label = _("List of %s layers") % self.importType.upper()
        self.layerBox.SetLabel(" %s - %s " %
                               (label, _("right click to (un)select all")))

        # list of layers
        columns = [_('Layer id'),
                   _('Layer name'),
                   _('Name for output GRASS map (editable)')]
        if itype == 'ogr':
            columns.insert(2, _('Feature type'))
            columns.insert(3, _('Projection match'))
        elif itype == 'gdal':
            columns.insert(2, _('Projection match'))

        self.list = LayersList(parent=self.panel, columns=columns)
        self.list.LoadData()

        self.override = wx.CheckBox(
            parent=self.panel, id=wx.ID_ANY,
            label=_("Override projection check (use current location's projection)"))

        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.overwrite.Bind(wx.EVT_CHECKBOX, self.OnCheckOverwrite)
        if UserSettings.Get(group='cmd', key='overwrite',
                            subkey='enabled'):
            self.list.validate = False

        self.add = wx.CheckBox(parent=self.panel, id=wx.ID_ANY)
        self.closeOnFinish = wx.CheckBox(parent=self.panel, id=wx.ID_ANY,
                                         label=_("Close dialog on finish"))
        self.closeOnFinish.SetValue(
            UserSettings.Get(
                group='cmd',
                key='closeDlg',
                subkey='enabled'))

        #
        # buttons
        #
        # cancel
        self.btn_close = CloseButton(parent=self.panel)
        self.btn_close.SetToolTip(_("Close dialog"))
        self.btn_close.Bind(wx.EVT_BUTTON, self.OnClose)
        # run
        self.btn_run = Button(
            parent=self.panel, id=wx.ID_OK, label=_("&Import"))
        self.btn_run.SetToolTip(_("Import selected layers"))
        self.btn_run.SetDefault()
        self.btn_run.Bind(wx.EVT_BUTTON, self.OnRun)

        self.Bind(wx.EVT_CLOSE, lambda evt: self.Destroy())

        self.notebook = GNotebook(parent=self,
                                  style=globalvar.FNPageDStyle)

        self.notebook.AddPage(page=self.panel,
                              text=_('Source settings'),
                              name='source')

        self.createSettingsPage()

    def createSettingsPage(self):

        self._blackList = {
            'enabled': True,
            'items': {
                self._getCommand(): {
                    'params': self._getBlackListedParameters(),
                    'flags': self._getBlackListedFlags()}}}

        grass_task = gtask.parse_interface(self._getCommand(),
                                           blackList=self._blackList)

        self.advancedPagePanel = CmdPanel(
            parent=self, giface=None, task=grass_task, frame=None)

        self.notebook.AddPage(page=self.advancedPagePanel,
                              text=_('Import settings'),
                              name='settings')

    def doLayout(self):
        """Do layout"""
        dialogSizer = wx.BoxSizer(wx.VERTICAL)

        # dsn input
        dialogSizer.Add(self.dsnInput, proportion=0,
                        flag=wx.EXPAND)

        #
        # list of DXF layers
        #
        layerSizer = wx.StaticBoxSizer(self.layerBox, wx.HORIZONTAL)

        layerSizer.Add(self.list, proportion=1,
                       flag=wx.ALL | wx.EXPAND, border=5)

        dialogSizer.Add(
            layerSizer,
            proportion=1,
            flag=wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND,
            border=5)

        dialogSizer.Add(self.override, proportion=0,
                        flag=wx.LEFT | wx.RIGHT | wx.BOTTOM, border=5)

        dialogSizer.Add(self.overwrite, proportion=0,
                        flag=wx.LEFT | wx.RIGHT | wx.BOTTOM, border=5)

        dialogSizer.Add(self.add, proportion=0,
                        flag=wx.LEFT | wx.RIGHT | wx.BOTTOM, border=5)

        dialogSizer.Add(self.closeOnFinish, proportion=0,
                        flag=wx.LEFT | wx.RIGHT | wx.BOTTOM, border=5)
        #
        # buttons
        #
        btnsizer = wx.BoxSizer(orient=wx.HORIZONTAL)

        btnsizer.Add(self.btn_close, proportion=0,
                     flag=wx.LEFT | wx.RIGHT | wx.ALIGN_CENTER,
                     border=10)

        btnsizer.Add(self.btn_run, proportion=0,
                     flag=wx.RIGHT | wx.ALIGN_CENTER,
                     border=10)

        dialogSizer.Add(
            btnsizer,
            proportion=0,
            flag=wx.BOTTOM | wx.ALIGN_RIGHT,
            border=10)

        # dialogSizer.SetSizeHints(self.panel)
        self.panel.SetAutoLayout(True)
        self.panel.SetSizer(dialogSizer)
        dialogSizer.Fit(self.panel)

        # auto-layout seems not work here - FIXME
        size = wx.Size(globalvar.DIALOG_GSELECT_SIZE[0] + 322, 550)
        self.SetMinSize(size)
        self.SetSize((size.width, size.height + 100))
        # width = self.GetSize()[0]
        # self.list.SetColumnWidth(col = 1, width = width / 2 - 50)
        self.Layout()

    def _getCommand(self):
        """Get command"""
        raise NotImplementedError()

    def _getBlackListedParameters(self):
        """Get parameters which will not be showed in Settings page"""
        raise NotImplementedError()

    def _getBlackListedFlags(self):
        """Get flags which will not be showed in Settings page"""
        raise NotImplementedError()

    def _nameValidationFailed(self, layers_list):
        """Output map name validation callback

        :param layers_list: LayersList class instance
        """
        if isinstance(layers_list.output_map, list):
            maps = [
                '<{}>'.format(m) for m in layers_list.output_map]
            message = _(
                "Output map names %(names)s exist. "
            ) % {
                'names': ', '.join(maps)}
        else:
            message = _(
                "Output map name <%(name)s> exist. "
                ) % {
                'name': layers_list.output_map}
        GError(parent=self, message=message, caption=_("Invalid name"))

    def _validateOutputMapName(self):
        """Enable/disable output map name validation according the
        overwrite state"""
        if not self.overwrite.IsChecked():
            if not self.list.GetValidator().\
               Validate(win=self.list, validate_all=True):
                return False
        return True

    def OnClose(self, event=None):
        """Close dialog"""
        self.Close()

    def OnRun(self, event):
        """Import/Link data (each layes as separate vector map)"""
        pass

    def OnCheckOverwrite(self, event):
        """Check/uncheck overwrite checkbox widget"""
        if self.overwrite.IsChecked():
            self.list.validate = False
        else:
            self.list.validate = True

    def AddLayers(self, returncode, cmd=None, userData=None):
        """Add imported/linked layers into layer tree"""
        if not self.add.IsChecked() or returncode != 0:
            return

        # TODO: if importing map creates more map the folowing does not work
        # * do nothing if map does not exist or
        # * try to determine names using regexp or
        # * persuade import tools to report map names
        self.commandId += 1
        layer, output = self.list.GetLayers()[self.commandId][:2]

        if '@' not in output:
            name = output + '@' + grass.gisenv()['MAPSET']
        else:
            name = output

        # add imported layers into layer tree
        # an alternative would be emit signal (mapCreated) and (optionally)
        # connect to this signal
        llist = self._giface.GetLayerList()
        if self.importType == 'gdal':
            if userData:
                nBands = int(userData.get('nbands', 1))
            else:
                nBands = 1

            if UserSettings.Get(group='rasterLayer',
                                key='opaque', subkey='enabled'):
                nFlag = True
            else:
                nFlag = False

            for i in range(1, nBands + 1):
                nameOrig = name
                if nBands > 1:
                    mapName, mapsetName = name.split('@')
                    mapName += '.%d' % i
                    name = mapName + '@' + mapsetName

                cmd = ['d.rast',
                       'map=%s' % name]
                if nFlag:
                    cmd.append('-n')

                llist.AddLayer(ltype='raster',
                               name=name, checked=True,
                               cmd=cmd)
                name = nameOrig
        else:
            llist.AddLayer(ltype='vector',
                           name=name, checked=True,
                           cmd=['d.vect',
                                'map=%s' % name] + GetDisplayVectSettings())

        self._giface.GetMapWindow().ZoomToMap()

    def OnAbort(self, event):
        """Abort running import

        .. todo::
            not yet implemented
        """
        pass

    def OnCmdDone(self, event):
        """Do what has to be done after importing"""
        pass

    def _getLayersToReprojetion(self, projMatch_idx, grassName_idx):
        """If there are layers with different projection from loation projection,
           show dialog to user to explicitly select layers which will be reprojected..."""
        differentProjLayers = []
        data = self.list.GetData(checked=True)

        for itm in data:

            layerId = itm[-1]

            # select only layers with different projetion
            if self.layersData[layerId][projMatch_idx] == 0:
                dt = [itm[0], itm[grassName_idx]]
                differentProjLayers.append(tuple(dt))

        layers = self.list.GetLayers()

        if not self.link and \
           differentProjLayers and \
           not self.override.IsChecked(): # '-o' not in self.getSettingsPageCmd():

            dlg = ReprojectionDialog(
                parent=self,
                giface=self._giface,
                data=differentProjLayers)

            ret = dlg.ShowModal()

            if ret == wx.ID_OK:

                # do not import unchecked layers
                for itm in reversed(list(dlg.GetData(checked=False))):
                    idx = itm[-1]
                    layers.pop(idx)
            else:
                return None

        return layers

    def getSettingsPageCmd(self):

        return self.advancedPagePanel.createCmd(
            ignoreErrors=True, ignoreRequired=True)
Example #20
0
class SearchModuleWindow(wx.Panel):
    """Menu tree and search widget for searching modules.

    Signal:
        showNotification - attribute 'message'
    """
    def __init__(self,
                 parent,
                 handlerObj,
                 giface,
                 model,
                 id=wx.ID_ANY,
                 **kwargs):
        self.parent = parent
        self._handlerObj = handlerObj
        self._giface = giface

        self.showNotification = Signal('SearchModuleWindow.showNotification')
        wx.Panel.__init__(self, parent=parent, id=id, **kwargs)

        # tree
        self._tree = CTreeView(model=model, parent=self)
        self._tree.SetToolTip(
            _("Double-click or Ctrl-Enter to run selected module"))

        #        self._dataBox = wx.StaticBox(parent = self, id = wx.ID_ANY,
        #                                     label = " %s " % _("Module tree"))

        # search widget
        self._search = SearchModuleWidget(parent=self,
                                          model=model,
                                          showChoice=False)
        self._search.showSearchResult.connect(
            lambda result: self._tree.Select(result))
        self._search.showNotification.connect(self.showNotification)

        self._helpText = StaticText(
            parent=self,
            id=wx.ID_ANY,
            label="Press Enter for next match, Ctrl+Enter to run command")
        self._helpText.SetForegroundColour(
            wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT))

        # buttons
        self._btnRun = Button(self, id=wx.ID_OK, label=_("&Run"))
        self._btnRun.SetToolTip(_("Run selected module from the tree"))
        self._btnHelp = Button(self, id=wx.ID_ANY, label=_("H&elp"))
        self._btnHelp.SetToolTip(
            _("Show manual for selected module from the tree"))
        self._btnAdvancedSearch = Button(self,
                                         id=wx.ID_ANY,
                                         label=_("Adva&nced search..."))
        self._btnAdvancedSearch.SetToolTip(
            _("Do advanced search using %s module") % 'g.search.module')

        # bindings
        self._btnRun.Bind(wx.EVT_BUTTON, lambda evt: self.Run())
        self._btnHelp.Bind(wx.EVT_BUTTON, lambda evt: self.Help())
        self._btnAdvancedSearch.Bind(wx.EVT_BUTTON,
                                     lambda evt: self.AdvancedSearch())
        self.Bind(wx.EVT_KEY_UP, self.OnKeyUp)

        self._tree.selectionChanged.connect(self.OnItemSelected)
        self._tree.itemActivated.connect(lambda node: self.Run(node))

        self._layout()

        self._search.SetFocus()

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

        # body
        dataSizer = wx.BoxSizer(wx.HORIZONTAL)
        dataSizer.Add(self._tree, proportion=1, flag=wx.EXPAND)

        # buttons
        btnSizer = wx.BoxSizer(wx.HORIZONTAL)
        btnSizer.Add(self._btnAdvancedSearch, proportion=0)
        btnSizer.AddStretchSpacer()
        btnSizer.Add(self._btnHelp, proportion=0)
        btnSizer.Add(self._btnRun, proportion=0)

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

        sizer.Add(self._search,
                  proportion=0,
                  flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
                  border=5)

        sizer.Add(btnSizer,
                  proportion=0,
                  flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
                  border=5)

        sizer.Add(self._helpText,
                  proportion=0,
                  flag=wx.EXPAND | wx.LEFT,
                  border=5)

        sizer.Fit(self)
        sizer.SetSizeHints(self)

        self.SetSizer(sizer)

        self.Fit()
        self.SetAutoLayout(True)
        self.Layout()

    def _GetSelectedNode(self):
        selection = self._tree.GetSelected()
        if not selection:
            return None
        return selection[0]

    def Run(self, node=None):
        """Run selected command.

        :param node: a tree node associated with the module or other item
        """
        if not node:
            node = self._GetSelectedNode()
        # nothing selected
        if not node:
            return
        data = node.data
        # non-leaf nodes
        if not data:
            return

        # extract name of the handler and create a new call
        handler = 'self._handlerObj.' + data['handler'].lstrip('self.')

        if data['command']:
            eval(handler)(event=None, cmd=data['command'].split())
        else:
            eval(handler)(event=None)

    def Help(self, node=None):
        """Show documentation for a module"""
        if not node:
            node = self._GetSelectedNode()
        # nothing selected
        if not node:
            return
        data = node.data
        # non-leaf nodes
        if not data:
            return

        if not data['command']:
            # showing nothing for non-modules
            return
        # strip parameters from command if present
        name = data['command'].split()[0]
        self._giface.Help(name)
        self.showNotification.emit(
            message=_("Documentation for %s is now open in the web browser") %
            name)

    def AdvancedSearch(self):
        """Show advanced search window"""
        self._handlerObj.RunMenuCmd(cmd=['g.search.modules'])

    def OnKeyUp(self, event):
        """Key or key combination pressed"""
        if event.ControlDown() and \
                event.GetKeyCode() in (wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER):
            self.Run()

    def OnItemSelected(self, node):
        """Item selected"""
        data = node.data
        if not data or 'command' not in data:
            return

        if data['command']:
            label = data['command']
            if data['description']:
                label += ' -- ' + data['description']
        else:
            label = data['description']

        self.showNotification.emit(message=label)
Example #21
0
class AboutWindow(wx.Frame):
    """Create custom About Window
    """
    def __init__(self,
                 parent,
                 size=(770, 460),
                 title=_('About GRASS GIS'),
                 **kwargs):
        wx.Frame.__init__(self,
                          parent=parent,
                          id=wx.ID_ANY,
                          title=title,
                          size=size,
                          **kwargs)

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

        # icon
        self.SetIcon(
            wx.Icon(os.path.join(globalvar.ICONDIR, 'grass.ico'),
                    wx.BITMAP_TYPE_ICO))

        # notebook
        self.aboutNotebook = FormNotebook(self.panel, style=wx.BK_LEFT)

        for title, win in ((_("Info"),
                            self._pageInfo()), (_("Copyright"),
                                                self._pageCopyright()),
                           (_("License"),
                            self._pageLicense()), (_("Citation"),
                                                   self._pageCitation()),
                           (_("Authors"),
                            self._pageCredit()), (_("Contributors"),
                                                  self._pageContributors()),
                           (_("Extra contributors"),
                            self._pageContributors(extra=True)),
                           (_("Translators"),
                            self._pageTranslators()), (_("Translation status"),
                                                       self._pageStats())):
            self.aboutNotebook.AddPage(page=win, text=title)
        wx.CallAfter(self.aboutNotebook.SetSelection, 0)
        wx.CallAfter(self.aboutNotebook.Refresh)

        # buttons
        self.btnClose = Button(parent=self.panel, id=wx.ID_CLOSE)
        self.btnClose.Bind(wx.EVT_BUTTON, self.OnCloseWindow)

        self._doLayout()

    def _doLayout(self):
        btnSizer = wx.BoxSizer(wx.HORIZONTAL)
        btnSizer.Add(self.btnClose, proportion=0, flag=wx.ALL, border=5)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.aboutNotebook,
                  proportion=1,
                  flag=wx.EXPAND | wx.ALL,
                  border=1)
        sizer.Add(btnSizer,
                  proportion=0,
                  flag=wx.ALL | wx.ALIGN_RIGHT,
                  border=1)

        self.SetMinSize((400, 400))

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

        self.Layout()

    def _pageInfo(self):
        """Info page"""
        # get version and web site
        vInfo = grass.version()
        if not vInfo:
            sys.stderr.write(_("Unable to get GRASS version\n"))

        infoTxt = ScrolledPanel(self.aboutNotebook)
        infoTxt.SetupScrolling()
        infoSizer = wx.BoxSizer(wx.VERTICAL)
        infoGridSizer = wx.GridBagSizer(vgap=5, hgap=5)
        logo = os.path.join(globalvar.ICONDIR, "grass-64x64.png")
        logoBitmap = wx.StaticBitmap(
            infoTxt, wx.ID_ANY, wx.Bitmap(name=logo, type=wx.BITMAP_TYPE_PNG))
        infoSizer.Add(logoBitmap,
                      proportion=0,
                      flag=wx.ALL | wx.ALIGN_CENTER,
                      border=20)

        infoLabel = 'GRASS GIS %s' % vInfo.get('version', _('unknown version'))
        if 'x86_64' in vInfo.get('build_platform', ''):
            infoLabel += ' (64bit)'
        info = StaticText(parent=infoTxt,
                          id=wx.ID_ANY,
                          label=infoLabel + os.linesep)
        info.SetFont(wx.Font(13, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
        info.SetForegroundColour(wx.Colour(35, 142, 35))
        infoSizer.Add(info,
                      proportion=0,
                      flag=wx.BOTTOM | wx.ALIGN_CENTER,
                      border=1)

        team = StaticText(parent=infoTxt, label=_grassDevTeam(1999) + '\n')
        infoSizer.Add(team,
                      proportion=0,
                      flag=wx.BOTTOM | wx.ALIGN_CENTER,
                      border=1)

        row = 0
        infoGridSizer.Add(StaticText(parent=infoTxt,
                                     id=wx.ID_ANY,
                                     label=_('Official GRASS site:')),
                          pos=(row, 0),
                          flag=wx.ALIGN_RIGHT)

        infoGridSizer.Add(HyperLinkCtrl(parent=infoTxt,
                                        id=wx.ID_ANY,
                                        label='https://grass.osgeo.org'),
                          pos=(row, 1),
                          flag=wx.ALIGN_LEFT)

        row += 2
        infoGridSizer.Add(StaticText(parent=infoTxt,
                                     id=wx.ID_ANY,
                                     label='%s:' % _('Code Revision')),
                          pos=(row, 0),
                          flag=wx.ALIGN_RIGHT)

        infoGridSizer.Add(HyperLinkCtrl(
            parent=infoTxt,
            id=wx.ID_ANY,
            label=vInfo.get('revision', '?'),
            URL='https://github.com/OSGeo/grass.git'),
                          pos=(row, 1),
                          flag=wx.ALIGN_LEFT)

        row += 1
        infoGridSizer.Add(StaticText(parent=infoTxt,
                                     id=wx.ID_ANY,
                                     label='%s:' % _('Build Date')),
                          pos=(row, 0),
                          flag=wx.ALIGN_RIGHT)

        infoGridSizer.Add(StaticText(parent=infoTxt,
                                     id=wx.ID_ANY,
                                     label=vInfo.get('build_date', '?')),
                          pos=(row, 1),
                          flag=wx.ALIGN_LEFT)

        # show only basic info
        # row += 1
        # infoGridSizer.Add(item = wx.StaticText(parent = infoTxt, id = wx.ID_ANY,
        #                                        label = '%s:' % _('GIS Library Revision')),
        #                   pos = (row, 0),
        #                   flag = wx.ALIGN_RIGHT)

        # infoGridSizer.Add(item = wx.StaticText(parent = infoTxt, id = wx.ID_ANY,
        #                                        label = vInfo['libgis_revision'] + ' (' +
        #                                        vInfo['libgis_date'].split(' ')[0] + ')'),
        #                   pos = (row, 1),
        #                   flag = wx.ALIGN_LEFT)

        row += 2
        infoGridSizer.Add(StaticText(parent=infoTxt,
                                     id=wx.ID_ANY,
                                     label='Python:'),
                          pos=(row, 0),
                          flag=wx.ALIGN_RIGHT)

        infoGridSizer.Add(StaticText(parent=infoTxt,
                                     id=wx.ID_ANY,
                                     label=platform.python_version()),
                          pos=(row, 1),
                          flag=wx.ALIGN_LEFT)

        row += 1
        infoGridSizer.Add(StaticText(parent=infoTxt,
                                     id=wx.ID_ANY,
                                     label='wxPython:'),
                          pos=(row, 0),
                          flag=wx.ALIGN_RIGHT)

        infoGridSizer.Add(StaticText(parent=infoTxt,
                                     id=wx.ID_ANY,
                                     label=wx.__version__),
                          pos=(row, 1),
                          flag=wx.ALIGN_LEFT)

        infoGridSizer.AddGrowableCol(0)
        infoGridSizer.AddGrowableCol(1)
        infoSizer.Add(infoGridSizer, proportion=1, flag=wx.EXPAND)

        row += 2
        infoGridSizer.Add(StaticText(parent=infoTxt,
                                     id=wx.ID_ANY,
                                     label="%s:" % _('Language')),
                          pos=(row, 0),
                          flag=wx.ALIGN_RIGHT)
        self.langUsed = grass.gisenv().get('LANG', None)
        if not self.langUsed:
            import locale
            loc = locale.getdefaultlocale()
            if loc == (None, None):
                self.langUsed = _('unknown')
            else:
                self.langUsed = u'%s.%s' % (loc[0], loc[1])
        infoGridSizer.Add(StaticText(parent=infoTxt,
                                     id=wx.ID_ANY,
                                     label=self.langUsed),
                          pos=(row, 1),
                          flag=wx.ALIGN_LEFT)

        infoTxt.SetSizer(infoSizer)
        infoSizer.Fit(infoTxt)

        return infoTxt

    def _pageCopyright(self):
        """Copyright information"""
        copyfile = os.path.join(os.getenv("GISBASE"), "COPYING")
        if os.path.exists(copyfile):
            copyrightFile = open(copyfile, 'r')
            copytext = copyrightFile.read()
            copyrightFile.close()
        else:
            copytext = _('%s file missing') % 'COPYING'

        # put text into a scrolling panel
        copyrightwin = ScrolledPanel(self.aboutNotebook)
        copyrighttxt = TextCtrl(copyrightwin,
                                id=wx.ID_ANY,
                                value=copytext,
                                style=wx.TE_MULTILINE | wx.TE_READONLY)
        copyrightwin.SetAutoLayout(True)
        copyrightwin.sizer = wx.BoxSizer(wx.VERTICAL)
        copyrightwin.sizer.Add(copyrighttxt,
                               proportion=1,
                               flag=wx.EXPAND | wx.ALL,
                               border=3)
        copyrightwin.SetSizer(copyrightwin.sizer)
        copyrightwin.Layout()
        copyrightwin.SetupScrolling()

        return copyrightwin

    def _pageLicense(self):
        """Licence about"""
        licfile = os.path.join(os.getenv("GISBASE"), "GPL.TXT")
        if os.path.exists(licfile):
            licenceFile = open(licfile, 'r')
            license = ''.join(licenceFile.readlines())
            licenceFile.close()
        else:
            license = _('%s file missing') % 'GPL.TXT'
        # put text into a scrolling panel
        licensewin = ScrolledPanel(self.aboutNotebook)
        licensetxt = TextCtrl(licensewin,
                              id=wx.ID_ANY,
                              value=license,
                              style=wx.TE_MULTILINE | wx.TE_READONLY)
        licensewin.SetAutoLayout(True)
        licensewin.sizer = wx.BoxSizer(wx.VERTICAL)
        licensewin.sizer.Add(licensetxt,
                             proportion=1,
                             flag=wx.EXPAND | wx.ALL,
                             border=3)
        licensewin.SetSizer(licensewin.sizer)
        licensewin.Layout()
        licensewin.SetupScrolling()

        return licensewin

    def _pageCitation(self):
        """Citation information"""
        try:
            # import only when needed
            import grass.script as gscript
            text = gscript.read_command('g.version', flags='x')
        except CalledModuleError as error:
            text = _("Unable to provide citation suggestion,"
                     " see GRASS GIS website instead."
                     " The error was: {0}").format(error)

        # put text into a scrolling panel
        window = ScrolledPanel(self.aboutNotebook)
        stat_text = TextCtrl(window,
                             id=wx.ID_ANY,
                             value=text,
                             style=wx.TE_MULTILINE | wx.TE_READONLY)
        window.SetAutoLayout(True)
        window.sizer = wx.BoxSizer(wx.VERTICAL)
        window.sizer.Add(stat_text,
                         proportion=1,
                         flag=wx.EXPAND | wx.ALL,
                         border=3)
        window.SetSizer(window.sizer)
        window.Layout()
        window.SetupScrolling()

        return window

    def _pageCredit(self):
        """Credit about"""
        # credits
        authfile = os.path.join(os.getenv("GISBASE"), "AUTHORS")
        if os.path.exists(authfile):
            with codecs.open(authfile, encoding='utf-8',
                             mode='r') as authorsFile:
                authors = ''.join(authorsFile.readlines())
        else:
            authors = _('%s file missing') % 'AUTHORS'
        authorwin = ScrolledPanel(self.aboutNotebook)
        authortxt = TextCtrl(authorwin,
                             id=wx.ID_ANY,
                             value=authors,
                             style=wx.TE_MULTILINE | wx.TE_READONLY)
        authorwin.SetAutoLayout(True)
        authorwin.SetupScrolling()
        authorwin.sizer = wx.BoxSizer(wx.VERTICAL)
        authorwin.sizer.Add(authortxt,
                            proportion=1,
                            flag=wx.EXPAND | wx.ALL,
                            border=3)
        authorwin.SetSizer(authorwin.sizer)
        authorwin.Layout()

        return authorwin

    def _pageContributors(self, extra=False):
        """Contributors info"""
        if extra:
            contribfile = os.path.join(os.getenv("GISBASE"),
                                       "contributors_extra.csv")
        else:
            contribfile = os.path.join(os.getenv("GISBASE"),
                                       "contributors.csv")
        if os.path.exists(contribfile):
            contribFile = codecs.open(contribfile, encoding='utf-8', mode='r')
            contribs = list()
            errLines = list()
            for line in contribFile.readlines()[1:]:
                line = line.rstrip('\n')
                try:
                    if extra:
                        name, email, country, rfc2_agreed = line.split(',')
                    else:
                        cvs_id, name, email, country, osgeo_id, rfc2_agreed = line.split(
                            ',')
                except ValueError:
                    errLines.append(line)
                    continue
                if extra:
                    contribs.append((name, email, country))
                else:
                    contribs.append((name, email, country, osgeo_id))

            contribFile.close()

            if errLines:
                GError(
                    parent=self,
                    message=_("Error when reading file '%s'.") % contribfile +
                    "\n\n" + _("Lines:") +
                    " %s" % os.linesep.join(map(DecodeString, errLines)))
        else:
            contribs = None

        contribwin = ScrolledPanel(self.aboutNotebook)
        contribwin.SetAutoLayout(True)
        contribwin.SetupScrolling()
        contribwin.sizer = wx.BoxSizer(wx.VERTICAL)

        if not contribs:
            contribtxt = StaticText(contribwin,
                                    id=wx.ID_ANY,
                                    label=_('%s file missing') % contribfile)
            contribwin.sizer.Add(contribtxt,
                                 proportion=1,
                                 flag=wx.EXPAND | wx.ALL,
                                 border=3)
        else:
            if extra:
                items = (_('Name'), _('E-mail'), _('Country'))
            else:
                items = (_('Name'), _('E-mail'), _('Country'), _('OSGeo_ID'))
            contribBox = wx.FlexGridSizer(cols=len(items), vgap=5, hgap=5)
            for item in items:
                text = StaticText(parent=contribwin, id=wx.ID_ANY, label=item)
                text.SetFont(wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0,
                                     ""))
                contribBox.Add(text)
            for vals in sorted(contribs, key=lambda x: x[0]):
                for item in vals:
                    contribBox.Add(
                        StaticText(parent=contribwin, id=wx.ID_ANY,
                                   label=item))
            contribwin.sizer.Add(contribBox,
                                 proportion=1,
                                 flag=wx.EXPAND | wx.ALL,
                                 border=3)

        contribwin.SetSizer(contribwin.sizer)
        contribwin.Layout()

        return contribwin

    def _pageTranslators(self):
        """Translators info"""
        translatorsfile = os.path.join(os.getenv("GISBASE"), "translators.csv")
        if os.path.exists(translatorsfile):
            translatorsFile = codecs.open(translatorsfile,
                                          encoding='utf-8',
                                          mode='r')
            translators = dict()
            errLines = list()
            for line in translatorsFile.readlines()[1:]:
                line = line.rstrip('\n')
                try:
                    name, email, languages = line.split(',')
                except ValueError:
                    errLines.append(line)
                    continue
                for language in languages.split(' '):
                    if language not in translators:
                        translators[language] = list()
                    translators[language].append((name, email))
            translatorsFile.close()

            if errLines:
                GError(parent=self,
                       message=_("Error when reading file '%s'.") %
                       translatorsfile + "\n\n" + _("Lines:") +
                       " %s" % os.linesep.join(map(DecodeString, errLines)))
        else:
            translators = None

        translatorswin = ScrolledPanel(self.aboutNotebook)
        translatorswin.SetAutoLayout(True)
        translatorswin.SetupScrolling()
        translatorswin.sizer = wx.BoxSizer(wx.VERTICAL)

        if not translators:
            translatorstxt = StaticText(translatorswin,
                                        id=wx.ID_ANY,
                                        label=_('%s file missing') %
                                        'translators.csv')
            translatorswin.sizer.Add(translatorstxt,
                                     proportion=1,
                                     flag=wx.EXPAND | wx.ALL,
                                     border=3)
        else:
            translatorsBox = wx.FlexGridSizer(cols=4, vgap=5, hgap=5)
            languages = sorted(translators.keys())
            tname = StaticText(parent=translatorswin,
                               id=wx.ID_ANY,
                               label=_('Name'))
            tname.SetFont(wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
            translatorsBox.Add(tname)
            temail = StaticText(parent=translatorswin,
                                id=wx.ID_ANY,
                                label=_('E-mail'))
            temail.SetFont(wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
            translatorsBox.Add(temail)
            tlang = StaticText(parent=translatorswin,
                               id=wx.ID_ANY,
                               label=_('Language'))
            tlang.SetFont(wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
            translatorsBox.Add(tlang)
            tnat = StaticText(parent=translatorswin,
                              id=wx.ID_ANY,
                              label=_('Nation'))
            tnat.SetFont(wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
            translatorsBox.Add(tnat)
            for lang in languages:
                for translator in translators[lang]:
                    name, email = translator
                    translatorsBox.Add(
                        StaticText(parent=translatorswin,
                                   id=wx.ID_ANY,
                                   label=name))
                    translatorsBox.Add(
                        StaticText(parent=translatorswin,
                                   id=wx.ID_ANY,
                                   label=email))
                    translatorsBox.Add(
                        StaticText(parent=translatorswin,
                                   id=wx.ID_ANY,
                                   label=lang))
                    flag = os.path.join(globalvar.ICONDIR, "flags",
                                        "%s.png" % lang.lower())
                    if os.path.exists(flag):
                        flagBitmap = wx.StaticBitmap(
                            translatorswin, wx.ID_ANY,
                            wx.Bitmap(name=flag, type=wx.BITMAP_TYPE_PNG))
                        translatorsBox.Add(flagBitmap)
                    else:
                        translatorsBox.Add(
                            StaticText(parent=translatorswin,
                                       id=wx.ID_ANY,
                                       label=lang))

            translatorswin.sizer.Add(translatorsBox,
                                     proportion=1,
                                     flag=wx.EXPAND | wx.ALL,
                                     border=3)

        translatorswin.SetSizer(translatorswin.sizer)
        translatorswin.Layout()

        return translatorswin

    def _langString(self, k, v):
        """Return string for the status of translation"""
        allStr = "%s :" % k.upper()
        try:
            allStr += _("   %d translated" % v['good'])
        except:
            pass
        try:
            allStr += _("   %d fuzzy" % v['fuzzy'])
        except:
            pass
        try:
            allStr += _("   %d untranslated" % v['bad'])
        except:
            pass
        return allStr

    def _langBox(self, par, k, v):
        """Return box"""
        langBox = wx.FlexGridSizer(cols=4, vgap=5, hgap=5)
        tkey = StaticText(parent=par, id=wx.ID_ANY, label=k.upper())
        langBox.Add(tkey)
        try:
            tgood = StaticText(parent=par,
                               id=wx.ID_ANY,
                               label=_("%d translated" % v['good']))
            tgood.SetForegroundColour(wx.Colour(35, 142, 35))
            langBox.Add(tgood)
        except:
            tgood = StaticText(parent=par, id=wx.ID_ANY, label="")
            langBox.Add(tgood)
        try:
            tfuzzy = StaticText(parent=par,
                                id=wx.ID_ANY,
                                label=_("   %d fuzzy" % v['fuzzy']))
            tfuzzy.SetForegroundColour(wx.Colour(255, 142, 0))
            langBox.Add(tfuzzy)
        except:
            tfuzzy = StaticText(parent=par, id=wx.ID_ANY, label="")
            langBox.Add(tfuzzy)
        try:
            tbad = StaticText(parent=par,
                              id=wx.ID_ANY,
                              label=_("   %d untranslated" % v['bad']))
            tbad.SetForegroundColour(wx.Colour(255, 0, 0))
            langBox.Add(tbad)
        except:
            tbad = StaticText(parent=par, id=wx.ID_ANY, label="")
            langBox.Add(tbad)
        return langBox

    def _langPanel(self, lang, js):
        """Create panel for each languages"""
        text = self._langString(lang, js['total'])
        panel = wx.CollapsiblePane(self.statswin,
                                   -1,
                                   label=text,
                                   style=wx.CP_DEFAULT_STYLE
                                   | wx.CP_NO_TLW_RESIZE)
        panel.Bind(wx.EVT_COLLAPSIBLEPANE_CHANGED, self.OnPaneChanged)
        win = panel.GetPane()
        # TODO IT DOESN'T WORK
        # TO ADD ONLY WHEN TAB IS OPENED
        # if lang == self.langUsed.split('_')[0]:
        # panel.Collapse(False)
        # else:
        # panel.Collapse(True)
        pageSizer = wx.BoxSizer(wx.VERTICAL)
        for k, v in six.iteritems(js):
            if k != 'total' and k != 'name':
                box = self._langBox(win, k, v)
                pageSizer.Add(box,
                              proportion=1,
                              flag=wx.EXPAND | wx.ALL,
                              border=3)

        win.SetSizer(pageSizer)
        pageSizer.SetSizeHints(win)

        return panel

    def OnPaneChanged(self, evt):
        """Redo the layout"""
        # TODO better to test on Windows
        self.statswin.SetupScrolling(scrollToTop=False)

    def _pageStats(self):
        """Translation statistics info"""
        fname = "translation_status.json"
        statsfile = os.path.join(os.getenv("GISBASE"), fname)
        if os.path.exists(statsfile):
            statsFile = open(statsfile)
            import json
            jsStats = json.load(statsFile)
        else:
            jsStats = None
        self.statswin = ScrolledPanel(self.aboutNotebook)
        self.statswin.SetAutoLayout(True)

        if not jsStats:
            Debug.msg(5, _("File <%s> not found") % fname)
            statsSizer = wx.BoxSizer(wx.VERTICAL)
            statstext = StaticText(self.statswin,
                                   id=wx.ID_ANY,
                                   label=_('%s file missing') % fname)
            statsSizer.Add(statstext,
                           proportion=1,
                           flag=wx.EXPAND | wx.ALL,
                           border=3)
        else:
            languages = sorted(jsStats['langs'].keys())

            statsSizer = wx.BoxSizer(wx.VERTICAL)
            for lang in languages:
                v = jsStats['langs'][lang]
                panel = self._langPanel(lang, v)
                statsSizer.Add(panel)

        self.statswin.SetSizer(statsSizer)
        self.statswin.SetupScrolling(scroll_x=False, scroll_y=True)
        self.statswin.Layout()
        self.statswin.Fit()
        return self.statswin

    def OnCloseWindow(self, event):
        """Close window"""
        self.Close()
Example #22
0
    def __init__(
        self,
        parent,
        map,
        query=None,
        cats=None,
        line=None,
        style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER,
        pos=wx.DefaultPosition,
        action="add",
        ignoreError=False,
    ):
        """Standard dialog used to add/update/display attributes linked
        to the vector map.

        Attribute data can be selected based on layer and category number
        or coordinates.

        :param parent:
        :param map: vector map
        :param query: query coordinates and distance (used for v.edit)
        :param cats: {layer: cats}
        :param line: feature id (requested for cats)
        :param style:
        :param pos:
        :param action: (add, update, display)
        :param ignoreError: True to ignore errors
        """
        self.parent = parent  # mapdisplay.BufferedWindow
        self.map = map
        self.action = action

        # ids/cats of selected features
        # fid : {layer : cats}
        self.cats = {}
        self.fid = -1  # feature id

        # get layer/table/column information
        self.mapDBInfo = VectorDBInfo(self.map)

        layers = self.mapDBInfo.layers.keys()  # get available layers

        # check if db connection / layer exists
        if len(layers) <= 0:
            if not ignoreError:
                dlg = wx.MessageDialog(
                    parent=self.parent,
                    message=_("No attribute table found.\n\n"
                              "Do you want to create a new attribute table "
                              "and defined a link to vector map <%s>?") %
                    self.map,
                    caption=_("Create table?"),
                    style=wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION,
                )
                if dlg.ShowModal() == wx.ID_YES:
                    lmgr = self.parent.lmgr
                    lmgr.OnShowAttributeTable(event=None, selection="layers")

                dlg.Destroy()

            self.mapDBInfo = None

        wx.Dialog.__init__(self,
                           parent=self.parent,
                           id=wx.ID_ANY,
                           title="",
                           style=style,
                           pos=pos)

        # dialog body
        mainSizer = wx.BoxSizer(wx.VERTICAL)

        # notebook
        self.notebook = wx.Notebook(parent=self,
                                    id=wx.ID_ANY,
                                    style=wx.BK_DEFAULT)

        self.closeDialog = wx.CheckBox(parent=self,
                                       id=wx.ID_ANY,
                                       label=_("Close dialog on submit"))
        self.closeDialog.SetValue(True)
        if self.action == "display":
            self.closeDialog.Enable(False)

        # feature id (text/choice for duplicates)
        self.fidMulti = wx.Choice(parent=self, id=wx.ID_ANY, size=(150, -1))
        self.fidMulti.Bind(wx.EVT_CHOICE, self.OnFeature)
        self.fidText = StaticText(parent=self, id=wx.ID_ANY)

        self.noFoundMsg = StaticText(parent=self,
                                     id=wx.ID_ANY,
                                     label=_("No attributes found"))

        self.UpdateDialog(query=query, cats=cats)

        # set title
        if self.action == "update":
            self.SetTitle(_("Update attributes"))
        elif self.action == "add":
            self.SetTitle(_("Define attributes"))
        else:
            self.SetTitle(_("Display attributes"))

        # buttons
        btnCancel = Button(self, wx.ID_CANCEL)
        btnReset = Button(self, wx.ID_UNDO, _("&Reload"))
        btnSubmit = Button(self, wx.ID_OK, _("&Submit"))
        if self.action == "display":
            btnSubmit.Enable(False)

        btnSizer = wx.StdDialogButtonSizer()
        btnSizer.AddButton(btnCancel)
        btnSizer.AddButton(btnReset)
        btnSizer.SetNegativeButton(btnReset)
        btnSubmit.SetDefault()
        btnSizer.AddButton(btnSubmit)
        btnSizer.Realize()

        mainSizer.Add(self.noFoundMsg,
                      proportion=0,
                      flag=wx.EXPAND | wx.ALL,
                      border=5)
        mainSizer.Add(self.notebook,
                      proportion=1,
                      flag=wx.EXPAND | wx.ALL,
                      border=5)
        fidSizer = wx.BoxSizer(wx.HORIZONTAL)
        fidSizer.Add(
            StaticText(parent=self, id=wx.ID_ANY, label=_("Feature id:")),
            proportion=0,
            border=5,
            flag=wx.ALIGN_CENTER_VERTICAL,
        )
        fidSizer.Add(self.fidMulti,
                     proportion=0,
                     flag=wx.EXPAND | wx.ALL,
                     border=5)
        fidSizer.Add(self.fidText,
                     proportion=0,
                     flag=wx.EXPAND | wx.ALL,
                     border=5)
        mainSizer.Add(fidSizer,
                      proportion=0,
                      flag=wx.EXPAND | wx.LEFT | wx.RIGHT,
                      border=5)
        mainSizer.Add(
            self.closeDialog,
            proportion=0,
            flag=wx.EXPAND | wx.LEFT | wx.RIGHT,
            border=5,
        )
        mainSizer.Add(btnSizer,
                      proportion=0,
                      flag=wx.EXPAND | wx.ALL,
                      border=5)

        # bindigs
        btnReset.Bind(wx.EVT_BUTTON, self.OnReset)
        btnSubmit.Bind(wx.EVT_BUTTON, self.OnSubmit)
        btnCancel.Bind(wx.EVT_BUTTON, self.OnClose)
        self.Bind(wx.EVT_CLOSE, self.OnClose)

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

        # set min size for dialog
        w, h = self.GetBestSize()
        w += 50
        if h < 200:
            self.SetMinSize((w, 200))
        else:
            self.SetMinSize((w, h))

        if self.notebook.GetPageCount() == 0:
            Debug.msg(2, "DisplayAttributesDialog(): Nothing found!")
Example #23
0
    def __init__(self, parent, giface, title=_("Digitization settings"),
                 style=wx.DEFAULT_DIALOG_STYLE):
        """Standard settings dialog for digitization purposes
        """
        wx.Dialog.__init__(
            self,
            parent=parent,
            id=wx.ID_ANY,
            title=title,
            style=style)

        self._giface = giface
        self.parent = parent                     # MapFrame
        self.digit = self.parent.MapWindow.digit

        # notebook
        notebook = wx.Notebook(parent=self, id=wx.ID_ANY, style=wx.BK_DEFAULT)
        self._createGeneralPage(notebook)
        self._createSymbologyPage(notebook)
        self.digit.SetCategory()
        self._createAttributesPage(notebook)
        self._createQueryPage(notebook)

        # buttons
        btnApply = Button(self, wx.ID_APPLY)
        btnCancel = Button(self, wx.ID_CLOSE)
        btnSave = Button(self, wx.ID_SAVE)
        btnSave.SetDefault()

        # bindigs
        btnApply.Bind(wx.EVT_BUTTON, self.OnApply)
        btnApply.SetToolTip(_("Apply changes for this session"))
        btnApply.SetDefault()
        btnSave.Bind(wx.EVT_BUTTON, self.OnSave)
        btnSave.SetToolTip(
            _("Close dialog and save changes to user settings file"))
        btnCancel.Bind(wx.EVT_BUTTON, self.OnCancel)
        btnCancel.SetToolTip(_("Close dialog and ignore changes"))

        # sizers
        btnSizer = wx.BoxSizer(wx.HORIZONTAL)
        btnSizer.Add(btnCancel, proportion=0,
                     flag=wx.ALL, border=5)
        btnSizer.Add(btnApply, proportion=0,
                     flag=wx.ALL, border=5)
        btnSizer.Add(btnSave, proportion=0,
                     flag=wx.ALL, border=5)

        mainSizer = wx.BoxSizer(wx.VERTICAL)
        mainSizer.Add(
            notebook,
            proportion=1,
            flag=wx.EXPAND | wx.ALL,
            border=5)
        mainSizer.Add(btnSizer, proportion=0,
                      flag=wx.ALIGN_RIGHT, border=5)

        self.Bind(wx.EVT_CLOSE, self.OnCancel)

        self.SetSizer(mainSizer)
        mainSizer.Fit(self)
Example #24
0
class RLiSetupFrame(wx.Frame):
    def __init__(self,
                 parent,
                 giface=None,
                 id=wx.ID_ANY,
                 title=_("GRASS"
                         " GIS Setup for r.li modules"),
                 style=wx.DEFAULT_FRAME_STYLE | wx.RESIZE_BORDER,
                 **kwargs):
        # VARIABLES
        self.parent = parent
        #        self.cmd = "r.li.setup"
        self.rlipath = retRLiPath()
        self.listfiles = self.ListFiles()
        # END VARIABLES
        # init of frame
        wx.Frame.__init__(self, parent=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)
        # box for select configuration file
        self.confilesBox = StaticBox(
            parent=self.panel,
            id=wx.ID_ANY,
            label=_('Available sampling area configuration files'))
        self.listfileBox = wx.ListBox(parent=self.panel,
                                      id=wx.ID_ANY,
                                      choices=self.listfiles)

        # BUTTONS      #definition
        self.btn_close = Button(parent=self, id=wx.ID_CLOSE)
        self.btn_help = Button(parent=self, id=wx.ID_HELP)
        self.btn_remove = Button(parent=self, id=wx.ID_ANY, label=_("Remove"))
        self.btn_remove.SetToolTip(_('Remove a configuration file'))
        self.btn_new = Button(parent=self, id=wx.ID_ANY, label=_("Create"))
        self.btn_new.SetToolTip(_('Create a new configuration file'))
        self.btn_rename = Button(parent=self, id=wx.ID_ANY, label=_("Rename"))
        self.btn_rename.SetToolTip(_('Rename a configuration file'))
        self.btn_view = Button(parent=self, id=wx.ID_ANY, label=_("View/Edit"))
        self.btn_view.SetToolTip(_('View and edit a configuration file'))
        # set action for button
        self.btn_close.Bind(wx.EVT_BUTTON, self.OnClose)
        self.btn_help.Bind(wx.EVT_BUTTON, self.OnHelp)
        self.btn_remove.Bind(wx.EVT_BUTTON, self.OnRemove)
        self.btn_new.Bind(wx.EVT_BUTTON, self.OnNew)
        self.btn_rename.Bind(wx.EVT_BUTTON, self.OnRename)
        self.btn_view.Bind(wx.EVT_BUTTON, self.OnView)
        self._layout()
        # END BUTTONS
        # SIZE FRAME
        self.SetMinSize(self.GetBestSize())
        # Please check this because without this the size it is not the min
        self.SetClientSize(self.GetBestSize())
        # END SIZE

    def _layout(self):
        """Set the layout"""
        panelsizer = wx.GridBagSizer(1, 1)
        mainsizer = wx.BoxSizer(wx.VERTICAL)
        # CONFILES
        confilesSizer = wx.StaticBoxSizer(self.confilesBox, wx.HORIZONTAL)
        confilesSizer.Add(self.listfileBox, proportion=1, flag=wx.EXPAND)
        # END CONFILES
        # BUTTONS
        buttonSizer = wx.BoxSizer(wx.HORIZONTAL)
        buttonSizer.Add(self.btn_new, flag=wx.ALL, border=5)
        buttonSizer.Add(self.btn_rename, flag=wx.ALL, border=5)
        buttonSizer.Add(self.btn_view, flag=wx.ALL, border=5)
        buttonSizer.Add(self.btn_remove, flag=wx.ALL, border=5)
        buttonSizer.Add(self.btn_help, flag=wx.ALL, border=5)
        buttonSizer.Add(self.btn_close, flag=wx.ALL, border=5)
        # END BUTTONS
        # add listbox to staticbox
        panelsizer.Add(confilesSizer, pos=(0, 0), flag=wx.EXPAND, border=3)

        # add panel and buttons
        mainsizer.Add(self.panel, proportion=1, flag=wx.EXPAND, border=3)
        mainsizer.Add(buttonSizer, proportion=0, flag=wx.EXPAND, border=3)

        panelsizer.AddGrowableRow(0)
        panelsizer.AddGrowableCol(0)

        self.panel.SetAutoLayout(True)
        self.panel.SetSizerAndFit(panelsizer)
        self.SetSizer(mainsizer)
        self.Layout()

    def ListFiles(self):
        """Check the configuration files inside the path"""
        # list of configuration file
        listfiles = []
        # return all the configuration files in self.rlipath, check if there are
        # link or directory and doesn't add them
        for l in os.listdir(self.rlipath):
            if os.path.isfile(os.path.join(self.rlipath, l)):
                listfiles.append(l)
        return sorted(listfiles)

    def OnClose(self, event):
        """Close window"""
        self.Destroy()

    def OnHelp(self, event):
        """Launches help"""
        gcmd.RunCommand('g.manual', parent=self, entry='wxGUI.rlisetup')

    def OnRemove(self, event):
        """Remove configuration file from path and update the list"""
        confile = self.listfiles[self.listfileBox.GetSelections()[0]]
        dlg = wx.MessageDialog(
            parent=self.parent,
            message=_("Do you want remove r.li "
                      "configuration file <%s>?") % confile,
            caption=_("Remove new r.li configuration file?"),
            style=wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION)

        if dlg.ShowModal() == wx.ID_YES:
            self.listfileBox.Delete(self.listfileBox.GetSelections()[0])
            try_remove(os.path.join(self.rlipath, confile))
            self.listfiles = self.ListFiles()
        dlg.Destroy()
        return

    def OnNew(self, event):
        """Remove configuration file from path and update the list"""
        RLIWizard(self)
        self.listfiles = self.ListFiles()
        self.listfileBox.Clear()
        self.listfileBox.Set(self.listfiles)

    def OnRename(self, event):
        """Rename an existing configuration file"""
        try:
            confile = self.listfiles[self.listfileBox.GetSelections()[0]]
        except:
            gcmd.GMessage(parent=self,
                          message=_("You have to select a configuration file"))
            return
        dlg = wx.TextEntryDialog(parent=self.parent,
                                 message=_('Set the new name for %s " \
                                           "configuration file') % confile,
                                 caption=_('Rename configuration file'))
        if dlg.ShowModal() == wx.ID_OK:
            res = dlg.GetValue()
            newname = "%s%s%s" % (self.rlipath, os.sep, res)
            os.rename(os.path.join(self.rlipath, confile), newname)
            self.listfiles = self.ListFiles()
            self.listfileBox.Clear()
            self.listfileBox.Set(self.listfiles)

    def OnView(self, event):
        """Show and edit a configuration file"""
        try:
            confile = self.listfiles[self.listfileBox.GetSelections()[0]]
        except:
            gcmd.GMessage(parent=self,
                          message=_("You have to select a configuration file"))
            return
        frame = ViewFrame(self, conf=confile)
        frame.Show()
Example #25
0
class ManageExtensionWindow(wx.Frame):
    def __init__(
            self,
            parent,
            id=wx.ID_ANY,
            title=_("Manage installed GRASS Addons extensions"),
            **kwargs,
    ):
        self.parent = parent

        wx.Frame.__init__(self, parent=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.extBox = StaticBox(
            parent=self.panel,
            id=wx.ID_ANY,
            label=" %s " % _("List of installed extensions"),
        )

        self.extList = CheckListExtension(parent=self.panel)

        # buttons
        self.btnUninstall = Button(parent=self.panel,
                                   id=wx.ID_REMOVE,
                                   label=_("Uninstall"))
        self.btnUninstall.SetToolTip(_("Uninstall selected Addons extensions"))
        self.btnUpdate = Button(parent=self.panel,
                                id=wx.ID_REFRESH,
                                label=_("Reinstall"))
        self.btnUpdate.SetToolTip(_("Reinstall selected Addons extensions"))

        self.btnClose = Button(parent=self.panel, id=wx.ID_CLOSE)

        self.btnUninstall.Bind(wx.EVT_BUTTON, self.OnUninstall)
        self.btnUpdate.Bind(wx.EVT_BUTTON, self.OnUpdate)
        self.btnClose.Bind(wx.EVT_BUTTON, lambda evt: self.Close())

        self._layout()

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

        extSizer = wx.StaticBoxSizer(self.extBox, wx.HORIZONTAL)
        extSizer.Add(self.extList,
                     proportion=1,
                     flag=wx.ALL | wx.EXPAND,
                     border=1)

        btnSizer = wx.BoxSizer(wx.HORIZONTAL)
        btnSizer.Add(self.btnClose, proportion=0, flag=wx.RIGHT, border=5)
        btnSizer.Add(self.btnUpdate, proportion=0, flag=wx.RIGHT, border=5)
        btnSizer.Add(self.btnUninstall, proportion=0)

        sizer.Add(extSizer, proportion=1, flag=wx.ALL | wx.EXPAND, border=3)
        sizer.Add(btnSizer,
                  proportion=0,
                  flag=wx.ALIGN_RIGHT | wx.ALL,
                  border=5)

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

        self.Layout()

    def _getSelectedExtensions(self):
        eList = self.extList.GetExtensions()
        if not eList:
            GMessage(_("No extension selected. "
                       "Operation canceled."),
                     parent=self)
            return []

        return eList

    def OnUninstall(self, event):
        """Uninstall selected extensions"""
        eList = self._getSelectedExtensions()
        if not eList:
            return

        for ext in eList:
            files = RunCommand(
                "g.extension",
                parent=self,
                read=True,
                quiet=True,
                extension=ext,
                operation="remove",
            ).splitlines()
            if len(files) > 10:
                files = files[:10]
                files.append("...")
            dlg = wx.MessageDialog(
                parent=self,
                message=_("List of files to be removed:\n%(files)s\n\n"
                          "Do you want really to remove <%(ext)s> extension?")
                % {
                    "files": os.linesep.join(files),
                    "ext": ext
                },
                caption=_("Remove extension"),
                style=wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION,
            )

            if dlg.ShowModal() == wx.ID_YES:
                RunCommand(
                    "g.extension",
                    flags="f",
                    parent=self,
                    quiet=True,
                    extension=ext,
                    operation="remove",
                )

        self.extList.LoadData()

        # update prompt
        globalvar.UpdateGRASSAddOnCommands(eList)
        toolboxesOutdated()

    def OnUpdate(self, event):
        """Update selected extensions"""
        eList = self._getSelectedExtensions()
        if not eList:
            return

        log = self.parent.GetLogWindow()

        for ext in eList:
            log.RunCmd(["g.extension", "extension=%s" % ext, "operation=add"])
Example #26
0
class ViewFrame(wx.Frame):
    def __init__(self,
                 parent,
                 conf,
                 giface=None,
                 id=wx.ID_ANY,
                 title=_("Modify the configuration file"),
                 style=wx.DEFAULT_FRAME_STYLE | wx.RESIZE_BORDER,
                 **kwargs):
        # VARIABLES
        self.parent = parent
        self.rlipath = retRLiPath()
        self.confile = conf
        self.pathfile = os.path.join(self.rlipath, conf)
        wx.Frame.__init__(self, parent=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.confilesBox = StaticBox(
            parent=self.panel,
            id=wx.ID_ANY,
            label=_("View and modify the "
                    "configuration file '{name}'".format(name=self.confile)))
        self.textCtrl = TextCtrl(parent=self.panel,
                                 id=wx.ID_ANY,
                                 style=wx.TE_MULTILINE,
                                 size=(-1, 75))
        self.textCtrl.Bind(wx.EVT_TEXT, self.OnFileText)
        f = open(self.pathfile)
        self.textCtrl.SetValue(''.join(f.readlines()))
        f.close()
        # BUTTONS      #definition
        self.btn_close = Button(parent=self, id=wx.ID_EXIT)
        self.btn_ok = Button(parent=self, id=wx.ID_SAVE)
        self.btn_close.Bind(wx.EVT_BUTTON, self.OnClose)
        self.btn_ok.Bind(wx.EVT_BUTTON, self.OnOk)
        self._layout()
        self.enc = locale.getdefaultlocale()[1]

    def _layout(self):
        """Set the layout"""
        panelsizer = wx.GridBagSizer(1, 1)
        mainsizer = wx.BoxSizer(wx.VERTICAL)
        # CONFILES
        confilesSizer = wx.StaticBoxSizer(self.confilesBox, wx.HORIZONTAL)
        confilesSizer.Add(self.textCtrl, proportion=1, flag=wx.EXPAND)
        # END CONFILES
        # BUTTONS
        buttonSizer = wx.BoxSizer(wx.HORIZONTAL)
        buttonSizer.Add(self.btn_ok, flag=wx.ALL, border=5)
        buttonSizer.Add(self.btn_close, flag=wx.ALL, border=5)
        # END BUTTONS
        # add listbox to staticbox
        panelsizer.Add(confilesSizer, pos=(0, 0), flag=wx.EXPAND, border=3)
        # add panel and buttons
        mainsizer.Add(self.panel, proportion=1, flag=wx.EXPAND, border=3)
        mainsizer.Add(buttonSizer, proportion=0, flag=wx.EXPAND, border=3)
        panelsizer.AddGrowableRow(0)
        panelsizer.AddGrowableCol(0)
        self.panel.SetAutoLayout(True)
        self.panel.SetSizerAndFit(panelsizer)
        self.SetSizer(mainsizer)
        self.Layout()

    def OnClose(self, event):
        """Close window"""
        self.Destroy()

    def OnOk(self, event):
        """Launches help"""
        dlg = wx.MessageDialog(parent=self.parent,
                               message=_("Are you sure that you want modify"
                                         " r.li configuration file {name}?"
                                         "\nYou could broke the configuration"
                                         " file...").format(name=self.confile),
                               caption=_("WARNING"),
                               style=wx.YES_NO | wx.YES_DEFAULT
                               | wx.ICON_WARNING)

        if dlg.ShowModal() == wx.ID_YES:
            f = codecs.open(self.pathfile,
                            encoding=self.enc,
                            mode='w',
                            errors='replace')
            f.write(self.text + os.linesep)
            f.close()
        dlg.Destroy()
        self.Destroy()

    def OnFileText(self, event):
        """File input interactively entered"""
        self.text = event.GetString()
Example #27
0
class GConsoleWindow(wx.SplitterWindow):
    """Create and manage output console for commands run by GUI.
    """
    def __init__(self,
                 parent,
                 gconsole,
                 menuModel=None,
                 margin=False,
                 style=wx.TAB_TRAVERSAL | wx.FULL_REPAINT_ON_RESIZE,
                 gcstyle=GC_EMPTY,
                 **kwargs):
        """
        :param parent: gui parent
        :param gconsole: console logic
        :param menuModel: tree model of modules (from menu)
        :param margin: use margin in output pane (GStc)
        :param style: wx.SplitterWindow style
        :param gcstyle: GConsole style
                        (GC_EMPTY, GC_PROMPT to show command prompt,
                        GC_SEARCH to show search widget)
        """
        wx.SplitterWindow.__init__(self,
                                   parent,
                                   id=wx.ID_ANY,
                                   style=style,
                                   **kwargs)
        self.SetName("GConsole")

        self.panelOutput = wx.Panel(parent=self, id=wx.ID_ANY)
        self.panelProgress = wx.Panel(parent=self.panelOutput,
                                      id=wx.ID_ANY,
                                      name='progressPanel')
        self.panelPrompt = wx.Panel(parent=self, id=wx.ID_ANY)
        # initialize variables
        self.parent = parent  # GMFrame | CmdPanel | ?
        self._gconsole = gconsole
        self._menuModel = menuModel

        self._gcstyle = gcstyle
        self.lineWidth = 80

        # signal which requests showing of a notification
        self.showNotification = Signal("GConsoleWindow.showNotification")
        # signal emitted when text appears in the console
        # parameter 'notification' suggests form of notification (according to
        # core.giface.Notification)
        self.contentChanged = Signal("GConsoleWindow.contentChanged")

        # progress bar
        self.progressbar = wx.Gauge(parent=self.panelProgress,
                                    id=wx.ID_ANY,
                                    range=100,
                                    pos=(110, 50),
                                    size=(-1, 25),
                                    style=wx.GA_HORIZONTAL)
        self._gconsole.Bind(EVT_CMD_PROGRESS, self.OnCmdProgress)
        self._gconsole.Bind(EVT_CMD_OUTPUT, self.OnCmdOutput)
        self._gconsole.Bind(EVT_CMD_RUN, self.OnCmdRun)
        self._gconsole.Bind(EVT_CMD_DONE, self.OnCmdDone)

        self._gconsole.writeLog.connect(self.WriteLog)
        self._gconsole.writeCmdLog.connect(self.WriteCmdLog)
        self._gconsole.writeWarning.connect(self.WriteWarning)
        self._gconsole.writeError.connect(self.WriteError)

        # text control for command output
        self.cmdOutput = GStc(parent=self.panelOutput,
                              id=wx.ID_ANY,
                              margin=margin,
                              wrap=None)

        # search & command prompt
        # move to the if below
        # search depends on cmd prompt
        self.cmdPrompt = GPromptSTC(parent=self, menuModel=self._menuModel)
        self.cmdPrompt.promptRunCmd.connect(
            lambda cmd: self._gconsole.RunCmd(command=cmd))
        self.cmdPrompt.showNotification.connect(self.showNotification)

        if not self._gcstyle & GC_PROMPT:
            self.cmdPrompt.Hide()

        if self._gcstyle & GC_SEARCH:
            self.infoCollapseLabelExp = _(
                "Click here to show search module engine")
            self.infoCollapseLabelCol = _(
                "Click here to hide search module engine")
            self.searchPane = wx.CollapsiblePane(
                parent=self.panelOutput,
                label=self.infoCollapseLabelExp,
                style=wx.CP_DEFAULT_STYLE | wx.CP_NO_TLW_RESIZE | wx.EXPAND)
            self.MakeSearchPaneContent(self.searchPane.GetPane(),
                                       self._menuModel)
            self.searchPane.Collapse(True)
            self.Bind(wx.EVT_COLLAPSIBLEPANE_CHANGED, self.OnSearchPaneChanged,
                      self.searchPane)
            self.search.moduleSelected.connect(
                lambda name: self.cmdPrompt.SetTextAndFocus(name + ' '))
        else:
            self.search = None

        if self._gcstyle & GC_PROMPT:
            cmdLabel = _("Command prompt")
            self.outputBox = wx.StaticBox(parent=self.panelOutput,
                                          id=wx.ID_ANY,
                                          label=" %s " % _("Output window"))

            self.cmdBox = wx.StaticBox(parent=self.panelOutput,
                                       id=wx.ID_ANY,
                                       label=" %s " % cmdLabel)

        # buttons
        self.btnOutputClear = Button(parent=self.panelOutput, id=wx.ID_CLEAR)
        self.btnOutputClear.SetToolTip(_("Clear output window content"))
        self.btnCmdClear = Button(parent=self.panelOutput, id=wx.ID_CLEAR)
        self.btnCmdClear.SetToolTip(_("Clear command prompt content"))
        self.btnOutputSave = Button(parent=self.panelOutput, id=wx.ID_SAVE)
        self.btnOutputSave.SetToolTip(
            _("Save output window content to the file"))
        self.btnCmdAbort = Button(parent=self.panelProgress, id=wx.ID_STOP)
        self.btnCmdAbort.SetToolTip(_("Abort running command"))
        self.btnCmdProtocol = ToggleButton(parent=self.panelOutput,
                                           id=wx.ID_ANY,
                                           label=_("&Log file"),
                                           size=self.btnCmdClear.GetSize())
        self.btnCmdProtocol.SetToolTip(
            _("Toggle to save list of executed commands into "
              "a file; content saved when switching off."))

        if not self._gcstyle & GC_PROMPT:
            self.btnCmdClear.Hide()
            self.btnCmdProtocol.Hide()

        self.btnCmdClear.Bind(wx.EVT_BUTTON, self.cmdPrompt.OnCmdErase)
        self.btnOutputClear.Bind(wx.EVT_BUTTON, self.OnOutputClear)
        self.btnOutputSave.Bind(wx.EVT_BUTTON, self.OnOutputSave)
        self.btnCmdAbort.Bind(wx.EVT_BUTTON, self._gconsole.OnCmdAbort)
        self.btnCmdProtocol.Bind(wx.EVT_TOGGLEBUTTON, self.OnCmdProtocol)

        self._layout()

    def _layout(self):
        """Do layout"""
        self.outputSizer = wx.BoxSizer(wx.VERTICAL)
        progressSizer = wx.BoxSizer(wx.HORIZONTAL)
        btnSizer = wx.BoxSizer(wx.HORIZONTAL)
        if self._gcstyle & GC_PROMPT:
            outBtnSizer = wx.StaticBoxSizer(self.outputBox, wx.HORIZONTAL)
            cmdBtnSizer = wx.StaticBoxSizer(self.cmdBox, wx.HORIZONTAL)
        else:
            outBtnSizer = wx.BoxSizer(wx.HORIZONTAL)
            cmdBtnSizer = wx.BoxSizer(wx.HORIZONTAL)

        if self._gcstyle & GC_PROMPT:
            promptSizer = wx.BoxSizer(wx.VERTICAL)
            promptSizer.Add(self.cmdPrompt,
                            proportion=1,
                            flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP,
                            border=3)
            helpText = wx.StaticText(
                self.panelPrompt,
                id=wx.ID_ANY,
                label=
                "Press Tab to display command help, Ctrl+Space to autocomplete"
            )
            helpText.SetForegroundColour(
                wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT))
            promptSizer.Add(helpText,
                            proportion=0,
                            flag=wx.EXPAND | wx.LEFT,
                            border=5)

        if self._gcstyle & GC_SEARCH:
            self.outputSizer.Add(self.searchPane,
                                 proportion=0,
                                 flag=wx.EXPAND | wx.ALL,
                                 border=3)
        self.outputSizer.Add(self.cmdOutput,
                             proportion=1,
                             flag=wx.EXPAND | wx.ALL,
                             border=3)
        if self._gcstyle & GC_PROMPT:
            proportion = 1
        else:
            proportion = 0
            outBtnSizer.AddStretchSpacer()

        outBtnSizer.Add(self.btnOutputClear,
                        proportion=proportion,
                        flag=wx.ALIGN_LEFT | wx.LEFT | wx.RIGHT | wx.BOTTOM,
                        border=5)

        outBtnSizer.Add(self.btnOutputSave,
                        proportion=proportion,
                        flag=wx.ALIGN_RIGHT | wx.RIGHT | wx.BOTTOM,
                        border=5)

        cmdBtnSizer.Add(self.btnCmdProtocol,
                        proportion=1,
                        flag=wx.ALIGN_CENTER | wx.ALIGN_CENTER_VERTICAL
                        | wx.LEFT | wx.RIGHT | wx.BOTTOM,
                        border=5)
        cmdBtnSizer.Add(self.btnCmdClear,
                        proportion=1,
                        flag=wx.ALIGN_CENTER | wx.RIGHT | wx.BOTTOM,
                        border=5)
        progressSizer.Add(self.btnCmdAbort,
                          proportion=0,
                          flag=wx.ALL | wx.ALIGN_CENTER,
                          border=5)
        progressSizer.Add(self.progressbar,
                          proportion=1,
                          flag=wx.ALIGN_CENTER | wx.RIGHT | wx.TOP | wx.BOTTOM,
                          border=5)

        self.panelProgress.SetSizer(progressSizer)
        progressSizer.Fit(self.panelProgress)

        btnSizer.Add(outBtnSizer,
                     proportion=1,
                     flag=wx.ALL | wx.ALIGN_CENTER,
                     border=5)
        btnSizer.Add(cmdBtnSizer,
                     proportion=1,
                     flag=wx.ALIGN_CENTER | wx.TOP | wx.BOTTOM | wx.RIGHT,
                     border=5)
        self.outputSizer.Add(self.panelProgress, proportion=0, flag=wx.EXPAND)
        self.outputSizer.Add(btnSizer, proportion=0, flag=wx.EXPAND)

        self.outputSizer.Fit(self)
        self.outputSizer.SetSizeHints(self)
        self.panelOutput.SetSizer(self.outputSizer)
        # eliminate gtk_widget_size_allocate() warnings
        # avoid to use a deprecated method in wxPython >= 2.9
        getattr(self.outputSizer, 'FitInside',
                self.outputSizer.SetVirtualSizeHints)(self.panelOutput)

        if self._gcstyle & GC_PROMPT:
            promptSizer.Fit(self)
            promptSizer.SetSizeHints(self)
            self.panelPrompt.SetSizer(promptSizer)

        # split window
        if self._gcstyle & GC_PROMPT:
            self.SplitHorizontally(self.panelOutput, self.panelPrompt, -50)
        else:
            self.SplitHorizontally(self.panelOutput, self.panelPrompt, -45)
            self.Unsplit()
        self.SetMinimumPaneSize(self.btnCmdClear.GetSize()[1] + 25)

        self.SetSashGravity(1.0)

        self.outputSizer.Hide(self.panelProgress)
        # layout
        self.SetAutoLayout(True)
        self.Layout()

    def MakeSearchPaneContent(self, pane, model):
        """Create search pane"""
        border = wx.BoxSizer(wx.VERTICAL)

        self.search = SearchModuleWidget(parent=pane, model=model)

        self.search.showNotification.connect(self.showNotification)

        border.Add(self.search,
                   proportion=0,
                   flag=wx.EXPAND | wx.ALL,
                   border=1)

        pane.SetSizer(border)
        border.Fit(pane)

    def OnSearchPaneChanged(self, event):
        """Collapse search module box"""
        if self.searchPane.IsExpanded():
            self.searchPane.SetLabel(self.infoCollapseLabelCol)
        else:
            self.searchPane.SetLabel(self.infoCollapseLabelExp)

        self.panelOutput.Layout()
        self.panelOutput.SendSizeEvent()

    def GetPanel(self, prompt=True):
        """Get panel

        :param prompt: get prompt / output panel

        :return: wx.Panel reference
        """
        if prompt:
            return self.panelPrompt

        return self.panelOutput

    def WriteLog(self,
                 text,
                 style=None,
                 wrap=None,
                 notification=Notification.HIGHLIGHT):
        """Generic method for writing log message in
        given style.

        Emits contentChanged signal.

        :param line: text line
        :param style: text style (see GStc)
        :param stdout: write to stdout or stderr
        :param notification: form of notification
        """

        self.cmdOutput.SetStyle()

        # documenting old behavior/implementation:
        # switch notebook if required
        # now, let user to bind to the old event

        if not style:
            style = self.cmdOutput.StyleDefault

        # p1 = self.cmdOutput.GetCurrentPos()
        p1 = self.cmdOutput.GetEndStyled()
        # self.cmdOutput.GotoPos(p1)
        self.cmdOutput.DocumentEnd()

        for line in text.splitlines():
            # fill space
            if len(line) < self.lineWidth:
                diff = self.lineWidth - len(line)
                line += diff * ' '

            self.cmdOutput.AddTextWrapped(line, wrap=wrap)  # adds '\n'

            p2 = self.cmdOutput.GetCurrentPos()

            self.cmdOutput.StartStyling(p1, 0xff)
            self.cmdOutput.SetStyling(p2 - p1, style)

        self.cmdOutput.EnsureCaretVisible()

        self.contentChanged.emit(notification=notification)

    def WriteCmdLog(self,
                    text,
                    pid=None,
                    notification=Notification.MAKE_VISIBLE):
        """Write message in selected style

        :param text: message to be printed
        :param pid: process pid or None
        :param switchPage: True to switch page
        """
        if pid:
            text = '(' + str(pid) + ') ' + text
        self.WriteLog(text,
                      style=self.cmdOutput.StyleCommand,
                      notification=notification)

    def WriteWarning(self, text):
        """Write message in warning style"""
        self.WriteLog(text,
                      style=self.cmdOutput.StyleWarning,
                      notification=Notification.MAKE_VISIBLE)

    def WriteError(self, text):
        """Write message in error style"""
        self.WriteLog(text,
                      style=self.cmdOutput.StyleError,
                      notification=Notification.MAKE_VISIBLE)

    def OnOutputClear(self, event):
        """Clear content of output window"""
        self.cmdOutput.SetReadOnly(False)
        self.cmdOutput.ClearAll()
        self.cmdOutput.SetReadOnly(True)
        self.progressbar.SetValue(0)

    def GetProgressBar(self):
        """Return progress bar widget"""
        return self.progressbar

    def OnOutputSave(self, event):
        """Save (selected) text from output window to the file"""
        text = self.cmdOutput.GetSelectedText()
        if not text:
            text = self.cmdOutput.GetText()

        # add newline if needed
        if len(text) > 0 and text[-1] != '\n':
            text += '\n'

        dlg = wx.FileDialog(
            self,
            message=_("Save file as..."),
            defaultFile="grass_cmd_output.txt",
            wildcard=_("%(txt)s (*.txt)|*.txt|%(files)s (*)|*") % {
                'txt': _("Text files"),
                'files': _("Files")
            },
            style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT)

        # Show the dialog and retrieve the user response. If it is the OK response,
        # process the data.
        if dlg.ShowModal() == wx.ID_OK:
            path = dlg.GetPath()

            try:
                output = open(path, "w")
                output.write(EncodeString(text))
            except IOError as e:
                GError(
                    _("Unable to write file '%(path)s'.\n\nDetails: %(error)s")
                    % {
                        'path': path,
                        'error': e
                    })
            finally:
                output.close()
            message = _("Command output saved into '%s'") % path
            self.showNotification.emit(message=message)

        dlg.Destroy()

    def SetCopyingOfSelectedText(self, copy):
        """Enable or disable copying of selected text in to clipboard.
        Effects prompt and output.

        :param bool copy: True for enable, False for disable
        """
        if copy:
            self.cmdPrompt.Bind(stc.EVT_STC_PAINTED,
                                self.cmdPrompt.OnTextSelectionChanged)
            self.cmdOutput.Bind(stc.EVT_STC_PAINTED,
                                self.cmdOutput.OnTextSelectionChanged)
        else:
            self.cmdPrompt.Unbind(stc.EVT_STC_PAINTED)
            self.cmdOutput.Unbind(stc.EVT_STC_PAINTED)

    def OnCmdOutput(self, event):
        """Prints command output.

        Emits contentChanged signal.
        """
        message = event.text
        type = event.type

        self.cmdOutput.AddStyledMessage(message, type)

        if event.type in ('warning', 'error'):
            self.contentChanged.emit(notification=Notification.MAKE_VISIBLE)
        else:
            self.contentChanged.emit(notification=Notification.HIGHLIGHT)

    def OnCmdProgress(self, event):
        """Update progress message info"""
        self.progressbar.SetValue(event.value)
        event.Skip()

    def CmdProtocolSave(self):
        """Save list of manually entered commands into a text log file"""
        if not hasattr(self, 'cmdFileProtocol'):
            return  # it should not happen

        try:
            output = open(self.cmdFileProtocol, "a")
            cmds = self.cmdPrompt.GetCommands()
            output.write('\n'.join(cmds))
            if len(cmds) > 0:
                output.write('\n')
        except IOError as e:
            GError(
                _("Unable to write file '%(filePath)s'.\n\nDetails: %(error)s")
                % {
                    'filePath': self.cmdFileProtocol,
                    'error': e
                })
        finally:
            output.close()

        message = _("Command log saved to '%s'") % self.cmdFileProtocol
        self.showNotification.emit(message=message)
        del self.cmdFileProtocol

    def OnCmdProtocol(self, event=None):
        """Save commands into file"""
        if not event.IsChecked():
            # stop capturing commands, save list of commands to the
            # protocol file
            self.CmdProtocolSave()
        else:
            # start capturing commands
            self.cmdPrompt.ClearCommands()
            # ask for the file
            dlg = wx.FileDialog(
                self,
                message=_("Save file as..."),
                defaultFile="grass_cmd_log.txt",
                wildcard=_("%(txt)s (*.txt)|*.txt|%(files)s (*)|*") % {
                    'txt': _("Text files"),
                    'files': _("Files")
                },
                style=wx.FD_SAVE)
            if dlg.ShowModal() == wx.ID_OK:
                self.cmdFileProtocol = dlg.GetPath()
            else:
                wx.CallAfter(self.btnCmdProtocol.SetValue, False)

            dlg.Destroy()

        event.Skip()

    def OnCmdRun(self, event):
        """Run command"""
        self.outputSizer.Show(self.panelProgress)
        self.outputSizer.Layout()
        event.Skip()

    def OnCmdDone(self, event):
        """Command done (or aborted)
        """
        self.progressbar.SetValue(0)  # reset progress bar on '0%'
        wx.CallLater(100, self._hideProgress)
        event.Skip()

    def _hideProgress(self):
        self.outputSizer.Hide(self.panelProgress)
        self.outputSizer.Layout()

    def ResetFocus(self):
        """Reset focus"""
        self.cmdPrompt.SetFocus()

    def GetPrompt(self):
        """Get prompt"""
        return self.cmdPrompt
Example #28
0
class WSPanel(wx.Panel):
    def __init__(self, parent, web_service, **kwargs):
        """Show data from capabilities file.

        Signal: capParsed - this signal is emitted when capabilities file is downloaded
                            (after ConnectToServer method was called)

        :param parent:  parent widget
        :param web_service:  web service to be panel generated for
        """
        wx.Panel.__init__(self, parent=parent, id=wx.ID_ANY)

        self.parent = parent
        self.ws = web_service

        self.capParsed = Signal("WSPanel.capParsed")

        # stores widgets, which represents parameters/flags of d.wms
        self.params = {}
        self.flags = {}

        self.o_layer_name = ""

        # stores err output from r.in.wms during getting capabilities
        self.cmd_err_str = ""

        # stores selected layer from layer list
        self.sel_layers = []

        # downloaded and parsed data from server successfully?
        self.is_connected = False

        # common part of command for r.in.wms -c and d.wms
        self.ws_cmdl = None

        # provides information about driver parameters
        self.drv_info = WMSDriversInfo()
        self.drv_props = self.drv_info.GetDrvProperties(self.ws)

        self.ws_drvs = {
            "WMS_1.1.1": {
                "cmd": ["wms_version=1.1.1", "driver=WMS_GRASS"],
                "cap_parser": lambda temp_file: WMSCapabilities(temp_file, "1.1.1"),
            },
            "WMS_1.3.0": {
                "cmd": ["wms_version=1.3.0", "driver=WMS_GRASS"],
                "cap_parser": lambda temp_file: WMSCapabilities(temp_file, "1.3.0"),
            },
            "WMTS": {
                "cmd": ["driver=WMTS_GRASS"],
                "cap_parser": WMTSCapabilities,
            },
            "OnEarth": {
                "cmd": ["driver=OnEarth_GRASS"],
                "cap_parser": OnEarthCapabilities,
            },
        }

        self.cmdStdErr = GStderr(self)
        self.cmd_thread = CmdThread(self)
        self.cap_file = grass.tempfile()

        reqDataBox = StaticBox(parent=self, label=_(" Requested data settings "))
        self._nb_sizer = wx.StaticBoxSizer(reqDataBox, wx.VERTICAL)
        self.notebook = GNotebook(
            parent=self, style=FN.FNB_FANCY_TABS | FN.FNB_NO_X_BUTTON | FN.FNB_NODRAG
        )

        self._requestPage()
        self._advancedSettsPage()

        self._layout()

        self.layerSelected = self.list.layerSelected

        self.Bind(EVT_CMD_DONE, self.OnCapDownloadDone)
        self.Bind(EVT_CMD_OUTPUT, self.OnCmdOutput)

        self.SetMinSize((-1, 300))

    def __del__(self):
        self.cmd_thread.abort(abortall=True)
        grass.try_remove(self.cap_file)

    def _layout(self):
        self._nb_sizer.Add(self.notebook, proportion=1, flag=wx.EXPAND)
        self.SetSizer(self._nb_sizer)

    def _requestPage(self):
        """Create request page"""
        self.req_page_panel = wx.Panel(parent=self, id=wx.ID_ANY)
        self.notebook.AddPage(
            page=self.req_page_panel, text=_("Request"), name="request"
        )

        # list of layers
        self.layersBox = StaticBox(
            parent=self.req_page_panel, id=wx.ID_ANY, label=_("List of layers ")
        )

        style = wx.TR_DEFAULT_STYLE | wx.TR_HAS_BUTTONS | wx.TR_FULL_ROW_HIGHLIGHT
        if self.drv_props["req_multiple_layers"]:
            style = style | wx.TR_MULTIPLE
        if "WMS" not in self.ws:
            style = style | wx.TR_HIDE_ROOT

        self.list = LayersList(
            parent=self.req_page_panel, web_service=self.ws, style=style
        )

        self.params["format"] = None

        self.params["srs"] = None
        if "srs" not in self.drv_props["ignored_params"]:
            projText = StaticText(
                parent=self.req_page_panel, id=wx.ID_ANY, label=_("Source projection:")
            )
            self.params["srs"] = wx.Choice(parent=self.req_page_panel, id=wx.ID_ANY)

        self.list.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnListSelChanged)

        # layout
        self.req_page_sizer = wx.BoxSizer(wx.VERTICAL)

        layersSizer = wx.StaticBoxSizer(self.layersBox, wx.HORIZONTAL)

        layersSizer.Add(
            self.list,
            proportion=1,
            flag=wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND,
            border=5,
        )

        self.req_page_sizer.Add(
            layersSizer,
            proportion=1,
            flag=wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND,
            border=5,
        )

        self.source_sizer = wx.BoxSizer(wx.HORIZONTAL)

        if self.params["format"] is not None:
            self.source_sizer.Add(
                self.params["format"], flag=wx.LEFT | wx.RIGHT | wx.BOTTOM, border=5
            )

        if self.params["srs"] is not None:
            self.source_sizer.Add(
                projText, flag=wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5
            )
            self.source_sizer.Add(
                self.params["srs"],
                flag=wx.ALIGN_CENTER_VERTICAL | wx.RIGHT | wx.TOP | wx.BOTTOM,
                border=5,
            )

        self.req_page_sizer.Add(
            self.source_sizer, flag=wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border=5
        )

        self.req_page_panel.SetSizer(self.req_page_sizer)

    def enableButtons(self, enable=True):
        """Enable/disable up, down, buttons"""
        self.btnUp.Enable(enable)
        self.btnDown.Enable(enable)

    def _advancedSettsPage(self):
        """Create advanced settings page"""
        # TODO parse maxcol, maxrow, settings from d.wms module?
        # TODO OnEarth driver - add selection of time
        adv_setts_panel = ScrolledPanel(
            parent=self, id=wx.ID_ANY, style=wx.TAB_TRAVERSAL | wx.SUNKEN_BORDER
        )
        self.notebook.AddPage(
            page=adv_setts_panel,
            text=_("Advanced request settings"),
            name="adv_req_setts",
        )

        labels = {}
        self.l_odrder_list = None
        if "WMS" in self.ws:
            labels["l_order"] = StaticBox(
                parent=adv_setts_panel,
                id=wx.ID_ANY,
                label=_("Order of layers in raster"),
            )
            self.l_odrder_list = wx.ListBox(
                adv_setts_panel,
                id=wx.ID_ANY,
                choices=[],
                style=wx.LB_SINGLE | wx.LB_NEEDED_SB,
            )
            self.btnUp = Button(adv_setts_panel, id=wx.ID_ANY, label=_("Up"))
            self.btnDown = Button(adv_setts_panel, id=wx.ID_ANY, label=_("Down"))

            self.btnUp.Bind(wx.EVT_BUTTON, self.OnUp)
            self.btnDown.Bind(wx.EVT_BUTTON, self.OnDown)

        labels["method"] = StaticText(
            parent=adv_setts_panel, id=wx.ID_ANY, label=_("Reprojection method:")
        )

        self.reproj_methods = ["nearest", "linear", "cubic", "cubicspline"]
        self.params["method"] = wx.Choice(
            parent=adv_setts_panel,
            id=wx.ID_ANY,
            choices=[
                _("Nearest neighbor"),
                _("Linear interpolation"),
                _("Cubic interpolation"),
                _("Cubic spline interpolation"),
            ],
        )

        labels["maxcols"] = StaticText(
            parent=adv_setts_panel,
            id=wx.ID_ANY,
            label=_("Maximum columns to request from server at time:"),
        )
        self.params["maxcols"] = SpinCtrl(
            parent=adv_setts_panel, id=wx.ID_ANY, size=(100, -1)
        )

        labels["maxrows"] = StaticText(
            parent=adv_setts_panel,
            id=wx.ID_ANY,
            label=_("Maximum rows to request from server at time:"),
        )
        self.params["maxrows"] = SpinCtrl(
            parent=adv_setts_panel, id=wx.ID_ANY, size=(100, -1)
        )

        min = 100
        max = 10000
        self.params["maxcols"].SetRange(min, max)
        self.params["maxrows"].SetRange(min, max)

        val = 500
        self.params["maxcols"].SetValue(val)
        self.params["maxrows"].SetValue(val)

        self.flags["o"] = self.params["bgcolor"] = None
        if "o" not in self.drv_props["ignored_flags"]:
            self.flags["o"] = wx.CheckBox(
                parent=adv_setts_panel,
                id=wx.ID_ANY,
                label=_("Do not request transparent data"),
            )

            self.flags["o"].Bind(wx.EVT_CHECKBOX, self.OnTransparent)
            labels["bgcolor"] = StaticText(
                parent=adv_setts_panel, id=wx.ID_ANY, label=_("Background color:")
            )
            self.params["bgcolor"] = csel.ColourSelect(
                parent=adv_setts_panel,
                id=wx.ID_ANY,
                colour=(255, 255, 255),
                size=globalvar.DIALOG_COLOR_SIZE,
            )
            self.params["bgcolor"].Enable(False)

        self.params["urlparams"] = None
        if self.params["urlparams"] not in self.drv_props["ignored_params"]:
            labels["urlparams"] = StaticText(
                parent=adv_setts_panel,
                id=wx.ID_ANY,
                label=_("Additional query parameters for server:"),
            )
            self.params["urlparams"] = TextCtrl(parent=adv_setts_panel, id=wx.ID_ANY)

        # layout

        border = wx.BoxSizer(wx.VERTICAL)

        if "WMS" in self.ws:

            boxSizer = wx.StaticBoxSizer(labels["l_order"], wx.VERTICAL)
            gridSizer = wx.GridBagSizer(hgap=3, vgap=3)

            gridSizer.Add(
                self.l_odrder_list,
                pos=(0, 0),
                span=(4, 1),
                flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND,
                border=0,
            )

            gridSizer.Add(
                self.btnUp, pos=(0, 1), flag=wx.ALIGN_CENTER_VERTICAL, border=0
            )

            gridSizer.Add(
                self.btnDown, pos=(1, 1), flag=wx.ALIGN_CENTER_VERTICAL, border=0
            )

            gridSizer.AddGrowableCol(0)
            boxSizer.Add(gridSizer, flag=wx.EXPAND | wx.ALL, border=5)

            border.Add(boxSizer, flag=wx.LEFT | wx.RIGHT | wx.UP | wx.EXPAND, border=5)

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

        row = 0
        for k in ["method", "maxcols", "maxrows", "o", "bgcolor"]:

            if k in self.params:
                param = self.params[k]
            elif k in self.flags:
                param = self.flags[k]

            if param is None:
                continue

            if k in labels or k == "o":
                if k != "o":
                    label = labels[k]
                else:
                    label = param

                gridSizer.Add(
                    label, flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL, pos=(row, 0)
                )

            if k != "o":
                gridSizer.Add(
                    param, flag=wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL, pos=(row, 1)
                )
            row += 1

        gridSizer.AddGrowableCol(0)
        border.Add(gridSizer, flag=wx.LEFT | wx.RIGHT | wx.TOP | wx.EXPAND, border=5)

        if self.params["urlparams"]:
            gridSizer = wx.GridBagSizer(hgap=3, vgap=3)

            row = 0
            gridSizer.Add(
                labels["urlparams"],
                flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL,
                pos=(row, 0),
            )

            gridSizer.Add(
                self.params["urlparams"],
                flag=wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL | wx.EXPAND,
                pos=(row, 1),
            )

            gridSizer.AddGrowableCol(1)

            border.Add(
                gridSizer, flag=wx.LEFT | wx.RIGHT | wx.TOP | wx.EXPAND, border=5
            )

        adv_setts_panel.SetSizer(border)
        adv_setts_panel.SetAutoLayout(True)
        adv_setts_panel.SetupScrolling()

    def OnUp(self, event):
        """Move selected layer up"""
        if self.l_odrder_list.GetSelections():
            pos = self.l_odrder_list.GetSelection()
            if pos:
                self.sel_layers.insert(pos - 1, self.sel_layers.pop(pos))
            if pos > 0:
                self._updateLayerOrderList(selected=(pos - 1))
            else:
                self._updateLayerOrderList(selected=0)

    def OnDown(self, event):
        """Move selected to down"""
        if self.l_odrder_list.GetSelections():
            pos = self.l_odrder_list.GetSelection()
            if pos != len(self.sel_layers) - 1:
                self.sel_layers.insert(pos + 1, self.sel_layers.pop(pos))
            if pos < len(self.sel_layers) - 1:
                self._updateLayerOrderList(selected=(pos + 1))
            else:
                self._updateLayerOrderList(selected=len(self.sel_layers) - 1)

    def _updateLayerOrderList(self, selected=None):
        """Update order in list."""

        def getlayercaption(l):
            if l["title"]:
                cap = l["title"]
            else:
                cap = l["name"]

            if l["style"]:
                if l["style"]["title"]:
                    cap += " / " + l["style"]["title"]
                else:
                    cap += " / " + l["style"]["name"]
            return cap

        layer_capts = [getlayercaption(l) for l in self.sel_layers]
        self.l_odrder_list.Set(layer_capts)
        if self.l_odrder_list.IsEmpty():
            self.enableButtons(False)
        else:
            self.enableButtons(True)
            if selected is not None:
                self.l_odrder_list.SetSelection(selected)
                self.l_odrder_list.EnsureVisible(selected)

    def OnTransparent(self, event):
        checked = event.IsChecked()
        if checked:
            self.params["bgcolor"].Enable(True)
        else:
            self.params["bgcolor"].Enable(False)

    def ConnectToServer(self, url, username, password):
        """Download and parse data from capabilities file.

        :param url: server url
        :type url: str
        :param username: username for connection
        :type username: str
        :param password: password for connection
        :type password: str
        """
        self._prepareForNewConn(url, username, password)
        cap_cmd = [
            "r.in.wms",
            "-c",
            ("capfile_output=%s" % self.cap_file),
            "--overwrite",
        ] + self.ws_cmdl

        self.currentPid = self.cmd_thread.GetId()
        self.cmd_thread.RunCmd(cap_cmd, stderr=self.cmdStdErr)

    def OnCmdOutput(self, event):
        """Manage cmd output."""
        if Debug.GetLevel() != 0:
            Debug.msg(1, event.text)
        elif event.type != "message" and event.type != "warning":
            self.cmd_err_str += event.text + os.linesep

    def _prepareForNewConn(self, url, username, password):
        """Prepare panel for new connection"""
        self.is_connected = False

        self.sel_layers = []
        self.formats_list = []
        self.projs_list = []

        self.conn = {"url": url, "password": password, "username": username}

        conn_cmd = []
        for k, v in six.iteritems(self.conn):
            if v:
                conn_cmd.append("%s=%s" % (k, v))

        self.ws_cmdl = self.ws_drvs[self.ws]["cmd"] + conn_cmd

    def OnCapDownloadDone(self, event):
        """Process downloaded capabilities file and emits capParsed
        signal (see class constructor).
        """
        if event.pid != self.currentPid:
            return

        if event.returncode != 0:
            if self.cmd_err_str:
                self.cmd_err_str = (
                    _(
                        "Unable to download %s capabilities file\nfrom <%s>:\n"
                        % (self.ws.replace("_", " "), self.conn["url"])
                    )
                    + self.cmd_err_str
                )
            self._postCapParsedEvt(error_msg=self.cmd_err_str)
            self.cmd_err_str = ""
            return

        self._parseCapFile(self.cap_file)

    def _parseCapFile(self, cap_file):
        """Parse capabilities data and emits capParsed signal
        (see class constructor).
        """
        try:
            self.cap = self.ws_drvs[self.ws]["cap_parser"](cap_file)
        except (IOError, ParseError) as error:
            error_msg = _(
                "%s web service was not found in fetched capabilities file from <%s>:\n%s\n"
                % (self.ws, self.conn["url"], str(error))
            )
            if Debug.GetLevel() != 0:
                Debug.msg(1, error_msg)
                self._postCapParsedEvt(None)
            else:
                self._postCapParsedEvt(error_msg=error_msg)
            return

        self.is_connected = True

        # WMS standard has formats defined for all layers
        if "WMS" in self.ws:
            self.formats_list = sorted(self._getFormats())
            self._updateFormatRadioBox(self.formats_list)
            self._setDefaultFormatVal()

        self.list.LoadData(self.cap)
        self.OnListSelChanged(event=None)

        self._postCapParsedEvt(None)

    def ParseCapFile(
        self,
        url,
        username,
        password,
        cap_file=None,
    ):
        """Parse capabilities data and emits capParsed signal
        (see class constructor).
        """
        self._prepareForNewConn(url, username, password)

        if cap_file is None or not url:
            self._postCapParsedEvt(None)
            return

        shutil.copyfile(cap_file, self.cap_file)

        self._parseCapFile(self.cap_file)

    def UpdateWidgetsByCmd(self, cmd):
        """Update panel widgets accordnig to passed cmd tuple

        :param cmd: cmd in tuple
        """

        dcmd = cmd[1]

        layers = []

        if "layers" in dcmd:
            layers = dcmd["layers"]

        styles = []
        if "styles" in dcmd:
            styles = dcmd["styles"]

        if "WMS" in self.ws:
            layers = layers.split(",")
            styles = styles.split(",")
        else:
            layers = [layers]
            styles = [styles]

        if len(layers) != len(styles):
            styles = [""] * len(layers)

        l_st_list = []
        for i in range(len(layers)):
            l_st_list.append({"style": styles[i], "layer": layers[i]})

        # WMS standard - first layer in params is most bottom...
        # therefore layers order need to be reversed
        l_st_list = [l for l in reversed(l_st_list)]
        self.list.SelectLayers(l_st_list)

        params = {}
        if "format" in dcmd:
            params["format"] = dcmd["format"]
        if "srs" in dcmd:
            params["srs"] = "EPSG:" + dcmd["srs"]
        if "method" in dcmd:
            params["method"] = dcmd["method"]

        for p, v in six.iteritems(params):
            if self.params[p]:
                self.params[p].SetStringSelection(v)

        for p, conv_f in [("urlparams", None), ("maxcols", int), ("maxrows", int)]:
            if p in dcmd:
                v = dcmd[p]
                if conv_f:
                    v = conv_f(v)
                self.params[p].SetValue(v)

        if "flags" in dcmd and "o" in dcmd["flags"]:
            self.flags["o"].SetValue(1)
            self.params["bgcolor"].Enable(True)

        if "bgcolor" in dcmd and self.params["bgcolor"]:
            bgcolor = dcmd["bgcolor"].strip().lower()
            if len(bgcolor) == 8 and "0x" == bgcolor[:2]:

                colour = "#" + bgcolor[2:]
                self.params["bgcolor"].SetColour(colour)

    def IsConnected(self):
        """Was successful in downloading and parsing capabilities data?"""
        return self.is_connected

    def _postCapParsedEvt(self, error_msg):
        """Helper function"""
        self.capParsed.emit(error_msg=error_msg)

    def CreateCmd(self):
        """Create d.wms cmd from values of panels widgets

        :return: cmd list
        :return: None if required widgets do not have selected/filled values.
        """

        # check required widgets
        if not self._checkImportValues():
            return None

        # create d.wms command
        lcmd = self.ws_cmdl
        lcmd = ["d.wms"] + lcmd

        layers = "layers="
        styles = "styles="
        first = True

        # WMS standard - first layer in params is most bottom...
        # therefore layers order need to be reversed
        for layer in reversed(self.sel_layers):
            if not first:
                layers += ","
                styles += ","
            first = False
            layers += layer["name"]
            if layer["style"] is not None:
                styles += layer["style"]["name"]

        lcmd.append(layers)
        lcmd.append(styles)

        if "format" not in self.drv_props["ignored_params"]:
            i_format = self.params["format"].GetSelection()
            lcmd.append("format=%s" % self.formats_list[i_format])

        if "srs" not in self.drv_props["ignored_params"]:
            i_srs = self.params["srs"].GetSelection()
            srs = self.projs_list[i_srs].split(":")[-1]
            epsg_num = int("".join(re.findall(r"\d+", srs)))

            lcmd.append("srs=%s" % epsg_num)

        for k in ["maxcols", "maxrows", "urlparams"]:
            lcmd.append(k + "=" + str(self.params[k].GetValue()))

        i_method = self.params["method"].GetSelection()
        lcmd.append("method=" + self.reproj_methods[i_method])

        if "o" not in self.drv_props["ignored_flags"] and self.flags["o"].IsChecked():
            lcmd.append("-o")

            c = self.params["bgcolor"].GetColour()
            hex_color = wx.Colour(c[0], c[1], c[2]).GetAsString(wx.C2S_HTML_SYNTAX)
            lcmd.append("bgcolor=" + "0x" + hex_color[1:])

        lcmd.append("map=" + self.o_layer_name)

        return lcmd

    def OnListSelChanged(self, event):
        """Update widgets according to selected layer in list."""
        curr_sel_ls = self.list.GetSelectedLayers()
        # update self.sel_layers (selected layer list)
        if "WMS" in self.ws:
            for sel_l in self.sel_layers[:]:
                if sel_l not in curr_sel_ls:
                    self.sel_layers.remove(sel_l)

            for l in curr_sel_ls:
                if l not in self.sel_layers:
                    self.sel_layers.append(l)

            self._updateLayerOrderList()
        else:
            self.sel_layers = curr_sel_ls

        # update projection

        self.projs_list = []
        projs_list = []

        intersect_proj = []
        first = True
        for l in curr_sel_ls:
            layer_projs = l["cap_intf_l"].GetLayerData("srs")
            if first:
                projs_list = layer_projs
                first = False
                continue

            projs_list = set(projs_list).intersection(layer_projs)

        if "srs" not in self.drv_props["ignored_params"]:

            for proj in projs_list:
                proj_code = Srs(proj.strip()).getcode()
                proj_spl = proj_code.split(":")
                if proj_spl[0].strip().lower() in self.drv_info.GetSrs():
                    # accept ogc:crs code
                    self.projs_list.append(proj_code)

            cur_sel = self.params["srs"].GetStringSelection()

            self.projs_list = sorted(self.projs_list)
            self.params["srs"].SetItems(self.projs_list)

            if cur_sel:
                self.params["srs"].SetStringSelection(cur_sel)
            else:
                try:
                    i = self.projs_list.index("EPSG:4326")
                    self.params["srs"].SetSelection(i)
                except ValueError:
                    if len(self.projs_list) > 0:
                        self.params["srs"].SetSelection(0)

        # update format

        if "WMS" not in self.ws and "format" not in self.drv_props["ignored_params"]:
            self.formats_list = []
            cur_sel = None

            if self.params["format"]:
                cur_sel = self.params["format"].GetStringSelection()

            if len(curr_sel_ls) > 0:
                self.formats_list = sorted(
                    self._getFormats(curr_sel_ls[0]["cap_intf_l"])
                )
                self._updateFormatRadioBox(self.formats_list)

                if cur_sel:
                    if self.params["format"]:
                        self.params["format"].SetStringSelection(cur_sel)
                else:
                    self._setDefaultFormatVal()

        self.Layout()

    def _setDefaultFormatVal(self):
        """Set default format value."""
        try:
            i = self.formats_list.index("png")
            self.params["format"].SetSelection(i)
        except ValueError:
            pass

    def _updateFormatRadioBox(self, formats_list):
        """Helper function"""
        if self.params["format"]:
            self.req_page_sizer.Detach(self.params["format"])
            self.params["format"].Destroy()
        if len(self.formats_list) > 0:
            self.params["format"] = wx.RadioBox(
                parent=self.req_page_panel,
                id=wx.ID_ANY,
                label=_("Source image format"),
                pos=wx.DefaultPosition,
                choices=formats_list,
                majorDimension=4,
                style=wx.RA_SPECIFY_COLS,
            )
            self.source_sizer.Insert(
                2,
                window=self.params["format"],
                flag=wx.LEFT | wx.RIGHT | wx.BOTTOM,
                border=5,
            )

    def _getFormats(self, layer=None):
        """Get formats

        WMS has formats defined generally for whole cap.
        In WMTS and NASA OnEarh formats are defined for layer.
        """
        formats_label = []
        if layer is None:
            formats_list = self.cap.GetFormats()
        else:
            formats_list = layer.GetLayerData("format")

        for frmt in formats_list:
            frmt = frmt.strip()
            label = self.drv_info.GetFormatLabel(frmt)

            if label:
                formats_label.append(label)

        return formats_label

    def _checkImportValues(
        self,
    ):
        """Check if required widgets are selected/filled"""
        warning_str = ""
        show_war = False
        if not self.list or not self.list.GetSelectedLayers():
            warning_str += _("Select layer in layer list.\n")
            show_war = True

        if (
            self.params["format"] is not None
            and self.params["format"].GetSelection() == -1
        ):
            warning_str += _("Select source image format.\n")
            show_war = True

        if self.params["srs"] is not None and self.params["srs"].GetSelection() == -1:
            warning_str += _("Select source projection.\n")
            show_war = True

        if not self.o_layer_name:
            warning_str += _("Choose output layer name.\n")
            show_war = True

        if show_war:
            GMessage(parent=self.parent, message=warning_str)
            return False

        return True

    def SetOutputLayerName(self, name):
        """Set name of layer to be added to layer tree"""
        self.o_layer_name = name

    def GetOutputLayerName(self):
        return self.o_layer_name

    def GetCapFile(self):
        """Get path to file where capabilities are saved"""
        return self.cap_file

    def GetWebService(self):
        """Get web service"""
        return self.ws
Example #29
0
class SQLBuilderSelect(SQLBuilder):
    """Class for building SELECT SQL statement"""

    def __init__(self, parent, vectmap, id=wx.ID_ANY,
                 layer=1, evtHandler=None):

        self.evtHandler = evtHandler

        # set dialog title
        title = _("GRASS SQL Builder (%(type)s) - <%(map)s>") % \
            {'type': "SELECT", 'map': vectmap}

        modeChoices = [_("Column to show (SELECT clause)"),
                       _("Constraint for query (WHERE clause)")]

        SQLBuilder.__init__(self, parent, title, vectmap, id=wx.ID_ANY,
                            modeChoices=modeChoices, layer=layer)

    def _doLayout(self, modeChoices):
        """Do dialog layout"""

        SQLBuilder._doLayout(self, modeChoices)

        self.text_sql.SetValue("SELECT * FROM %s" % self.tablename)
        self.text_sql.SetToolTip(
            _("Example: %s") %
            "SELECT * FROM roadsmajor WHERE MULTILANE = 'no' OR OBJECTID < 10")

        self.btn_verify = Button(parent=self.panel, id=wx.ID_ANY,
                                    label=_("Verify"))
        self.btn_verify.SetToolTip(_("Verify SQL statement"))

        self.buttonsizer.Insert(1, self.btn_verify)

        self.text_sql.Bind(wx.EVT_TEXT, self.OnText)
        self.btn_verify.Bind(wx.EVT_BUTTON, self.OnVerify)

        self.text_sql.SetInsertionPoint(self.text_sql.GetLastPosition())
        self.statusbar.SetStatusText(_("SQL statement not verified"), 0)

    def OnApply(self, event):
        """Apply button pressed"""
        if self.evtHandler:
            self.evtHandler(event='apply')

        if self.close_onapply.IsChecked():
            self.Destroy()

        event.Skip()

    def OnClear(self, event):
        """Clear button pressed"""
        self.text_sql.SetValue("SELECT * FROM %s" % self.tablename)

    def OnMode(self, event):
        """Adjusts builder for chosen mode"""
        if self.mode.GetSelection() == 0:
            self.valuespanel.Hide()
            self.btn_logicpanel.Hide()
        elif self.mode.GetSelection() == 1:
            self.valuespanel.Show()
            self.btn_logicpanel.Show()
        self.pagesizer.Layout()

    def OnText(self, event):
        """Query string changed"""
        if len(self.text_sql.GetValue()) > 0:
            self.btn_verify.Enable(True)
        else:
            self.btn_verify.Enable(False)

    def OnVerify(self, event):
        """Verify button pressed"""
        ret, msg = RunCommand('db.select',
                              getErrorMsg=True,
                              table=self.tablename,
                              sql=self.text_sql.GetValue(),
                              flags='t',
                              driver=self.driver,
                              database=self.database)

        if ret != 0 and msg:
            self.statusbar.SetStatusText(_("SQL statement is not valid"), 0)
            GError(parent=self,
                   message=_("SQL statement is not valid.\n\n%s") % msg)
        else:
            self.statusbar.SetStatusText(_("SQL statement is valid"), 0)

    def _add(self, element, value):
        """Add element to the query

        :param element: element to add (column, value)
        """
        sqlstr = self.text_sql.GetValue()
        curspos = self.text_sql.GetInsertionPoint()
        newsqlstr = ''
        if element == 'column':
            if self.mode.GetSelection() == 0:  # -> column
                idx1 = len('select')
                idx2 = sqlstr.lower().find('from')
                colstr = sqlstr[idx1:idx2].strip()
                if colstr == '*':
                    cols = []
                else:
                    cols = colstr.split(',')
                if value in cols:
                    cols.remove(value)
                else:
                    cols.append(value)

                if len(cols) < 1:
                    cols = ['*', ]
                newsqlstr = 'SELECT ' + ','.join(cols) + ' '
                curspos = len(newsqlstr)
                newsqlstr += sqlstr[idx2:]
            else:  # -> where
                newsqlstr = ''
                if sqlstr.lower().find('where') < 0:
                    newsqlstr += ' WHERE'
                newsqlstr += ' ' + value
                curspos = self.text_sql.GetLastPosition() + len(newsqlstr)
                newsqlstr = sqlstr + newsqlstr

        elif element in ['value', 'mark']:
            addstr = ' ' + value + ' '
            newsqlstr = sqlstr[:curspos] + addstr + sqlstr[curspos:]
            curspos += len(addstr)

        if newsqlstr:
            self.text_sql.SetValue(newsqlstr)

        wx.CallAfter(self.text_sql.SetFocus)
        self.text_sql.SetInsertionPoint(curspos)

    def CloseOnApply(self):
        """Return True if the dialog will be close on apply"""
        return self.close_onapply.IsChecked()

    def OnClose(self, event):
        """Close button pressed"""
        if self.evtHandler:
            self.evtHandler(event='close')

        SQLBuilder.OnClose(self, event)
Example #30
0
class DataCatalogFrame(wx.Frame):
    """Frame for testing purposes only."""
    def __init__(self, parent, giface=None):
        wx.Frame.__init__(self,
                          parent=parent,
                          title=_('GRASS GIS Data Catalog'))
        self.SetName("DataCatalog")
        self.SetIcon(
            wx.Icon(os.path.join(ICONDIR, 'grass.ico'), wx.BITMAP_TYPE_ICO))

        self._giface = giface
        self.panel = wx.Panel(self)

        self.toolbar = DataCatalogToolbar(parent=self)
        # workaround for http://trac.wxwidgets.org/ticket/13888
        if sys.platform != 'darwin':
            self.SetToolBar(self.toolbar)

        # tree
        self.tree = DataCatalogTree(parent=self.panel, giface=self._giface)
        self.tree.ReloadTreeItems()
        self.tree.UpdateCurrentDbLocationMapsetNode()
        self.tree.ExpandCurrentMapset()
        self.tree.changeMapset.connect(
            lambda mapset: self.ChangeDbLocationMapset(location=None,
                                                       mapset=mapset))
        self.tree.changeLocation.connect(
            lambda mapset, location, dbase: self.ChangeDbLocationMapset(
                dbase=dbase, location=location, mapset=mapset))

        # buttons
        self.btnClose = Button(parent=self.panel, id=wx.ID_CLOSE)
        self.btnClose.SetToolTip(_("Close GRASS GIS Data Catalog"))
        self.btnClose.SetDefault()

        # events
        self.btnClose.Bind(wx.EVT_BUTTON, self.OnCloseWindow)
        self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)

        self._layout()

    def _layout(self):
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.tree, proportion=1, flag=wx.EXPAND)

        btnSizer = wx.BoxSizer(wx.HORIZONTAL)
        btnSizer.AddStretchSpacer()
        btnSizer.Add(self.btnClose)

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

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

        self.SetMinSize((400, 500))

    def OnCloseWindow(self, event):
        """Cancel button pressed"""
        if not isinstance(event, wx.CloseEvent):
            self.Destroy()

        event.Skip()

    def OnReloadTree(self, event):
        """Reload whole tree"""
        self.tree.ReloadTreeItems()
        self.tree.ExpandCurrentMapset()

    def OnReloadCurrentMapset(self, event):
        """Reload current mapset tree only"""
        self.tree.ReloadCurrentMapset()

    def OnAddGrassDB(self, event):
        """Add an existing grass database"""
        dlg = wx.DirDialog(self, _("Choose GRASS data directory:"),
                           os.getcwd(), wx.DD_DEFAULT_STYLE)
        if dlg.ShowModal() == wx.ID_OK:
            grassdatabase = dlg.GetPath()
            self.tree.InsertGrassDb(name=grassdatabase)

        dlg.Destroy()

    def OnCreateMapset(self, event):
        """Create new mapset in current location"""
        db_node, loc_node, mapset_node = self.tree.GetCurrentDbLocationMapsetNode(
        )
        self.tree.CreateMapset(db_node, loc_node)

    def OnCreateLocation(self, event):
        """Create new location"""
        db_node, loc_node, mapset_node = self.tree.GetCurrentDbLocationMapsetNode(
        )
        self.tree.CreateLocation(db_node)

    def OnDownloadLocation(self, event):
        """Download location online"""
        db_node, loc_node, mapset_node = self.tree.GetCurrentDbLocationMapsetNode(
        )
        self.tree.DownloadLocation(db_node)

    def SetRestriction(self, restrict):
        """Allow editing other mapsets or restrict editing to current mapset"""
        self.tree.SetRestriction(restrict)

    def ChangeDbLocationMapset(self, mapset, location=None, dbase=None):
        """Change mapset, location or db"""
        if dbase:
            if RunCommand('g.mapset',
                          parent=self,
                          location=location,
                          mapset=mapset,
                          dbase=dbase) == 0:
                GMessage(parent=self,
                         message=_("Current GRASS database is <%(dbase)s>.\n"
                                   "Current location is <%(loc)s>.\n"
                                   "Current mapset is <%(mapset)s>.") % {
                                       'dbase': dbase,
                                       'loc': location,
                                       'mapset': mapset
                                   })
        elif location:
            if RunCommand('g.mapset',
                          parent=self,
                          location=location,
                          mapset=mapset) == 0:
                GMessage(parent=self,
                         message=_("Current location is <%(loc)s>.\n"
                                   "Current mapset is <%(mapset)s>.") % {
                                       'loc': location,
                                       'mapset': mapset
                                   })
        else:
            if RunCommand('g.mapset', parent=self, mapset=mapset) == 0:
                GMessage(parent=self,
                         message=_("Current mapset is <%s>.") % mapset)

    def Filter(self, text):
        self.tree.Filter(text=text)