src/eric7/UI/Browser.py

branch
eric7
changeset 9221
bf71ee032bb4
parent 9209
b99e7fd55fd3
child 9278
36448ca469c2
--- a/src/eric7/UI/Browser.py	Wed Jul 13 11:16:20 2022 +0200
+++ b/src/eric7/UI/Browser.py	Wed Jul 13 14:55:47 2022 +0200
@@ -11,13 +11,24 @@
 import shutil
 
 from PyQt6.QtCore import (
-    pyqtSignal, pyqtSlot, Qt, QUrl, QCoreApplication, QItemSelectionModel,
-    QModelIndex, QElapsedTimer
+    pyqtSignal,
+    pyqtSlot,
+    Qt,
+    QUrl,
+    QCoreApplication,
+    QItemSelectionModel,
+    QModelIndex,
+    QElapsedTimer,
 )
 from PyQt6.QtGui import QAction, QDesktopServices
 from PyQt6.QtWidgets import (
-    QTreeView, QApplication, QMenu, QAbstractItemView, QInputDialog,
-    QLineEdit, QDialog
+    QTreeView,
+    QApplication,
+    QMenu,
+    QAbstractItemView,
+    QInputDialog,
+    QLineEdit,
+    QDialog,
 )
 
 from EricWidgets.EricApplication import ericApp
@@ -25,10 +36,17 @@
 
 from Project.ProjectBrowserModel import ProjectBrowserSimpleDirectoryItem
 from .BrowserModel import (
-    BrowserModel, BrowserDirectoryItem, BrowserFileItem, BrowserClassItem,
-    BrowserMethodItem, BrowserClassAttributeItem, BrowserImportItem,
-    BrowserImportsItem, BrowserSysPathItem, BrowserGlobalsItem,
-    BrowserItemDirectory
+    BrowserModel,
+    BrowserDirectoryItem,
+    BrowserFileItem,
+    BrowserClassItem,
+    BrowserMethodItem,
+    BrowserClassAttributeItem,
+    BrowserImportItem,
+    BrowserImportsItem,
+    BrowserSysPathItem,
+    BrowserGlobalsItem,
+    BrowserItemDirectory,
 )
 from .BrowserSortFilterProxyModel import BrowserSortFilterProxyModel
 
@@ -41,11 +59,11 @@
 class Browser(QTreeView):
     """
     Class used to display a file system tree.
-    
+
     Via the context menu that
     is displayed by a right click the user can select various actions on
     the selected file.
-    
+
     @signal sourceFile(filename) emitted to open a Python file at a line (str)
     @signal sourceFile(filename, lineno) emitted to open a Python file at a
         line (str, int)
@@ -72,10 +90,11 @@
     @signal testFile(filename) emitted to open a Python file for a
         unit test (str)
     """
-    sourceFile = pyqtSignal((str, ), (str, int), (str, list), (str, int, str))
+
+    sourceFile = pyqtSignal((str,), (str, int), (str, list), (str, int, str))
     designerFile = pyqtSignal(str)
     linguistFile = pyqtSignal(str)
-    trpreview = pyqtSignal((list, ), (list, bool))
+    trpreview = pyqtSignal((list,), (list, bool))
     projectFile = pyqtSignal(str)
     multiProjectFile = pyqtSignal(str)
     pixmapFile = pyqtSignal(str)
@@ -84,82 +103,83 @@
     umlFile = pyqtSignal(str)
     binaryFile = pyqtSignal(str)
     testFile = pyqtSignal(str)
-    
+
     def __init__(self, parent=None):
         """
         Constructor
-        
+
         @param parent parent widget (QWidget)
         """
         super().__init__(parent)
-        
-        self.setWindowTitle(QCoreApplication.translate('Browser',
-                                                       'File-Browser'))
+
+        self.setWindowTitle(QCoreApplication.translate("Browser", "File-Browser"))
         self.setWindowIcon(UI.PixmapCache.getIcon("eric"))
-        
+
         self.__model = BrowserModel()
         self.__sortModel = BrowserSortFilterProxyModel()
         self.__sortModel.setSourceModel(self.__model)
         self.setModel(self.__sortModel)
-        
+
         self.selectedItemsFilter = [BrowserFileItem]
-        
+
         self._activating = False
-        
+
         self.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
         self.customContextMenuRequested.connect(self._contextMenuRequested)
         self.activated.connect(self._openItem)
         self.expanded.connect(self._resizeColumns)
         self.collapsed.connect(self._resizeColumns)
