Ejemplo n.º 1
0
class AttributeManager(wx.Frame, DbMgrBase):
    def __init__(self,
                 parent,
                 id=wx.ID_ANY,
                 title=None,
                 vectorName=None,
                 item=None,
                 log=None,
                 selection=None,
                 **kwargs):
        """GRASS Attribute Table Manager window

        :param parent: parent window
        :param id: window id
        :param title: window title or None for default title
        :param vectorName: name of vector map
        :param item: item from Layer Tree
        :param log: log window
        :param selection: name of page to be selected
        :param kwagrs: other wx.Frame's arguments
        """
        self.parent = parent
        try:
            mapdisplay = self.parent.GetMapDisplay()
        except:
            mapdisplay = None

        DbMgrBase.__init__(self,
                           id=id,
                           mapdisplay=mapdisplay,
                           vectorName=vectorName,
                           item=item,
                           log=log,
                           statusbar=self,
                           **kwargs)

        wx.Frame.__init__(self, parent, id, *kwargs)

        # title
        if not title:
            title = "%s" % _("GRASS GIS Attribute Table Manager - ")
            if not self.dbMgrData['editable']:
                title += _("READONLY - ")
            title += "<%s>" % (self.dbMgrData['vectName'])

        self.SetTitle(title)

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

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

        if len(self.dbMgrData['mapDBInfo'].layers.keys()) == 0:
            GMessage(parent=self.parent,
                     message=_("Database connection for vector map <%s> "
                               "is not defined in DB file. "
                               "You can define new connection in "
                               "'Manage layers' tab.") %
                     self.dbMgrData['vectName'])

        busy = wx.BusyInfo(_("Please wait, loading attribute data..."),
                           parent=self.parent)
        wx.SafeYield()
        self.CreateStatusBar(number=1)

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

        self.CreateDbMgrPage(parent=self, pageName='browse')

        self.notebook.AddPage(page=self.pages['browse'],
                              text=_("Browse data"),
                              name='browse')
        self.pages['browse'].SetTabAreaColour(globalvar.FNPageColor)

        self.CreateDbMgrPage(parent=self, pageName='manageTable')

        self.notebook.AddPage(page=self.pages['manageTable'],
                              text=_("Manage tables"),
                              name='table')
        self.pages['manageTable'].SetTabAreaColour(globalvar.FNPageColor)

        self.CreateDbMgrPage(parent=self, pageName='manageLayer')
        self.notebook.AddPage(page=self.pages['manageLayer'],
                              text=_("Manage layers"),
                              name='layers')
        del busy

        if selection:
            wx.CallAfter(self.notebook.SetSelectionByName, selection)
        else:
            wx.CallAfter(self.notebook.SetSelection, 0)  # select browse tab

        # buttons
        self.btnClose = CloseButton(parent=self.panel)
        self.btnClose.SetToolTip(_("Close Attribute Table Manager"))
        self.btnReload = Button(parent=self.panel, id=wx.ID_REFRESH)
        self.btnReload.SetToolTip(
            _("Reload currently selected attribute data"))
        self.btnReset = ClearButton(parent=self.panel)
        self.btnReset.SetToolTip(
            _("Reload all attribute data (drop current selection)"))

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

        # events
        self.btnClose.Bind(wx.EVT_BUTTON, self.OnCloseWindow)
        self.btnReload.Bind(wx.EVT_BUTTON, self.OnReloadData)
        self.btnReset.Bind(wx.EVT_BUTTON, self.OnReloadDataAll)
        self.notebook.Bind(FN.EVT_FLATNOTEBOOK_PAGE_CHANGED,
                           self.OnPageChanged)
        self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)

        # do layout
        self._layout()

        # self.SetMinSize(self.GetBestSize())
        self.SetSize((700, 550))  # FIXME hard-coded size
        self.SetMinSize(self.GetSize())

    def _layout(self):
        """Do layout"""
        # frame body
        mainSizer = wx.BoxSizer(wx.VERTICAL)

        # buttons
        btnSizer = wx.BoxSizer(wx.HORIZONTAL)
        btnSizer.Add(self.btnReset, proportion=1, flag=wx.ALL, border=5)
        btnSizer.Add(self.btnReload, proportion=1, flag=wx.ALL, border=5)
        btnSizer.Add(self.btnClose, proportion=1, flag=wx.ALL, border=5)

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

        self.panel.SetAutoLayout(True)
        self.panel.SetSizer(mainSizer)
        mainSizer.Fit(self.panel)
        self.Layout()

    def OnCloseWindow(self, event):
        """Cancel button pressed"""
        if self.parent and self.parent.GetName() == 'LayerManager':
            # deregister ATM
            self.parent.dialogs['atm'].remove(self)

        if not isinstance(event, wx.CloseEvent):
            self.Destroy()

        event.Skip()

    def OnReloadData(self, event):
        """Reload data"""
        if self.pages['browse']:
            self.pages['browse'].OnDataReload(event)  # TODO replace by signal

    def OnReloadDataAll(self, event):
        """Reload all data"""
        if self.pages['browse']:
            self.pages['browse'].ResetPage()

    def OnPageChanged(self, event):
        """On page in ATM is changed"""
        try:
            if self.pages["browse"]:
                selPage = self.pages["browse"].selLayer
                id = self.pages["browse"].layerPage[selPage]['data']
            else:
                id = None
        except KeyError:
            id = None

        if event.GetSelection() == self.notebook.GetPageIndexByName(
                'browse') and id:
            win = self.FindWindowById(id)
            if win:
                self.log.write(
                    _("Number of loaded records: %d") % win.GetItemCount())
            else:
                self.log.write("")
            self.btnReload.Enable()
            self.btnReset.Enable()
        else:
            self.log.write("")
            self.btnReload.Enable(False)
            self.btnReset.Enable(False)

        event.Skip()

    def OnTextEnter(self, event):
        pass

    def UpdateDialog(self, layer):
        """Updates dialog layout for given layer"""
        DbMgrBase.UpdateDialog(self, layer=layer)
        # set current page selection
        self.notebook.SetSelectionByName('layers')
