diff --git a/python/python-community-configure/src/com/jetbrains/python/newProject/steps/PyAddExistingSdkPanel.kt b/python/python-community-configure/src/com/jetbrains/python/newProject/steps/PyAddExistingSdkPanel.kt index 3c7029e6085a..5ff1d99b68ac 100644 --- a/python/python-community-configure/src/com/jetbrains/python/newProject/steps/PyAddExistingSdkPanel.kt +++ b/python/python-community-configure/src/com/jetbrains/python/newProject/steps/PyAddExistingSdkPanel.kt @@ -13,6 +13,7 @@ import com.intellij.openapi.util.SystemInfo import com.intellij.openapi.util.component1 import com.intellij.openapi.util.component2 import com.intellij.openapi.util.text.StringUtil +import com.intellij.util.PathMappingSettings import com.intellij.util.ui.FormBuilder import com.intellij.util.ui.UIUtil import com.jetbrains.python.remote.PyProjectSynchronizer @@ -34,6 +35,12 @@ class PyAddExistingSdkPanel(project: Project?, override val panelName: String = "Existing interpreter" + /** + * Path mappings of current synchronizer. + * Once set, [remotePathField] will be updated on any change of local path passed through mappings + */ + private var defaultMappings: List? = null + override val sdk: Sdk? get() = sdkChooserCombo.comboBox.selectedItem as? Sdk @@ -44,6 +51,7 @@ class PyAddExistingSdkPanel(project: Project?, set(value) { field = value sdkChooserCombo.setNewProjectPath(value) + updateRemotePathIfNeeded() } private val sdkChooserCombo: PythonSdkChooserCombo @@ -101,16 +109,34 @@ class PyAddExistingSdkPanel(project: Project?, } } + private fun update() { val synchronizer = sdk?.projectSynchronizer remotePathField.mainPanel.isVisible = synchronizer != null if (synchronizer != null) { val defaultRemotePath = synchronizer.getDefaultRemotePath() + defaultMappings = synchronizer.getAutoMappings() + assert(defaultRemotePath == null || defaultMappings == null) { "Can't have both: default mappings and default value" } + assert(!(defaultRemotePath?.isEmpty() ?: false)) { "Mappings are empty" } + val textField = remotePathField.textField if (defaultRemotePath != null && StringUtil.isEmpty(textField.text)) { textField.text = defaultRemotePath } } + // DefaultMappings revokes user ability to change mapping by her self, so field is readonly + remotePathField.setReadOnly(defaultMappings != null) + updateRemotePathIfNeeded() + } + + /** + * Remote path should be updated automatically if [defaultMappings] are set. + * See [PyProjectSynchronizer.getAutoMappings]. + */ + private fun updateRemotePathIfNeeded() { + val path = newProjectPath ?: return + val mappings = defaultMappings ?: return + remotePathField.textField.text = mappings.find { it.canReplaceLocal(path) }?.mapToRemote(path) ?: "?" } companion object { @@ -136,7 +162,10 @@ class PyAddExistingSdkPanel(project: Project?, } panel.isVisible = true val wrapper = object : DialogWrapper(true) { - init { init() } + init { + init() + } + override fun createCenterPanel() = panel } return if (wrapper.showAndGet()) supplier.get() else null diff --git a/python/python-community-configure/src/com/jetbrains/python/newProject/steps/PyRemotePathField.java b/python/python-community-configure/src/com/jetbrains/python/newProject/steps/PyRemotePathField.java index 2049a668e471..8cda007de4f1 100644 --- a/python/python-community-configure/src/com/jetbrains/python/newProject/steps/PyRemotePathField.java +++ b/python/python-community-configure/src/com/jetbrains/python/newProject/steps/PyRemotePathField.java @@ -38,6 +38,11 @@ public final class PyRemotePathField { return myMainPanel; } + void setReadOnly(final boolean readOnly) { + myLocationField.setEditable(! readOnly); + myLocationField.getButton().setVisible(! readOnly); + } + /** * Add listener for "browse" button */ diff --git a/python/src/com/jetbrains/python/remote/PyProjectSynchronizer.kt b/python/src/com/jetbrains/python/remote/PyProjectSynchronizer.kt index 35c93bdd4f68..1d636a645b07 100644 --- a/python/src/com/jetbrains/python/remote/PyProjectSynchronizer.kt +++ b/python/src/com/jetbrains/python/remote/PyProjectSynchronizer.kt @@ -17,6 +17,7 @@ package com.jetbrains.python.remote import com.intellij.openapi.module.Module import com.intellij.openapi.project.Project +import com.intellij.util.PathMappingSettings import java.io.File import java.util.function.Consumer @@ -48,12 +49,19 @@ interface PyProjectSynchronizer { fun checkSynchronizationAvailable(syncCheckStrategy: PySyncCheckStrategy): String? /** - * @return if remote box allows user to configure remote path, this method returns default path + * if remote box allows user to configure remote path, this method returns default path * that should be shown to user. - * If returns null, user can't configure remote path and GUI should not provide such ability + * + * Must return null if [getAutoMappings] are not null. */ fun getDefaultRemotePath(): String? + /** + * If remote box does not allow user to configure path mapping then these mappings could be used to automatically convert + * local path to remote path. If set, can't be empty and can't coexist with [getDefaultRemotePath] + */ + fun getAutoMappings(): List? = null + /** * Synchronizes project.