src/eric7/Project/Project.py

branch
eric7
changeset 9214
bd28e56047d7
parent 9210
15743bae8a50
child 9221
bf71ee032bb4
--- a/src/eric7/Project/Project.py	Mon Jul 11 16:09:04 2022 +0200
+++ b/src/eric7/Project/Project.py	Mon Jul 11 16:42:50 2022 +0200
@@ -52,6 +52,8 @@
 
 from Tasks.TasksFile import TasksFile
 
+from CodeFormatting.BlackFormattingAction import BlackFormattingAction
+
 
 class Project(QObject):
     """
@@ -2346,6 +2348,7 @@
             self.menuMakeAct.setEnabled(
                 self.pdata["MAKEPARAMS"]["MakeEnabled"])
             self.menuOtherToolsAct.setEnabled(True)
+            self.menuFormattingAct.setEnabled(True)
             
             self.projectAboutToBeCreated.emit()
             
@@ -3039,6 +3042,7 @@
                     self.menuMakeAct.setEnabled(
                         self.pdata["MAKEPARAMS"]["MakeEnabled"])
                     self.menuOtherToolsAct.setEnabled(True)
+                    self.menuFormattingAct.setEnabled(True)
                     
                     # open a project debugger properties file being quiet
                     # about errors
@@ -3296,6 +3300,7 @@
         self.makeGrp.setEnabled(False)
         self.menuMakeAct.setEnabled(False)
         self.menuOtherToolsAct.setEnabled(False)
+        self.menuFormattingAct.setEnabled(False)
         
         self.__model.projectClosed()
         self.projectClosedHooks.emit()
@@ -3505,10 +3510,14 @@
         pwl = ""
         if self.pdata["SPELLWORDS"]:
             pwl = os.path.join(self.ppath, self.pdata["SPELLWORDS"])
+            if not os.path.isfile(pwl):
+                pwl = ""
         
         pel = ""
         if self.pdata["SPELLEXCLUDES"]:
             pel = os.path.join(self.ppath, self.pdata["SPELLEXCLUDES"])
+            if not os.path.isfile(pel):
+                pel = ""
         
         return (pwl, pel)
         
@@ -3923,6 +3932,10 @@
         """
         self.actions = []
         
+        ###################################################################
+        ## Project actions
+        ###################################################################
+        
         self.actGrp1 = createActionGroup(self)
         
         act = EricAction(
@@ -3988,7 +4001,11 @@
         ))
         self.saveasAct.triggered.connect(self.saveProjectAs)
         self.actions.append(self.saveasAct)
-
+        
+        ###################################################################
+        ## Project management actions
+        ###################################################################
+        
         self.actGrp2 = createActionGroup(self)
         
         self.addFilesAct = EricAction(
@@ -4128,7 +4145,11 @@
         ))
         self.lexersAct.triggered.connect(self.__showLexerAssociations)
         self.actions.append(self.lexersAct)
-
+        
+        ###################################################################
+        ## Project debug actions
+        ###################################################################
+        
         self.dbgActGrp = createActionGroup(self)
         
         act = EricAction(
@@ -4193,8 +4214,12 @@
         act.triggered.connect(self.__initDebugProperties)
         self.actions.append(act)
         
+        ###################################################################
+        ## Project session actions
+        ###################################################################
+        
         self.sessActGrp = createActionGroup(self)
-
+        
         act = EricAction(
             self.tr('Load session'),
             self.tr('Load session'), 0, 0,
@@ -4243,6 +4268,10 @@
         act.triggered.connect(self.__deleteSession)
         self.actions.append(act)
         
+        ###################################################################
+        ## Project Tools - check actions
+        ###################################################################
+        
         self.chkGrp = createActionGroup(self)
 
         self.codeMetricsAct = EricAction(
@@ -4285,6 +4314,10 @@
         ))
         self.codeProfileAct.triggered.connect(self.__showProfileData)
         self.actions.append(self.codeProfileAct)
+        
+        ###################################################################
+        ## Project Tools - graphics actions
+        ###################################################################
 
         self.graphicsGrp = createActionGroup(self)
 
@@ -4314,9 +4347,13 @@
         ))
         self.loadDiagramAct.triggered.connect(self.__loadDiagram)
         self.actions.append(self.loadDiagramAct)
-
+        
+        ###################################################################
+        ## Project Tools - plugin packaging actions
+        ###################################################################
+        
         self.pluginGrp = createActionGroup(self)
-
+        
         self.pluginPkgListAct = EricAction(
             self.tr('Create Package List'),
             UI.PixmapCache.getIcon("pluginArchiveList"),
@@ -4368,6 +4405,10 @@
         self.pluginSArchiveAct.triggered.connect(
             self.__pluginCreateSnapshotArchives)
         self.actions.append(self.pluginSArchiveAct)
+        
+        ###################################################################
+        ## Project Tools - make actions
+        ###################################################################
 
         self.makeGrp = createActionGroup(self)
 
@@ -4400,10 +4441,16 @@
             lambda: self.__executeMake(questionOnly=True))
         self.actions.append(self.makeTestAct)
         