-        
-        self.setWhatsThis(QCoreApplication.translate(
-            'Browser',
-            """<b>The Browser Window</b>"""
-            """<p>This allows you to easily navigate the hierarchy of"""
-            """ directories and files on your system, identify the Python"""
-            """ programs and open them up in a Source Viewer window. The"""
-            """ window displays several separate hierarchies.</p>"""
-            """<p>The first hierarchy is only shown if you have opened a"""
-            """ program for debugging and its root is the directory"""
-            """ containing that program. Usually all of the separate files"""
-            """ that make up a Python application are held in the same"""
-            """ directory, so this hierarchy gives you easy access to most"""
-            """ of what you will need.</p>"""
-            """<p>The next hierarchy is used to easily navigate the"""
-            """ directories that are specified in the Python"""
-            """ <tt>sys.path</tt> variable.</p>"""
-            """<p>The remaining hierarchies allow you navigate your system"""
-            """ as a whole. On a UNIX system there will be a hierarchy with"""
-            """ <tt>/</tt> at its root and another with the user home"""
-            """ directory. On a Windows system there will be a hierarchy for"""
-            """ each drive on the"""
-            """ system.</p>"""
-            """<p>Python programs (i.e. those with a <tt>.py</tt> file name"""
-            """ suffix) are identified in the hierarchies with a Python"""
-            """ icon. The right mouse button will popup a menu which lets"""
-            """ you open the file in a Source Viewer window, open the file"""
-            """ for debugging or use it for a test run.</p>"""
-            """<p>The context menu of a class, function or method allows you"""
-            """ to open the file defining this class, function or method and"""
-            """ will ensure, that the correct source line is visible.</p>"""
-            """<p>Qt-Designer files (i.e. those with a <tt>.ui</tt> file"""
-            """ name suffix) are shown with a Designer icon. The context"""
-            """ menu of these files allows you to start Qt-Designer with"""
-            """ that file.</p>"""
-            """<p>Qt-Linguist files (i.e. those with a <tt>.ts</tt> file"""
-            """ name suffix) are shown with a Linguist icon. The context"""
-            """ menu of these files allows you to start Qt-Linguist with"""
-            """ that file.</p>"""
-        ))
-        
+
+        self.setWhatsThis(
+            QCoreApplication.translate(
+                "Browser",
+                """<b>The Browser Window</b>"""
+                """<p>This allows you to easily navigate the hierarchy of"""
+                """ directories and files on your system, identify the Python"""
+                """ programs and open them up in a Source Viewer window. The"""
+                """ window displays several separate hierarchies.</p>"""
+                """<p>The first hierarchy is only shown if you have opened a"""
+                """ program for debugging and its root is the directory"""
+                """ containing that program. Usually all of the separate files"""
+                """ that make up a Python application are held in the same"""
+                """ directory, so this hierarchy gives you easy access to most"""
+                """ of what you will need.</p>"""
+                """<p>The next hierarchy is used to easily navigate the"""
+                """ directories that are specified in the Python"""
+                """ <tt>sys.path</tt> variable.</p>"""
+                """<p>The remaining hierarchies allow you navigate your system"""
+                """ as a whole. On a UNIX system there will be a hierarchy with"""
+                """ <tt>/</tt> at its root and another with the user home"""
+                """ directory. On a Windows system there will be a hierarchy for"""
+                """ each drive on the"""
+                """ system.</p>"""
+                """<p>Python programs (i.e. those with a <tt>.py</tt> file name"""
+                """ suffix) are identified in the hierarchies with a Python"""
+                """ icon. The right mouse button will popup a menu which lets"""
+                """ you open the file in a Source Viewer window, open the file"""
+                """ for debugging or use it for a test run.</p>"""
+                """<p>The context menu of a class, function or method allows you"""
+                """ to open the file defining this class, function or method and"""
+                """ will ensure, that the correct source line is visible.</p>"""
+                """<p>Qt-Designer files (i.e. those with a <tt>.ui</tt> file"""
+                """ name suffix) are shown with a Designer icon. The context"""
+                """ menu of these files allows you to start Qt-Designer with"""
+                """ that file.</p>"""
+                """<p>Qt-Linguist files (i.e. those with a <tt>.ts</tt> file"""
+                """ name suffix) are shown with a Linguist icon. The context"""
+                """ menu of these files allows you to start Qt-Linguist with"""
+                """ that file.</p>""",
+            )
+        )
+
         self.__createPopupMenus()
-        
-        self._init()    # perform common initialization tasks
-        
+
+        self._init()  # perform common initialization tasks
+
         self._keyboardSearchString = ""
         self._keyboardSearchTimer = QElapsedTimer()
         self._keyboardSearchTimer.invalidate()
-        
+
     def _init(self):
         """
         Protected method to perform initialization tasks common to this
@@ -167,205 +187,226 @@
         """
         self.setRootIsDecorated(True)
         self.setAlternatingRowColors(True)
-        
+
         header = self.header()
         header.setSortIndicator(0, Qt.SortOrder.AscendingOrder)
         header.setSortIndicatorShown(True)
         header.setSectionsClickable(True)
-        
+
         self.setSortingEnabled(True)
-        
-        self.setSelectionMode(
-            QAbstractItemView.SelectionMode.ExtendedSelection)
-        self.setSelectionBehavior(
-            QAbstractItemView.SelectionBehavior.SelectRows)
-        
+
+        self.setSelectionMode(QAbstractItemView.SelectionMode.ExtendedSelection)
+        self.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows)
+
         self.header().setStretchLastSection(True)
         self.headerSize0 = 0
         self.layoutDisplay()
-        
+
     def layoutDisplay(self):
         """
         Public slot to perform a layout operation.
         """
         self._resizeColumns(QModelIndex())
         self._resort()
-        
+
     def _resizeColumns(self, index):
         """
         Protected slot to resize the view when items get expanded or collapsed.
-        
+
         @param index index of item (QModelIndex)
         """
         w = max(100, self.sizeHintForColumn(0))
         if w != self.headerSize0:
             self.header().resizeSection(0, w)
             self.headerSize0 = w
-    
+
     def _resort(self):
         """
         Protected slot to resort the tree.
         """
-        self.model().sort(self.header().sortIndicatorSection(),
-                          self.header().sortIndicatorOrder())
-        
+        self.model().sort(
+            self.header().sortIndicatorSection(), self.header().sortIndicatorOrder()
+        )
+
     def __createPopupMenus(self):
         """
         Private method to generate the various popup menus.
         """
         self.showHiddenFilesAct = QAction(
-            QCoreApplication.translate('Browser', 'Show Hidden Files'))
+            QCoreApplication.translate("Browser", "Show Hidden Files")
+        )
         self.showHiddenFilesAct.setCheckable(True)
         self.showHiddenFilesAct.toggled.connect(self._showHidden)
