diff -r b6f5e27daeb5 -r bb0149571d94 src/eric7/Project/PropertiesDialog.py --- a/src/eric7/Project/PropertiesDialog.py Fri Feb 23 16:52:01 2024 +0100 +++ b/src/eric7/Project/PropertiesDialog.py Mon Feb 26 10:41:10 2024 +0100 @@ -31,7 +31,7 @@ Class implementing the project properties dialog. """ - def __init__(self, project, new=True, parent=None, name=None): + def __init__(self, project, new=True, isRemote=False, parent=None, name=None): """ Constructor @@ -40,6 +40,8 @@ @param new flag indicating the generation of a new project (defaults to True) @type bool (optional) + @param isRemote flag indicating a remote project (defaults to False) + @type bool (optional) @param parent parent widget of this dialog (defaults to None) @type QWidget (optional) @param name name of this dialog (defaults to None) @@ -50,9 +52,19 @@ self.setObjectName(name) self.setupUi(self) + self.__remoteProject = isRemote + self.__remotefsInterface = ( + ericApp().getObject("EricServer").getServiceInterface("FileSystem") + ) + self.dirPicker.setMode(EricPathPickerModes.DIRECTORY_MODE) + self.dirPicker.setRemote(isRemote) + self.srcDirPicker.setMode(EricPathPickerModes.DIRECTORY_MODE) + self.srcDirPicker.setRemote(isRemote) + self.mainscriptPicker.setMode(EricPathPickerModes.OPEN_FILE_MODE) + self.mainscriptPicker.setRemote(isRemote) self.makeButton.setIcon(EricPixmapCache.getIcon("makefile")) @@ -62,21 +74,19 @@ self.project = project self.newProject = new + self.transPropertiesDlg = None self.spellPropertiesDlg = None self.makePropertiesDlg = None self.__fileTypesDict = {} - patterns = [] - for pattern, filetype in self.project.getProjectData( - dataKey="FILETYPES" - ).items(): - if filetype == "SOURCES": - patterns.append(pattern) - filters = self.tr("Source Files ({0});;All Files (*)").format( - " ".join(sorted(patterns)) - ) - self.mainscriptPicker.setFilters(filters) + if self.__remoteProject: + # some stuff is not supported for remote projects + self.makeCheckBox.setEnabled(False) + self.makeButton.setEnabled(False) + self.testingFrameworkComboBox.setEnabled(False) + self.embeddedVenvCheckBox.setEnabled(False) + self.spellPropertiesButton.setEnabled(False) self.languageComboBox.addItems(project.getProgrammingLanguages()) @@ -87,18 +97,28 @@ for projectType in sorted(projectTypes): self.projectTypeComboBox.addItem(projectType[0], projectType[1]) - ipath = Preferences.getMultiProject("Workspace") or OSUtilities.getHomeDir() - self.__initPaths = [ - FileSystemUtilities.fromNativeSeparators(ipath), - FileSystemUtilities.fromNativeSeparators(ipath) + "/", - ] + if self.__remoteProject: + self.__initPaths = [self.__remotefsInterface.getcwd()] + else: + ipath = Preferences.getMultiProject("Workspace") or OSUtilities.getHomeDir() + self.__initPaths = [ + FileSystemUtilities.fromNativeSeparators(ipath), + FileSystemUtilities.fromNativeSeparators(ipath) + "/", + ] self.licenseComboBox.lineEdit().setClearButtonEnabled(True) self.__populateLicenseComboBox() if not new: - name = os.path.splitext(self.project.pfile)[0] - self.nameEdit.setText(os.path.basename(name)) + self.nameEdit.setReadOnly(True) + self.dirPicker.setReadOnly(True) + + if self.__remoteProject: + name = self.__remotefsInterface.splitext(self.project.pfile)[0] + self.nameEdit.setText(self.__remotefsInterface.basename(name)) + else: + name = os.path.splitext(self.project.pfile)[0] + self.nameEdit.setText(os.path.basename(name)) self.languageComboBox.setCurrentIndex( self.languageComboBox.findText( self.project.getProjectData(dataKey="PROGLANGUAGE") @@ -126,40 +146,53 @@ ) self.eolComboBox.setCurrentIndex(self.project.getProjectData(dataKey="EOL")) self.vcsLabel.show() - if self.project.vcs is not None: - vcsSystemsDict = ( - ericApp() - .getObject("PluginManager") - .getPluginDisplayStrings("version_control") + if not self.__remoteProject: + # VCS not supported for remote projects + if self.project.vcs is not None: + vcsSystemsDict = ( + ericApp() + .getObject("PluginManager") + .getPluginDisplayStrings("version_control") + ) + try: + vcsSystemDisplay = vcsSystemsDict[ + self.project.getProjectData(dataKey="VCS") + ] + except KeyError: + vcsSystemDisplay = "None" + self.vcsLabel.setText( + self.tr( + "The project is version controlled by <b>{0}</b>." + ).format(vcsSystemDisplay) + ) + self.vcsInfoButton.show() + else: + self.vcsLabel.setText( + self.tr("The project is not version controlled.") + ) + self.vcsInfoButton.hide() + else: + self.vcsLabel.setText( + self.tr("Version control is not available for remote projects.") ) - try: - vcsSystemDisplay = vcsSystemsDict[ - self.project.getProjectData(dataKey="VCS") - ] - except KeyError: - vcsSystemDisplay = "None" - self.vcsLabel.setText( - self.tr("The project is version controlled by <b>{0}</b>.").format( - vcsSystemDisplay - ) - ) - self.vcsInfoButton.show() - else: - self.vcsLabel.setText(self.tr("The project is not version controlled.")) self.vcsInfoButton.hide() self.vcsCheckBox.hide() - self.makeCheckBox.setChecked( - self.project.getProjectData(dataKey="MAKEPARAMS")["MakeEnabled"] - ) + if self.__remoteProject: + self.makeCheckBox.setChecked(False) + else: + self.makeCheckBox.setChecked( + self.project.getProjectData(dataKey="MAKEPARAMS")["MakeEnabled"] + ) cindex = self.docstringStyleComboBox.findData( self.project.getProjectData(dataKey="DOCSTRING") ) self.docstringStyleComboBox.setCurrentIndex(cindex) - with contextlib.suppress(KeyError): - cindex = self.testingFrameworkComboBox.findData( - self.project.getProjectData(dataKey="TESTING_FRAMEWORK") - ) - self.testingFrameworkComboBox.setCurrentIndex(cindex) + if not self.__remoteProject: + with contextlib.suppress(KeyError): + cindex = self.testingFrameworkComboBox.findData( + self.project.getProjectData(dataKey="TESTING_FRAMEWORK") + ) + self.testingFrameworkComboBox.setCurrentIndex(cindex) with contextlib.suppress(KeyError): self.licenseComboBox.setCurrentText( self.project.getProjectData(dataKey="LICENSE") @@ -176,13 +209,15 @@ self.versionEdit.setText("0.1") self.vcsLabel.hide() self.vcsInfoButton.hide() - if not self.project.vcsSoftwareAvailable(): + if self.__remoteProject or not self.project.vcsSoftwareAvailable(): self.vcsCheckBox.hide() self.__origProgrammingLanguage = self.languageComboBox.currentText() self.__origMixedFlag = self.mixedLanguageCheckBox.isChecked() self.__origProjectType = self.getProjectType() + self.__initFileTypesDict(force=True) + self.languageComboBox.currentTextChanged.connect(self.__initFileTypesDict) self.mixedLanguageCheckBox.stateChanged.connect(self.__initFileTypesDict) self.projectTypeComboBox.currentIndexChanged.connect(self.__initFileTypesDict) @@ -192,6 +227,23 @@ and self.dirPicker.text() not in self.__initPaths ) + def __setMainScriptPickerFilters(self): + """ + Private method to set the filters for the main script file picker. + """ + patterns = [] + for pattern, filetype in self.__fileTypesDict.items(): + if filetype == "SOURCES": + patterns.append(pattern) + filters = ( + self.tr("Source Files ({0});;All Files (*)").format( + " ".join(sorted(patterns)) + ) + if patterns + else self.tr("All Files (*)") + ) + self.mainscriptPicker.setFilters(filters) + def __populateLicenseComboBox(self): """ Private method to populate the license selector with the list of trove @@ -243,10 +295,17 @@ @param txt name of the project directory @type str """ - self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setEnabled( - bool(txt) - and FileSystemUtilities.fromNativeSeparators(txt) not in self.__initPaths - ) + if self.__remoteProject: + self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setEnabled( + FileSystemUtilities.isRemoteFileName(txt) + and txt not in self.__initPaths + ) + else: + self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setEnabled( + bool(txt) + and FileSystemUtilities.fromNativeSeparators(txt) + not in self.__initPaths + ) @pyqtSlot(str) def on_srcDirPicker_pathSelected(self, srcDir): @@ -259,7 +318,13 @@ if srcDir: ppath = self.dirPicker.text() if ppath: - ppath = QDir(ppath).absolutePath() + QDir.separator() + if self.__remoteProject: + ppath = ( + FileSystemUtilities.remoteFileName(ppath) + + self.__remotefsInterface.separator() + ) + else: + ppath = os.path.abspath(ppath) + os.sep srcDir = srcDir.replace(ppath, "") self.srcDirPicker.setText(srcDir) @@ -271,7 +336,10 @@ """ ppath = self.dirPicker.text() if not ppath: - ppath = QDir.currentPath() + if self.__remoteProject: + ppath = self.__remotefsInterface.getcwd() + else: + ppath = QDir.currentPath() self.srcDirPicker.setDefaultDirectory(ppath) @pyqtSlot() @@ -298,7 +366,7 @@ if self.transPropertiesDlg is None: self.transPropertiesDlg = TranslationPropertiesDialog( - self.project, self.newProject, self + self.project, self.newProject, self, isRemote=self.__remoteProject ) else: self.transPropertiesDlg.initFilters() @@ -332,7 +400,13 @@ if script: ppath = self.dirPicker.text() if ppath: - ppath = QDir(ppath).absolutePath() + QDir.separator() + if self.__remoteProject: + ppath = ( + FileSystemUtilities.remoteFileName(ppath) + + self.__remotefsInterface.separator() + ) + else: + ppath = os.path.abspath(ppath) + os.sep script = script.replace(ppath, "") self.mainscriptPicker.setText(script) @@ -344,7 +418,10 @@ """ ppath = self.dirPicker.text() if not ppath: - ppath = QDir.currentPath() + if self.__remoteProject: + ppath = self.__remotefsInterface.getcwd() + else: + ppath = QDir.currentPath() self.mainscriptPicker.setDefaultDirectory(ppath) @pyqtSlot() @@ -379,15 +456,22 @@ @return data of the project directory edit @rtype str """ - return os.path.abspath(self.dirPicker.text()) + if self.__remoteProject: + return FileSystemUtilities.remoteFileName(self.dirPicker.text()) + else: + return os.path.abspath(self.dirPicker.text()) @pyqtSlot() - def __initFileTypesDict(self): + def __initFileTypesDict(self, force=False): """ Private slot to (re-)initialize the filetype dictionary. + + @param force flag indicating to force the initialization (defaults to False) + @type bool (optional) """ if ( - self.__origProgrammingLanguage != self.languageComboBox.currentText() + force + or self.__origProgrammingLanguage != self.languageComboBox.currentText() or self.__origMixedFlag != self.mixedLanguageCheckBox.isChecked() or self.__origProjectType != self.getProjectType() ): @@ -401,6 +485,8 @@ # all of the defining data was changed back to original self.__fileTypesDict = self.project.getProjectData(dataKey="FILETYPES") + self.__setMainScriptPickerFilters() + @pyqtSlot() def on_filetypesButton_clicked(self): """ @@ -428,18 +514,35 @@ if dlg.exec() == QDialog.DialogCode.Accepted: self.__fileTypesDict = dlg.getData() + self.__setMainScriptPickerFilters() + def storeData(self): """ Public method to store the entered/modified data. """ - self.project.ppath = os.path.abspath(self.dirPicker.text()) - fn = self.nameEdit.text() - if fn: - self.project.name = fn - fn = f"{fn}.epj" - self.project.pfile = os.path.join(self.project.ppath, fn) - else: - self.project.pfile = "" + if self.newProject: + if self.__remoteProject: + self.project.ppath = FileSystemUtilities.remoteFileName( + self.__remotefsInterface.abspath(self.dirPicker.text()) + ) + fn = self.nameEdit.text() + if fn: + self.project.name = fn + fn = f"{fn}.epj" + self.project.pfile = self.__remotefsInterface.join( + self.project.ppath, fn + ) + else: + self.project.pfile = "" + else: + self.project.ppath = os.path.abspath(self.dirPicker.text()) + fn = self.nameEdit.text() + if fn: + self.project.name = fn + fn = f"{fn}.epj" + self.project.pfile = os.path.join(self.project.ppath, fn) + else: + self.project.pfile = "" self.project.setProjectData(self.versionEdit.text(), dataKey="VERSION") srcDir = self.srcDirPicker.text() if srcDir: @@ -451,7 +554,10 @@ if fn: fn = self.project.getRelativePath(fn) self.project.setProjectData(fn, dataKey="MAINSCRIPT") - self.project.translationsRoot = os.path.splitext(fn)[0] + if self.__remoteProject: + self.project.translationsRoot = self.__remotefsInterface.splitext(fn)[0] + else: + self.project.translationsRoot = os.path.splitext(fn)[0] else: self.project.setProjectData("", dataKey="MAINSCRIPT") self.project.translationsRoot = ""