⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 findservice.py

📁 Wxpython Implemented on Windows CE, Source code
💻 PY
📖 第 1 页 / 共 2 页
字号:
#----------------------------------------------------------------------------
# Name:         FindService.py
# Purpose:      Find Service for pydocview
#
# Author:       Peter Yared, Morgan Hua
#
# Created:      8/15/03
# CVS-ID:       $Id: FindService.py,v 1.3 2005/12/30 23:01:34 RD Exp $
# Copyright:    (c) 2003-2005 ActiveGrid, Inc.
# License:      wxWindows License
#----------------------------------------------------------------------------

import wx
import wx.lib.docview
import wx.lib.pydocview
import re
_ = wx.GetTranslation


#----------------------------------------------------------------------------
# Constants
#----------------------------------------------------------------------------
FIND_MATCHPATTERN = "FindMatchPattern"
FIND_MATCHREPLACE = "FindMatchReplace"
FIND_MATCHCASE = "FindMatchCase"
FIND_MATCHWHOLEWORD = "FindMatchWholeWordOnly"
FIND_MATCHREGEXPR = "FindMatchRegularExpr"
FIND_MATCHWRAP = "FindMatchWrap"
FIND_MATCHUPDOWN = "FindMatchUpDown"

FIND_SYNTAXERROR = -2

SPACE = 10
HALF_SPACE = 5


#----------------------------------------------------------------------------
# Classes
#----------------------------------------------------------------------------

