diff --git a/python/ide/src/com/jetbrains/python/configuration/PyActiveSdkConfigurable.java b/python/ide/src/com/jetbrains/python/configuration/PyActiveSdkConfigurable.java index b7ac9c3fe53f..b2a7d915aaa2 100644 --- a/python/ide/src/com/jetbrains/python/configuration/PyActiveSdkConfigurable.java +++ b/python/ide/src/com/jetbrains/python/configuration/PyActiveSdkConfigurable.java @@ -137,7 +137,7 @@ public class PyActiveSdkConfigurable implements UnnamedConfigurable { @Override public void consume(Sdk sdk) { if (sdk == null) return; - final PyRemovedSdkService sdkService = PyRemovedSdkService.getInstance(); + final PySdkService sdkService = PySdkService.getInstance(); sdkService.restoreSdk(sdk); if (myProjectSdksModel.findSdk(sdk) == null) { myProjectSdksModel.addSdk(sdk); @@ -283,6 +283,7 @@ public class PyActiveSdkConfigurable implements UnnamedConfigurable { mySdkCombo.setSelectedItem(newSdk); myProjectSdksModel.apply(); } + PySdkService.getInstance().solidifySdk(item); } else { final Sdk sdk = myProjectSdksModel.findSdk(item); diff --git a/python/ide/src/com/jetbrains/python/configuration/PyConfigurableInterpreterList.java b/python/ide/src/com/jetbrains/python/configuration/PyConfigurableInterpreterList.java index c7176dd811f9..9cdaf97a6ca5 100644 --- a/python/ide/src/com/jetbrains/python/configuration/PyConfigurableInterpreterList.java +++ b/python/ide/src/com/jetbrains/python/configuration/PyConfigurableInterpreterList.java @@ -24,10 +24,7 @@ import com.intellij.openapi.projectRoots.impl.SdkConfigurationUtil; import com.intellij.openapi.roots.ui.configuration.projectRoot.ProjectSdksModel; import com.intellij.openapi.util.Comparing; import com.jetbrains.python.psi.LanguageLevel; -import com.jetbrains.python.sdk.PyDetectedSdk; -import com.jetbrains.python.sdk.PySdkUtil; -import com.jetbrains.python.sdk.PythonSdkAdditionalData; -import com.jetbrains.python.sdk.PythonSdkType; +import com.jetbrains.python.sdk.*; import com.jetbrains.python.sdk.flavors.PythonSdkFlavor; import com.jetbrains.python.sdk.flavors.VirtualEnvSdkFlavor; import org.jetbrains.annotations.Nullable; @@ -112,6 +109,7 @@ public class PyConfigurableInterpreterList { } }); + final PySdkService sdkService = PySdkService.getInstance(); final List sdkHomes = new ArrayList(); sdkHomes.addAll(VirtualEnvSdkFlavor.INSTANCE.suggestHomePaths()); for (PythonSdkFlavor flavor : PythonSdkFlavor.getApplicableFlavors()) { @@ -122,10 +120,13 @@ public class PyConfigurableInterpreterList { for (String sdkHome : SdkConfigurationUtil.filterExistingPaths(PythonSdkType.getInstance(), sdkHomes, getModel().getSdks())) { result.add(new PyDetectedSdk(sdkHome)); } + for (String sdkHome : SdkConfigurationUtil.filterExistingPaths(PythonSdkType.getInstance(), sdkService.getAddedSdks(), getModel().getSdks())) { + result.add(new PyDetectedSdk(sdkHome)); + } Iterables.removeIf(result, new Predicate() { @Override public boolean apply(@Nullable Sdk input) { - return input != null && PyRemovedSdkService.getInstance().isRemoved(input); + return input != null && sdkService.isRemoved(input); } }); return result; diff --git a/python/ide/src/com/jetbrains/python/configuration/PythonSdkDetailsDialog.java b/python/ide/src/com/jetbrains/python/configuration/PythonSdkDetailsDialog.java index b39f5f4029ab..be4273d99da6 100644 --- a/python/ide/src/com/jetbrains/python/configuration/PythonSdkDetailsDialog.java +++ b/python/ide/src/com/jetbrains/python/configuration/PythonSdkDetailsDialog.java @@ -272,7 +272,7 @@ public class PythonSdkDetailsDialog extends DialogWrapper { private void addCreatedSdk(@Nullable final Sdk sdk, boolean newVirtualEnv) { if (sdk != null) { - final PyRemovedSdkService sdkService = PyRemovedSdkService.getInstance(); + final PySdkService sdkService = PySdkService.getInstance(); sdkService.restoreSdk(sdk); boolean isVirtualEnv = PythonSdkType.isVirtualEnv(sdk); @@ -385,7 +385,7 @@ public class PythonSdkDetailsDialog extends DialogWrapper { private void removeSdk() { final Sdk currentSdk = getSelectedSdk(); if (currentSdk != null) { - final PyRemovedSdkService sdkService = PyRemovedSdkService.getInstance(); + final PySdkService sdkService = PySdkService.getInstance(); sdkService.removeSdk(currentSdk); myProjectSdksModel.removeSdk(currentSdk); if (myModificators.containsKey(currentSdk)) { diff --git a/python/src/META-INF/python-core.xml b/python/src/META-INF/python-core.xml index 9c2d824a4403..c15dcce907dd 100644 --- a/python/src/META-INF/python-core.xml +++ b/python/src/META-INF/python-core.xml @@ -375,8 +375,8 @@ serviceImplementation="com.jetbrains.python.codeInsight.PyCodeInsightSettings"/> - + diff --git a/python/src/com/jetbrains/python/sdk/CreateVirtualEnvDialog.java b/python/src/com/jetbrains/python/sdk/CreateVirtualEnvDialog.java index a74fd85aba7d..9236e4e2c4f4 100644 --- a/python/src/com/jetbrains/python/sdk/CreateVirtualEnvDialog.java +++ b/python/src/com/jetbrains/python/sdk/CreateVirtualEnvDialog.java @@ -22,6 +22,9 @@ import com.intellij.facet.ui.FacetValidatorsManager; import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; +import com.intellij.openapi.fileChooser.FileChooser; +import com.intellij.openapi.fileChooser.FileChooserDescriptor; +import com.intellij.openapi.fileChooser.PathChooserDialog; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.progress.Task; @@ -33,6 +36,7 @@ import com.intellij.openapi.ui.ComboBox; import com.intellij.openapi.ui.FixedSizeButton; import com.intellij.openapi.ui.TextFieldWithBrowseButton; import com.intellij.openapi.util.Computable; +import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.LocalFileSystem; @@ -81,7 +85,7 @@ public class CreateVirtualEnvDialog extends IdeaDialog { void virtualEnvCreated(Sdk sdk, boolean associateWithProject); } - private void setupVirtualEnvSdk(List allSdks, + private static void setupVirtualEnvSdk(List allSdks, final String path, boolean associateWithProject, VirtualEnvCallback callback) { @@ -243,16 +247,50 @@ public class CreateVirtualEnvDialog extends IdeaDialog { myMainPanel.add(myMakeAvailableToAllProjectsCheckbox, c); button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { - SdkConfigurationUtil.createSdk(myProject, allSdks.toArray(new Sdk[allSdks.size()]), new NullableConsumer() { + final PySdkService sdkService = PySdkService.getInstance(); + + final PythonSdkType sdkType = PythonSdkType.getInstance(); + final FileChooserDescriptor descriptor = sdkType.getHomeChooserDescriptor(); + if (SystemInfo.isMac) { + descriptor.putUserData(PathChooserDialog.NATIVE_MAC_CHOOSER_SHOW_HIDDEN_FILES, Boolean.TRUE); + } + String suggestedPath = sdkType.suggestHomePath(); + VirtualFile suggestedDir = suggestedPath == null + ? null + : LocalFileSystem.getInstance().findFileByPath(FileUtil.toSystemIndependentName(suggestedPath)); + final NullableConsumer consumer = new NullableConsumer() { @Override public void consume(@Nullable Sdk sdk) { if (sdk == null) return; if (!allSdks.contains(sdk)) { allSdks.add(sdk); + sdkService.addSdk(sdk); } updateSdkList(allSdks, sdk); } - }, false, PythonSdkType.getInstance()); + }; + FileChooser.chooseFiles(descriptor, myProject, suggestedDir, new FileChooser.FileChooserConsumer() { + @Override + public void consume(List selectedFiles) { + final String path = selectedFiles.get(0).getPath(); + if (sdkType.isValidSdkHome(path)) { + Sdk newSdk = null; + for (Sdk sdk : allSdks) { + if (path.equals(sdk.getHomePath())) { + newSdk = sdk; + } + } + if (newSdk == null) + newSdk = new PyDetectedSdk(path); + consumer.consume(newSdk); + } + } + + @Override + public void cancelled() { + } + }); + } }); } diff --git a/python/ide/src/com/jetbrains/python/configuration/PyRemovedSdkService.java b/python/src/com/jetbrains/python/sdk/PySdkService.java similarity index 63% rename from python/ide/src/com/jetbrains/python/configuration/PyRemovedSdkService.java rename to python/src/com/jetbrains/python/sdk/PySdkService.java index f0927f7d1c81..0337e3d58fce 100644 --- a/python/ide/src/com/jetbrains/python/configuration/PyRemovedSdkService.java +++ b/python/src/com/jetbrains/python/sdk/PySdkService.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.jetbrains.python.configuration; +package com.jetbrains.python.sdk; import com.intellij.openapi.components.*; import com.intellij.openapi.projectRoots.Sdk; @@ -24,22 +24,34 @@ import java.util.HashSet; import java.util.Set; @State( - name = "PyRemovedSdkService", + name = "PySdkService", storages = { @Storage( file = StoragePathMacros.APP_CONFIG + "/removedInterpreters.xml" )} ) -public class PyRemovedSdkService implements PersistentStateComponent { +public class PySdkService implements PersistentStateComponent { - public static PyRemovedSdkService getInstance() { - return ServiceManager.getService(PyRemovedSdkService.class); + public static PySdkService getInstance() { + return ServiceManager.getService(PySdkService.class); } public Set REMOVED_SDKS = new HashSet(); + public Set ADDED_SDKS = new HashSet(); public void removeSdk(@NotNull final Sdk sdk) { - REMOVED_SDKS.add(sdk.getHomePath()); + final String homePath = sdk.getHomePath(); + if (ADDED_SDKS.contains(homePath)) + ADDED_SDKS.remove(homePath); + REMOVED_SDKS.add(homePath); + } + + public void addSdk(@NotNull final Sdk sdk) { + ADDED_SDKS.add(sdk.getHomePath()); + } + + public Set getAddedSdks() { + return ADDED_SDKS; } public void restoreSdk(@NotNull final Sdk sdk) { @@ -54,13 +66,20 @@ public class PyRemovedSdkService implements PersistentStateComponent { private DialogWrapper myMore; @@ -154,7 +155,7 @@ public class PythonSdkDetailsStep extends BaseListPopupStep { Iterables.removeIf(allSdks, new Predicate() { @Override public boolean apply(Sdk sdk) { - return sdk.getSdkType() instanceof PythonSdkType; + return !(sdk.getSdkType() instanceof PythonSdkType); } }); final List flavors = PythonSdkFlavor.getApplicableFlavors(false); @@ -164,7 +165,10 @@ public class PythonSdkDetailsStep extends BaseListPopupStep { allSdks.add(new PyDetectedSdk(string)); } } - + final Set sdks = PySdkService.getInstance().getAddedSdks(); + for (String string : SdkConfigurationUtil.filterExistingPaths(PythonSdkType.getInstance(), sdks, myExistingSdks)) { + allSdks.add(new PyDetectedSdk(string)); + } if (myProject != null) { dialog = new CreateVirtualEnvDialog(myProject, allSdks, null); }