+        ###################################################################
+        ## Project Tools - other tools actions
+        ###################################################################
+        
+        self.othersGrp = createActionGroup(self)
+        
         self.createSBOMAct = EricAction(
             self.tr('Create SBOM File'),
             self.tr('Create &SBOM File'), 0, 0,
-            self, 'project_create_sbom')
+            self.othersGrp, 'project_create_sbom')
         self.createSBOMAct.setStatusTip(
             self.tr("Create a SBOM file of the project dependencies."))
         self.createSBOMAct.setWhatsThis(self.tr(
@@ -4414,7 +4461,96 @@
         ))
         self.createSBOMAct.triggered.connect(self.__createSBOMFile)
         self.actions.append(self.createSBOMAct)
-
+        
+        ###################################################################
+        ## Project Tools - code formatting actions
+        ###################################################################
+        
+        self.blackFormattingGrp = createActionGroup(self)
+        
+        self.blackAboutAct = EricAction(
+            self.tr("About Black"),
+            self.tr("&Black"),
+            0, 0,
+            self.blackFormattingGrp, "project_black_about"
+        )
+        self.blackAboutAct.setStatusTip(
+            self.tr("Show some information about 'Black'.")
+        )
+        self.blackAboutAct.setWhatsThis(self.tr(
+            "<b>Black</b>"
+            "<p>This shows some information about the installed 'Black' tool.</p>"
+        ))
+        self.blackAboutAct.triggered.connect(self.__aboutBlack)
+        self.actions.append(self.blackAboutAct)
+        font = self.blackAboutAct.font()
+        font.setBold(True)
+        self.blackAboutAct.setFont(font)
+        
+        self.blackFormatAct = EricAction(
+            self.tr("Format Code"),
+            self.tr("&Format Code"),
+            0, 0,
+            self.blackFormattingGrp, "project_black_format_code"
+        )
+        self.blackFormatAct.setStatusTip(
+            self.tr("Format the project sources with 'Black'.")
+        )
+        self.blackFormatAct.setWhatsThis(self.tr(
+            "<b>Format Code</b>"
+            "<p>This shows a dialog to enter parameters for the formatting run and"
+            " reformats the project sources using 'Black'.</p>"
+        ))
+        self.blackFormatAct.triggered.connect(
+            lambda: self.__performFormatWithBlack(BlackFormattingAction.Format)
+        )
+        self.actions.append(self.blackFormatAct)
+        
+        self.blackCheckFormattingAct = EricAction(
+            self.tr("Check Code Formatting"),
+            self.tr("&Check Code Formatting"),
+            0, 0,
+            self.blackFormattingGrp, "project_black_check_code"
+        )
+        self.blackCheckFormattingAct.setStatusTip(
+            self.tr(
+                "Check, if the project sources need to be reformatted with 'Black'."
+            )
+        )
+        self.blackCheckFormattingAct.setWhatsThis(self.tr(
+            "<b>Check Code Formatting</b>"
+            "<p>This shows a dialog to enter parameters for the format check run and"
+            " performs a check, if the project sources need to be reformatted using"
+            " 'Black'.</p>"
+        ))
+        self.blackCheckFormattingAct.triggered.connect(
+            lambda: self.__performFormatWithBlack(BlackFormattingAction.Check)
+        )
+        self.actions.append(self.blackCheckFormattingAct)
+        
+        self.blackDiffFormattingAct = EricAction(
+            self.tr("Code Formatting Diff"),
+            self.tr("Code Formatting &Diff"),
+            0, 0,
+            self.blackFormattingGrp, "project_black_diff_code"
+        )
+        self.blackDiffFormattingAct.setStatusTip(
+            self.tr(
+                "Generate a unified diff of potential project source reformatting"
+                " with 'Black'."
+            )
+        )
+        self.blackDiffFormattingAct.setWhatsThis(self.tr(
+            "<b>Diff Code Formatting</b>"
+            "<p>This shows a dialog to enter parameters for the format diff run and"
+            " generates a unified diff of potential project source reformatting using"
+            " 'Black'.</p>"
+        ))
+        self.blackDiffFormattingAct.triggered.connect(
+            lambda: self.__performFormatWithBlack(BlackFormattingAction.Diff)
+        )
+        self.actions.append(self.blackDiffFormattingAct)
+        
         self.closeAct.setEnabled(False)
         self.saveAct.setEnabled(False)
         self.saveasAct.setEnabled(False)
@@ -4446,6 +4582,8 @@
         self.vcsMenu.setEnabled(self.vcsSoftwareAvailable())
         self.checksMenu = QMenu(self.tr('Chec&k'), toolsMenu)
         self.checksMenu.setTearOffEnabled(True)