-        self.showHiddenFilesAct.setChecked(
-            Preferences.getUI("BrowsersListHiddenFiles"))
-        
-        self.__newMenu = QMenu(QCoreApplication.translate('Browser', "New"),
-                               self)
+        self.showHiddenFilesAct.setChecked(Preferences.getUI("BrowsersListHiddenFiles"))
+
+        self.__newMenu = QMenu(QCoreApplication.translate("Browser", "New"), self)
         self.__newMenu.addAction(
-            QCoreApplication.translate('Browser', 'Directory'),
-            self._newDirectory)
+            QCoreApplication.translate("Browser", "Directory"), self._newDirectory
+        )
         self.__newMenu.addAction(
-            QCoreApplication.translate('Browser', 'File'), self._newFile)
-        
+            QCoreApplication.translate("Browser", "File"), self._newFile
+        )
+
         # create the popup menu for source files
         self.sourceMenu = QMenu(self)
         self.sourceMenu.addAction(
-            QCoreApplication.translate('Browser', 'Open'), self._openItem)
+            QCoreApplication.translate("Browser", "Open"), self._openItem
+        )
         self.testingAct = self.sourceMenu.addAction(
-            QCoreApplication.translate('Browser', 'Run Test...'),
-            self.handleTesting)
+            QCoreApplication.translate("Browser", "Run Test..."), self.handleTesting
+        )
         self.sourceMenu.addSeparator()
         self.mimeTypeAct = self.sourceMenu.addAction(
-            QCoreApplication.translate('Browser', 'Show Mime-Type'),
-            self.__showMimeType)
+            QCoreApplication.translate("Browser", "Show Mime-Type"), self.__showMimeType
+        )
         self.sourceMenu.addSeparator()
         self.sourceMenu.addAction(
-            QCoreApplication.translate('Browser', 'Refresh Source File'),
-            self.__refreshSource)
+            QCoreApplication.translate("Browser", "Refresh Source File"),
+            self.__refreshSource,
+        )
         self.sourceMenu.addSeparator()
         self.sourceMenu.addAction(
-            QCoreApplication.translate('Browser', 'Copy Path to Clipboard'),
-            self._copyToClipboard)
+            QCoreApplication.translate("Browser", "Copy Path to Clipboard"),
+            self._copyToClipboard,
+        )
         self.sourceMenu.addSeparator()
         self.sourceMenu.addAction(self.showHiddenFilesAct)
         self.sourceMenu.addSeparator()
         self.sourceMenu.addMenu(self.__newMenu)
         self.sourceMenu.addAction(
-            QCoreApplication.translate('Browser', 'Delete'),
-            self._deleteFileOrDirectory)
-        
+            QCoreApplication.translate("Browser", "Delete"), self._deleteFileOrDirectory
+        )
+
         # create the popup menu for general use
         self.menu = QMenu(self)
         self.menu.addAction(
-            QCoreApplication.translate('Browser', 'Open'), self._openItem)
+            QCoreApplication.translate("Browser", "Open"), self._openItem
+        )
         self.menu.addAction(
-            QCoreApplication.translate('Browser', 'Open in Hex Editor'),
-            self._openHexEditor)
+            QCoreApplication.translate("Browser", "Open in Hex Editor"),
+            self._openHexEditor,
+        )
         self.editPixmapAct = self.menu.addAction(
-            QCoreApplication.translate('Browser', 'Open in Icon Editor'),
-            self._editPixmap)
+            QCoreApplication.translate("Browser", "Open in Icon Editor"),
+            self._editPixmap,
+        )
         self.openInEditorAct = self.menu.addAction(
-            QCoreApplication.translate('Browser', 'Open in Editor'),
-            self._openFileInEditor)
+            QCoreApplication.translate("Browser", "Open in Editor"),
+            self._openFileInEditor,
+        )
         self.menu.addSeparator()
         self.mimeTypeAct = self.menu.addAction(
-            QCoreApplication.translate('Browser', 'Show Mime-Type'),
-            self.__showMimeType)
+            QCoreApplication.translate("Browser", "Show Mime-Type"), self.__showMimeType
+        )
         self.menu.addSeparator()
         self.menu.addAction(
-            QCoreApplication.translate('Browser', 'Copy Path to Clipboard'),
-            self._copyToClipboard)
+            QCoreApplication.translate("Browser", "Copy Path to Clipboard"),
+            self._copyToClipboard,
+        )
         self.menu.addSeparator()
         self.menu.addAction(self.showHiddenFilesAct)
         self.menu.addSeparator()
         self.menu.addMenu(self.__newMenu)
         self.menu.addAction(
-            QCoreApplication.translate('Browser', 'Delete'),
-            self._deleteFileOrDirectory)
-        
+            QCoreApplication.translate("Browser", "Delete"), self._deleteFileOrDirectory
+        )
+
         # create the menu for multiple selected files
         self.multiMenu = QMenu(self)
         self.multiMenu.addAction(
-            QCoreApplication.translate('Browser', 'Open'), self._openItem)
+            QCoreApplication.translate("Browser", "Open"), self._openItem
+        )
         self.multiMenu.addSeparator()
         self.multiMenu.addAction(self.showHiddenFilesAct)
         self.multiMenu.addSeparator()
         self.multiMenu.addAction(
-            QCoreApplication.translate('Browser', 'Delete'),
-            self.__deleteMultiple)
-        
+            QCoreApplication.translate("Browser", "Delete"), self.__deleteMultiple
+        )
+
         # create the directory menu
         self.dirMenu = QMenu(self)
         self.dirMenu.addAction(
-            QCoreApplication.translate('Browser', 'New toplevel directory...'),
-            self.__newToplevelDir)
+            QCoreApplication.translate("Browser", "New toplevel directory..."),
+            self.__newToplevelDir,
+        )
         self.addAsTopLevelAct = self.dirMenu.addAction(
-            QCoreApplication.translate('Browser', 'Add as toplevel directory'),
-            self.__addAsToplevelDir)
+            QCoreApplication.translate("Browser", "Add as toplevel directory"),
+            self.__addAsToplevelDir,
+        )
         self.removeFromToplevelAct = self.dirMenu.addAction(
-            QCoreApplication.translate('Browser', 'Remove from toplevel'),
-            self.__removeToplevel)
+            QCoreApplication.translate("Browser", "Remove from toplevel"),
+            self.__removeToplevel,
+        )
         self.dirMenu.addSeparator()
         self.dirMenu.addAction(
-            QCoreApplication.translate('Browser', 'Refresh directory'),
-            self.__refreshDirectory)
+            QCoreApplication.translate("Browser", "Refresh directory"),
+            self.__refreshDirectory,
+        )
         self.dirMenu.addSeparator()
         self.dirMenu.addAction(
-            QCoreApplication.translate('Browser', 'Find in this directory'),
-            self.__findInDirectory)
+            QCoreApplication.translate("Browser", "Find in this directory"),
+            self.__findInDirectory,
+        )
         self.dirMenu.addAction(
-            QCoreApplication.translate(
-                'Browser', 'Find && Replace in this directory'),
-            self.__replaceInDirectory)
+            QCoreApplication.translate("Browser", "Find && Replace in this directory"),
+            self.__replaceInDirectory,
+        )
         self.dirMenu.addAction(
-            QCoreApplication.translate('Browser', 'Copy Path to Clipboard'),
-            self._copyToClipboard)
+            QCoreApplication.translate("Browser", "Copy Path to Clipboard"),
+            self._copyToClipboard,
+        )
         self.dirMenu.addSeparator()
         self.dirMenu.addAction(self.showHiddenFilesAct)
         self.dirMenu.addSeparator()
         self.dirMenu.addMenu(self.__newMenu)
         self.dirMenu.addAction(
-            QCoreApplication.translate('Browser', 'Delete'),
-            self._deleteFileOrDirectory)
-        
+            QCoreApplication.translate("Browser", "Delete"), self._deleteFileOrDirectory
+        )
+
         # create the attribute menu