Ejemplo n.º 2
0
class KrigingPanel(wx.Panel):
    """Main panel. Contains all widgets except Menus and Statusbar."""
    def __init__(self, parent, Rinstance, controller, *args, **kwargs):
        wx.Panel.__init__(self, parent, *args, **kwargs)

        self.parent = parent
        self.border = 4

        #    1. Input data
        InputBoxSizer = wx.StaticBoxSizer(
            wx.StaticBox(self, id=wx.ID_ANY, label=_("Input Data")),
            orient=wx.HORIZONTAL,
        )

        flexSizer = wx.FlexGridSizer(cols=3, hgap=5, vgap=5)
        flexSizer.AddGrowableCol(1)

        flexSizer.Add(
            wx.StaticText(self, id=wx.ID_ANY, label=_("Point dataset:")),
            flag=wx.ALIGN_CENTER_VERTICAL,
        )
        self.InputDataMap = gselect.VectorSelect(parent=self,
                                                 ftype="points",
                                                 updateOnPopup=False)
        self.InputDataMap.SetFocus()
        flexSizer.Add(self.InputDataMap, flag=wx.ALIGN_CENTER_VERTICAL)

        RefreshButton = wx.Button(self, id=wx.ID_REFRESH)
        RefreshButton.Bind(wx.EVT_BUTTON, self.OnButtonRefresh)
        flexSizer.Add(RefreshButton, flag=wx.ALIGN_CENTER_VERTICAL)

        flexSizer.Add(
            wx.StaticText(self, id=wx.ID_ANY, label=_("Numeric column:")),
            flag=wx.ALIGN_CENTER_VERTICAL,
        )
        self.InputDataColumn = gselect.ColumnSelect(self, id=wx.ID_ANY)
        flexSizer.Add(self.InputDataColumn)

        self.InputDataMap.GetChildren()[0].Bind(wx.EVT_TEXT,
                                                self.OnInputMapChanged)
        self.InputDataColumn.GetChildren()[0].Bind(wx.EVT_TEXT,
                                                   self.OnInputColumnChanged)

        InputBoxSizer.Add(flexSizer)

        # 2. Kriging. In book pages one for each R package. Includes variogram
        # fit.
        KrigingSizer = wx.StaticBoxSizer(
            wx.StaticBox(self, id=wx.ID_ANY, label=_("Kriging")),
            wx.HORIZONTAL)

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

        # , "geoR"]: #@TODO: enable it if/when it'll be implemented.
        for Rpackage in ["gstat"]:
            self.CreatePage(package=Rpackage,
                            Rinstance=Rinstance,
                            controller=controller)

        # Command output. From menuform module, cmdPanel class
        self._gconsole = gconsole.GConsole(guiparent=self)
        self.goutput = goutput.GConsoleWindow(parent=self,
                                              gconsole=self._gconsole,
                                              margin=False)
        self.goutputId = self.RPackagesBook.GetPageCount()
        self.outpage = self.RPackagesBook.AddPage(page=self.goutput,
                                                  text=_("Command output"),
                                                  name="output")
        self._gconsole.Bind(
            gconsole.EVT_CMD_RUN,
            lambda event: self._switchPageHandler(
                event=event, notification=Notification.MAKE_VISIBLE),
        )
        self._gconsole.Bind(
            gconsole.EVT_CMD_DONE,
            lambda event: self._switchPageHandler(
                event=event, notification=Notification.RAISE_WINDOW),
        )
        self.RPackagesBook.SetSelection(0)
        KrigingSizer.Add(self.RPackagesBook, proportion=1, flag=wx.EXPAND)

        #    3. Output Parameters.
        OutputSizer = wx.StaticBoxSizer(
            wx.StaticBox(self, id=wx.ID_ANY, label=_("Output")), wx.HORIZONTAL)

        OutputParameters = wx.GridBagSizer(hgap=5, vgap=5)
        OutputParameters.Add(
            wx.StaticText(self,
                          id=wx.ID_ANY,
                          label=_("Name for the output raster map:")),
            flag=wx.ALIGN_CENTER_VERTICAL,
            pos=(0, 0),
        )
        self.OutputMapName = gselect.Select(parent=self,
                                            id=wx.ID_ANY,
                                            type="raster",
                                            mapsets=[grass.gisenv()["MAPSET"]])
        OutputParameters.Add(self.OutputMapName,
                             flag=wx.EXPAND | wx.ALL,
                             pos=(0, 1))
        self.VarianceRasterCheckbox = wx.CheckBox(
            self, id=wx.ID_ANY, label=_("Export variance map as well: "))
        self.VarianceRasterCheckbox.SetValue(state=True)
        OutputParameters.Add(self.VarianceRasterCheckbox,
                             flag=wx.ALIGN_CENTER_VERTICAL,
                             pos=(1, 0))
        self.OutputVarianceMapName = gselect.Select(
            parent=self,
            id=wx.ID_ANY,
            type="raster",
            mapsets=[grass.gisenv()["MAPSET"]])
        self.VarianceRasterCheckbox.Bind(wx.EVT_CHECKBOX,
                                         self.OnVarianceCBChecked)
        OutputParameters.Add(self.OutputVarianceMapName,
                             flag=wx.EXPAND | wx.ALL,
                             pos=(1, 1))

        self.OverwriteCheckBox = wx.CheckBox(
            self,
            id=wx.ID_ANY,
            label=_("Allow output files to overwrite existing files"),
        )
        self.OverwriteCheckBox.SetValue(
            UserSettings.Get(group="cmd", key="overwrite", subkey="enabled"))
        OutputParameters.Add(self.OverwriteCheckBox, pos=(2, 0), span=(1, 2))

        OutputParameters.AddGrowableCol(1)
        OutputSizer.Add(OutputParameters,
                        proportion=0,
                        flag=wx.EXPAND | wx.ALL,
                        border=self.border)

        #    4. Run Button and Quit Button
        ButtonSizer = wx.BoxSizer(wx.HORIZONTAL)
        HelpButton = wx.Button(self, id=wx.ID_HELP)
        HelpButton.Bind(wx.EVT_BUTTON, self.OnHelpButton)
        QuitButton = wx.Button(self, id=wx.ID_EXIT)
        QuitButton.Bind(wx.EVT_BUTTON, self.OnCloseWindow)
        # no stock ID for Run button..
        self.RunButton = wx.Button(self, id=wx.ID_ANY, label=_("&Run"))
        self.RunButton.Bind(wx.EVT_BUTTON, self.OnRunButton)
        # disable it on loading the interface, as input map is not set
        self.RunButton.Enable(False)
        ButtonSizer.Add(HelpButton,
                        proportion=0,
                        flag=wx.ALIGN_LEFT | wx.ALL,
                        border=self.border)
        ButtonSizer.Add(QuitButton,
                        proportion=0,
                        flag=wx.ALIGN_RIGHT | wx.ALL,
                        border=self.border)
        ButtonSizer.Add(
            self.RunButton,
            proportion=0,
            flag=wx.ALIGN_RIGHT | wx.ALL,
            border=self.border,
        )

        #    Main Sizer. Add each child sizer as soon as it is ready.
        Sizer = wx.BoxSizer(wx.VERTICAL)
        Sizer.Add(InputBoxSizer,
                  proportion=0,
                  flag=wx.EXPAND | wx.ALL,
                  border=self.border)
        Sizer.Add(KrigingSizer,
                  proportion=1,
                  flag=wx.EXPAND | wx.ALL,
                  border=self.border)
        Sizer.Add(OutputSizer,
                  proportion=0,
                  flag=wx.EXPAND | wx.ALL,
                  border=self.border)
        Sizer.Add(ButtonSizer,
                  proportion=0,
                  flag=wx.ALIGN_RIGHT | wx.ALL,
                  border=self.border)
        self.SetSizerAndFit(Sizer)

        # last action of __init__: update imput data list.
        # it's performed in the few seconds gap while user examines interface before clicking anything.
        # @TODO: implement a splashcreen IF the maps cause a noticeable lag [markus' suggestion]
        self.InputDataMap.GetElementList()

    def CreatePage(self, package, Rinstance, controller):
        """Creates the three notebook pages, one for each R package"""
        for package in [
                "gstat"
        ]:  # @TODO add here other packages when they will be implemented
            classobj = eval("RBook" + package + "Panel")
            setattr(
                self,
                "RBook" + package + "Panel",
                (classobj(self,
                          id=wx.ID_ANY,
                          Rinstance=Rinstance,
                          controller=controller)),
            )
            self.RPackagesBook.AddPage(page=getattr(
                self, "RBook" + package + "Panel"),
                                       text=package)

    def OnButtonRefresh(self, event):
        """Forces refresh of list of available layers."""
        self.InputDataMap.GetElementList()

    def OnCloseWindow(self, event):
        """Cancel button pressed"""
        self.parent.Close()
        event.Skip()

    def OnHelpButton(self, event):
        grass.run_command("g.manual", entry="v.krige")
        event.Skip()

    def OnInputMapChanged(self, event):
        """Refreshes list of columns."""
        MapName = event.GetString()
        self.InputDataColumn.InsertColumns(
            vector=MapName,
            layer=1,
            excludeKey=False,
            type=["integer", "double precision"],
        )

    def OnInputColumnChanged(self, event):
        """Fills output map name TextCtrl"""
        MapName = self.InputDataMap.GetValue()
        enable = bool(self.InputDataColumn.GetValue())
        self.RunButton.Enable(enable)
        self.RBookgstatPanel.PlotButton.Enable(enable)

        if enable:
            self.OutputMapName.SetValue(MapName.split("@")[0] + "_kriging")
            self.OutputVarianceMapName.SetValue(
                MapName.split("@")[0] + "_kriging.var")
        else:
            self.OutputMapName.SetValue("")
            self.OutputVarianceMapName.SetValue("")

    def OnRunButton(self, event):
        """Execute R analysis."""
        # @FIXME: send data to main method instead of running it here.

        # -1: get the selected notebook page. The user shall know that [s]he can modify settings in all
        # pages, but only the selected one will be executed when Run is
        # pressed.
        SelectedPanel = self.RPackagesBook.GetCurrentPage()

        if (self.RPackagesBook.GetPageText(
                self.RPackagesBook.GetSelection()) == "Command output"):
            self._gconsole.WriteError(
                'No parameters for running. Please select "gstat" tab, check parameters and re-run.'
            )
            return False  # no break invoked by above function

        # mount command string as it would have been written on CLI
        command = [
            "v.krige",
            "input=" + self.InputDataMap.GetValue(),
            "column=" + self.InputDataColumn.GetValue(),
            "output=" + self.OutputMapName.GetValue(),
            "package=" + "%s" %
            self.RPackagesBook.GetPageText(self.RPackagesBook.GetSelection()),
        ]

        if (not hasattr(SelectedPanel, "VariogramCheckBox")
                or not SelectedPanel.VariogramCheckBox.IsChecked()):
            command.append("model=" + "%s" % SelectedPanel.ModelChoicebox.
                           GetStringSelection().split(" ")[0])

        for i in ["Psill", "Nugget", "Range", "Kappa"]:
            if getattr(SelectedPanel, i + "ChextBox").IsChecked():
                command.append(i.lower() + "=" + "%s" %
                               getattr(SelectedPanel, i + "Ctrl").GetValue())

        if SelectedPanel.KrigingRadioBox.GetStringSelection(
        ) == "Block kriging":
            command.append("block=" +
                           "%s" % SelectedPanel.BlockSpinBox.GetValue())
        if self.OverwriteCheckBox.IsChecked():
            command.append("--overwrite")
        if self.VarianceRasterCheckbox.IsChecked():
            command.append("output_var=" +
                           self.OutputVarianceMapName.GetValue())

        # give it to the output console
        # @FIXME: it runs the command as a NEW instance. Reimports data, recalculates variogram fit..
        # otherwise I can use Controller() and mimic RunCmd behaviour.
        self._gconsole.RunCmd(command)

    def OnVarianceCBChecked(self, event):
        self.OutputVarianceMapName.Enable(event.IsChecked())

    def _switchPageHandler(self, event, notification):
        self._switchPage(notification=notification)
        event.Skip()

    def _switchPage(self, notification):
        """Manages @c 'output' notebook page according to event notification."""
        if notification == Notification.HIGHLIGHT:
            self.RPackagesBook.HighlightPageByName("output")
        if notification == Notification.MAKE_VISIBLE:
            self.RPackagesBook.SetSelectionByName("output")
        if notification == Notification.RAISE_WINDOW:
            self.RPackagesBook.SetSelectionByName("output")
            self.SetFocus()
            self.Raise()