]> git.saurik.com Git - wxWidgets.git/blobdiff - wxPython/samples/ide/activegrid/tool/IDEFindService.py
Added the ActiveGrid IDE as a sample application
[wxWidgets.git] / 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 (file)
index 0000000..cd1b74b
--- /dev/null
@@ -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)
+
+