X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/510bb7480c5138dd5127ed3d8b1d9cbab39983c9..1f780e48af479e7bf9a07eaaa1ab6b41f1ffb17b:/wxPython/samples/ide/activegrid/tool/IDEFindService.py diff --git a/wxPython/samples/ide/activegrid/tool/IDEFindService.py b/wxPython/samples/ide/activegrid/tool/IDEFindService.py new file mode 100644 index 0000000000..cd1b74b363 --- /dev/null +++ b/wxPython/samples/ide/activegrid/tool/IDEFindService.py @@ -0,0 +1,445 @@ +#---------------------------------------------------------------------------- +# Name: IDEFindService.py +# Purpose: Find Service for pydocview +# +# Author: Morgan Hua +# +# Created: 8/15/03 +# CVS-ID: $Id$ +# Copyright: (c) 2004-2005 ActiveGrid, Inc. +# License: wxWindows License +#---------------------------------------------------------------------------- + +import wx +import wx.lib.docview +import os +from os.path import join +import re +import ProjectEditor +import MessageService +import FindService +import OutlineService +_ = wx.GetTranslation + + +#---------------------------------------------------------------------------- +# Constants +#---------------------------------------------------------------------------- +FILENAME_MARKER = _("Found in file: ") +PROJECT_MARKER = _("Searching project: ") +FIND_MATCHDIR = "FindMatchDir" +FIND_MATCHDIRSUBFOLDERS = "FindMatchDirSubfolders" + +SPACE = 10 +HALF_SPACE = 5 + + +class IDEFindService(FindService.FindService): + + #---------------------------------------------------------------------------- + # Constants + #---------------------------------------------------------------------------- + FINDALL_ID = wx.NewId() # for bringing up Find All dialog box + FINDDIR_ID = wx.NewId() # for bringing up Find Dir dialog box + + + def InstallControls(self, frame, menuBar = None, toolBar = None, statusBar = None, document = None): + FindService.FindService.InstallControls(self, frame, menuBar, toolBar, statusBar, document) + + editMenu = menuBar.GetMenu(menuBar.FindMenu(_("&Edit"))) + wx.EVT_MENU(frame, IDEFindService.FINDALL_ID, self.ProcessEvent) + wx.EVT_UPDATE_UI(frame, IDEFindService.FINDALL_ID, self.ProcessUpdateUIEvent) + editMenu.Append(IDEFindService.FINDALL_ID, _("Find in Project...\tCtrl+Shift+F"), _("Searches for the specified text in all the files in the project")) + wx.EVT_MENU(frame, IDEFindService.FINDDIR_ID, self.ProcessEvent) + wx.EVT_UPDATE_UI(frame, IDEFindService.FINDDIR_ID, self.ProcessUpdateUIEvent) + editMenu.Append(IDEFindService.FINDDIR_ID, _("Find in Directory..."), _("Searches for the specified text in all the files in the directory")) + + + def ProcessEvent(self, event): + id = event.GetId() + if id == IDEFindService.FINDALL_ID: + self.ShowFindAllDialog() + return True + elif id == IDEFindService.FINDDIR_ID: + self.ShowFindDirDialog() + return True + else: + return FindService.FindService.ProcessEvent(self, event) + + + def ProcessUpdateUIEvent(self, event): + id = event.GetId() + if id == IDEFindService.FINDALL_ID: + projectService = wx.GetApp().GetService(ProjectEditor.ProjectService) + view = projectService.GetView() + if view and view.GetDocument() and view.GetDocument().GetFiles(): + event.Enable(True) + else: + event.Enable(False) + return True + elif id == IDEFindService.FINDDIR_ID: + event.Enable(True) + else: + return FindService.FindService.ProcessUpdateUIEvent(self, event) + + + def ShowFindDirDialog(self): + config = wx.ConfigBase_Get() + + frame = wx.Dialog(None, -1, _("Find in Directory"), size= (320,200)) + borderSizer = wx.BoxSizer(wx.HORIZONTAL) + + contentSizer = wx.BoxSizer(wx.VERTICAL) + lineSizer = wx.BoxSizer(wx.HORIZONTAL) + lineSizer.Add(wx.StaticText(frame, -1, _("Directory:")), 0, wx.ALIGN_CENTER | wx.RIGHT, HALF_SPACE) + dirCtrl = wx.TextCtrl(frame, -1, config.Read(FIND_MATCHDIR, ""), size=(200,-1)) + dirCtrl.SetToolTipString(dirCtrl.GetValue()) + lineSizer.Add(dirCtrl, 0, wx.LEFT, HALF_SPACE) + findDirButton = wx.Button(frame, -1, "Browse...") + lineSizer.Add(findDirButton, 0, wx.LEFT, HALF_SPACE) + contentSizer.Add(lineSizer, 0, wx.BOTTOM, SPACE) + + def OnBrowseButton(event): + dlg = wx.DirDialog(frame, _("Choose a directory:"), style=wx.DD_DEFAULT_STYLE) + dir = dirCtrl.GetValue() + if len(dir): + dlg.SetPath(dir) + if dlg.ShowModal() == wx.ID_OK: + dirCtrl.SetValue(dlg.GetPath()) + dirCtrl.SetToolTipString(dirCtrl.GetValue()) + dirCtrl.SetInsertionPointEnd() + + dlg.Destroy() + wx.EVT_BUTTON(findDirButton, -1, OnBrowseButton) + + subfolderCtrl = wx.CheckBox(frame, -1, _("Search in subfolders")) + subfolderCtrl.SetValue(config.ReadInt(FIND_MATCHDIRSUBFOLDERS, True)) + contentSizer.Add(subfolderCtrl, 0, wx.BOTTOM, SPACE) + + lineSizer = wx.BoxSizer(wx.VERTICAL) # let the line expand horizontally without vertical expansion + lineSizer.Add(wx.StaticLine(frame, -1, size = (10,-1)), 0, flag=wx.EXPAND) + contentSizer.Add(lineSizer, flag=wx.EXPAND|wx.ALIGN_CENTER_VERTICAL|wx.BOTTOM, border=HALF_SPACE) + + lineSizer = wx.BoxSizer(wx.HORIZONTAL) + lineSizer.Add(wx.StaticText(frame, -1, _("Find what:")), 0, wx.ALIGN_CENTER | wx.RIGHT, HALF_SPACE) + findCtrl = wx.TextCtrl(frame, -1, config.Read(FindService.FIND_MATCHPATTERN, ""), size=(200,-1)) + lineSizer.Add(findCtrl, 0, wx.LEFT, HALF_SPACE) + contentSizer.Add(lineSizer, 0, wx.BOTTOM, SPACE) + wholeWordCtrl = wx.CheckBox(frame, -1, _("Match whole word only")) + wholeWordCtrl.SetValue(config.ReadInt(FindService.FIND_MATCHWHOLEWORD, False)) + matchCaseCtrl = wx.CheckBox(frame, -1, _("Match case")) + matchCaseCtrl.SetValue(config.ReadInt(FindService.FIND_MATCHCASE, False)) + regExprCtrl = wx.CheckBox(frame, -1, _("Regular expression")) + regExprCtrl.SetValue(config.ReadInt(FindService.FIND_MATCHREGEXPR, False)) + contentSizer.Add(wholeWordCtrl, 0, wx.BOTTOM, SPACE) + contentSizer.Add(matchCaseCtrl, 0, wx.BOTTOM, SPACE) + contentSizer.Add(regExprCtrl, 0, wx.BOTTOM, SPACE) + borderSizer.Add(contentSizer, 0, wx.TOP | wx.BOTTOM | wx.LEFT, SPACE) + + buttonSizer = wx.BoxSizer(wx.VERTICAL) + findBtn = wx.Button(frame, wx.ID_OK, _("Find")) + findBtn.SetDefault() + buttonSizer.Add(findBtn, 0, wx.BOTTOM, HALF_SPACE) + buttonSizer.Add(wx.Button(frame, wx.ID_CANCEL, _("Cancel")), 0) + borderSizer.Add(buttonSizer, 0, wx.ALL, SPACE) + + frame.SetSizer(borderSizer) + frame.Fit() + + status = frame.ShowModal() + + # save user choice state for this and other Find Dialog Boxes + dirString = dirCtrl.GetValue() + searchSubfolders = subfolderCtrl.IsChecked() + self.SaveFindDirConfig(dirString, searchSubfolders) + + findString = findCtrl.GetValue() + matchCase = matchCaseCtrl.IsChecked() + wholeWord = wholeWordCtrl.IsChecked() + regExpr = regExprCtrl.IsChecked() + self.SaveFindConfig(findString, wholeWord, matchCase, regExpr) + + while not os.path.exists(dirString): + dlg = wx.MessageDialog(frame, + _("'%s' does not exist.") % dirString, + _("Find in Directory"), + wx.OK | wx.ICON_EXCLAMATION + ) + dlg.ShowModal() + dlg.Destroy() + + status = frame.ShowModal() + + # save user choice state for this and other Find Dialog Boxes + dirString = dirCtrl.GetValue() + searchSubfolders = subfolderCtrl.IsChecked() + self.SaveFindDirConfig(dirString, searchSubfolders) + + findString = findCtrl.GetValue() + matchCase = matchCaseCtrl.IsChecked() + wholeWord = wholeWordCtrl.IsChecked() + regExpr = regExprCtrl.IsChecked() + self.SaveFindConfig(findString, wholeWord, matchCase, regExpr) + + if status == wx.ID_CANCEL: + break + + + if status == wx.ID_OK: + frame.Destroy() + + messageService = wx.GetApp().GetService(MessageService.MessageService) + messageService.ShowWindow() + + view = messageService.GetView() + if view: + wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT)) + view.ClearLines() + view.SetCallback(self.OnJumpToFoundLine) + + view.AddLines(_("Searching for '%s' in '%s'\n\n") % (findString, dirString)) + + if os.path.isfile(dirString): + try: + docFile = file(dirString, 'r') + lineNum = 1 + needToDisplayFilename = True + line = docFile.readline() + while line: + count, foundStart, foundEnd, newText = self.DoFind(findString, None, line, 0, 0, True, matchCase, wholeWord, regExpr) + if count != -1: + if needToDisplayFilename: + view.AddLines(FILENAME_MARKER + dirString + "\n") + needToDisplayFilename = False + line = repr(lineNum).zfill(4) + ":" + line + view.AddLines(line) + line = docFile.readline() + lineNum += 1 + if not needToDisplayFilename: + view.AddLines("\n") + except IOError, (code, message): + print _("Warning, unable to read file: '%s'. %s") % (dirString, message) + else: + # do search in files on disk + for root, dirs, files in os.walk(dirString): + if not searchSubfolders and root != dirString: + break + + for name in files: + filename = os.path.join(root, name) + try: + docFile = file(filename, 'r') + except IOError, (code, message): + print _("Warning, unable to read file: '%s'. %s") % (filename, message) + continue + + lineNum = 1 + needToDisplayFilename = True + line = docFile.readline() + while line: + count, foundStart, foundEnd, newText = self.DoFind(findString, None, line, 0, 0, True, matchCase, wholeWord, regExpr) + if count != -1: + if needToDisplayFilename: + view.AddLines(FILENAME_MARKER + filename + "\n") + needToDisplayFilename = False + line = repr(lineNum).zfill(4) + ":" + line + view.AddLines(line) + line = docFile.readline() + lineNum += 1 + if not needToDisplayFilename: + view.AddLines("\n") + + view.AddLines(_("Search completed.")) + wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) + + return True + else: + frame.Destroy() + return False + + + def SaveFindDirConfig(self, dirString, searchSubfolders): + """ Save search dir patterns and flags to registry. + + dirString = search directory + searchSubfolders = Search subfolders + """ + config = wx.ConfigBase_Get() + config.Write(FIND_MATCHDIR, dirString) + config.WriteInt(FIND_MATCHDIRSUBFOLDERS, searchSubfolders) + + + def ShowFindAllDialog(self): + config = wx.ConfigBase_Get() + + frame = wx.Dialog(None, -1, _("Find in Project"), size= (320,200)) + borderSizer = wx.BoxSizer(wx.HORIZONTAL) + + contentSizer = wx.BoxSizer(wx.VERTICAL) + lineSizer = wx.BoxSizer(wx.HORIZONTAL) + lineSizer.Add(wx.StaticText(frame, -1, _("Find what:")), 0, wx.ALIGN_CENTER | wx.RIGHT, HALF_SPACE) + findCtrl = wx.TextCtrl(frame, -1, config.Read(FindService.FIND_MATCHPATTERN, ""), size=(200,-1)) + lineSizer.Add(findCtrl, 0, wx.LEFT, HALF_SPACE) + contentSizer.Add(lineSizer, 0, wx.BOTTOM, SPACE) + wholeWordCtrl = wx.CheckBox(frame, -1, _("Match whole word only")) + wholeWordCtrl.SetValue(config.ReadInt(FindService.FIND_MATCHWHOLEWORD, False)) + matchCaseCtrl = wx.CheckBox(frame, -1, _("Match case")) + matchCaseCtrl.SetValue(config.ReadInt(FindService.FIND_MATCHCASE, False)) + regExprCtrl = wx.CheckBox(frame, -1, _("Regular expression")) + regExprCtrl.SetValue(config.ReadInt(FindService.FIND_MATCHREGEXPR, False)) + contentSizer.Add(wholeWordCtrl, 0, wx.BOTTOM, SPACE) + contentSizer.Add(matchCaseCtrl, 0, wx.BOTTOM, SPACE) + contentSizer.Add(regExprCtrl, 0, wx.BOTTOM, SPACE) + borderSizer.Add(contentSizer, 0, wx.TOP | wx.BOTTOM | wx.LEFT, SPACE) + + buttonSizer = wx.BoxSizer(wx.VERTICAL) + findBtn = wx.Button(frame, wx.ID_OK, _("Find")) + findBtn.SetDefault() + buttonSizer.Add(findBtn, 0, wx.BOTTOM, HALF_SPACE) + buttonSizer.Add(wx.Button(frame, wx.ID_CANCEL, _("Cancel")), 0) + borderSizer.Add(buttonSizer, 0, wx.ALL, SPACE) + + frame.SetSizer(borderSizer) + frame.Fit() + + status = frame.ShowModal() + + # save user choice state for this and other Find Dialog Boxes + findString = findCtrl.GetValue() + matchCase = matchCaseCtrl.IsChecked() + wholeWord = wholeWordCtrl.IsChecked() + regExpr = regExprCtrl.IsChecked() + self.SaveFindConfig(findString, wholeWord, matchCase, regExpr) + + if status == wx.ID_OK: + frame.Destroy() + + messageService = wx.GetApp().GetService(MessageService.MessageService) + messageService.ShowWindow() + + view = messageService.GetView() + if view: + view.ClearLines() + view.SetCallback(self.OnJumpToFoundLine) + + projectService = wx.GetApp().GetService(ProjectEditor.ProjectService) + projectFilenames = projectService.GetFilesFromCurrentProject() + + projView = projectService.GetView() + if projView: + projName = wx.lib.docview.FileNameFromPath(projView.GetDocument().GetFilename()) + view.AddLines(PROJECT_MARKER + projName + "\n\n") + + # do search in open files first, open files may have been modified and different from disk because it hasn't been saved + openDocs = wx.GetApp().GetDocumentManager().GetDocuments() + openDocsInProject = filter(lambda openDoc: openDoc.GetFilename() in projectFilenames, openDocs) + for openDoc in openDocsInProject: + if isinstance(openDoc, ProjectEditor.ProjectDocument): # don't search project model + continue + + openDocView = openDoc.GetFirstView() + # some views don't have a in memory text object to search through such as the PM and the DM + # even if they do have a non-text searchable object, how do we display it in the message window? + if not hasattr(openDocView, "GetValue"): + continue + text = openDocView.GetValue() + + lineNum = 1 + needToDisplayFilename = True + start = 0 + end = 0 + count = 0 + while count != -1: + count, foundStart, foundEnd, newText = self.DoFind(findString, None, text, start, end, True, matchCase, wholeWord, regExpr) + if count != -1: + if needToDisplayFilename: + view.AddLines(FILENAME_MARKER + openDoc.GetFilename() + "\n") + needToDisplayFilename = False + + lineNum = openDocView.LineFromPosition(foundStart) + line = repr(lineNum).zfill(4) + ":" + openDocView.GetLine(lineNum) + view.AddLines(line) + + start = text.find("\n", foundStart) + if start == -1: + break + end = start + if not needToDisplayFilename: + view.AddLines("\n") + openDocNames = map(lambda openDoc: openDoc.GetFilename(), openDocs) + + # do search in closed files, skipping the open ones we already searched + filenames = filter(lambda filename: filename not in openDocNames, projectFilenames) + for filename in filenames: + try: + docFile = file(filename, 'r') + except IOError, (code, message): + print _("Warning, unable to read file: '%s'. %s") % (filename, message) + continue + + lineNum = 1 + needToDisplayFilename = True + line = docFile.readline() + while line: + count, foundStart, foundEnd, newText = self.DoFind(findString, None, line, 0, 0, True, matchCase, wholeWord, regExpr) + if count != -1: + if needToDisplayFilename: + view.AddLines(FILENAME_MARKER + filename + "\n") + needToDisplayFilename = False + line = repr(lineNum).zfill(4) + ":" + line + view.AddLines(line) + line = docFile.readline() + lineNum += 1 + if not needToDisplayFilename: + view.AddLines("\n") + + view.AddLines(_("Search for '%s' completed.") % findString) + + return True + else: + frame.Destroy() + return False + + + def OnJumpToFoundLine(self, event): + messageService = wx.GetApp().GetService(MessageService.MessageService) + lineText, pos = messageService.GetView().GetCurrLine() + if lineText == "\n" or lineText.find(FILENAME_MARKER) != -1 or lineText.find(PROJECT_MARKER) != -1: + return + lineEnd = lineText.find(":") + if lineEnd == -1: + return + else: + lineNum = int(lineText[0:lineEnd]) + + text = messageService.GetView().GetText() + curPos = messageService.GetView().GetCurrentPos() + + startPos = text.rfind(FILENAME_MARKER, 0, curPos) + endPos = text.find("\n", startPos) + filename = text[startPos + len(FILENAME_MARKER):endPos] + + foundView = None + openDocs = wx.GetApp().GetDocumentManager().GetDocuments() + for openDoc in openDocs: + if openDoc.GetFilename() == filename: + foundView = openDoc.GetFirstView() + break + + if not foundView: + doc = wx.GetApp().GetDocumentManager().CreateDocument(filename, wx.lib.docview.DOC_SILENT) + foundView = doc.GetFirstView() + + if foundView: + foundView.GetFrame().SetFocus() + foundView.Activate() + if hasattr(foundView, "GotoLine"): + foundView.GotoLine(lineNum) + startPos = foundView.PositionFromLine(lineNum) + # wxBug: Need to select in reverse order, (end, start) to put cursor at head of line so positioning is correct + # Also, if we use the correct positioning order (start, end), somehow, when we open a edit window for the first + # time, we don't see the selection, it is scrolled off screen + foundView.SetSelection(startPos - 1 + len(lineText[lineEnd:].rstrip("\n")), startPos) + wx.GetApp().GetService(OutlineService.OutlineService).LoadOutline(foundView, position=startPos) + +