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 __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()
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)
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()
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)
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)