-        self.gotoMenu = QMenu(QCoreApplication.translate('Browser', "Goto"),
-                              self)
+        self.gotoMenu = QMenu(QCoreApplication.translate("Browser", "Goto"), self)
         self.gotoMenu.aboutToShow.connect(self._showGotoMenu)
         self.gotoMenu.triggered.connect(self._gotoAttribute)
-        
+
         self.attributeMenu = QMenu(self)
         self.attributeMenu.addAction(
-            QCoreApplication.translate('Browser', 'New toplevel directory...'),
-            self.__newToplevelDir)
+            QCoreApplication.translate("Browser", "New toplevel directory..."),
+            self.__newToplevelDir,
+        )
         self.attributeMenu.addSeparator()
         self.attributeMenu.addMenu(self.gotoMenu)
-        
+
         # create the background menu
         self.backMenu = QMenu(self)
         self.backMenu.addAction(
-            QCoreApplication.translate('Browser', 'New toplevel directory...'),
-            self.__newToplevelDir)
+            QCoreApplication.translate("Browser", "New toplevel directory..."),
+            self.__newToplevelDir,
+        )
         self.backMenu.addSeparator()
         self.backMenu.addAction(self.showHiddenFilesAct)
 
     def mouseDoubleClickEvent(self, mouseEvent):
         """
         Protected method of QAbstractItemView.
-        
+
         Reimplemented to disable expanding/collapsing of items when
         double-clicking. Instead the double-clicked entry is opened.
-        
+
         @param mouseEvent the mouse event (QMouseEvent)
         """
         index = self.indexAt(mouseEvent.position().toPoint())
         if index.isValid():
             itm = self.model().item(index)
-            if isinstance(itm, (
-                    BrowserDirectoryItem, BrowserImportsItem,
-                    ProjectBrowserSimpleDirectoryItem, BrowserSysPathItem,
-                    BrowserGlobalsItem)):
+            if isinstance(
+                itm,
+                (
+                    BrowserDirectoryItem,
+                    BrowserImportsItem,
+                    ProjectBrowserSimpleDirectoryItem,
+                    BrowserSysPathItem,
+                    BrowserGlobalsItem,
+                ),
+            ):
                 self.setExpanded(index, not self.isExpanded(index))
             else:
                 self._openItem()
@@ -373,32 +414,32 @@
     def _contextMenuRequested(self, coord):
         """
         Protected slot to show the context menu of the listview.
-        
+
         @param coord the position of the mouse pointer (QPoint)
         """
         categories = self.getSelectedItemsCountCategorized(
-            [BrowserDirectoryItem, BrowserFileItem,
-             BrowserClassItem, BrowserMethodItem])
+            [BrowserDirectoryItem, BrowserFileItem, BrowserClassItem, BrowserMethodItem]
+        )
         cnt = categories["sum"]
         bfcnt = categories[str(BrowserFileItem)]
         if cnt > 1 and cnt == bfcnt:
             self.multiMenu.popup(self.mapToGlobal(coord))
         else:
             index = self.indexAt(coord)
-            
+
             if index.isValid():
                 self.setCurrentIndex(index)
                 flags = (
-                    QItemSelectionModel.SelectionFlag.ClearAndSelect |
-                    QItemSelectionModel.SelectionFlag.Rows
+                    QItemSelectionModel.SelectionFlag.ClearAndSelect
+                    | QItemSelectionModel.SelectionFlag.Rows
                 )
                 self.selectionModel().select(index, flags)
-                
+
                 itm = self.model().item(index)
                 coord = self.mapToGlobal(coord)
                 if isinstance(itm, BrowserFileItem):
                     if itm.isPython3File():
-                        if itm.fileName().endswith('.py'):
+                        if itm.fileName().endswith(".py"):
                             self.testingAct.setEnabled(True)
                         else:
                             self.testingAct.setEnabled(False)
@@ -408,8 +449,7 @@
                         self.openInEditorAct.setVisible(itm.isSvgFile())
                         self.menu.popup(coord)
                 elif isinstance(
-                    itm,
-                    (BrowserClassItem, BrowserMethodItem, BrowserImportItem)
+                    itm, (BrowserClassItem, BrowserMethodItem, BrowserImportItem)
                 ):
                     self.editPixmapAct.setVisible(False)
                     self.menu.popup(coord)
