mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
second iteration for python project interpreters page
Added More/Show All buttons filter out symlinks from suggested interpreters homepath Add detected sdk to project Sorting for interpreters combobox Added separators to interpreter combobox
This commit is contained in:
@@ -224,7 +224,7 @@ public class PyIdeCommonOptionsForm implements AbstractPyCommonOptionsForm {
|
||||
}
|
||||
|
||||
public void updateSdkList(boolean preserveSelection, PyConfigurableInterpreterList myInterpreterList) {
|
||||
myPythonSdks = myInterpreterList.getAllPythonSdks();
|
||||
myPythonSdks = myInterpreterList.getAllPythonSdks(myProject);
|
||||
Sdk selection = preserveSelection ? (Sdk)myInterpreterComboBox.getSelectedItem() : null;
|
||||
if (!myPythonSdks.contains(selection)) {
|
||||
selection = null;
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package com.jetbrains.python.configuration;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.EditorFactory;
|
||||
import com.intellij.openapi.editor.ex.EditorEx;
|
||||
@@ -27,12 +28,14 @@ import com.intellij.openapi.options.UnnamedConfigurable;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.projectRoots.SdkModel;
|
||||
import com.intellij.openapi.projectRoots.impl.SdkConfigurationUtil;
|
||||
import com.intellij.openapi.projectRoots.impl.SdkListCellRenderer;
|
||||
import com.intellij.openapi.roots.ModuleRootManager;
|
||||
import com.intellij.openapi.roots.ModuleRootModificationUtil;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.ProjectSdksModel;
|
||||
import com.intellij.openapi.ui.ComboBox;
|
||||
import com.intellij.openapi.ui.DialogBuilder;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.ui.CollectionComboBoxModel;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
@@ -42,8 +45,7 @@ import com.intellij.webcore.packaging.PackagesNotificationPanel;
|
||||
import com.jetbrains.python.packaging.ui.PyInstalledPackagesPanel;
|
||||
import com.jetbrains.python.packaging.ui.PyPackageManagementService;
|
||||
import com.jetbrains.python.psi.LanguageLevel;
|
||||
import com.jetbrains.python.sdk.DetailsChooser;
|
||||
import com.jetbrains.python.sdk.PySdkListCellRenderer;
|
||||
import com.jetbrains.python.sdk.*;
|
||||
import com.jetbrains.python.sdk.flavors.PythonSdkFlavor;
|
||||
import icons.PythonIcons;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -53,6 +55,7 @@ import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class PyActiveSdkConfigurable implements UnnamedConfigurable {
|
||||
@@ -66,6 +69,7 @@ public class PyActiveSdkConfigurable implements UnnamedConfigurable {
|
||||
private ComboBox mySdkCombo;
|
||||
private PyInstalledPackagesPanel myPackagesPanel;
|
||||
private JButton myDetailsButton;
|
||||
private static final String SHOW_ALL = "Show All";
|
||||
|
||||
public PyActiveSdkConfigurable(@NotNull Project project) {
|
||||
myModule = null;
|
||||
@@ -101,7 +105,7 @@ public class PyActiveSdkConfigurable implements UnnamedConfigurable {
|
||||
myDetailsButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
DetailsChooser.show(myProject, myProjectSdksModel.getSdks(),
|
||||
DetailsChooser.show(myProject, myProjectSdksModel.getSdks(), new PythonSdkConfigurable(myProject).createComponent(),
|
||||
RelativePoint.fromScreen(myDetailsButton.getLocationOnScreen()), true,
|
||||
new NullableConsumer<Sdk>() {
|
||||
@Override
|
||||
@@ -114,8 +118,8 @@ public class PyActiveSdkConfigurable implements UnnamedConfigurable {
|
||||
myInterpreterList.setSelectedSdk(sdk);
|
||||
|
||||
mySdkCombo.getModel().setSelectedItem(sdk);
|
||||
myPackagesPanel
|
||||
.updatePackages(new PyPackageManagementService(myProject, sdk));
|
||||
myPackagesPanel.updatePackages(
|
||||
new PyPackageManagementService(myProject, sdk));
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -130,7 +134,22 @@ public class PyActiveSdkConfigurable implements UnnamedConfigurable {
|
||||
myPanel = new JPanel(layout);
|
||||
final JLabel label = new JLabel("Project Interpreter:");
|
||||
final JLabel label1 = new JLabel(" ");
|
||||
mySdkCombo = new ComboBox();
|
||||
mySdkCombo = new ComboBox() {
|
||||
@Override
|
||||
public void setSelectedItem(Object item)
|
||||
{
|
||||
if (SHOW_ALL.equals(item)) {
|
||||
DialogBuilder dialog = new DialogBuilder(myProject);
|
||||
dialog.setTitle("Python Interpreters");
|
||||
dialog.setCenterPanel(new PythonSdkConfigurable(myProject).createComponent());
|
||||
dialog.show();
|
||||
return;
|
||||
}
|
||||
if (!PySdkListCellRenderer.SEPARATOR.equals(item.toString()))
|
||||
super.setSelectedItem(item);
|
||||
}
|
||||
};
|
||||
mySdkCombo.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE);
|
||||
mySdkCombo.setRenderer(new SdkListCellRenderer("<None>"));
|
||||
|
||||
PackagesNotificationPanel notificationsArea = new PackagesNotificationPanel(myProject);
|
||||
@@ -199,7 +218,8 @@ public class PyActiveSdkConfigurable implements UnnamedConfigurable {
|
||||
@Override
|
||||
public boolean isModified() {
|
||||
final Sdk sdk = getSdk();
|
||||
return sdk != myProjectSdksModel.findSdk((Sdk)mySdkCombo.getSelectedItem());
|
||||
final Sdk selectedItem = (Sdk)mySdkCombo.getSelectedItem();
|
||||
return selectedItem instanceof PyDetectedSdk || sdk != myProjectSdksModel.findSdk(selectedItem);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -213,8 +233,18 @@ public class PyActiveSdkConfigurable implements UnnamedConfigurable {
|
||||
|
||||
@Override
|
||||
public void apply() throws ConfigurationException {
|
||||
final Sdk item = (Sdk)mySdkCombo.getSelectedItem();
|
||||
if (item instanceof PyDetectedSdk) {
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final Sdk sdk = SdkConfigurationUtil.createAndAddSDK(item.getName(), PythonSdkType.getInstance());
|
||||
SdkConfigurationUtil.setDirectoryProjectSdk(myProject, sdk);
|
||||
}
|
||||
}, ModalityState.any());
|
||||
}
|
||||
myProjectSdksModel.apply();
|
||||
final Sdk selectedSdk = myProjectSdksModel.findSdk((Sdk)mySdkCombo.getSelectedItem());
|
||||
final Sdk selectedSdk = myProjectSdksModel.findSdk(item);
|
||||
if (myModule == null) {
|
||||
final ProjectRootManager rootManager = ProjectRootManager.getInstance(myProject);
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
@@ -280,7 +310,7 @@ public class PyActiveSdkConfigurable implements UnnamedConfigurable {
|
||||
}
|
||||
|
||||
private void updateSdkList(boolean preserveSelection) {
|
||||
final List<Sdk> sdkList = myInterpreterList.getAllPythonSdks();
|
||||
final List<Sdk> sdkList = myInterpreterList.getAllPythonSdks(myProject);
|
||||
Sdk selection = preserveSelection ? (Sdk)mySdkCombo.getSelectedItem() : null;
|
||||
if (!sdkList.contains(selection)) {
|
||||
selection = null;
|
||||
@@ -290,9 +320,44 @@ public class PyActiveSdkConfigurable implements UnnamedConfigurable {
|
||||
if (selection != null && !sdkList.contains(selection)) {
|
||||
sdkList.add(0, selection);
|
||||
}
|
||||
sdkList.add(0, null);
|
||||
List<Object> items = new ArrayList<Object>();
|
||||
items.add(null);
|
||||
|
||||
boolean remoteSeparator = true;
|
||||
boolean separator = true;
|
||||
boolean detectedSeparator = true;
|
||||
boolean hasAssociationsWithDifferentProject = false;
|
||||
final String projectBasePath = myProject.getBasePath();
|
||||
for (Sdk sdk : sdkList) {
|
||||
if (!PythonSdkType.isVirtualEnv(sdk) && !PythonSdkType.isRemote(sdk) &&
|
||||
!(sdk instanceof PyDetectedSdk) && separator) {
|
||||
items.add(PySdkListCellRenderer.SEPARATOR);
|
||||
separator = false;
|
||||
}
|
||||
if (PythonSdkType.isRemote(sdk) && remoteSeparator) {
|
||||
items.add(PySdkListCellRenderer.SEPARATOR);
|
||||
remoteSeparator = false;
|
||||
}
|
||||
if (sdk instanceof PyDetectedSdk && detectedSeparator) {
|
||||
items.add(PySdkListCellRenderer.SEPARATOR);
|
||||
detectedSeparator = false;
|
||||
}
|
||||
items.add(sdk);
|
||||
|
||||
final PythonSdkAdditionalData data = (PythonSdkAdditionalData)sdk.getSdkAdditionalData();
|
||||
if (data != null) {
|
||||
final String path = data.getAssociatedProjectPath();
|
||||
if (path != null && !path.equals(projectBasePath)) hasAssociationsWithDifferentProject = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasAssociationsWithDifferentProject) {
|
||||
items.add(PySdkListCellRenderer.SEPARATOR);
|
||||
items.add(SHOW_ALL);
|
||||
}
|
||||
|
||||
mySdkCombo.setRenderer(new PySdkListCellRenderer());
|
||||
mySdkCombo.setModel(new CollectionComboBoxModel(sdkList, selection));
|
||||
mySdkCombo.setModel(new CollectionComboBoxModel(items, selection));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+55
-5
@@ -18,15 +18,18 @@ package com.jetbrains.python.configuration;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
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.flavors.PythonSdkFlavor;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Manages the SDK model shared between PythonSdkConfigurable and PyActiveSdkConfigurable.
|
||||
@@ -65,19 +68,66 @@ public class PyConfigurableInterpreterList {
|
||||
}
|
||||
}
|
||||
|
||||
public List<Sdk> getAllPythonSdks() {
|
||||
public List<Sdk> getAllPythonSdks(final Project project) {
|
||||
List<Sdk> result = new ArrayList<Sdk>();
|
||||
for (Sdk sdk : getModel().getSdks()) {
|
||||
if (sdk.getSdkType() instanceof PythonSdkType) {
|
||||
result.add(sdk);
|
||||
}
|
||||
}
|
||||
Collection<String> sdkHomes = PythonSdkType.getInstance().suggestHomePaths();
|
||||
|
||||
Collections.sort(result, new Comparator<Sdk>() {
|
||||
@Override
|
||||
public int compare(Sdk o1, Sdk o2) {
|
||||
if (!(o1.getSdkType() instanceof PythonSdkType) ||
|
||||
!(o2.getSdkType() instanceof PythonSdkType))
|
||||
return -Comparing.compare(o1.getName(), o2.getName());
|
||||
|
||||
final boolean isVEnv1 = PythonSdkType.isVirtualEnv(o1);
|
||||
final boolean isVEnv2 = PythonSdkType.isVirtualEnv(o2);
|
||||
final boolean isRemote1 = PySdkUtil.isRemote(o1);
|
||||
final boolean isRemote2 = PySdkUtil.isRemote(o2);
|
||||
final PythonSdkFlavor flavor1 = PythonSdkFlavor.getFlavor(o1);
|
||||
final PythonSdkFlavor flavor2 = PythonSdkFlavor.getFlavor(o2);
|
||||
final LanguageLevel level1 = flavor1 != null ? flavor1.getLanguageLevel(o1) : LanguageLevel.getDefault();
|
||||
final LanguageLevel level2 = flavor2 != null ? flavor2.getLanguageLevel(o2) : LanguageLevel.getDefault();
|
||||
|
||||
if (isVEnv1) {
|
||||
if (associatedWithCurrent(o1, project)) return -1;
|
||||
if (isVEnv2) {
|
||||
final int compare = Comparing.compare(level1, level2);
|
||||
if (compare != 0) return -compare;
|
||||
return Comparing.compare(o1.getName(), o2.getName());
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
if (isVEnv2) {
|
||||
return 1;
|
||||
}
|
||||
if (isRemote1) return 1;
|
||||
if (isRemote2) return -1;
|
||||
|
||||
final int compare = Comparing.compare(level1, level2);
|
||||
if (compare != 0) return -compare;
|
||||
return Comparing.compare(o1.getName(), o2.getName());
|
||||
}
|
||||
});
|
||||
for (String sdkHome : SdkConfigurationUtil.filterExistingPaths(PythonSdkType.getInstance(), sdkHomes, getModel().getSdks())) {
|
||||
result.add(new PyDetectedSdk(sdkHome, PythonSdkType.getInstance()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static boolean associatedWithCurrent(Sdk o1, Project project) {
|
||||
final PythonSdkAdditionalData data = (PythonSdkAdditionalData)o1.getSdkAdditionalData();
|
||||
if (data != null) {
|
||||
final String path = data.getAssociatedProjectPath();
|
||||
final String projectBasePath = project.getBasePath();
|
||||
if (path != null && path.equals(projectBasePath)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -247,7 +247,7 @@ public class PythonSdkConfigurable implements Configurable, Configurable.NoScrol
|
||||
addCreatedSdk(sdk, true);
|
||||
}
|
||||
};
|
||||
final List<Sdk> allSdks = PyConfigurableInterpreterList.getInstance(myProject).getAllPythonSdks();
|
||||
final List<Sdk> allSdks = PyConfigurableInterpreterList.getInstance(myProject).getAllPythonSdks(myProject);
|
||||
final CreateVirtualEnvDialog dialog = new CreateVirtualEnvDialog(myProject, myNewProject, allSdks, sdk);
|
||||
dialog.show();
|
||||
if (dialog.isOK()) {
|
||||
@@ -335,7 +335,7 @@ public class PythonSdkConfigurable implements Configurable, Configurable.NoScrol
|
||||
}
|
||||
|
||||
private void refreshSdkList() {
|
||||
final List<Sdk> pythonSdks = myInterpreterList.getAllPythonSdks();
|
||||
final List<Sdk> pythonSdks = myInterpreterList.getAllPythonSdks(myProject);
|
||||
Sdk projectSdk = myProjectSdksModel.getProjectSdk();
|
||||
if (!myShowOtherProjectVirtualenvs) {
|
||||
VirtualEnvProjectFilter.removeNotMatching(myProject, pythonSdks);
|
||||
@@ -366,7 +366,7 @@ public class PythonSdkConfigurable implements Configurable, Configurable.NoScrol
|
||||
|
||||
private void addSdk(AnActionButton button) {
|
||||
DetailsChooser
|
||||
.show(myProject, myProjectSdksModel.getSdks(), button.getPreferredPopupPoint(), false, new NullableConsumer<Sdk>() {
|
||||
.show(myProject, myProjectSdksModel.getSdks(), new PythonSdkConfigurable(myProject).createComponent(), button.getPreferredPopupPoint(), false, new NullableConsumer<Sdk>() {
|
||||
@Override
|
||||
public void consume(Sdk sdk) {
|
||||
myMakeActiveAdded = false;
|
||||
|
||||
Reference in New Issue
Block a user