Ejemplo n.º 1
0
    def __init__(self, parent):
        """Main toolbar constructor"""

        BaseToolbar.__init__(self, parent)

        self.InitToolbar(self._toolbarData())
        self.filter_element = None
        self.filter = SearchCtrl(parent=self)
        self.filter.SetDescriptiveText(_("Search"))
        self.filter.ShowCancelButton(True)
        self.filter.SetSize((150, self.filter.GetBestSize()[1]))
        self.filter.Bind(
            wx.EVT_TEXT,
            lambda event: self.parent.Filter(self.filter.GetValue(), self.
                                             filter_element),
        )
        self.filter.Bind(wx.EVT_SEARCHCTRL_CANCEL_BTN,
                         lambda evt: self.parent.Filter(""))
        self.AddControl(self.filter)
        filterMenu = wx.Menu()
        item = filterMenu.AppendRadioItem(-1, "All")
        self.Bind(wx.EVT_MENU, self.OnFilterMenu, item)
        item = filterMenu.AppendRadioItem(-1, "Raster maps")
        self.Bind(wx.EVT_MENU, self.OnFilterMenu, item)
        item = filterMenu.AppendRadioItem(-1, "Vector maps")
        self.Bind(wx.EVT_MENU, self.OnFilterMenu, item)
        item = filterMenu.AppendRadioItem(-1, "3D raster maps")
        self.Bind(wx.EVT_MENU, self.OnFilterMenu, item)
        self.filter.SetMenu(filterMenu)
        help = _("Type to search database by map type or name. "
                 "Use Python regular expressions to refine your search.")
        self.SetToolShortHelp(self.filter.GetId(), help)
        # realize the toolbar
        self.Realize()
Ejemplo n.º 2
0
    def __init__(self,
                 parent,
                 handlerObj,
                 giface,
                 model,
                 id=wx.ID_ANY,
                 **kwargs):
        self.parent = parent
        self._handlerObj = handlerObj
        self._giface = giface
        self._model = model

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

        # search widget
        self._search = SearchCtrl(self)
        self._search.SetDescriptiveText(_("Search"))
        self._search.ShowCancelButton(True)
        self._btnAdvancedSearch = Button(self,
                                         id=wx.ID_ANY,
                                         label=_("Adva&nced search..."))
        self._btnAdvancedSearch.SetToolTip(
            _("Do advanced search using %s module") % "g.search.module")
        # tree
        self._tree = CTreeView(model=model, parent=self)
        self._tree.SetToolTip(_("Double-click to run selected module"))

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

        # bindings
        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._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._tree.selectionChanged.connect(self.OnItemSelected)
        self._tree.itemActivated.connect(lambda node: self.Run(node))

        self._layout()

        self._search.SetFocus()