@@ -427,69 +467,72 @@
                     self.backMenu.popup(coord)
             else:
                 self.backMenu.popup(self.mapToGlobal(coord))
-        
+
     def _showGotoMenu(self):
         """
         Protected slot to prepare the goto submenu of the attribute menu.
         """
         self.gotoMenu.clear()
-        
+
         itm = self.model().item(self.currentIndex())
         linenos = itm.linenos()
         fileName = itm.fileName()
-        
+
         for lineno in sorted(linenos):
             act = self.gotoMenu.addAction(
-                QCoreApplication.translate(
-                    'Browser', "Line {0}").format(lineno))
+                QCoreApplication.translate("Browser", "Line {0}").format(lineno)
+            )
             act.setData([fileName, lineno])
-        
+
     def _gotoAttribute(self, act):
         """
         Protected slot to handle the selection of the goto menu.
-        
+
         @param act reference to the action (EricAction)
         """
         fileName, lineno = act.data()
         self.sourceFile[str, int].emit(fileName, lineno)
-        
+
     def handlePreferencesChanged(self):
         """
         Public slot used to handle the preferencesChanged signal.
         """
         self.model().preferencesChanged()
         self._resort()
-        
+
     def _openItem(self):
         """
         Protected slot to handle the open popup menu entry.
         """
         itmList = self.getSelectedItems(
-            [BrowserFileItem, BrowserClassItem,
-             BrowserMethodItem, BrowserClassAttributeItem,
-             BrowserImportItem])
-        
+            [
+                BrowserFileItem,
+                BrowserClassItem,
+                BrowserMethodItem,
+                BrowserClassAttributeItem,
+                BrowserImportItem,
+            ]
+        )
+
         if not self._activating:
             self._activating = True
             for itm in itmList:
                 if isinstance(itm, BrowserFileItem):
                     if (
-                        itm.isPython3File() or
-                        itm.isIdlFile() or
-                        itm.isProtobufFile() or
-                        itm.isResourcesFile()
+                        itm.isPython3File()
+                        or itm.isIdlFile()
+                        or itm.isProtobufFile()
+                        or itm.isResourcesFile()
                     ):
                         self.sourceFile[str].emit(itm.fileName())
                     elif itm.isRubyFile():
-                        self.sourceFile[str, int, str].emit(
-                            itm.fileName(), -1, "Ruby")
+                        self.sourceFile[str, int, str].emit(itm.fileName(), -1, "Ruby")
                     elif itm.isDFile():
-                        self.sourceFile[str, int, str].emit(
-                            itm.fileName(), -1, "D")
+                        self.sourceFile[str, int, str].emit(itm.fileName(), -1, "D")
                     elif itm.isDesignerFile():
                         self.designerFile.emit(itm.fileName())
                     elif itm.isLinguistFile():
-                        if itm.fileExt() == '.ts':
+                        if itm.fileExt() == ".ts":
                             self.linguistFile.emit(itm.fileName())
                         else:
                             self.trpreview.emit([itm.fileName()])
@@ -510,69 +553,77 @@
                             QDesktopServices.openUrl(QUrl(itm.fileName()))
                 elif isinstance(itm, BrowserClassItem):
                     self.sourceFile[str, int].emit(
-                        itm.fileName(), itm.classObject().lineno)
+                        itm.fileName(), itm.classObject().lineno
+                    )
                 elif isinstance(itm, BrowserMethodItem):
                     self.sourceFile[str, int].emit(
-                        itm.fileName(), itm.functionObject().lineno)
+                        itm.fileName(), itm.functionObject().lineno
+                    )
                 elif isinstance(itm, BrowserClassAttributeItem):
                     self.sourceFile[str, int].emit(
-                        itm.fileName(), itm.attributeObject().lineno)
+                        itm.fileName(), itm.attributeObject().lineno
+                    )
                 elif isinstance(itm, BrowserImportItem):
-                    self.sourceFile[str, list].emit(
-                        itm.fileName(), itm.linenos())
+                    self.sourceFile[str, list].emit(itm.fileName(), itm.linenos())
             self._activating = False
-        
+
     def __showMimeType(self):
         """
         Private slot to show the mime type of the selected entry.
         """
         itmList = self.getSelectedItems(
-            [BrowserFileItem, BrowserClassItem,
-             BrowserMethodItem, BrowserClassAttributeItem,
-             BrowserImportItem])
+            [
+                BrowserFileItem,
+                BrowserClassItem,
+                BrowserMethodItem,
+                BrowserClassAttributeItem,
+                BrowserImportItem,
+            ]
+        )
         if itmList:
             mimetype = Utilities.MimeTypes.mimeType(itmList[0].fileName())
             if mimetype is None:
                 EricMessageBox.warning(
                     self,
-                    QCoreApplication.translate('Browser', "Show Mime-Type"),
+                    QCoreApplication.translate("Browser", "Show Mime-Type"),
                     QCoreApplication.translate(
-                        'Browser',
-                        """The mime type of the file could not be"""
-                        """ determined."""))
+                        "Browser",
+                        """The mime type of the file could not be""" """ determined.""",
+                    ),
+                )
             elif mimetype.split("/")[0] == "text":
                 EricMessageBox.information(
                     self,
-                    QCoreApplication.translate('Browser', "Show Mime-Type"),
+                    QCoreApplication.translate("Browser", "Show Mime-Type"),
                     QCoreApplication.translate(
-                        'Browser',
-                        """The file has the mime type <b>{0}</b>.""")
-                    .format(mimetype))
+                        "Browser", """The file has the mime type <b>{0}</b>."""
+                    ).format(mimetype),
+                )
             else:
                 textMimeTypesList = Preferences.getUI("TextMimeTypes")
                 if mimetype in textMimeTypesList:
                     EricMessageBox.information(
                         self,
-                        QCoreApplication.translate(
-                            'Browser', "Show Mime-Type"),
+                        QCoreApplication.translate("Browser", "Show Mime-Type"),
                         QCoreApplication.translate(
-                            'Browser',
-                            """The file has the mime type <b>{0}</b>.""")
-                        .format(mimetype))
+                            "Browser", """The file has the mime type <b>{0}</b>."""
+                        ).format(mimetype),
+                    )
                 else:
                     ok = EricMessageBox.yesNo(
                         self,
+                        QCoreApplication.translate("Browser", "Show Mime-Type"),
                         QCoreApplication.translate(
-                            'Browser', "Show Mime-Type"),
-                        QCoreApplication.translate(
-                            'Browser',
+                            "Browser",
                             """The file has the mime type <b>{0}</b>."""
                             """<br/> Shall it be added to the list of"""
-                            """ text mime types?""").format(mimetype))
+                            """ text mime types?""",
+                        ).format(mimetype),
+                    )
                     if ok:
                         textMimeTypesList.append(mimetype)
                         Preferences.setUI("TextMimeTypes", textMimeTypesList)