class FindService(wx.lib.pydocview.DocService):

    #----------------------------------------------------------------------------
    # Constants
    #----------------------------------------------------------------------------
    FIND_ID = wx.NewId()            # for bringing up Find dialog box
    FINDONE_ID = wx.NewId()         # for doing Find
    FIND_PREVIOUS_ID = wx.NewId()   # for doing Find Next
    FIND_NEXT_ID = wx.NewId()       # for doing Find Prev
    REPLACE_ID = wx.NewId()         # for bringing up Replace dialog box
    REPLACEONE_ID = wx.NewId()      # for doing a Replace
    REPLACEALL_ID = wx.NewId()      # for doing Replace All
    GOTO_LINE_ID = wx.NewId()       # for bringing up Goto dialog box

    # Extending bitmasks: wx.FR_WHOLEWORD, wx.FR_MATCHCASE, and wx.FR_DOWN
    FR_REGEXP = max([wx.FR_WHOLEWORD, wx.FR_MATCHCASE, wx.FR_DOWN]) << 1
    FR_WRAP = FR_REGEXP << 1


    def __init__(self):
        self._replaceDialog = None
        self._findDialog = None
        self._findReplaceData = wx.FindReplaceData()
        self._findReplaceData.SetFlags(wx.FR_DOWN)


    def InstallControls(self, frame, menuBar = None, toolBar = None, statusBar = None, document = None):
        """ Install Find Service Menu Items """
        editMenu = menuBar.GetMenu(menuBar.FindMenu(_("&Edit")))
        editMenu.AppendSeparator()
        editMenu.Append(FindService.FIND_ID, _("&Find...\tCtrl+F"), _("Finds the specified text"))
        wx.EVT_MENU(frame, FindService.FIND_ID, frame.ProcessEvent)
        wx.EVT_UPDATE_UI(frame, FindService.FIND_ID, frame.ProcessUpdateUIEvent)
        editMenu.Append(FindService.FIND_PREVIOUS_ID, _("Find &Previous\tShift+F3"), _("Finds the specified text"))
        wx.EVT_MENU(frame, FindService.FIND_PREVIOUS_ID, frame.ProcessEvent)
        wx.EVT_UPDATE_UI(frame, FindService.FIND_PREVIOUS_ID, frame.ProcessUpdateUIEvent)
        editMenu.Append(FindService.FIND_NEXT_ID, _("Find &Next\tF3"), _("Finds the specified text"))
        wx.EVT_MENU(frame, FindService.FIND_NEXT_ID, frame.ProcessEvent)
        wx.EVT_UPDATE_UI(frame, FindService.FIND_NEXT_ID, frame.ProcessUpdateUIEvent)
        editMenu.Append(FindService.REPLACE_ID, _("R&eplace...\tCtrl+H"), _("Replaces specific text with different text"))
        wx.EVT_MENU(frame, FindService.REPLACE_ID, frame.ProcessEvent)
        wx.EVT_UPDATE_UI(frame, FindService.REPLACE_ID, frame.ProcessUpdateUIEvent)
        editMenu.Append(FindService.GOTO_LINE_ID, _("&Go to Line...\tCtrl+G"), _("Goes to a certain line in the file"))
        wx.EVT_MENU(frame, FindService.GOTO_LINE_ID, frame.ProcessEvent)
        wx.EVT_UPDATE_UI(frame, FindService.GOTO_LINE_ID, frame.ProcessUpdateUIEvent)

        # wxBug: wxToolBar::GetToolPos doesn't exist, need it to find cut tool and then insert find in front of it.
        toolBar.InsertTool(6, FindService.FIND_ID, getFindBitmap(), shortHelpString = _("Find"), longHelpString = _("Finds the specified text"))
        toolBar.InsertSeparator(6)
        toolBar.Realize()

        frame.Bind(wx.EVT_FIND, frame.ProcessEvent)
        frame.Bind(wx.EVT_FIND_NEXT, frame.ProcessEvent)
        frame.Bind(wx.EVT_FIND_REPLACE, frame.ProcessEvent)
        frame.Bind(wx.EVT_FIND_REPLACE_ALL, frame.ProcessEvent)


    def ProcessUpdateUIEvent(self, event):
        id = event.GetId()
        if (id == FindService.FIND_ID
        or id == FindService.FIND_PREVIOUS_ID
        or id == FindService.FIND_NEXT_ID
        or id == FindService.REPLACE_ID
        or id == FindService.GOTO_LINE_ID):
            event.Enable(False)
            return True
        else:
            return False


    def ShowFindReplaceDialog(self, findString="", replace = False):
        """ Display find/replace dialog box.
        
            Parameters: findString is the default value shown in the find/replace dialog input field.
            If replace is True, the replace dialog box is shown, otherwise only the find dialog box is shown. 
        """
        if replace:
            if self._findDialog != None:
                # No reason to have both find and replace dialogs up at the same time
                self._findDialog.DoClose()
                self._findDialog = None

            self._replaceDialog = FindReplaceDialog(self.GetDocumentManager().FindSuitableParent(), -1, _("Replace"), size=(320,200), findString=findString)
            self._replaceDialog.CenterOnParent()
            self._replaceDialog.Show(True)
        else:
            if self._replaceDialog != None:
                # No reason to have both find and replace dialogs up at the same time
                self._replaceDialog.DoClose()
                self._replaceDialog = None

            self._findDialog = FindDialog(self.GetDocumentManager().FindSuitableParent(), -1, _("Find"), size=(320,200), findString=findString)
            self._findDialog.CenterOnParent()
            self._findDialog.Show(True)



    def OnFindClose(self, event):
        """ Cleanup handles when find/replace dialog is closed """
        if self._findDialog != None:
            self._findDialog = None
        elif self._replaceDialog != None:
            self._replaceDialog = None


    def GetCurrentDialog(self):
        """ return handle to either the find or replace dialog """
        if self._findDialog != None:
            return self._findDialog
        return self._replaceDialog


    def GetLineNumber(self, parent):
        """ Display Goto Line Number dialog box """
        line = -1
        dialog = wx.TextEntryDialog(parent, _("Enter line number to go to:"), _("Go to Line"))
        dialog.CenterOnParent()
        if dialog.ShowModal() == wx.ID_OK:
            try:
                line = int(dialog.GetValue())
                if line > 65535:
                    line = 65535
            except:
                pass
        dialog.Destroy()
        # This one is ugly:  wx.GetNumberFromUser("", _("Enter line number to go to:"), _("Go to Line"), 1, min = 1, max = 65535, parent = parent)
        return line


    def DoFind(self, findString, replaceString, text, startLoc, endLoc, down, matchCase, wholeWord, regExpr = False, replace = False, replaceAll = False, wrap = False):
        """ Do the actual work of the find/replace.
        
            Returns the tuple (count, start, end, newText).
            count = number of string replacements
            start = start position of found string
            end = end position of found string
            newText = new replaced text 
        """
        flags = 0
        if regExpr:
            pattern = findString
        else:
            pattern = re.escape(findString)  # Treat the strings as a literal string
        if not matchCase:
            flags = re.IGNORECASE
        if wholeWord:
            pattern = r"\b%s\b" % pattern
            
        try:
            reg = re.compile(pattern, flags)
        except:
            # syntax error of some sort
            import sys
            msgTitle = wx.GetApp().GetAppName()
            if not msgTitle:
                msgTitle = _("Regular Expression Search")
            wx.MessageBox(_("Invalid regular expression \"%s\". %s") % (pattern, sys.exc_value),
                          msgTitle,
                          wx.OK | wx.ICON_EXCLAMATION,
                          self.GetView())
            return FIND_SYNTAXERROR, None, None, None

        if replaceAll:
            newText, count = reg.subn(replaceString, text)
            if count == 0:
                return -1, None, None, None
            else:
                return count, None, None, newText

        start = -1
        if down:
            match = reg.search(text, endLoc)
            if match == None:
                if wrap:  # try again, but this time from top of file
                    match = reg.search(text, 0)
                    if match == None:
                        return -1, None, None, None
                else:
                    return -1, None, None, None
            start = match.start()
            end = match.end()
        else:
            match = reg.search(text)
            if match == None:
                return -1, None, None, None
            found = None
            i, j = match.span()
            while i < startLoc and j <= startLoc:
                found = match
                if i == j:
                    j = j + 1
                match = reg.search(text, j)
                if match == None:
                    break
                i, j = match.span()
            if found == None:
                if wrap:  # try again, but this time from bottom of file
                    match = reg.search(text, startLoc)
                    if match == None:
                        return -1, None, None, None
                    found = None
                    i, j = match.span()
                    end = len(text)
                    while i < end and j <= end:
                        found = match
                        if i == j:
                            j = j + 1
                        match = reg.search(text, j)
                        if match == None:
                            break
                        i, j = match.span()
                    if found == None:
                        return -1, None, None, None
                else:
                    return -1, None, None, None
            start = found.start()
            end = found.end()

        if replace and start != -1:
            newText, count = reg.subn(replaceString, text, 1)
            return count, start, end, newText

        return 0, start, end, None


    def SaveFindConfig(self, findString, wholeWord, matchCase, regExpr = None, wrap = None, upDown = None, replaceString = None):
        """ Save find/replace patterns and search flags to registry.
        
            findString = search pattern

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -