--- a/src/eric7/Project/ProjectOthersBrowser.py Sun Jul 14 17:24:03 2024 +0200 +++ b/src/eric7/Project/ProjectOthersBrowser.py Sun Jul 14 17:38:30 2024 +0200 @@ -9,6 +9,7 @@ """ import contextlib +import os from PyQt6.QtCore import QUrl, pyqtSignal from PyQt6.QtGui import QDesktopServices @@ -16,7 +17,9 @@ from eric7 import Preferences from eric7.EricGui import EricPixmapCache -from eric7.EricWidgets import EricMessageBox +from eric7.EricWidgets import EricMessageBox, EricPathPickerDialog +from eric7.EricWidgets.EricApplication import ericApp +from eric7.EricWidgets.EricPathPickerDialog import EricPathPickerModes from eric7.SystemUtilities import FileSystemUtilities from eric7.UI.DeleteFilesConfirmationDialog import DeleteFilesConfirmationDialog from eric7.Utilities import MimeTypes @@ -155,6 +158,9 @@ act = self.menu.addAction(self.tr("Delete"), self.__deleteItem) self.menuActions.append(act) self.menu.addSeparator() + self.menu.addAction(self.tr("New file..."), self.__addNewOthersFile) + self.menu.addAction(self.tr("New directory..."), self.__addNewOthersDirectory) + self.menu.addSeparator() self.menu.addAction(self.tr("Add files..."), self.__addOthersFiles) self.menu.addAction(self.tr("Add directory..."), self.__addOthersDirectory) self.menu.addSeparator() @@ -180,6 +186,11 @@ ) self.dirMenuActions.append(self.deleteDirAct) self.dirMenu.addSeparator() + self.dirMenu.addAction(self.tr("New file..."), self.__addNewOthersFile) + self.dirMenu.addAction( + self.tr("New directory..."), self.__addNewOthersDirectory + ) + self.dirMenu.addSeparator() self.dirMenu.addAction(self.tr("Add files..."), self.__addOthersFiles) self.dirMenu.addAction(self.tr("Add directory..."), self.__addOthersDirectory) self.dirMenu.addSeparator() @@ -197,6 +208,15 @@ self.backMenu = QMenu(self) self.backMenu.addAction( + self.tr("New file..."), + lambda: self.__addNewOthersFile(useCurrent=False), + ) + self.backMenu.addAction( + self.tr("New directory..."), + lambda: self.__addNewOthersDirectory(useCurrent=False), + ) + self.backMenu.addSeparator() + self.backMenu.addAction( self.tr("Add files..."), lambda: self.project.addFiles("OTHERS") ) self.backMenu.addAction( @@ -461,6 +481,175 @@ textMimeTypesList.append(mimetype) Preferences.setUI("TextMimeTypes", textMimeTypesList) + def __addNewOthersDirectory(self, useCurrent=True): + """ + Private method to add a new directory to the project. + + @param useCurrent flag indicating to use the current index for the directory + dialog (defaults to True) + @type bool (optional) + """ + from .NewDirectoryDialog import NewDirectoryDialog + + isRemote = FileSystemUtilities.isRemoteFileName(self.project.getProjectPath()) + remotefsInterface = ( + ericApp().getObject("EricServer").getServiceInterface("FileSystem") + ) + + dn = self.currentDirectory() if useCurrent else self.project.getProjectPath() + dlg = NewDirectoryDialog(strPath=dn, defaultDirectory=dn, remote=isRemote) + if dlg.exec() == QDialog.DialogCode.Accepted: + dirname, addToProject = dlg.getDirectory() + exists = ( + remotefsInterface.exists(dirname) + if isRemote + else os.path.exists(dirname) + ) + if exists: + EricMessageBox.critical( + self, + self.tr("New directory"), + self.tr( + "<p>A file or directory named <b>{0}</b> already exists." + " The action will be aborted.</p>" + ).format(dirname), + ) + return + + try: + if isRemote: + remotefsInterface.makedirs(dirname) + else: + os.makedirs(dirname) + except OSError as err: + EricMessageBox.critical( + self, + self.tr("New directory"), + self.tr( + "<p>The directory <b>{0}</b> could not be created." + " Aborting...</p><p>Reason: {1}</p>" + ).format(dirname, str(err)), + ) + return + + parentDirname = ( + remotefsInterface.dirname(dirname) + if isRemote + else os.path.dirname(dirname) + ) + + if addToProject and not self.project.isProjectCategory(dirname, "OTHERS"): + self.project.addToOthers(dirname) + elif parentDirname == self.project.getProjectPath(): + dn = self.project.getRelativePath(dirname) + self._model.addNewItem("OTHERS", dn, simple=True) + while True: + # recursively expand all parent items + dirname = ( + remotefsInterface.dirname(dirname) + if isRemote + else os.path.dirname(dirname) + ) + dirIndex = self._sortModel.mapFromSource( + self._model.itemIndexByName(dirname) + ) + if dirIndex.isValid(): + self.expand(dirIndex) + else: + break + + def __addNewOthersFile(self, useCurrent=True): + """ + Private method to add a new source file to the project. + + @param useCurrent flag indicating to use the current index for the directory + dialog (defaults to True) + @type bool (optional) + """ + isRemote = FileSystemUtilities.isRemoteFileName(self.project.getProjectPath()) + remotefsInterface = ( + ericApp().getObject("EricServer").getServiceInterface("FileSystem") + ) + + dn = self.currentDirectory() if useCurrent else self.project.getProjectPath() + filename, ok = EricPathPickerDialog.getStrPath( + self, + self.tr("New file"), + self.tr("Enter the path of the new file:"), + mode=EricPathPickerModes.SAVE_FILE_ENSURE_EXTENSION_MODE, + strPath=dn, + defaultDirectory=dn, + filters=self.project.getFileCategoryFilters( + categories=["OTHERS"], withAll=False + ), + remote=isRemote, + ) + if ok: + exists = ( + remotefsInterface.exists(filename) + if isRemote + else os.path.exists(filename) + ) + if exists: + EricMessageBox.critical( + self, + self.tr("New file"), + self.tr( + "<p>The file <b>{0}</b> already exists. The action will be" + " aborted.</p>" + ).format(filename), + ) + return + + dirname = ( + remotefsInterface.dirname(filename) + if isRemote + else os.path.dirname(filename) + ) + try: + if isRemote: + remotefsInterface.makedirs(dirname, exist_ok=True) + else: + os.makedirs(dirname, exist_ok=True) + newline = ( + None if self.project.useSystemEol() else self.project.getEolString() + ) + if isRemote: + remotefsInterface.writeFile(filename, b"", newline=newline) + else: + with open(filename, "w", newline=newline) as f: + f.write("") + except OSError as err: + EricMessageBox.critical( + self, + self.tr("New file"), + self.tr( + "<p>The file <b>{0}</b> could not be created. Aborting...</p>" + "<p>Reason: {1}</p>" + ).format(filename, str(err)), + ) + return + + if not self.project.isProjectCategory(filename, "OTHERS"): + self.project.appendFile(filename) + while True: + # recursively expand all parent items + dirIndex = self._sortModel.mapFromSource( + self._model.itemIndexByName(dirname) + ) + if dirIndex.isValid(): + self.expand(dirIndex) + dirname = ( + remotefsInterface.dirname(dirname) + if isRemote + else os.path.dirname(dirname) + ) + else: + break + + if MimeTypes.isTextFile(filename): + self.sourceFile.emit(filename) + def __addOthersFiles(self): """ Private method to add files to the project.