-    
+
     def __refreshSource(self):
         """
         Private slot to refresh the structure of a source file.
@@ -580,37 +631,37 @@
         itmList = self.getSelectedItems([BrowserFileItem])
         if itmList:
             self.__model.repopulateFileItem(itmList[0])
-    
+
     def _editPixmap(self):
         """
         Protected slot to handle the open in icon editor popup menu entry.
         """
         itmList = self.getSelectedItems([BrowserFileItem])
-        
+
         for itm in itmList:
             if isinstance(itm, BrowserFileItem) and itm.isPixmapFile():
                 self.pixmapEditFile.emit(itm.fileName())
-        
+
     def _openHexEditor(self):
         """
         Protected slot to handle the open in hex editor popup menu entry.
         """
         itmList = self.getSelectedItems([BrowserFileItem])
-        
+
         for itm in itmList:
             if isinstance(itm, BrowserFileItem):
                 self.binaryFile.emit(itm.fileName())
-    
+
     def _openFileInEditor(self):
         """
         Protected slot to handle the Open in Editor menu action.
         """
         itmList = self.getSelectedItems([BrowserFileItem])
-        
+
         for itm in itmList:
             if Utilities.MimeTypes.isTextFile(itm.fileName()):
                 self.sourceFile.emit(itm.fileName())
-        
+
     def _copyToClipboard(self):
         """
         Protected method to copy the text shown for an entry to the clipboard.
@@ -623,23 +674,23 @@
                 fn = itm.dirName()
             except AttributeError:
                 fn = ""
-        
+
         if fn:
             cb = QApplication.clipboard()
             cb.setText(fn)
-    
+
     @pyqtSlot(bool)
     def _showHidden(self, checked):
         """
         Protected slot to show or hide hidden files.
-        
+
         @param checked flag indicating the state of the action
         @type bool
         """
         self.__sortModel.setShowHiddenFiles(checked)
         # remember the current state
         Preferences.setUI("BrowsersListHiddenFiles", checked)
-    
+
     def handleTesting(self):
         """
         Public slot to handle the testing popup menu entry.
@@ -653,20 +704,21 @@
 
         if pyfn is not None:
             self.testFile.emit(pyfn)
-        
+
     def __newToplevelDir(self):
         """
         Private slot to handle the New toplevel directory popup menu entry.
         """
         dname = EricFileDialog.getExistingDirectory(
             None,
-            QCoreApplication.translate('Browser', "New toplevel directory"),
+            QCoreApplication.translate("Browser", "New toplevel directory"),
             "",
-            EricFileDialog.ShowDirsOnly)
+            EricFileDialog.ShowDirsOnly,
+        )
         if dname:
             dname = os.path.abspath(Utilities.toNativeSeparators(dname))
             self.__model.addTopLevelDir(dname)
-        
+
     def __removeToplevel(self):
         """
         Private slot to handle the Remove from toplevel popup menu entry.
@@ -674,7 +726,7 @@
         index = self.currentIndex()
         sindex = self.model().mapToSource(index)
         self.__model.removeToplevelDir(sindex)
-        
+
     def __addAsToplevelDir(self):
         """
         Private slot to handle the Add as toplevel directory popup menu entry.
@@ -682,7 +734,7 @@
         index = self.currentIndex()
         dname = self.model().item(index).dirName()
         self.__model.addTopLevelDir(dname)
-        
+
     def __refreshDirectory(self):
         """
         Private slot to refresh a directory entry.
@@ -690,60 +742,58 @@
         index = self.currentIndex()
         refreshDir = self.model().item(index).dirName()
         self.__model.directoryChanged(refreshDir)
-        
+
     def __findInDirectory(self):
         """
         Private slot to handle the Find in directory popup menu entry.
         """
         index = self.currentIndex()
         searchDir = self.model().item(index).dirName()
-        
-        ericApp().getObject("UserInterface").showFindFilesWidget(
-            searchDir=searchDir)
-        
+
+        ericApp().getObject("UserInterface").showFindFilesWidget(searchDir=searchDir)
+
     def __replaceInDirectory(self):
         """
         Private slot to handle the Find&Replace in directory popup menu entry.
         """
         index = self.currentIndex()
         searchDir = self.model().item(index).dirName()
-        
-        ericApp().getObject("UserInterface").showReplaceFilesWidget(
-            searchDir=searchDir)
-        
+
+        ericApp().getObject("UserInterface").showReplaceFilesWidget(searchDir=searchDir)
+
     def handleProgramChange(self, fn):
         """
         Public slot to handle the programChange signal.
-        
+
         @param fn file name (string)
         """
         self.__model.programChange(os.path.dirname(fn))
