Added capability to configure use of an external "Find/Replace In Files" dialog. external_find

Fri, 29 Apr 2022 15:40:17 +0200

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Fri, 29 Apr 2022 15:40:17 +0200
branch
external_find
changeset 9038
90bcfdd63d47
parent 9037
907540e4f741
child 9039
3c8aa997bad8

Added capability to configure use of an external "Find/Replace In Files" dialog.

eric7/Preferences/ConfigurationPages/InterfacePage.py file | annotate | diff | comparison | revisions
eric7/Preferences/ConfigurationPages/InterfacePage.ui file | annotate | diff | comparison | revisions
eric7/Preferences/__init__.py file | annotate | diff | comparison | revisions
eric7/UI/FindFileWidget.py file | annotate | diff | comparison | revisions
eric7/UI/UserInterface.py file | annotate | diff | comparison | revisions
--- a/eric7/Preferences/ConfigurationPages/InterfacePage.py	Fri Apr 29 11:40:00 2022 +0200
+++ b/eric7/Preferences/ConfigurationPages/InterfacePage.py	Fri Apr 29 15:40:17 2022 +0200
@@ -87,6 +87,10 @@
         
         # integrated tools activation
         # left side
+        self.findReplaceCheckBox.setChecked(
+            Preferences.getUI("ShowFindFileWidget"))
+        self.findLocationCheckBox.setChecked(
+            Preferences.getUI("ShowFindLocationWidget"))
         self.templateViewerCheckBox.setChecked(
             Preferences.getUI("ShowTemplateViewer"))
         self.fileBrowserCheckBox.setChecked(
@@ -184,6 +188,12 @@
         # save the integrated tools activation
         # left side
         Preferences.setUI(
+            "ShowFindFileWidget",
+            self.findReplaceCheckBox.isChecked())
+        Preferences.setUI(
+            "ShowFindLocationWidget",
+            self.findLocationCheckBox.isChecked())
+        Preferences.setUI(
             "ShowTemplateViewer",
             self.templateViewerCheckBox.isChecked())
         Preferences.setUI(
--- a/eric7/Preferences/ConfigurationPages/InterfacePage.ui	Fri Apr 29 11:40:00 2022 +0200
+++ b/eric7/Preferences/ConfigurationPages/InterfacePage.ui	Fri Apr 29 15:40:17 2022 +0200
@@ -433,7 +433,17 @@
          <string>Left Side</string>
         </property>
         <layout class="QGridLayout" name="gridLayout_5">
-         <item row="0" column="0">
+         <item row="2" column="0">
+          <widget class="QCheckBox" name="symbolsCheckBox">
+           <property name="toolTip">
+            <string>Select to activate the Symbols widget</string>
+           </property>
+           <property name="text">
+            <string>Symbols</string>
+           </property>
+          </widget>
+         </item>
+         <item row="1" column="0">
           <widget class="QCheckBox" name="templateViewerCheckBox">
            <property name="toolTip">
             <string>Select to activate the Template viewer</string>
@@ -443,7 +453,7 @@
            </property>
           </widget>
          </item>
-         <item row="0" column="1">
+         <item row="1" column="1">
           <widget class="QCheckBox" name="fileBrowserCheckBox">
            <property name="toolTip">
             <string>Select to activate the File-Browser widget</string>
@@ -453,13 +463,23 @@
            </property>
           </widget>
          </item>
-         <item row="1" column="0">
-          <widget class="QCheckBox" name="symbolsCheckBox">
+         <item row="0" column="0">
+          <widget class="QCheckBox" name="findReplaceCheckBox">
            <property name="toolTip">
-            <string>Select to activate the Symbols widget</string>
+            <string>Select to activate the embedded Find/Replace In Files tool.</string>
            </property>
            <property name="text">
-            <string>Symbols</string>
+            <string>Find/Replace In Files</string>
+           </property>
+          </widget>
+         </item>
+         <item row="0" column="1">
+          <widget class="QCheckBox" name="findLocationCheckBox">
+           <property name="toolTip">
+            <string>Select to activate the embedded Find File tool.</string>
+           </property>
+           <property name="text">
+            <string>Find File</string>
            </property>
           </widget>
          </item>
@@ -643,6 +663,8 @@
   <tabstop>combinedLeftRightSidebarCheckBox</tabstop>
   <tabstop>languageComboBox</tabstop>
   <tabstop>layoutComboBox</tabstop>
+  <tabstop>findReplaceCheckBox</tabstop>
+  <tabstop>findLocationCheckBox</tabstop>
   <tabstop>templateViewerCheckBox</tabstop>
   <tabstop>fileBrowserCheckBox</tabstop>
   <tabstop>symbolsCheckBox</tabstop>
--- a/eric7/Preferences/__init__.py	Fri Apr 29 11:40:00 2022 +0200
+++ b/eric7/Preferences/__init__.py	Fri Apr 29 15:40:17 2022 +0200
@@ -142,6 +142,8 @@
         "ShowTemplateViewer": True,             # left side
         "ShowFileBrowser": True,                # left side
         "ShowSymbolsViewer": True,              # left side
+        "ShowFindFileWidget": True,             # left side
+        "ShowFindLocationWidget": True,         # left side
         "ShowCodeDocumentationViewer": True,    # right side
         "ShowPyPIPackageManager": True,         # right side
         "ShowCondaPackageManager": True,        # right side
@@ -1930,37 +1932,39 @@
     @param key the key of the value to get
     @return the requested UI setting
     """
-    if key in ["BrowsersListFoldersFirst", "BrowsersHideNonPublic",
-               "BrowsersListContentsByOccurrence", "BrowsersListHiddenFiles",
-               "BrowserShowCoding", "LogViewerAutoRaise",
-               "SingleApplicationMode", "TabViewManagerFilenameOnly",
-               "ShowFilePreview", "ShowFilePreviewJS", "ShowFilePreviewSSI",
-               "CaptionShowsFilename", "ShowSplash",
-               "SplitOrientationVertical", "DynamicOnlineCheck",
-               "UseProxy", "UseSystemProxy", "UseHttpProxyForAll",
-               "RequestDownloadFilename", "CheckErrorLog",
-               "OpenCrashSessionOnStartup", "CrashSessionEnabled",
-               "ShowCodeDocumentationViewer", "ShowPyPIPackageManager",
-               "ShowCondaPackageManager", "ShowCooperation", "ShowIrc",
-               "ShowTemplateViewer", "ShowFileBrowser", "ShowSymbolsViewer",
-               "ShowNumbersViewer", "ShowMicroPython",
-               "ShowInternalHelpViewer", "UseNativeMenuBar",
-               "CombinedLeftRightSidebar"]:
+    if key in [
+        "BrowsersListFoldersFirst", "BrowsersHideNonPublic",
+        "BrowsersListContentsByOccurrence", "BrowsersListHiddenFiles",
+        "BrowserShowCoding", "LogViewerAutoRaise", "SingleApplicationMode",
+        "TabViewManagerFilenameOnly", "ShowFilePreview", "ShowFilePreviewJS",
+        "ShowFilePreviewSSI", "CaptionShowsFilename", "ShowSplash",
+        "SplitOrientationVertical", "DynamicOnlineCheck", "UseProxy",
+        "UseSystemProxy", "UseHttpProxyForAll", "RequestDownloadFilename",
+        "CheckErrorLog", "OpenCrashSessionOnStartup", "CrashSessionEnabled",
+        "ShowCodeDocumentationViewer", "ShowPyPIPackageManager",
+        "ShowCondaPackageManager", "ShowCooperation", "ShowIrc",
+        "ShowTemplateViewer", "ShowFileBrowser", "ShowSymbolsViewer",
+        "ShowNumbersViewer", "ShowMicroPython", "ShowFindFileWidget",
+        "ShowFindLocationWidget", "ShowInternalHelpViewer", "UseNativeMenuBar",
+        "CombinedLeftRightSidebar",
+    ]:
         return toBool(Prefs.settings.value(
             "UI/" + key, Prefs.uiDefaults[key]))
-    elif key in ["TabViewManagerFilenameLength", "CaptionFilenameLength",
-                 "ProxyPort/Http", "ProxyPort/Https", "ProxyPort/Ftp",
-                 "OpenOnStartup", "PerformVersionCheck", "RecentNumber",
-                 "NotificationTimeout", "UpgraderDelay",
-                 "KeyboardInputInterval", "BackgroundServiceProcesses",
-                 "MinimumMessageTypeSeverity"]:
+    elif key in [
+        "TabViewManagerFilenameLength", "CaptionFilenameLength",
+        "ProxyPort/Http", "ProxyPort/Https", "ProxyPort/Ftp",
+        "OpenOnStartup", "PerformVersionCheck", "RecentNumber",
+        "NotificationTimeout", "UpgraderDelay", "KeyboardInputInterval",
+        "BackgroundServiceProcesses", "MinimumMessageTypeSeverity",
+    ]:
         return int(Prefs.settings.value(
             "UI/" + key, Prefs.uiDefaults[key]))
     elif key in ["ProxyType/Ftp", ]:
         return EricFtpProxyType(int(Prefs.settings.value(
             "UI/" + key, Prefs.uiDefaults[key].value)))
-    elif key in ["ProxyPassword/Http", "ProxyPassword/Https",
-                 "ProxyPassword/Ftp", ]:
+    elif key in [
+        "ProxyPassword/Http", "ProxyPassword/Https", "ProxyPassword/Ftp",
+    ]:
         from Utilities.crypto import pwConvert
         return pwConvert(
             Prefs.settings.value("UI/" + key, Prefs.uiDefaults[key]),
@@ -1999,8 +2003,10 @@
             return state
         else:
             return Prefs.uiDefaults[key]
-    elif key in ["LogViewerStdoutFilter", "LogViewerStderrFilter",
-                 "LogViewerStdxxxFilter", "TextMimeTypes"]:
+    elif key in [
+        "LogViewerStdoutFilter", "LogViewerStderrFilter",
+        "LogViewerStdxxxFilter", "TextMimeTypes"
+    ]:
         return toList(
             Prefs.settings.value("UI/" + key, Prefs.uiDefaults[key]))
     else:
--- a/eric7/UI/FindFileWidget.py	Fri Apr 29 11:40:00 2022 +0200
+++ b/eric7/UI/FindFileWidget.py	Fri Apr 29 15:40:17 2022 +0200
@@ -14,7 +14,8 @@
 from PyQt6.QtCore import pyqtSignal, pyqtSlot, Qt, QPoint, QUrl
 from PyQt6.QtGui import QCursor, QDesktopServices, QImageReader
 from PyQt6.QtWidgets import (
-    QWidget, QApplication, QMenu, QTreeWidgetItem, QComboBox
+    QWidget, QApplication, QMenu, QTreeWidgetItem, QComboBox, QDialog,
+    QDialogButtonBox, QVBoxLayout
 )
 
 from EricWidgets.EricApplication import ericApp
@@ -89,16 +90,20 @@
         self.stopButton.setEnabled(False)
         self.stopButton.clicked.connect(self.__stopSearch)
         self.stopButton.setIcon(UI.PixmapCache.getIcon("stopLoading"))
+        self.stopButton.setAutoDefault(False)
         
         self.findButton.setEnabled(False)
         self.findButton.clicked.connect(self.__doSearch)
         self.findButton.setIcon(UI.PixmapCache.getIcon("find"))
+        self.findButton.setAutoDefault(False)
         
         self.clearButton.setEnabled(False)
         self.clearButton.clicked.connect(self.__clearResults)
         self.clearButton.setIcon(UI.PixmapCache.getIcon("clear"))
+        self.clearButton.setAutoDefault(False)
         
         self.replaceButton.setIcon(UI.PixmapCache.getIcon("editReplace"))
+        self.replaceButton.setAutoDefault(False)
         
         self.modeToggleButton.clicked.connect(self.__toggleReplaceMode)
         
@@ -898,4 +903,96 @@
         cb = QApplication.clipboard()
         cb.setText(fn)
 
-# TODO: add separate dialog variant
+
+class FindFileDialog(QDialog):
+    """
+    Class implementing a dialog to search for text in files and replace it
+    with some other text.
+    
+    The occurrences found are displayed in a tree showing the file name,
+    the line number and the text found. The file will be opened upon a double
+    click onto the respective entry of the list. If the widget is in replace
+    mode the line below shows the text after replacement. Replacements can
+    be authorized by ticking them on. Pressing the replace button performs
+    all ticked replacement operations.
+    
+    @signal sourceFile(str, int, str, int, int) emitted to open a source file
+        at a specificline
+    @signal designerFile(str) emitted to open a Qt-Designer file
+    @signal linguistFile(str) emitted to open a Qt-Linguist (*.ts) file
+    @signal trpreview([str]) emitted to preview Qt-Linguist (*.qm) files
+    @signal pixmapFile(str) emitted to open a pixmap file
+    @signal svgFile(str) emitted to open a SVG file
+    @signal umlFile(str) emitted to open an eric UML file
+    """
+    sourceFile = pyqtSignal(str, int, str, int, int)
+    designerFile = pyqtSignal(str)
+    linguistFile = pyqtSignal(str)
+    trpreview = pyqtSignal(list)
+    pixmapFile = pyqtSignal(str)
+    svgFile = pyqtSignal(str)
+    umlFile = pyqtSignal(str)
+    
+    def __init__(self, project, parent=None):
+        """
+        Constructor
+        
+        @param project reference to the project object
+        @type Project
+        @param parent parent widget of this dialog (defaults to None)
+        @type QWidget (optional)
+        """
+        super().__init__(parent)
+        self.setWindowFlags(Qt.WindowType.Window)
+        
+        self.__layout = QVBoxLayout()
+        
+        self.__findWidget = FindFileWidget(project, self)
+        self.__layout.addWidget(self.__findWidget)
+        
+        self.__buttonBox = QDialogButtonBox(
+            QDialogButtonBox.StandardButton.Close,
+            Qt.Orientation.Horizontal,
+            self
+        )
+        self.__buttonBox.button(
+            QDialogButtonBox.StandardButton.Close).setAutoDefault(False)
+        self.__layout.addWidget(self.__buttonBox)
+        
+        self.setLayout(self.__layout)
+        self.resize(600, 800)
+        
+       # connect the widgets
+        self.__findWidget.sourceFile.connect(self.sourceFile)
+        self.__findWidget.designerFile.connect(self.designerFile)
+        self.__findWidget.linguistFile.connect(self.linguistFile)
+        self.__findWidget.trpreview.connect(self.trpreview)
+        self.__findWidget.pixmapFile.connect(self.pixmapFile)
+        self.__findWidget.svgFile.connect(self.svgFile)
+        self.__findWidget.umlFile.connect(self.umlFile)
+        
+        self.__buttonBox.accepted.connect(self.accept)
+        self.__buttonBox.rejected.connect(self.reject)
+    
+    def activate(self, replaceMode=False, txt="", searchDir="",
+                 openFiles=False):
+        """
+        Public method to activate the dialog with a given mode, a text
+        to search for and some search parameters.
+        
+        @param replaceMode flag indicating replacement mode (defaults to False)
+        @type bool (optional)
+        @param txt text to be searched for (defaults to "")
+        @type str (optional)
+        @param searchDir directory to search in (defaults to "")
+        @type str (optional)
+        @param openFiles flag indicating to operate on open files only
+            (defaults to False)
+        @type bool (optional)
+        """
+        self.__findWidget.activate(replaceMode=replaceMode, txt=txt,
+                                   searchDir=searchDir, openFiles=openFiles)
+        
+        self.raise_()
+        self.activateWindow()
+        self.show()
--- a/eric7/UI/UserInterface.py	Fri Apr 29 11:40:00 2022 +0200
+++ b/eric7/UI/UserInterface.py	Fri Apr 29 15:40:17 2022 +0200
@@ -944,18 +944,22 @@
         self.__virtualenvManagerWidget = VirtualenvManagerWidget(
             self.virtualenvManager, self)
         
-        # TODO: add separate dialog variant
-        # Create the find in files widget
-        from .FindFileWidget import FindFileWidget
-        self.__findFileWidget = FindFileWidget(self.project, self)
-        self.__findFileWidget.sourceFile.connect(
-            self.viewmanager.openSourceFile)
-        self.__findFileWidget.designerFile.connect(self.__designer)
-        self.__findFileWidget.linguistFile.connect(self.__linguist)
-        self.__findFileWidget.trpreview.connect(self.__TRPreviewer)
-        self.__findFileWidget.pixmapFile.connect(self.__showPixmap)
-        self.__findFileWidget.svgFile.connect(self.__showSvg)
-        self.__findFileWidget.umlFile.connect(self.__showUml)
+        self.__FindFileDialog = None
+        self.__replaceFileDialog = None
+        if Preferences.getUI("ShowFindFileWidget"):
+            # Create the find in files widget
+            from .FindFileWidget import FindFileWidget
+            self.__findFileWidget = FindFileWidget(self.project, self)
+            self.__findFileWidget.sourceFile.connect(
+                self.viewmanager.openSourceFile)
+            self.__findFileWidget.designerFile.connect(self.__designer)
+            self.__findFileWidget.linguistFile.connect(self.__linguist)
+            self.__findFileWidget.trpreview.connect(self.__TRPreviewer)
+            self.__findFileWidget.pixmapFile.connect(self.__showPixmap)
+            self.__findFileWidget.svgFile.connect(self.__showSvg)
+            self.__findFileWidget.umlFile.connect(self.__showUml)
+        else:
+            self.__findFileWidget = None
         
         # TODO: add separate dialog variant
         # Create the find location (file) widget
@@ -1086,9 +1090,10 @@
                               UI.PixmapCache.getIcon("projectViewer"),
                               self.tr("Project-Viewer"))
         
-        self.lToolbox.addItem(self.__findFileWidget,
-                              UI.PixmapCache.getIcon("find"),
-                              self.tr("Find/Replace In Files"))
+        if self.__findFileWidget:
+            self.lToolbox.addItem(self.__findFileWidget,
+                                  UI.PixmapCache.getIcon("find"),
+                                  self.tr("Find/Replace In Files"))
         
         self.lToolbox.addItem(self.__findLocationWidget,
                               UI.PixmapCache.getIcon("findLocation"),
@@ -1235,10 +1240,11 @@
             UI.PixmapCache.getIcon("sbProjectViewer96"),
             self.tr("Project-Viewer"))
         
-        self.leftSidebar.addTab(
-            self.__findFileWidget,
-            UI.PixmapCache.getIcon("sbFind96"),
-            self.tr("Find/Replace In Files"))
+        if self.__findFileWidget:
+            self.leftSidebar.addTab(
+                self.__findFileWidget,
+                UI.PixmapCache.getIcon("sbFind96"),
+                self.tr("Find/Replace In Files"))
         
         self.leftSidebar.addTab(
             self.__findLocationWidget,
@@ -2314,24 +2320,25 @@
             self.activateVirtualenvManager)
         self.actions.append(self.virtualenvManagerActivateAct)
         self.addAction(self.virtualenvManagerActivateAct)
-
-        self.findFileActivateAct = EricAction(
-            self.tr("Find/Replace In Files"),
-            self.tr("Find/Replace In Files"),
-            QKeySequence(self.tr("Ctrl+Alt+Shift+F")),
-            0, self,
-            'find_file_activate')
-        self.findFileActivateAct.setStatusTip(self.tr(
-            "Switch the input focus to the Find/Replace In Files window."))
-        self.findFileActivateAct.setWhatsThis(self.tr(
-            """<b>Find/Replace In Files</b>"""
-            """<p>This switches the input focus to the Find/Replace In Files"""
-            """ window.</p>"""
-        ))
-        self.findFileActivateAct.triggered.connect(
-            self.__activateFindFileWidget)
-        self.actions.append(self.findFileActivateAct)
-        self.addAction(self.findFileActivateAct)
+        
+        if self.__findFileWidget is not None:
+            self.findFileActivateAct = EricAction(
+                self.tr("Find/Replace In Files"),
+                self.tr("Find/Replace In Files"),
+                QKeySequence(self.tr("Ctrl+Alt+Shift+F")),
+                0, self,
+                'find_file_activate')
+            self.findFileActivateAct.setStatusTip(self.tr(
+                "Switch the input focus to the Find/Replace In Files window."))
+            self.findFileActivateAct.setWhatsThis(self.tr(
+                """<b>Find/Replace In Files</b>"""
+                """<p>This switches the input focus to the Find/Replace In"""
+                """ Files window.</p>"""
+            ))
+            self.findFileActivateAct.triggered.connect(
+                self.__activateFindFileWidget)
+            self.actions.append(self.findFileActivateAct)
+            self.addAction(self.findFileActivateAct)
 
         self.findLocationActivateAct = EricAction(
             self.tr("Find File"),
@@ -3468,7 +3475,8 @@
         self.__menus["subwindow"].addSection(self.tr("Left Side"))
         self.__menus["subwindow"].addAction(self.mpbActivateAct)
         self.__menus["subwindow"].addAction(self.pbActivateAct)
-        self.__menus["subwindow"].addAction(self.findFileActivateAct)
+        if self.__findFileWidget is not None:
+            self.__menus["subwindow"].addAction(self.findFileActivateAct)
         self.__menus["subwindow"].addAction(self.findLocationActivateAct)
         self.__menus["subwindow"].addAction(self.vcsStatusListActivateAct)
         if not self.rightSidebar:
@@ -7163,11 +7171,28 @@
             (defaults to False)
         @type bool (optional)
         """
-        # TODO: add separate dialog variant
-        self.__activateFindFileWidget()
-        self.__findFileWidget.activate(
-            replaceMode=False, txt=txt, searchDir=searchDir,
-            openFiles=openFiles)
+        if Preferences.getUI("ShowFindFileWidget"):
+            # embedded tool
+            self.__activateFindFileWidget()
+            self.__findFileWidget.activate(
+                replaceMode=False, txt=txt, searchDir=searchDir,
+                openFiles=openFiles)
+        else:
+            # external dialog
+            if self.__FindFileDialog is None:
+                from .FindFileWidget import FindFileDialog
+                self.__FindFileDialog = FindFileDialog(self.project)
+                self.__FindFileDialog.sourceFile.connect(
+                    self.viewmanager.openSourceFile)
+                self.__FindFileDialog.designerFile.connect(self.__designer)
+                self.__FindFileDialog.linguistFile.connect(self.__linguist)
+                self.__FindFileDialog.trpreview.connect(self.__TRPreviewer)
+                self.__FindFileDialog.pixmapFile.connect(self.__showPixmap)
+                self.__FindFileDialog.svgFile.connect(self.__showSvg)
+                self.__FindFileDialog.umlFile.connect(self.__showUml)
+            self.__FindFileDialog.activate(
+                replaceMode=False, txt=txt, searchDir=searchDir,
+                openFiles=openFiles)
     
     def showReplaceFilesWidget(self, txt="", searchDir="", openFiles=False):
         """
@@ -7181,11 +7206,27 @@
             (defaults to False)
         @type bool (optional)
         """
-        # TODO: add separate dialog variant
-        self.__activateFindFileWidget()
-        self.__findFileWidget.activate(
-            replaceMode=True, txt=txt, searchDir=searchDir,
-            openFiles=openFiles)
+        if Preferences.getUI("ShowFindFileWidget"):
+            self.__activateFindFileWidget()
+            self.__findFileWidget.activate(
+                replaceMode=True, txt=txt, searchDir=searchDir,
+                openFiles=openFiles)
+        else:
+            # external dialog
+            if self.__replaceFileDialog is None:
+                from .FindFileWidget import FindFileDialog
+                self.__replaceFileDialog = FindFileDialog(self.project)
+                self.__replaceFileDialog.sourceFile.connect(
+                    self.viewmanager.openSourceFile)
+                self.__replaceFileDialog.designerFile.connect(self.__designer)
+                self.__replaceFileDialog.linguistFile.connect(self.__linguist)
+                self.__replaceFileDialog.trpreview.connect(self.__TRPreviewer)
+                self.__replaceFileDialog.pixmapFile.connect(self.__showPixmap)
+                self.__replaceFileDialog.svgFile.connect(self.__showSvg)
+                self.__replaceFileDialog.umlFile.connect(self.__showUml)
+            self.__replaceFileDialog.activate(
+                replaceMode=True, txt=txt, searchDir=searchDir,
+                openFiles=openFiles)
     
     def __activateFindFileWidget(self):
         """

eric ide

mercurial