def OnUpdateTree(self, msg=None): """Update the tree when an action message is sent @param keyword: Message Object """ # Don't update when this window is not Active if self._mw != wx.GetApp().GetActiveWindow(): return page = self._GetCurrentCtrl() genfun = TagLoader.GetGenerator(page.GetLangId()) self._cjob += 1 # increment job Id if genfun is not None and self._ShouldUpdate(): ed_msg.PostMessage(ed_msg.EDMSG_PROGRESS_SHOW, (self._mw.GetId(), True)) # Start progress indicator in pulse mode ed_msg.PostMessage(ed_msg.EDMSG_PROGRESS_STATE, (self._mw.GetId(), -1, -1)) thread = TagGenThread(self, self._cjob, genfun, StringIO.StringIO(page.GetText())) wx.CallLater(75, thread.start) else: self._cdoc = None self.DeleteChildren(self.root) ed_msg.PostMessage(ed_msg.EDMSG_PROGRESS_SHOW, (self._mw.GetId(), False)) return
def OnFindAll(self, evt): """Find all results for the given query and display results in a L{FindResultsScreen} in the Shelf. """ smode = evt.GetSearchType() query = evt.GetFindString() if not query: return # Create a new search engine object engine = SearchEngine(query, evt.IsRegEx(), True, evt.IsMatchCase(), evt.IsWholeWord()) # Send the search function over to any interested parties that wish # to process the results. if smode == finddlg.LOCATION_CURRENT_DOC: stc = self._stc() fname = stc.GetFileName() if len(fname): ed_msg.PostMessage(ed_msg.EDMSG_START_SEARCH, (engine.SearchInFile, [fname,], dict())) else: engine.SetSearchPool(stc.GetTextRaw()) ed_msg.PostMessage(ed_msg.EDMSG_START_SEARCH, (engine.FindAllLines,)) elif smode == finddlg.LOCATION_OPEN_DOCS: files = [fname.GetFileName() for fname in self._parent.GetTextControls()] ed_msg.PostMessage(ed_msg.EDMSG_START_SEARCH, (engine.SearchInFiles, [files,], dict())) elif smode == finddlg.LOCATION_IN_FILES: path = evt.GetDirectory() ed_msg.PostMessage(ed_msg.EDMSG_START_SEARCH, (engine.SearchInDirectory, [path,], dict(recursive=evt.IsRecursive())))
def OnButton(self, evt): """Handle Button clicks""" e_id = evt.GetId() if e_id == wx.ID_NEW: # Get a unique label name for the new site lbl = _("New Site") count = 1 while lbl in self._tree.GetNodeLabels(): lbl = lbl + unicode(count) count += 1 # Add the new site to the config and tree view ConfigData.AddSite(lbl) item = self._tree.NewSite(lbl) ed_msg.PostMessage(EDMSG_FTPCFG_UPDATED, (lbl, )) elif e_id == wx.ID_DELETE: item = self._tree.GetSelection() # Cannot delete the root item. if item != self._tree.GetRootItem(): site = self._tree.GetItemText(item) # Delete from Config and tree view self._tree.Delete(item) ConfigData.RemoveSite(site) ed_msg.PostMessage(EDMSG_FTPCFG_UPDATED, (site, )) else: evt.Skip()
def OnJobTimer(self, evt): """Start a module find job""" if self._finder: util.Log("[PyFind][info] module %s" % self._module) mwid = self.GetMainWindow().GetId() ed_msg.PostMessage(ed_msg.EDMSG_PROGRESS_SHOW, (mwid, True)) ed_msg.PostMessage(ed_msg.EDMSG_PROGRESS_STATE, (mwid, -1, -1)) self._finder.Find(self._OnFindData)
def OnJobTimer(self, evt): """Start a syntax check job""" if self._checker: util.Log("[PyLint][info] fileName %s" % (self._curfile)) mwid = self.GetMainWindow().GetId() ed_msg.PostMessage(ed_msg.EDMSG_PROGRESS_SHOW, (mwid, True)) ed_msg.PostMessage(ed_msg.EDMSG_PROGRESS_STATE, (mwid, -1, -1)) # Update the label to show what file the results are for self._lbl.SetLabel(self._curfile) self._checker.Check(self._OnSyntaxData)
def GetPaths(self, path, files=False): """Get a list of paths that are part of the given path by default it will only return directories. @param path: Path to enumerate @keyword files: Get list of files too """ def append_slash(path): """Helper function that appends a slash to the path if it's a directory. """ if os.path.isdir(path) and not path.endswith(os.sep): return path + os.sep return path curdir = self._curdir head, tail = os.path.split(path) head = os.path.expanduser(head) head = os.path.expandvars(head) head = os.path.join(curdir, head) if not os.path.isdir(head): return [] # Return empty list of user does not have # read access to the directory if not os.access(head, os.R_OK): ed_msg.PostMessage( ed_msg.EDMSG_UI_SB_TXT, (ed_glob.SB_INFO, _("Access Denied: %s") % head)) wx.Bell() # Beep to alert return list() # We expanded head, so trim the suggestion list of its head # so we can add the tail of the suggestion back to the original head try: candidates = [ os.path.basename(p) for p in os.listdir(head) if p.startswith(tail) ] candidates = [ append_slash(os.path.join(os.path.dirname(path), cand)) for cand in candidates ] if not files: candidates = [ cand for cand in candidates if os.path.isdir(cand) ] except OSError: ed_msg.PostMessage(ed_msg.EDMSG_UI_SB_TXT, (ed_glob.SB_INFO, _("Invalid Path"))) candidates = list() return sorted(list(set(candidates)))
def _Busy(self, busy=True): """Start/stop the frames busy indicato @keyword busy: bool """ if busy: ed_msg.PostMessage(ed_msg.EDMSG_PROGRESS_SHOW, (self._pid, True)) ed_msg.PostMessage(ed_msg.EDMSG_PROGRESS_STATE, (self._pid, -1, -1)) else: ed_msg.PostMessage(ed_msg.EDMSG_PROGRESS_SHOW, (self._pid, False))
def SetCommandRunning(self, running=True): """Set whether a commadn is running or not @keyword running: bool """ self._busy = running self.GetParent().EnableCommandBar(not running) fid = self.GetTopLevelParent().GetId() if running: ed_msg.PostMessage(ed_msg.EDMSG_PROGRESS_SHOW, (fid, True)) ed_msg.PostMessage(ed_msg.EDMSG_PROGRESS_STATE, (fid, -1, -1)) else: ed_msg.PostMessage(ed_msg.EDMSG_PROGRESS_SHOW, (fid, False))
def _StartBusy(self, busy=True): """Start/Stop the main windows busy indicator @keyword busy: bool """ pid = self._mw.GetId() if busy: # Pulse ed_msg.PostMessage(ed_msg.EDMSG_PROGRESS_SHOW, (pid, True)) ed_msg.PostMessage(ed_msg.EDMSG_PROGRESS_STATE, (pid, -1, -1)) else: ed_msg.PostMessage(ed_msg.EDMSG_PROGRESS_STATE, (pid, 0, 0)) self._list.Enable(not busy)
def OnSaveSession(self, evt): """Save the current session""" ofiles = list() util.Log("[ed_session][info] OnSaveSession") if evt.EventObject is self._saveb: ed_msg.PostMessage(ed_msg.EDMSG_FILE_GET_OPENED, ofiles, self.TopLevelParent.Id) util.Log("[ed_session][info] OnSaveSession: %d files" % len(ofiles)) EdSessionMgr().SaveSession(self.GetSelectedSession(), ofiles) elif evt.EventObject is self._saveasb: ed_msg.PostMessage(ed_msg.EDMSG_SESSION_DO_SAVE, context=self.TopLevelParent.Id) # Bar will be updated by config change if the save succeeds else: evt.Skip()
def AddSite(self, name, url=u'', port=u'21', user=u'', pword=u'', path=u'', enc=u'utf-8'): """Add/Update a site in the configuration @param name: configuration name @keyword url: site url @keyword port: port number @keyword user: username @keyword pword: password @keyword path: default path @keyword enc: encoding """ data = dict(url=url, port=port, user=user, pword=pword, path=path, enc=enc) salt = os.urandom(8) pword = ed_crypt.Encrypt(data['pword'], salt) data['salt'] = salt data['pword'] = pword self._data[name] = data # Notify all others of change ed_msg.PostMessage(EDMSG_FTPCFG_UPDATED, (name, ))
def LoadFile(self, path): """Load the file at the given path into the buffer. Returns True if no errors and False otherwise. To retrieve the errors check the last error that was set in the file object returned by L{GetDocument}. @param path: path to file """ # Post notification that a file load is starting ed_msg.PostMessage(ed_msg.EDMSG_FILE_OPENING, path) self.file.SetPath(path) txt = self.file.Read() if txt is not None: if self.file.IsRawBytes() and not ebmlib.IsUnicode(txt): self.AddStyledText(txt) self.SetReadOnly(True) # Don't allow editing of raw bytes else: self.SetText(txt) else: self.file.SetPath('') return False if self.file.GetLastError() != 'None': # Return false if there was an encoding error and a fallback # was used. So the caller knows to check the error status return False else: return True
def LoadProject(self, proj): """Load the given project @param proj: ProjectFile instance or None to clear """ self.DeleteChildren(self.RootItem) if self.Project and self.Project.ProjectRoot: self.RemoveWatchDirectory(self._proj.ProjectRoot) self._proj = proj if not self.Project: return # cleared/closed current project # Repopulate root of tree item = self.AddWatchDirectory(self.Project.ProjectRoot) if item: iconmgr = ProjectUtil.FileIcons self.SetItemImage(item, iconmgr.IMG_PROJECT) self.Expand(item) # Update last project info ToolConfig.SetConfigValue(ToolConfig.TLC_LAST_PROJECT, self.Project.Path) ed_msg.PostMessage(PyStudioMessages.PYSTUDIO_PROJECT_LOADED, self.Project, self.Parent.MainWindow.Id) else: wx.MessageBox(_("Unable to load project: %s") % self.Project.ProjectName, _("PyStudio Error"), style=wx.OK | wx.CENTER | wx.ICON_ERROR) return
def DEBUGP(statement): """Prints debug messages and broadcasts them on the log message channel. Subscribing a listener with any of the EDMSG_LOG_* types will recieve its messages from this method. 1. Formatting - [object/module name][msg_type] message string 2. Message Type: - [err] : Notes an exception or error condition (high priority) - [warn] : Notes a error that is not severe (medium priority) - [info] : General information message (normal priority) - [evt] : Event related message (normal priority) Example: >>> DEBUGP("[ed_main][err] File failed to open") @param statement: Should be a formatted string that starts with two identifier blocks. The first is used to indicate the source of the message and is used as the primary means of filtering. The second block is the type of message, this is used to indicate the priority of the message and is used as the secondary means of filtering. """ # Create a LogMsg object from the statement string lbls = [lbl.strip() for lbl in RE_LOG_LBL.findall(statement)] info = RE_LOG_LBL.sub('', statement, 2).rstrip() if len(lbls) > 1: msg = LogMsg(info, lbls[0], lbls[1]) elif len(lbls) == 1: msg = LogMsg(info, lbls[0]) else: msg = LogMsg(info) # Only print to stdout when DEBUG is active if ed_glob.DEBUG: mstr = unicode(msg) print mstr.encode('utf-8', 'replace') # Check for trapped exceptions to print if ed_glob.VDEBUG and msg.Type in ('err', 'error'): traceback.print_exc() # Dispatch message to all interested parties if msg.Type in ('err', 'error'): mtype = ed_msg.EDMSG_LOG_ERROR if ed_glob.VDEBUG: msg = LogMsg(msg.Value + os.linesep + traceback.format_exc(), msg.Origin, msg.Type) elif msg.Type in ('warn', 'warning'): mtype = ed_msg.EDMSG_LOG_WARN elif msg.Type in ('evt', 'event'): mtype = ed_msg.EDMSG_LOG_EVENT elif msg.Type in ('info', 'information'): mtype = ed_msg.EDMSG_LOG_INFO else: mtype = ed_msg.EDMSG_LOG_ALL ed_msg.PostMessage(mtype, msg)
def SetOption(self, domain, optname, value): """Set a project option into the configuration @param optname: option name @param value: option value """ optionset = self._pxml.GetOptionSet(domain) if optionset is None: # Create the new grouping optionset = self._pxml.CreateOptionSet(domain) self._dirty = True # Set the option value in the option set option = optionset.GetOption(optname) if option is not None: if option.value != value: option.value = value self._dirty = True else: # New option optionset.SetOption(optname, value) self._dirty = True # Notify observers if self.Dirty: ed_msg.PostMessage( PyStudioMessages.PYSTUDIO_PROJECT_MODIFIED, dict(project=self, domain=domain, option=optname))
def _onitemrightclick(self, item): varname = self.GetItemText(item, VariablesList.COL_NAME) RpdbDebugger().setexpression(varname, True) RpdbDebugger().restoreexpressions() ed_msg.PostMessage( ed_msg.EDMSG_UI_SB_TXT, (ed_glob.SB_INFO, _("Added %s to PyExpression shelf.") % varname))
def ChangePage(self, pg_num, old=-2): """Change the page and focus to the the given page id @param pg_num: Page number to change @keyword old: previous selection """ cpage = self.GetSelection() if cpage != pg_num: self.SetSelection(pg_num) # Get the window that is the current page window = self.GetPage(pg_num) window.SetFocus() self.control = window # Update Frame Title self.frame.SetTitle(self.control.GetTitleString()) # Only post page changes when the change is not from the app exiting # NOTE: -2 is used as default value, cant use -1 as it comes from # page close events. if old > -2: cpage = old if not self.frame.IsExiting() and cpage != pg_num: ed_msg.PostMessage(ed_msg.EDMSG_UI_NB_CHANGED, (self, pg_num))
def ChangeDir(self, cmd): """Change to a directory based on cd command @param cmd: cd path """ path = cmd.replace('cd', '', 1).strip() if not os.path.isabs(path): if path.startswith('..'): path = os.path.abspath(path) elif path.startswith('~'): path = path.replace('~', wx.GetHomeDir(), 1) else: path = os.path.join(self._curdir, path) if os.path.exists(path) and os.path.isdir(path): if os.access(path, os.R_OK): os.chdir(path) self._curdir = os.path.abspath(os.path.curdir) + os.sep else: # Doesn't have permissions ed_msg.PostMessage(ed_msg.EDMSG_UI_SB_TXT, (ed_glob.SB_INFO, _("Can't change directory to: %s") % path)) wx.Bell() self.Clear() else: # Invalid path self.Clear() wx.Bell()
def OnMenu(self, evt): """Handle the context menu events for performing filesystem operations """ e_id = evt.GetId() path = self.GetItemPath(self._treeId) paths = self.GetPaths() ok = (False, '') if e_id == ID_EDIT: self.OpenFiles(paths) elif e_id == ID_OPEN: worker = OpenerThread(paths) worker.start() elif e_id == ID_REVEAL: worker = OpenerThread([os.path.dirname(fname) for fname in paths]) worker.start() elif e_id == ID_SEARCH_DIR: paths = self.GetPaths() if len(paths): path = paths[0] # Go off of the first selected item if not os.path.isdir(path): path = os.path.dirname(path) mdata = dict(mainw=self._mw, lookin=path) ed_msg.PostMessage(ed_msg.EDMSG_FIND_SHOW_DLG, mdata) elif e_id == ID_GETINFO: last = None for fname in paths: info = ed_mdlg.EdFileInfoDlg(self.GetTopLevelParent(), fname) if last is None: info.CenterOnParent() else: lpos = last.GetPosition() info.SetPosition((lpos[0] + 14, lpos[1] + 14)) info.Show() last = info elif e_id == ID_RENAME: self._tree.EditLabel(self._treeId) elif e_id == ID_NEW_FOLDER: ok = ebmlib.MakeNewFolder(path, _("Untitled_Folder")) elif e_id == ID_NEW_FILE: ok = ebmlib.MakeNewFile(path, _("Untitled_File") + ".txt") elif e_id == ID_DUPLICATE: for fname in paths: ok = DuplicatePath(fname) elif e_id == ID_ARCHIVE: ok = MakeArchive(path) elif e_id == ID_DELETE: ebmlib.MoveToTrash(paths) ok = (True, os.path.dirname(path)) else: evt.Skip() return if e_id in (ID_NEW_FOLDER, ID_NEW_FILE, ID_DUPLICATE, ID_ARCHIVE, ID_DELETE): if ok[0]: self.ReCreateTree() self._SCommand(self.SetPath, ok[1])
def _OnSyntaxData(self, data): # Data is something like # [('Syntax Error', '__all__ = ["CSVSMonitorThread"]', 7)] if len(data) != 0: self._listCtrl.PopulateRows(data) self._listCtrl.RefreshRows() mwid = self.GetMainWindow().GetId() ed_msg.PostMessage(ed_msg.EDMSG_PROGRESS_SHOW, (mwid, False))
def Save(self, force=False): """Save the project file to disk""" if self.Dirty or force: self._pxml.Write(self.Path) self._dirty = False # Post notification for any observers that project settings have # been saved to disk. ed_msg.PostMessage(PyStudioMessages.PYSTUDIO_PROJECT_SAVED, self)
def DoPostLoad(self): """Perform post file open actions""" if Profile_Get('SAVE_POS'): pos = self.DocMgr.GetPos(self.control.GetFileName()) self.control.GotoPos(pos) self.control.ScrollToColumn(0) ed_msg.PostMessage(ed_msg.EDMSG_FILE_OPENED, self.control.GetFileName())
def OnUpdateTree(self, msg=None, force=False): """Update the tree when an action message is sent @keyword msg: Message Object @keyword force: Force update """ # Don't update when this window is not Active if not force and not self._mw.IsActive(): return page = self._GetCurrentCtrl() cfname = page.GetFileName() # If its a blank document just clear out if not len(cfname): self._cdoc = None self.DeleteChildren(self.root) return # If document job is same as current don't start a new one if not force and self._lastjob == cfname: return else: self._lastjob = cfname # Get the generator method genfun = TagLoader.GetGenerator(page.GetLangId()) self._cjob += 1 # increment job Id # Check if we need to do updates if genfun is not None and (force or self._ShouldUpdate()): ed_msg.PostMessage(ed_msg.EDMSG_PROGRESS_SHOW, (self._mw.GetId(), True)) # Start progress indicator in pulse mode ed_msg.PostMessage(ed_msg.EDMSG_PROGRESS_STATE, (self._mw.GetId(), -1, -1)) thread = TagGenThread(self, self._cjob, genfun, StringIO.StringIO(page.GetText())) wx.CallLater(75, thread.start) else: self._cdoc = None self.DeleteChildren(self.root) ed_msg.PostMessage(ed_msg.EDMSG_PROGRESS_SHOW, (self._mw.GetId(), False)) return
def OpenFile(self, path): """Open a file from the connected ftp site @param path: file name """ ed_msg.PostMessage(ed_msg.EDMSG_UI_SB_TXT, (ed_glob.SB_INFO, _("Retrieving file") + u"...")) self._StartBusy(True) self._client.DownloadAsync(path)
def SetData(self, data): """Set the configurations site data @param data: dict(name=dict(url,port,user,pword,path,enc)) """ self._data = data # Notify of settings load ed_msg.PostMessage(EDMSG_FTPCFG_LOADED)
def OnPageClosed(self, evt): """Handles Paged Closed Event @param evt: event that called this handler @type evt: wx.lib.flatnotebook.EVT_FLATNOTEBOOK_PAGE_CLOSED """ cpage = self.GetSelection() evt.Skip() self.LOG("[ed_pages][evt] Closed Page: #%d" % cpage) ed_msg.PostMessage(ed_msg.EDMSG_UI_NB_CLOSED, (self, cpage))
def OnContextMenu(self, evt): """Handle right click menu events in the buffer""" self._menu.Clear() menu = ed_menu.EdMenu() menu.Append(ed_glob.ID_UNDO, _("Undo")) menu.Append(ed_glob.ID_REDO, _("Redo")) menu.AppendSeparator() menu.Append(ed_glob.ID_CUT, _("Cut")) menu.Append(ed_glob.ID_COPY, _("Copy")) menu.Append(ed_glob.ID_PASTE, _("Paste")) menu.AppendSeparator() menu.Append(ed_glob.ID_TO_UPPER, _("To Uppercase")) menu.Append(ed_glob.ID_TO_LOWER, _("To Lowercase")) menu.AppendSeparator() menu.Append(ed_glob.ID_SELECTALL, _("Select All")) # Allow clients to customize the context menu self._menu.SetMenu(menu) pos = evt.GetPosition() bpos = self.PositionFromPoint(self.ScreenToClient(pos)) self._menu.SetPosition(bpos) self._menu.SetUserData('buffer', self) ed_msg.PostMessage(ed_msg.EDMSG_UI_STC_CONTEXT_MENU, self._menu, self.GetId()) # Spell checking # TODO: de-couple to the forthcoming buffer service interface menu.InsertSeparator(0) words = self.GetWordFromPosition(bpos) self._spell_data['word'] = words sugg = self._spell.getSuggestions(words[0]) # Don't give suggestions if the selected word is in the suggestions list if words[0] in sugg: sugg = list() if not len(sugg): item = menu.Insert(0, EdEditorView.ID_NO_SUGGEST, _("No Suggestions")) item.Enable(False) else: sugg = reversed(sugg[:min(len(sugg), 3)]) ids = (ID_SPELL_1, ID_SPELL_2, ID_SPELL_3) del self._spell_data['choices'] self._spell_data['choices'] = list() for idx, sug in enumerate(sugg): id_ = ids[idx] self._menu.AddHandler(id_, self.OnSpelling) self._spell_data['choices'].append((id_, sug)) menu.Insert(0, id_, sug) self.PopupMenu(self._menu.Menu) evt.Skip()
def _OnFindData(self, data): """Find job callback @param data: PythonModuleFinder.FindResults """ self.taskbtn.Enable(True) self.textentry.Enable(True) self._listCtrl.PopulateRows(data) self._listCtrl.RefreshRows() mwid = self.GetMainWindow().GetId() ed_msg.PostMessage(ed_msg.EDMSG_PROGRESS_SHOW, (mwid, False))
def OnPageChanging(self, evt): """Page changing event handler. @param evt: event that called this handler @type evt: flatnotebook.EVT_FLATNOTEBOOK_PAGE_CHANGING """ evt.Skip() pages = (evt.GetOldSelection(), evt.GetSelection()) self.LOG("[ed_pages][evt] Control Changing from Page: " "%d to Page: %d\n" % pages) ed_msg.PostMessage(ed_msg.EDMSG_UI_NB_CHANGING, (self, ) + pages)
def RenameSite(self, oldSite, newName): """Re-associate the old sites data with the new sites name @param oldSite: old site name @param newName: new site name """ if oldSite in self._data: data = self._data[oldSite] self._data[newName] = data del self._data[oldSite] ed_msg.PostMessage(EDMSG_FTPCFG_UPDATED, (newName, ))