-        
+
     def handleInterpreterChanged(self, interpreter):
         """
         Public slot to handle a change of the debug client's interpreter.
-        
+
         @param interpreter interpreter of the debug client (string)
         """
         self.__model.interpreterChanged(interpreter)
-        
+
     def wantedItem(self, itm, filterList=None):
         """
         Public method to check type of an item.
-        
+
         @param itm the item to check (BrowserItem)
         @param filterList list of classes to check against
         @return flag indicating item is a valid type (boolean)
         """
         if filterList is None:
             filterList = self.selectedItemsFilter
-        
+
         return any(isinstance(itm, typ) for typ in filterList)
-    
+
     def getSelectedItems(self, filterList=None):
         """
         Public method to get the selected items.
-        
+
         @param filterList list of classes to check against
         @return list of selected items (list of BrowserItem)
         """
@@ -755,11 +805,11 @@
                 if self.wantedItem(itm, filterList):
                     selectedItems.append(itm)
         return selectedItems
-        
+
     def getSelectedItemsCount(self, filterList=None):
         """
         Public method to get the count of items selected.
-        
+
         @param filterList list of classes to check against
         @return count of items selected (integer)
         """
@@ -771,11 +821,11 @@
                 if self.wantedItem(itm, filterList):
                     count += 1
         return count
-        
+
     def getSelectedItemsCountCategorized(self, filterList=None):
         """
         Public method to get a categorized count of selected items.
-        
+
         @param filterList list of classes to check against
         @return a dictionary containing the counts of items belonging
             to the individual filter classes. The keys of the dictionary
@@ -790,7 +840,7 @@
         categories["sum"] = 0
         for typ in filterList:
             categories[str(typ)] = 0
-        
+
         indexes = self.selectedIndexes()
         for index in indexes:
             if index.column() == 0:
@@ -799,75 +849,74 @@
                     if isinstance(itm, typ):
                         categories["sum"] += 1
                         categories[str(typ)] += 1
-        
+
         return categories
-        
+
     def saveToplevelDirs(self):
         """
         Public slot to save the toplevel directories.
         """
         self.__model.saveToplevelDirs()
-    
+
     def keyboardSearch(self, search):
         """
         Public function to search the tree via the keyboard.
-        
+
         @param search the character entered via the keyboard
         @type str
         """
         if self.model().rowCount() == 0:
             return
-        
+
         startIndex = (
             self.currentIndex()
-            if self.currentIndex().isValid() else
-            self.model().index(0, 0)
+            if self.currentIndex().isValid()
+            else self.model().index(0, 0)
         )
-        
+
         keyboardSearchTimeWasValid = self._keyboardSearchTimer.isValid()
         keyboardSearchTimeElapsed = self._keyboardSearchTimer.restart()
         if (
-            not search or
-            not keyboardSearchTimeWasValid or
-            keyboardSearchTimeElapsed >
-                QApplication.keyboardInputInterval()
+            not search
+            or not keyboardSearchTimeWasValid
+            or keyboardSearchTimeElapsed > QApplication.keyboardInputInterval()
         ):
             self._keyboardSearchString = search.lower()
         else:
             self._keyboardSearchString += search.lower()
-        
+
         index = startIndex
         found = False
         while True:
             name = self.model().data(index)
-            if (
-                name.lower().startswith(self._keyboardSearchString) and
-                self._keyboardSearchType(self.model().item(index))
-            ):
+            if name.lower().startswith(
+                self._keyboardSearchString
+            ) and self._keyboardSearchType(self.model().item(index)):
                 found = True
                 break
-            
+
             index = self.indexBelow(index)
             if not index.isValid():
                 index = self.model().index(0, 0)
             if index == startIndex:
                 break
-        
+
         if found:
             self.setCurrentIndex(index)
-    
+
     def _keyboardSearchType(self, item):
         """
         Protected method to check, if the item is of the correct type.
-        
+
         @param item reference to the item
         @type BrowserItem
         @return flag indicating a correct type
         @rtype bool
         """
         return isinstance(
-            item, (BrowserDirectoryItem, BrowserFileItem, BrowserSysPathItem))
-    
+            item, (BrowserDirectoryItem, BrowserFileItem, BrowserSysPathItem)
+        )
+
     @pyqtSlot()
     def _newDirectory(self):
         """
@@ -880,16 +929,19 @@
                 self,
                 self.tr("New Directory"),
                 self.tr("Name for new directory:"),
-                QLineEdit.EchoMode.Normal)
+                QLineEdit.EchoMode.Normal,
+            )
             if ok and bool(newName):
                 dirpath = os.path.join(dname, newName)
                 if os.path.exists(dirpath):
                     EricMessageBox.warning(
                         self,
                         self.tr("New Directory"),
-                        self.tr("A file or directory named <b>{0}</b> exists"
-                                " already. Aborting...")
-                        .format(newName))
+                        self.tr(
+                            "A file or directory named <b>{0}</b> exists"
+                            " already. Aborting..."
+                        ).format(newName),
+                    )
                 else:
                     try:
                         os.mkdir(dirpath, mode=0o751)