Ejemplo n.º 3
0
class DataCatalogToolbar(BaseToolbar):
    """Main data catalog toolbar"""
    def __init__(self, parent):
        """Main toolbar constructor"""

        BaseToolbar.__init__(self, parent)

        self.InitToolbar(self._toolbarData())
        self.filter_element = None
        self.filter = SearchCtrl(parent=self)
        self.filter.SetDescriptiveText(_("Search"))
        self.filter.ShowCancelButton(True)
        self.filter.SetSize((150, self.filter.GetBestSize()[1]))
        self.filter.Bind(
            wx.EVT_TEXT,
            lambda event: self.parent.Filter(self.filter.GetValue(), self.
                                             filter_element),
        )
        self.filter.Bind(wx.EVT_SEARCHCTRL_CANCEL_BTN,
                         lambda evt: self.parent.Filter(""))
        self.AddControl(self.filter)
        filterMenu = wx.Menu()
        item = filterMenu.AppendRadioItem(-1, "All")
        self.Bind(wx.EVT_MENU, self.OnFilterMenu, item)
        item = filterMenu.AppendRadioItem(-1, "Raster maps")
        self.Bind(wx.EVT_MENU, self.OnFilterMenu, item)
        item = filterMenu.AppendRadioItem(-1, "Vector maps")
        self.Bind(wx.EVT_MENU, self.OnFilterMenu, item)
        item = filterMenu.AppendRadioItem(-1, "3D raster maps")
        self.Bind(wx.EVT_MENU, self.OnFilterMenu, item)
        self.filter.SetMenu(filterMenu)
        help = _("Type to search database by map type or name. "
                 "Use Python regular expressions to refine your search.")
        self.SetToolShortHelp(self.filter.GetId(), help)
        # realize the toolbar
        self.Realize()

    def _toolbarData(self):
        """Returns toolbar data (name, icon, handler)"""
        # BaseIcons are a set of often used icons. It is possible
        # to reuse icons in ./trunk/gui/icons/grass or add new ones there.
        return self._getToolbarData((
            ("reloadTree", icons["reloadTree"], self.parent.OnReloadTree),
            (
                "reloadMapset",
                icons["reloadMapset"],
                self.parent.OnReloadCurrentMapset,
            ),
            ("lock", icons["locked"], self.OnSetRestriction, wx.ITEM_CHECK),
            ("addGrassDB", icons["addGrassDB"], self.parent.OnAddGrassDB),
            ("addLocation", icons["addLocation"],
             self.parent.OnCreateLocation),
            (
                "downloadLocation",
                icons["downloadLocation"],
                self.parent.OnDownloadLocation,
            ),
            ("addMapset", icons["addMapset"], self.parent.OnCreateMapset),
            ("importRaster", icons["importRaster"],
             self.parent.OnImportGdalLayers),
            ("importVector", icons["importVector"],
             self.parent.OnImportOgrLayers),
            ("importLayer", icons["importLayer"], self.parent.OnImportMenu),
        ))

    def OnFilterMenu(self, event):
        """Decide the element to filter by"""
        filterMenu = self.filter.GetMenu().GetMenuItems()
        self.filter_element = None
        if filterMenu[1].IsChecked():
            self.filter_element = "raster"
        elif filterMenu[2].IsChecked():
            self.filter_element = "vector"
        elif filterMenu[3].IsChecked():
            self.filter_element = "raster_3d"
        # trigger filter on change
        if self.filter.GetValue():
            self.parent.Filter(self.filter.GetValue(), self.filter_element)

    def OnSetRestriction(self, event):
        if self.GetToolState(self.lock):
            self.SetToolNormalBitmap(self.lock, icons["unlocked"].GetBitmap())
            self.SetToolShortHelp(self.lock, icons["unlocked"].GetLabel())
            self.parent.SetRestriction(restrict=False)
        else:
            self.SetToolNormalBitmap(self.lock, icons["locked"].GetBitmap())
            self.SetToolShortHelp(self.lock, icons["locked"].GetLabel())
            self.parent.SetRestriction(restrict=True)
Ejemplo n.º 4
0
    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 modules "
        #                            "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 module"))
        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()
Ejemplo n.º 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 modules "
        #                            "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 module"))
        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 modules 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)
Ejemplo n.º 6
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._model = model

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

        # search widget
        self._search = SearchCtrl(self)
        self._search.SetDescriptiveText(_("Search"))
        self._search.ShowCancelButton(True)
        self._btnAdvancedSearch = Button(
            self, id=wx.ID_ANY, label=_("Adva&nced search...")
        )
        self._btnAdvancedSearch.SetToolTip(
            _("Do advanced search using %s tool") % "g.search.module"
        )
        # tree
        self._tree = CTreeView(model=model, parent=self)
        self._tree.SetToolTip(_("Double-click to run selected tool"))

        # buttons
        self._btnRun = Button(self, id=wx.ID_OK, label=_("&Run..."))
        self._btnRun.SetToolTip(_("Run selected tool from the tree"))
        self._btnHelp = Button(self, id=wx.ID_ANY, label=_("H&elp"))
        self._btnHelp.SetToolTip(_("Show manual for selected tool from the tree"))

        # bindings
        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._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._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)

        # search
        searchSizer = wx.BoxSizer(wx.HORIZONTAL)
        searchSizer.Add(self._search, proportion=1, flag=wx.EXPAND | wx.RIGHT, border=5)
        searchSizer.Add(self._btnAdvancedSearch, proportion=0, flag=wx.EXPAND)
        sizer.Add(searchSizer, proportion=0, flag=wx.EXPAND | wx.ALL, border=5)
        # body
        sizer.Add(
            self._tree, proportion=1, flag=wx.EXPAND | wx.LEFT | wx.RIGHT, border=5
        )

        # buttons
        btnSizer = wx.BoxSizer(wx.HORIZONTAL)
        btnSizer.AddStretchSpacer()
        btnSizer.Add(self._btnHelp, proportion=0, flag=wx.EXPAND | wx.RIGHT, border=5)
        btnSizer.Add(self._btnRun, proportion=0)

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

        self.SetSizerAndFit(sizer)
        self.SetAutoLayout(True)
        self.Layout()

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

    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:
            # expand/collapse location/mapset...
            if self._tree.IsNodeExpanded(node):
                self._tree.CollapseNode(node, recursive=False)
            else:
                self._tree.ExpandNode(node, recursive=False)
            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 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)