+        self.formattingMenu = QMenu(self.tr("Code &Formatting"), toolsMenu)
+        self.formattingMenu.setTearOffEnabled(True)
         self.menuShow = QMenu(self.tr('Sho&w'), toolsMenu)
         self.graphicsMenu = QMenu(self.tr('&Diagrams'), toolsMenu)
         self.packagersMenu = QMenu(self.tr('Pac&kagers'), toolsMenu)
@@ -4467,6 +4605,7 @@
             "Packagers": self.packagersMenu,
             "Make": self.makeMenu,
             "OtherTools": self.othersMenu,
+            "Formatting": self.formattingMenu,
         }
         
         # connect the aboutToShow signals
@@ -4482,6 +4621,7 @@
         self.debuggerMenu.aboutToShow.connect(self.__showContextMenuDebugger)
         self.makeMenu.aboutToShow.connect(self.__showContextMenuMake)
         self.othersMenu.aboutToShow.connect(self.__showContextMenuOthers)
+        self.formattingMenu.aboutToShow.connect(self.__showContextMenuFormat)
         menu.aboutToShow.connect(self.__showMenu)
         
         # build the show menu
@@ -4516,7 +4656,13 @@
         
         # build the 'Other Tools' menu
         self.othersMenu.setTearOffEnabled(True)
-        self.othersMenu.addAction(self.createSBOMAct)
+        self.othersMenu.addActions(self.othersGrp.actions())
+        self.othersMenu.addSeparator()
+        
+        # build the 'Code Formatting' menu
+        self.formattingMenu.setTearOffEnabled(True)
+        self.formattingMenu.addActions(self.blackFormattingGrp.actions())
+        self.formattingMenu.addSeparator()
         
         # build the project main menu
         menu.setTearOffEnabled(True)
@@ -4545,6 +4691,8 @@
         toolsMenu.addSeparator()
         self.menuCheckAct = toolsMenu.addMenu(self.checksMenu)
         toolsMenu.addSeparator()
+        self.menuFormattingAct = toolsMenu.addMenu(self.formattingMenu)
+        toolsMenu.addSeparator()
         self.menuMakeAct = toolsMenu.addMenu(self.makeMenu)
         toolsMenu.addSeparator()
         self.menuDiagramAct = toolsMenu.addMenu(self.graphicsMenu)
@@ -4566,6 +4714,7 @@
         self.menuPackagersAct.setEnabled(False)
         self.menuMakeAct.setEnabled(False)
         self.menuOtherToolsAct.setEnabled(False)
+        self.menuFormattingAct.setEnabled(False)
         
         self.__menu = menu
         self.__toolsMenu = toolsMenu
@@ -5956,7 +6105,7 @@
     #########################################################################
     ## Below are methods implementing the 'SBOM' support
     #########################################################################
-     
+    
     def __showContextMenuOthers(self):
         """
         Private slot called before the 'Other Tools' menu is shown.
@@ -5971,6 +6120,63 @@
         import CycloneDXInterface
         
         CycloneDXInterface.createCycloneDXFile("<project>")
+    
+    #########################################################################
+    ## Below are methods implementing the 'Code Formatting' support
+    #########################################################################
+    
+    def __showContextMenuFormat(self):
+        """
+        Private slot called before the 'Code Formatting' menu is shown.
+        """
+        self.showMenu.emit("Formatting", self.othersMenu)
+    
+    @pyqtSlot()
+    def __aboutBlack(self):
+        """
+        Private slot to show some information about the installed 'Black' tool.
+        """
+        import black
+        
+        EricMessageBox.information(
+            None,
+            self.tr("About Black"),
+            self.tr("""<p><b>Black Version {0}</b></p>"""
+                    """<p><i>Black</i> is the uncompromising Python code"""
+                    """ formatter.</p>""").format(black.__version__)
+        )
+    
+    def __performFormatWithBlack(self, action):
+        """
+        Private method to format the project sources using the 'Black' tool.
+        
+        Following actions are supported.
+        <ul>
+        <li>BlackFormattingAction.Format - the code reformatting is performed</li>
+        <li>BlackFormattingAction.Check - a check is performed, if code formatting
+            is necessary</li>
+        <li>BlackFormattingAction.Diff - a unified diff of potential code formatting
+            changes is generated</li>
+        </ul>
+        
+        @param action formatting operation to be performed
+        @type BlackFormattingAction
+        """
+        from CodeFormatting.BlackConfigurationDialog import BlackConfigurationDialog
+        from CodeFormatting.BlackFormattingDialog import BlackFormattingDialog
+        
+        if ericApp().getObject("ViewManager").checkAllDirty():
+            dlg = BlackConfigurationDialog(withProject=True)
+            if dlg.exec() == QDialog.DialogCode.Accepted:
+                config = dlg.getConfiguration()
+                
+                formattingDialog = BlackFormattingDialog(
+                    config,
+                    self.getProjectFiles("SOURCES", normalized=True),
+                    project=self,
+                    action=action
+                )
+                formattingDialog.exec()
 
 #
 # eflag: noqa = M601

eric ide

mercurial