@@ -897,10 +949,12 @@
                         EricMessageBox.critical(
                             self,
                             self.tr("New Directory"),
-                            self.tr("<p>The directory <b>{0}</b> could not be"
-                                    " created.</p><p>Reason: {1}</p>")
-                            .format(newName, str(err)))
-    
+                            self.tr(
+                                "<p>The directory <b>{0}</b> could not be"
+                                " created.</p><p>Reason: {1}</p>"
+                            ).format(newName, str(err)),
+                        )
+
     @pyqtSlot()
     def _newFile(self):
         """
@@ -913,16 +967,19 @@
                 self,
                 self.tr("New File"),
                 self.tr("Name for new file:"),
-                QLineEdit.EchoMode.Normal)
+                QLineEdit.EchoMode.Normal,
+            )
             if ok and bool(fname):
                 filepath = os.path.join(dname, fname)
                 if os.path.exists(filepath):
                     EricMessageBox.warning(
                         self,
                         self.tr("New File"),
-                        self.tr("A file or directory named <b>{0}</b> exists"
-                                " already. Aborting...")
-                        .format(fname))
+                        self.tr(
+                            "A file or directory named <b>{0}</b> exists"
+                            " already. Aborting..."
+                        ).format(fname),
+                    )
                 else:
                     try:
                         with open(filepath, "w"):
@@ -931,10 +988,12 @@
                         EricMessageBox.critical(
                             self,
                             self.tr("New File"),
-                            self.tr("<p>The file <b>{0}</b> could not be"
-                                    " created.</p><p>Reason: {1}</p>")
-                            .format(fname, str(err)))
-    
+                            self.tr(
+                                "<p>The file <b>{0}</b> could not be"
+                                " created.</p><p>Reason: {1}</p>"
+                            ).format(fname, str(err)),
+                        )
+
     @pyqtSlot()
     def _deleteFileOrDirectory(self):
         """
@@ -947,30 +1006,27 @@
                 self.__deleteDirectory(itm.dirName())
             else:
                 self.__deleteFile(itm.fileName())
-    
+
     def __deleteFile(self, fn):
         """
         Private method to delete a file.
-        
+
         @param fn filename to be deleted
         @type str
         """
         try:
             from send2trash import send2trash as s2t
-            trashMsg = self.tr("Do you really want to move this file to the"
-                               " trash?")
+
+            trashMsg = self.tr("Do you really want to move this file to the" " trash?")
         except ImportError:
             s2t = os.remove
             trashMsg = self.tr("Do you really want to delete this file?")
-        
-        from UI.DeleteFilesConfirmationDialog import (
-            DeleteFilesConfirmationDialog
-        )
+
+        from UI.DeleteFilesConfirmationDialog import DeleteFilesConfirmationDialog
+
         dlg = DeleteFilesConfirmationDialog(
-            self.parent(),
-            self.tr("Delete File"),
-            trashMsg,
-            [fn])
+            self.parent(), self.tr("Delete File"), trashMsg, [fn]
+        )
         if dlg.exec() == QDialog.DialogCode.Accepted:
             try:
                 s2t(fn)
@@ -980,34 +1036,33 @@
                     self.tr("Delete File"),
                     self.tr(
                         "<p>The selected file <b>{0}</b> could not be"
-                        " deleted.</p><p>Reason: {1}</p>")
-                    .format(fn, str(err))
+                        " deleted.</p><p>Reason: {1}</p>"
+                    ).format(fn, str(err)),
                 )
-    
+
     def __deleteDirectory(self, dn):
         """
         Private method to delete a directory.
-        
+
         @param dn directory name to be removed from the project
         @type str
         """
         try:
             from send2trash import send2trash
+
             s2tAvailable = True
-            trashMsg = self.tr("Do you really want to move this directory to"
-                               " the trash?")
+            trashMsg = self.tr(
+                "Do you really want to move this directory to" " the trash?"
+            )
         except ImportError:
             s2tAvailable = False
             trashMsg = self.tr("Do you really want to delete this directory?")
-        
-        from UI.DeleteFilesConfirmationDialog import (
-            DeleteFilesConfirmationDialog
-        )
+
+        from UI.DeleteFilesConfirmationDialog import DeleteFilesConfirmationDialog
+
         dlg = DeleteFilesConfirmationDialog(
-            self.parent(),
-            self.tr("Delete Directory"),
-            trashMsg,
-            [dn])
+            self.parent(), self.tr("Delete Directory"), trashMsg, [dn]
+        )
         if dlg.exec() == QDialog.DialogCode.Accepted:
             try:
                 if s2tAvailable:
@@ -1020,38 +1075,36 @@
                     self.tr("Delete Directory"),
                     self.tr(
                         "<p>The selected directory <b>{0}</b> could not be"
-                        " deleted.</p><p>Reason: {1}</p>")
-                    .format(dn, str(err))
+                        " deleted.</p><p>Reason: {1}</p>"
+                    ).format(dn, str(err)),
                 )
-    
+
     @pyqtSlot()
     def __deleteMultiple(self):
         """
         Private slot to delete multiple directories and files.
-        
+
         Note: The context menu for multi selection is only shown for file
         items.
         """
         fileNames = []
         for itm in self.getSelectedItems():
             fileNames.append(itm.fileName())
-        
+
         try:
             from send2trash import send2trash as s2t
-            trashMsg = self.tr("Do you really want to move these files to the"
-                               " trash?")
+
+            trashMsg = self.tr(
+                "Do you really want to move these files to the" " trash?"
+            )
         except ImportError:
             s2t = os.remove
             trashMsg = self.tr("Do you really want to delete these files?")
-        
-        from UI.DeleteFilesConfirmationDialog import (
-            DeleteFilesConfirmationDialog
-        )
+
+        from UI.DeleteFilesConfirmationDialog import DeleteFilesConfirmationDialog
+
         dlg = DeleteFilesConfirmationDialog(
-            self.parent(),
-            self.tr("Delete Files"),
-            trashMsg,
-            sorted(fileNames)
+            self.parent(), self.tr("Delete Files"), trashMsg, sorted(fileNames)
         )
         if dlg.exec() == QDialog.DialogCode.Accepted:
             for fn in fileNames:
@@ -1063,6 +1116,6 @@
                         self.tr("Delete File"),
                         self.tr(
                             "<p>The selected file <b>{0}</b> could not be"
-                            " deleted.</p><p>Reason: {1}</p>")
-                        .format(fn, str(err))
+                            " deleted.</p><p>Reason: {1}</p>"
+                        ).format(fn, str(err)),
                     )

eric ide

mercurial