mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge branch 'pycharm-interpreters-rework'
This commit is contained in:
+26
-6
@@ -54,7 +54,7 @@ public class SdkConfigurationUtil {
|
||||
|
||||
public static void createSdk(@Nullable final Project project,
|
||||
final Sdk[] existingSdks,
|
||||
final NullableConsumer<Sdk> onSdkCreatedCallBack,
|
||||
final NullableConsumer<Sdk> onSdkCreatedCallBack, final boolean createIfExists,
|
||||
final SdkType... sdkTypes) {
|
||||
if (sdkTypes.length == 0) {
|
||||
onSdkCreatedCallBack.consume(null);
|
||||
@@ -72,8 +72,19 @@ public class SdkConfigurationUtil {
|
||||
@Override
|
||||
public void consume(List<VirtualFile> selectedFiles) {
|
||||
for (SdkType sdkType : sdkTypes) {
|
||||
if (sdkType.isValidSdkHome(selectedFiles.get(0).getPath())) {
|
||||
onSdkCreatedCallBack.consume(setupSdk(existingSdks, selectedFiles.get(0), sdkType, false, null, null));
|
||||
final String path = selectedFiles.get(0).getPath();
|
||||
if (sdkType.isValidSdkHome(path)) {
|
||||
Sdk newSdk = null;
|
||||
if (!createIfExists) {
|
||||
for (Sdk sdk : existingSdks) {
|
||||
if (path.equals(sdk.getHomePath())) {
|
||||
newSdk = sdk;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (newSdk == null)
|
||||
newSdk = setupSdk(existingSdks, selectedFiles.get(0), sdkType, false, null, null);
|
||||
onSdkCreatedCallBack.consume(newSdk);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -85,6 +96,14 @@ public class SdkConfigurationUtil {
|
||||
onSdkCreatedCallBack.consume(null);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public static void createSdk(@Nullable final Project project,
|
||||
final Sdk[] existingSdks,
|
||||
final NullableConsumer<Sdk> onSdkCreatedCallBack,
|
||||
final SdkType... sdkTypes) {
|
||||
createSdk(project, existingSdks, onSdkCreatedCallBack, true, sdkTypes);
|
||||
}
|
||||
|
||||
private static FileChooserDescriptor createCompositeDescriptor(final SdkType... sdkTypes) {
|
||||
@@ -140,7 +159,7 @@ public class SdkConfigurationUtil {
|
||||
final ProjectJdkImpl sdk;
|
||||
try {
|
||||
String sdkPath = sdkType.sdkPath(homeDir);
|
||||
|
||||
|
||||
final String sdkName = customSdkSuggestedName == null
|
||||
? createUniqueSdkName(sdkType, sdkPath, sdksList)
|
||||
: createUniqueSdkName(customSdkSuggestedName, sdksList);
|
||||
@@ -313,8 +332,9 @@ public class SdkConfigurationUtil {
|
||||
@Nullable
|
||||
private static Sdk findByPath(SdkType sdkType, Sdk[] sdks, String sdkHome) {
|
||||
for (Sdk sdk : sdks) {
|
||||
if (sdk.getSdkType() == sdkType &&
|
||||
FileUtil.pathsEqual(FileUtil.toSystemIndependentName(sdk.getHomePath()), FileUtil.toSystemIndependentName(sdkHome))) {
|
||||
final String path = sdk.getHomePath();
|
||||
if (sdk.getSdkType() == sdkType && path != null &&
|
||||
FileUtil.pathsEqual(FileUtil.toSystemIndependentName(path), FileUtil.toSystemIndependentName(sdkHome))) {
|
||||
return sdk;
|
||||
}
|
||||
}
|
||||
|
||||
+95
-112
@@ -2,6 +2,7 @@ package com.intellij.webcore.packaging;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.application.Application;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
@@ -9,13 +10,13 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.ui.DoubleClickListener;
|
||||
import com.intellij.ui.ScrollPaneFactory;
|
||||
import com.intellij.ui.*;
|
||||
import com.intellij.ui.table.JBTable;
|
||||
import com.intellij.util.CatchingConsumer;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.IconUtil;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.containers.*;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -26,20 +27,16 @@ import javax.swing.table.DefaultTableCellRenderer;
|
||||
import javax.swing.table.DefaultTableModel;
|
||||
import javax.swing.table.TableCellRenderer;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class InstalledPackagesPanel extends JPanel {
|
||||
protected final JButton myInstallButton;
|
||||
private final JButton myUninstallButton;
|
||||
private final JButton myUpgradeButton;
|
||||
private final AnActionButton myUpgradeButton;
|
||||
protected final AnActionButton myInstallButton;
|
||||
private final AnActionButton myUninstallButton;
|
||||
|
||||
protected final JBTable myPackagesTable;
|
||||
private DefaultTableModel myPackagesTableModel;
|
||||
@@ -51,19 +48,9 @@ public class InstalledPackagesPanel extends JPanel {
|
||||
private final Set<InstalledPackage> myWaitingToUpgrade = ContainerUtil.newHashSet();
|
||||
|
||||
public InstalledPackagesPanel(Project project, PackagesNotificationPanel area) {
|
||||
super(new GridBagLayout());
|
||||
super(new BorderLayout());
|
||||
myProject = project;
|
||||
myNotificationArea = area;
|
||||
myInstallButton = new JButton("Install");
|
||||
myUninstallButton = new JButton("Uninstall");
|
||||
myUpgradeButton = new JButton("Upgrade");
|
||||
myInstallButton.setMnemonic('I');
|
||||
myUninstallButton.setMnemonic('U');
|
||||
myUpgradeButton.setMnemonic('p');
|
||||
|
||||
myInstallButton.setEnabled(false);
|
||||
myUninstallButton.setEnabled(false);
|
||||
myUpgradeButton.setEnabled(false);
|
||||
|
||||
myPackagesTableModel = new DefaultTableModel(new String[]{"Package", "Version", "Latest"}, 0) {
|
||||
@Override
|
||||
@@ -80,25 +67,41 @@ public class InstalledPackagesPanel extends JPanel {
|
||||
};
|
||||
myPackagesTable.getTableHeader().setReorderingAllowed(false);
|
||||
|
||||
Insets anInsets = new Insets(2, 2, 2, 2);
|
||||
JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(myPackagesTable,
|
||||
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
|
||||
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
||||
scrollPane.setPreferredSize(new Dimension(500, 500));
|
||||
add(scrollPane, new GridBagConstraints(0, 0, 1, 3, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH,
|
||||
anInsets, 0, 0));
|
||||
myUpgradeButton = new AnActionButton("Upgrade", IconUtil.getMoveUpIcon()) {
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
upgradeAction();
|
||||
}
|
||||
};
|
||||
final ToolbarDecorator decorator = ToolbarDecorator.createDecorator(myPackagesTable).disableUpDownActions()
|
||||
.setAddAction(new AnActionButtonRunnable() {
|
||||
@Override
|
||||
public void run(AnActionButton button) {
|
||||
if (myPackageManagementService != null) {
|
||||
ManagePackagesDialog dialog = createManagePackagesDialog();
|
||||
dialog.show();
|
||||
}
|
||||
}
|
||||
})
|
||||
.setRemoveAction(new AnActionButtonRunnable() {
|
||||
@Override
|
||||
public void run(AnActionButton button) {
|
||||
uninstallAction();
|
||||
}
|
||||
})
|
||||
.addExtraAction(myUpgradeButton);
|
||||
|
||||
addUninstallAction();
|
||||
addUpgradeAction();
|
||||
decorator.setPreferredSize(new Dimension(500, 500));
|
||||
add(decorator.createPanel());
|
||||
myInstallButton = decorator.getActionsPanel().getAnActionButton(CommonActionsPanel.Buttons.ADD);
|
||||
myUninstallButton = decorator.getActionsPanel().getAnActionButton(CommonActionsPanel.Buttons.REMOVE);
|
||||
myInstallButton.setEnabled(false);
|
||||
myUninstallButton.setEnabled(false);
|
||||
myUpgradeButton.setEnabled(false);
|
||||
|
||||
myInstallButton.getTemplatePresentation().setText("Install");
|
||||
myUninstallButton.getTemplatePresentation().setText("Uninstall");
|
||||
|
||||
add(myInstallButton,
|
||||
new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
|
||||
anInsets, 0, 0));
|
||||
add(myUninstallButton,
|
||||
new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
|
||||
anInsets, 0, 0));
|
||||
add(myUpgradeButton,
|
||||
new GridBagConstraints(1, 2, 1, 1, 0.0, 1.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, anInsets, 0, 0));
|
||||
|
||||
myPackagesTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
|
||||
@Override
|
||||
@@ -107,16 +110,6 @@ public class InstalledPackagesPanel extends JPanel {
|
||||
}
|
||||
});
|
||||
|
||||
myInstallButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (myPackageManagementService != null) {
|
||||
ManagePackagesDialog dialog = createManagePackagesDialog();
|
||||
dialog.show();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
new DoubleClickListener() {
|
||||
@Override
|
||||
protected boolean onDoubleClick(MouseEvent e) {
|
||||
@@ -162,38 +155,33 @@ public class InstalledPackagesPanel extends JPanel {
|
||||
myPathChangedListeners.add(consumer);
|
||||
}
|
||||
|
||||
private void addUpgradeAction() {
|
||||
myUpgradeButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
final int[] rows = myPackagesTable.getSelectedRows();
|
||||
if (myPackageManagementService != null) {
|
||||
final Set<String> upgradedPackages = new HashSet<String>();
|
||||
final Set<String> packagesShouldBePostponed = getPackagesToPostpone();
|
||||
for (int row : rows) {
|
||||
final Object packageObj = myPackagesTableModel.getValueAt(row, 0);
|
||||
if (packageObj instanceof InstalledPackage) {
|
||||
InstalledPackage pkg = (InstalledPackage)packageObj;
|
||||
final String packageName = pkg.getName();
|
||||
final String currentVersion = pkg.getVersion();
|
||||
final String availableVersion = (String)myPackagesTableModel.getValueAt(row, 2);
|
||||
private void upgradeAction() {
|
||||
final int[] rows = myPackagesTable.getSelectedRows();
|
||||
if (myPackageManagementService != null) {
|
||||
final Set<String> upgradedPackages = new HashSet<String>();
|
||||
final Set<String> packagesShouldBePostponed = getPackagesToPostpone();
|
||||
for (int row : rows) {
|
||||
final Object packageObj = myPackagesTableModel.getValueAt(row, 0);
|
||||
if (packageObj instanceof InstalledPackage) {
|
||||
InstalledPackage pkg = (InstalledPackage)packageObj;
|
||||
final String packageName = pkg.getName();
|
||||
final String currentVersion = pkg.getVersion();
|
||||
final String availableVersion = (String)myPackagesTableModel.getValueAt(row, 2);
|
||||
|
||||
if (packagesShouldBePostponed.contains(packageName)) {
|
||||
myWaitingToUpgrade.add((InstalledPackage)packageObj);
|
||||
}
|
||||
else if (PackageVersionComparator.VERSION_COMPARATOR.compare(currentVersion, availableVersion) < 0) {
|
||||
upgradePackage(pkg, availableVersion);
|
||||
upgradedPackages.add(packageName);
|
||||
}
|
||||
}
|
||||
if (packagesShouldBePostponed.contains(packageName)) {
|
||||
myWaitingToUpgrade.add((InstalledPackage)packageObj);
|
||||
}
|
||||
|
||||
if (myCurrentlyInstalling.isEmpty() && upgradedPackages.isEmpty() && !myWaitingToUpgrade.isEmpty()) {
|
||||
upgradePostponedPackages();
|
||||
else if (PackageVersionComparator.VERSION_COMPARATOR.compare(currentVersion, availableVersion) < 0) {
|
||||
upgradePackage(pkg, availableVersion);
|
||||
upgradedPackages.add(packageName);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (myCurrentlyInstalling.isEmpty() && upgradedPackages.isEmpty() && !myWaitingToUpgrade.isEmpty()) {
|
||||
upgradePostponedPackages();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void upgradePostponedPackages() {
|
||||
@@ -283,7 +271,7 @@ public class InstalledPackagesPanel extends JPanel {
|
||||
public void run() {
|
||||
final int[] selected = myPackagesTable.getSelectedRows();
|
||||
boolean upgradeAvailable = false;
|
||||
boolean canUninstall = true;
|
||||
boolean canUninstall = selected.length != 0;
|
||||
boolean canUpgrade = true;
|
||||
if (myPackageManagementService != null && selected.length != 0) {
|
||||
for (int i = 0; i != selected.length; ++i) {
|
||||
@@ -322,43 +310,38 @@ public class InstalledPackagesPanel extends JPanel {
|
||||
return true;
|
||||
}
|
||||
|
||||
private void addUninstallAction() {
|
||||
myUninstallButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(final ActionEvent e) {
|
||||
final List<InstalledPackage> packages = getSelectedPackages();
|
||||
final PackageManagementService selPackageManagementService = myPackageManagementService;
|
||||
if (selPackageManagementService != null) {
|
||||
PackageManagementService.Listener listener = new PackageManagementService.Listener() {
|
||||
@Override
|
||||
public void operationStarted(String packageName) {
|
||||
myPackagesTable.setPaintBusy(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void operationFinished(String packageName, @Nullable String errorDescription) {
|
||||
myPackagesTable.clearSelection();
|
||||
updatePackages(selPackageManagementService);
|
||||
myPackagesTable.setPaintBusy(false);
|
||||
if (errorDescription == null) {
|
||||
if (packageName != null) {
|
||||
myNotificationArea.showSuccess("Package '" + packageName + "' successfully uninstalled");
|
||||
}
|
||||
else {
|
||||
myNotificationArea.showSuccess("Packages successfully uninstalled");
|
||||
}
|
||||
}
|
||||
else {
|
||||
myNotificationArea.showError("Uninstall packages failed. <a href=\"xxx\">Details...</a>",
|
||||
"Uninstall Packages Failed",
|
||||
"Uninstall packages failed.\n" + errorDescription);
|
||||
}
|
||||
}
|
||||
};
|
||||
myPackageManagementService.uninstallPackages(packages, listener);
|
||||
private void uninstallAction() {
|
||||
final List<InstalledPackage> packages = getSelectedPackages();
|
||||
final PackageManagementService selPackageManagementService = myPackageManagementService;
|
||||
if (selPackageManagementService != null) {
|
||||
PackageManagementService.Listener listener = new PackageManagementService.Listener() {
|
||||
@Override
|
||||
public void operationStarted(String packageName) {
|
||||
myPackagesTable.setPaintBusy(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@Override
|
||||
public void operationFinished(String packageName, @Nullable String errorDescription) {
|
||||
myPackagesTable.clearSelection();
|
||||
updatePackages(selPackageManagementService);
|
||||
myPackagesTable.setPaintBusy(false);
|
||||
if (errorDescription == null) {
|
||||
if (packageName != null) {
|
||||
myNotificationArea.showSuccess("Package '" + packageName + "' successfully uninstalled");
|
||||
}
|
||||
else {
|
||||
myNotificationArea.showSuccess("Packages successfully uninstalled");
|
||||
}
|
||||
}
|
||||
else {
|
||||
myNotificationArea.showError("Uninstall packages failed. <a href=\"xxx\">Details...</a>",
|
||||
"Uninstall Packages Failed",
|
||||
"Uninstall packages failed.\n" + errorDescription);
|
||||
}
|
||||
}
|
||||
};
|
||||
myPackageManagementService.uninstallPackages(packages, listener);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -189,7 +189,7 @@ public class PlatformProjectOpenProcessor extends ProjectOpenProcessor {
|
||||
|
||||
if (project == null) return null;
|
||||
ProjectBaseDirectory.getInstance(project).setBaseDir(baseDir);
|
||||
final Module module = runConfigurators ? runDirectoryProjectConfigurators(baseDir, project) : null;
|
||||
final Module module = runConfigurators ? runDirectoryProjectConfigurators(baseDir, project) : ModuleManager.getInstance(project).getModules()[0];
|
||||
|
||||
openFileFromCommandLine(project, virtualFile, line);
|
||||
if (!projectManager.openProject(project)) {
|
||||
@@ -204,7 +204,7 @@ public class PlatformProjectOpenProcessor extends ProjectOpenProcessor {
|
||||
return project;
|
||||
}
|
||||
|
||||
if (callback != null && runConfigurators) {
|
||||
if (callback != null) {
|
||||
callback.projectOpened(project, module);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
@@ -266,7 +266,7 @@ public class PyIdeCommonOptionsForm implements AbstractPyCommonOptionsForm {
|
||||
return myPathMappingsComponent.getMappingSettings();
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
return new PathMappingSettings();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,18 +15,21 @@
|
||||
*/
|
||||
package com.jetbrains.python;
|
||||
|
||||
import com.intellij.openapi.options.ShowSettingsUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.projectRoots.SdkType;
|
||||
import com.intellij.openapi.projectRoots.impl.SdkListCellRenderer;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
import com.intellij.ui.CollectionComboBoxModel;
|
||||
import com.intellij.ui.ComboboxWithBrowseButton;
|
||||
import com.intellij.util.NullableConsumer;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.jetbrains.python.configuration.PythonSdkConfigurable;
|
||||
import com.jetbrains.python.sdk.flavors.PythonSdkFlavor;
|
||||
import com.jetbrains.python.configuration.PythonSdkDetailsDialog;
|
||||
import com.jetbrains.python.sdk.PyDetectedSdk;
|
||||
import com.jetbrains.python.sdk.PythonSdkType;
|
||||
import com.jetbrains.python.sdk.flavors.PythonSdkFlavor;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
@@ -39,10 +42,7 @@ import java.util.List;
|
||||
public class PythonSdkChooserCombo extends ComboboxWithBrowseButton {
|
||||
private final List<ActionListener> myChangedListeners = ContainerUtil.createLockFreeCopyOnWriteList();
|
||||
|
||||
//public PythonSdkChooserCombo(final Condition<Sdk> acceptableSdkCondition) {
|
||||
// this(PythonSdkType.getAllSdks(), acceptableSdkCondition);
|
||||
//}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public PythonSdkChooserCombo(final Project project, List<Sdk> sdks, final Condition<Sdk> acceptableSdkCondition) {
|
||||
Sdk initialSelection = null;
|
||||
for (Sdk sdk : sdks) {
|
||||
@@ -51,26 +51,30 @@ public class PythonSdkChooserCombo extends ComboboxWithBrowseButton {
|
||||
break;
|
||||
}
|
||||
}
|
||||
getComboBox().setModel(new CollectionComboBoxModel(sdks, initialSelection));
|
||||
getComboBox().setRenderer(new SdkListCellRenderer("<no interpreter>") {
|
||||
final JComboBox comboBox = getComboBox();
|
||||
comboBox.setModel(new CollectionComboBoxModel(sdks, initialSelection));
|
||||
comboBox.setRenderer(new SdkListCellRenderer("<no interpreter>") {
|
||||
@Override
|
||||
protected Icon getSdkIcon(Sdk sdk) {
|
||||
final PythonSdkFlavor flavor = PythonSdkFlavor.getFlavor(sdk);
|
||||
return flavor != null ? flavor.getIcon() : ((SdkType)sdk.getSdkType()).getIcon();
|
||||
final Icon icon = flavor != null ? flavor.getIcon() : ((SdkType)sdk.getSdkType()).getIcon();
|
||||
return sdk instanceof PyDetectedSdk ? IconLoader.getTransparentIcon(icon) : icon;
|
||||
}
|
||||
});
|
||||
addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
final PythonSdkConfigurable configurable = new PythonSdkConfigurable(project);
|
||||
configurable.setNewProject(true);
|
||||
ShowSettingsUtil.getInstance().editConfigurable(PythonSdkChooserCombo.this, configurable);
|
||||
Sdk selection = configurable.getRealSelectedSdk();
|
||||
final List<Sdk> sdks = PythonSdkType.getAllSdks();
|
||||
getComboBox().setModel(new CollectionComboBoxModel(sdks, selection));
|
||||
PythonSdkDetailsDialog dialog = new PythonSdkDetailsDialog(project, new NullableConsumer<Sdk>() {
|
||||
@Override
|
||||
public void consume(@Nullable Sdk sdk) {
|
||||
comboBox.setModel(new CollectionComboBoxModel(sdks, sdk));
|
||||
}
|
||||
});
|
||||
dialog.show();
|
||||
notifyChanged(e);
|
||||
}
|
||||
});
|
||||
getComboBox().addActionListener(new ActionListener() {
|
||||
comboBox.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
notifyChanged(e);
|
||||
}
|
||||
@@ -83,6 +87,7 @@ public class PythonSdkChooserCombo extends ComboboxWithBrowseButton {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public void addChangedListener(ActionListener listener) {
|
||||
myChangedListeners.add(listener);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.jetbrains.python.configuration.AddVEnvOptionsDialog">
|
||||
<grid id="27dc6" binding="myMainPanel" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<grid id="27dc6" binding="myMainPanel" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<xy x="20" y="20" width="500" height="400"/>
|
||||
@@ -8,23 +8,14 @@
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="6ea43" class="com.intellij.ui.components.JBCheckBox" binding="myUseForThisProjectJBCheckBox" default-binding="true">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<selected value="true"/>
|
||||
<text value="Set as project interpreter for &this project"/>
|
||||
</properties>
|
||||
</component>
|
||||
<vspacer id="46c2b">
|
||||
<constraints>
|
||||
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
|
||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
</vspacer>
|
||||
<component id="b3884" class="com.intellij.ui.components.JBCheckBox" binding="myMakeAvailableToAllJBCheckBox" default-binding="true">
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="Make available to &all projects"/>
|
||||
|
||||
@@ -25,7 +25,6 @@ import java.awt.*;
|
||||
* @author yole
|
||||
*/
|
||||
public class AddVEnvOptionsDialog extends DialogWrapper {
|
||||
private JBCheckBox myUseForThisProjectJBCheckBox;
|
||||
private JBCheckBox myMakeAvailableToAllJBCheckBox;
|
||||
private JPanel myMainPanel;
|
||||
|
||||
@@ -40,10 +39,6 @@ public class AddVEnvOptionsDialog extends DialogWrapper {
|
||||
return myMainPanel;
|
||||
}
|
||||
|
||||
public boolean useForThisProject() {
|
||||
return myUseForThisProjectJBCheckBox.isSelected();
|
||||
}
|
||||
|
||||
public boolean makeAvailableToAll() {
|
||||
return myMakeAvailableToAllJBCheckBox.isSelected();
|
||||
}
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.jetbrains.python.configuration.PyActiveSdkConfigurable">
|
||||
<grid id="27dc6" binding="myPanel" layout-manager="GridLayoutManager" row-count="3" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<xy x="20" y="20" width="500" height="400"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="70598" class="com.intellij.ui.components.JBLabel">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="Project Interpreter:"/>
|
||||
</properties>
|
||||
</component>
|
||||
<vspacer id="3aae9">
|
||||
<constraints>
|
||||
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
</vspacer>
|
||||
<component id="7421c" class="javax.swing.JComboBox" binding="mySdkCombo">
|
||||
<constraints>
|
||||
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
</component>
|
||||
<grid id="19f49" binding="myConfigureInterpretersPanel" layout-manager="BorderLayout" hgap="0" vgap="0">
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children/>
|
||||
</grid>
|
||||
</children>
|
||||
</grid>
|
||||
</form>
|
||||
@@ -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,68 +28,218 @@ 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.vfs.VirtualFile;
|
||||
import com.intellij.ui.CollectionComboBoxModel;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.util.NullableConsumer;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
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.PyDetectedSdk;
|
||||
import com.jetbrains.python.sdk.PySdkListCellRenderer;
|
||||
import com.jetbrains.python.sdk.PythonSdkDetailsStep;
|
||||
import com.jetbrains.python.sdk.PythonSdkType;
|
||||
import com.jetbrains.python.sdk.flavors.PythonSdkFlavor;
|
||||
import icons.PythonIcons;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public class PyActiveSdkConfigurable implements UnnamedConfigurable {
|
||||
private JPanel myPanel;
|
||||
private JPanel myMainPanel;
|
||||
private final Project myProject;
|
||||
@Nullable private final Module myModule;
|
||||
private JComboBox mySdkCombo;
|
||||
private JPanel myConfigureInterpretersPanel;
|
||||
private MySdkModelListener mySdkModelListener;
|
||||
private Sdk myAddedSdk = null;
|
||||
|
||||
private PyConfigurableInterpreterList myInterpreterList;
|
||||
private ProjectSdksModel myProjectSdksModel;
|
||||
private MyListener myListener;
|
||||
private ComboBox mySdkCombo;
|
||||
private PyInstalledPackagesPanel myPackagesPanel;
|
||||
private JButton myDetailsButton;
|
||||
private static final String SHOW_ALL = "Show All";
|
||||
private NullableConsumer<Sdk> myDetailsCallback;
|
||||
|
||||
public PyActiveSdkConfigurable(Project project) {
|
||||
public PyActiveSdkConfigurable(@NotNull Project project) {
|
||||
myModule = null;
|
||||
myProject = project;
|
||||
init();
|
||||
layoutPanel();
|
||||
initContent();
|
||||
}
|
||||
|
||||
public PyActiveSdkConfigurable(@NotNull Module module) {
|
||||
myModule = module;
|
||||
myProject = module.getProject();
|
||||
init();
|
||||
layoutPanel();
|
||||
initContent();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
private void initContent() {
|
||||
myInterpreterList = PyConfigurableInterpreterList.getInstance(myProject);
|
||||
myInterpreterList.setSdkCombo(mySdkCombo);
|
||||
|
||||
myProjectSdksModel = myInterpreterList.getModel();
|
||||
mySdkModelListener = new MySdkModelListener(this);
|
||||
myProjectSdksModel.addListener(mySdkModelListener);
|
||||
|
||||
mySdkCombo.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
final Sdk selectedSdk = (Sdk)mySdkCombo.getSelectedItem();
|
||||
myPackagesPanel.updatePackages(selectedSdk != null ? new PyPackageManagementService(myProject, selectedSdk) : null);
|
||||
}
|
||||
});
|
||||
myDetailsCallback = new NullableConsumer<Sdk>() {
|
||||
|
||||
@Override
|
||||
public void consume(@Nullable Sdk sdk) {
|
||||
if (sdk instanceof PyDetectedSdk) {
|
||||
final Sdk addedSdk = SdkConfigurationUtil.setupSdk(myProjectSdksModel.getSdks(), sdk.getHomeDirectory(),
|
||||
PythonSdkType.getInstance(), true,
|
||||
null, null);
|
||||
myAddedSdk = addedSdk;
|
||||
myProjectSdksModel.addSdk(addedSdk);
|
||||
myProjectSdksModel.removeSdk(sdk);
|
||||
mySdkCombo.setSelectedItem(addedSdk);
|
||||
}
|
||||
else if (getSdk() != sdk) {
|
||||
mySdkCombo.setSelectedItem(sdk);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
myDetailsButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
PythonSdkDetailsStep
|
||||
.show(myProject, myProjectSdksModel.getSdks(),
|
||||
myModule == null ? new PythonSdkDetailsDialog(myProject, myDetailsCallback) :
|
||||
new PythonSdkDetailsDialog(myModule, myDetailsCallback),
|
||||
RelativePoint.fromScreen(myDetailsButton.getLocationOnScreen()), true,
|
||||
new NullableConsumer<Sdk>() {
|
||||
@Override
|
||||
public void consume(Sdk sdk) {
|
||||
if (sdk == null) return;
|
||||
if (myProjectSdksModel.findSdk(sdk) == null) {
|
||||
myProjectSdksModel.addSdk(sdk);
|
||||
myAddedSdk = sdk;
|
||||
}
|
||||
updateSdkList(false);
|
||||
mySdkCombo.getModel().setSelectedItem(sdk);
|
||||
myPackagesPanel.updatePackages(new PyPackageManagementService(myProject, sdk));
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
private void layoutPanel() {
|
||||
final GridBagLayout layout = new GridBagLayout();
|
||||
myMainPanel = new JPanel(layout);
|
||||
final JLabel interpreterLabel = new JLabel("Project Interpreter:");
|
||||
final JLabel emptyLabel = new JLabel(" ");
|
||||
mySdkCombo = new ComboBox() {
|
||||
@Override
|
||||
public void setSelectedItem(Object item) {
|
||||
if (SHOW_ALL.equals(item)) {
|
||||
PythonSdkDetailsDialog options = myModule == null ? new PythonSdkDetailsDialog(myProject, myDetailsCallback) :
|
||||
new PythonSdkDetailsDialog(myModule, myDetailsCallback);
|
||||
options.show();
|
||||
return;
|
||||
}
|
||||
if (!PySdkListCellRenderer.SEPARATOR.equals(item))
|
||||
super.setSelectedItem(item);
|
||||
}
|
||||
};
|
||||
mySdkCombo.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE);
|
||||
mySdkCombo.setRenderer(new SdkListCellRenderer("<None>"));
|
||||
|
||||
myInterpreterList = PyConfigurableInterpreterList.getInstance(myProject);
|
||||
myProjectSdksModel = myInterpreterList.getModel();
|
||||
myListener = new MyListener(this);
|
||||
myProjectSdksModel.addListener(myListener);
|
||||
myConfigureInterpretersPanel.add(new PyConfigureInterpretersLinkPanel(myPanel), BorderLayout.CENTER);
|
||||
myInterpreterList.setSdkCombo(mySdkCombo);
|
||||
final PackagesNotificationPanel notificationsArea = new PackagesNotificationPanel(myProject);
|
||||
final JComponent notificationsComponent = notificationsArea.getComponent();
|
||||
notificationsComponent.setPreferredSize(new Dimension(500, 29));
|
||||
|
||||
myDetailsButton = new JButton();
|
||||
myDetailsButton.setIcon(PythonIcons.Python.InterpreterGear);
|
||||
myDetailsButton.setIconTextGap(0);
|
||||
myDetailsButton.setPreferredSize(new Dimension(29, 29));
|
||||
if (((UIUtil.isUnderAquaLookAndFeel())) || UIUtil.isUnderIntelliJLaF() || UIUtil.isUnderDarcula()) {
|
||||
myDetailsButton.putClientProperty("JButton.buttonType", "square");
|
||||
}
|
||||
|
||||
myPackagesPanel = new PyInstalledPackagesPanel(myProject, notificationsArea);
|
||||
mySdkCombo.setPreferredSize(new Dimension(250, 29));
|
||||
final GridBagConstraints c = new GridBagConstraints();
|
||||
c.fill = GridBagConstraints.HORIZONTAL;
|
||||
c.insets = new Insets(2,2,2,2);
|
||||
|
||||
c.gridx = 0;
|
||||
c.gridy = 0;
|
||||
myMainPanel.add(interpreterLabel, c);
|
||||
|
||||
c.gridx = 1;
|
||||
c.gridy = 0;
|
||||
c.weightx = 0.1;
|
||||
myMainPanel.add(mySdkCombo, c);
|
||||
|
||||
c.insets = new Insets(0,5,0,2);
|
||||
c.gridx = 2;
|
||||
c.gridy = 0;
|
||||
c.weightx = 0.0;
|
||||
myMainPanel.add(myDetailsButton, c);
|
||||
|
||||
c.insets = new Insets(2,2,2,2);
|
||||
c.gridx = 0;
|
||||
c.gridy = 1;
|
||||
c.gridwidth = 3;
|
||||
myMainPanel.add(emptyLabel, c);
|
||||
|
||||
c.gridx = 0;
|
||||
c.gridy = 2;
|
||||
c.weighty = 0.5;
|
||||
c.gridwidth = 3;
|
||||
c.gridheight = GridBagConstraints.RELATIVE;
|
||||
c.fill = GridBagConstraints.BOTH;
|
||||
myMainPanel.add(myPackagesPanel, c);
|
||||
|
||||
c.gridheight = GridBagConstraints.REMAINDER;
|
||||
c.gridx = 0;
|
||||
c.gridy = 3;
|
||||
c.gridwidth = 3;
|
||||
|
||||
c.fill = GridBagConstraints.HORIZONTAL;
|
||||
c.anchor = GridBagConstraints.SOUTH;
|
||||
|
||||
myMainPanel.add(notificationsComponent, c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JComponent createComponent() {
|
||||
return myPanel;
|
||||
return myMainPanel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isModified() {
|
||||
final Sdk sdk = getSdk();
|
||||
return sdk != myProjectSdksModel.findSdk((Sdk)mySdkCombo.getSelectedItem());
|
||||
final Sdk selectedItem = (Sdk)mySdkCombo.getSelectedItem();
|
||||
return myAddedSdk != null || selectedItem instanceof PyDetectedSdk || sdk != myProjectSdksModel.findSdk(selectedItem);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -102,28 +253,31 @@ public class PyActiveSdkConfigurable implements UnnamedConfigurable {
|
||||
|
||||
@Override
|
||||
public void apply() throws ConfigurationException {
|
||||
final Sdk selectedSdk = myProjectSdksModel.findSdk((Sdk)mySdkCombo.getSelectedItem());
|
||||
if (myModule == null) {
|
||||
final ProjectRootManager rootManager = ProjectRootManager.getInstance(myProject);
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
final Sdk item = (Sdk)mySdkCombo.getSelectedItem();
|
||||
if (item instanceof PyDetectedSdk) {
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
rootManager.setProjectSdk(selectedSdk);
|
||||
final Sdk sdk = SdkConfigurationUtil.createAndAddSDK(item.getName(), PythonSdkType.getInstance());
|
||||
myProjectSdksModel.removeSdk(item);
|
||||
myProjectSdksModel.addSdk(sdk);
|
||||
updateSdkList(true);
|
||||
mySdkCombo.setSelectedItem(sdk);
|
||||
setSdk(sdk);
|
||||
}
|
||||
});
|
||||
}, ModalityState.any());
|
||||
}
|
||||
else {
|
||||
ModuleRootModificationUtil.setModuleSdk(myModule, selectedSdk);
|
||||
if (item != null) {
|
||||
myProjectSdksModel.addSdk(item);
|
||||
myProjectSdksModel.apply(null, true);
|
||||
mySdkCombo.setSelectedItem(item);
|
||||
}
|
||||
else if (myAddedSdk != null) {
|
||||
myProjectSdksModel.apply(null, true);
|
||||
}
|
||||
final Sdk prevSdk = ProjectRootManager.getInstance(myProject).getProjectSdk();
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ProjectRootManager.getInstance(myProject).setProjectSdk(selectedSdk);
|
||||
}
|
||||
});
|
||||
|
||||
myProjectSdksModel.setProjectSdk(selectedSdk);
|
||||
final Sdk prevSdk = ProjectRootManager.getInstance(myProject).getProjectSdk();
|
||||
final Sdk selectedSdk = setSdk(item);
|
||||
|
||||
// update string literals if different LanguageLevel was selected
|
||||
if (prevSdk != null && selectedSdk != null) {
|
||||
@@ -141,6 +295,24 @@ public class PyActiveSdkConfigurable implements UnnamedConfigurable {
|
||||
rehighlightStrings(myProject);
|
||||
}
|
||||
|
||||
private Sdk setSdk(Sdk item) {
|
||||
myAddedSdk = null;
|
||||
final Sdk selectedSdk = myProjectSdksModel.findSdk(item);
|
||||
if (myModule == null) {
|
||||
final ProjectRootManager rootManager = ProjectRootManager.getInstance(myProject);
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
rootManager.setProjectSdk(selectedSdk);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
ModuleRootModificationUtil.setModuleSdk(myModule, selectedSdk);
|
||||
}
|
||||
return selectedSdk;
|
||||
}
|
||||
|
||||
public static void rehighlightStrings(final @NotNull Project project) {
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
@Override
|
||||
@@ -161,6 +333,14 @@ public class PyActiveSdkConfigurable implements UnnamedConfigurable {
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
if (myAddedSdk != null) {
|
||||
myProjectSdksModel.removeSdk(myAddedSdk);
|
||||
myAddedSdk = null;
|
||||
}
|
||||
resetSdkList();
|
||||
}
|
||||
|
||||
private void resetSdkList() {
|
||||
updateSdkList(false);
|
||||
|
||||
final Sdk sdk = getSdk();
|
||||
@@ -168,37 +348,64 @@ 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;
|
||||
}
|
||||
VirtualEnvProjectFilter.removeNotMatching(myProject, sdkList);
|
||||
final boolean showAll = VirtualEnvProjectFilter.removeNotMatching(myProject, sdkList);
|
||||
// if the selection is a non-matching virtualenv, show it anyway
|
||||
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;
|
||||
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);
|
||||
}
|
||||
|
||||
if (showAll) {
|
||||
items.add(PySdkListCellRenderer.SEPARATOR);
|
||||
items.add(SHOW_ALL);
|
||||
}
|
||||
|
||||
mySdkCombo.setRenderer(new PySdkListCellRenderer());
|
||||
mySdkCombo.setModel(new CollectionComboBoxModel(sdkList, selection));
|
||||
//noinspection unchecked
|
||||
mySdkCombo.setModel(new CollectionComboBoxModel(items, selection));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disposeUIResources() {
|
||||
myProjectSdksModel.removeListener(myListener);
|
||||
myProjectSdksModel.removeListener(mySdkModelListener);
|
||||
myInterpreterList.disposeModel();
|
||||
}
|
||||
|
||||
private static class MyListener implements SdkModel.Listener {
|
||||
private static class MySdkModelListener implements SdkModel.Listener {
|
||||
private final PyActiveSdkConfigurable myConfigurable;
|
||||
|
||||
public MyListener(PyActiveSdkConfigurable configurable) {
|
||||
public MySdkModelListener(PyActiveSdkConfigurable configurable) {
|
||||
myConfigurable = configurable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sdkAdded(Sdk sdk) {
|
||||
myConfigurable.reset();
|
||||
myConfigurable.resetSdkList();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-12
@@ -18,7 +18,6 @@ package com.jetbrains.python.configuration;
|
||||
import com.intellij.application.options.ModuleAwareProjectConfigurable;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleManager;
|
||||
import com.intellij.openapi.options.Configurable;
|
||||
import com.intellij.openapi.options.ConfigurationException;
|
||||
import com.intellij.openapi.options.UnnamedConfigurable;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -28,17 +27,12 @@ import com.jetbrains.python.sdk.PythonSdkUpdater;
|
||||
import com.jetbrains.python.testing.VFSTestFrameworkListener;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public class PyActiveSdkModuleConfigurable extends ModuleAwareProjectConfigurable implements Configurable.Composite {
|
||||
public class PyActiveSdkModuleConfigurable extends ModuleAwareProjectConfigurable {
|
||||
private final Project myProject;
|
||||
private final Configurable mySdkConfigurable;
|
||||
|
||||
public PyActiveSdkModuleConfigurable(Project project) {
|
||||
super(project, "Project Interpreter", "reference.settings.project.interpreter");
|
||||
myProject = project;
|
||||
mySdkConfigurable = new PythonSdkConfigurable(project);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -67,9 +61,4 @@ public class PyActiveSdkModuleConfigurable extends ModuleAwareProjectConfigurabl
|
||||
}
|
||||
PythonSdkUpdater.getInstance().updateActiveSdks(myProject, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Configurable[] getConfigurables() {
|
||||
return new Configurable[] { mySdkConfigurable };
|
||||
}
|
||||
}
|
||||
|
||||
+68
-5
@@ -18,15 +18,20 @@ 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 com.jetbrains.python.sdk.flavors.VirtualEnvSdkFlavor;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
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 +70,77 @@ public class PyConfigurableInterpreterList {
|
||||
}
|
||||
}
|
||||
|
||||
public List<Sdk> getAllPythonSdks() {
|
||||
public List<Sdk> getAllPythonSdks(@Nullable final Project project) {
|
||||
List<Sdk> result = new ArrayList<Sdk>();
|
||||
for (Sdk sdk : getModel().getSdks()) {
|
||||
if (sdk.getSdkType() instanceof PythonSdkType) {
|
||||
result.add(sdk);
|
||||
}
|
||||
}
|
||||
|
||||
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 (project != null && 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());
|
||||
}
|
||||
});
|
||||
|
||||
final Collection<String> sdkHomes = new ArrayList<String>();
|
||||
sdkHomes.addAll(VirtualEnvSdkFlavor.INSTANCE.suggestHomePaths());
|
||||
for (PythonSdkFlavor flavor : PythonSdkFlavor.getApplicableFlavors()) {
|
||||
if (flavor instanceof VirtualEnvSdkFlavor) continue;
|
||||
sdkHomes.addAll(flavor.suggestHomePaths());
|
||||
}
|
||||
|
||||
for (String sdkHome : SdkConfigurationUtil.filterExistingPaths(PythonSdkType.getInstance(), sdkHomes, getModel().getSdks())) {
|
||||
result.add(new PyDetectedSdk(sdkHome));
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
public List<Sdk> getAllPythonSdks() {
|
||||
return getAllPythonSdks(null);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -16,6 +16,7 @@
|
||||
package com.jetbrains.python.configuration;
|
||||
|
||||
import com.intellij.ide.DataManager;
|
||||
import com.intellij.openapi.options.SearchableConfigurable;
|
||||
import com.intellij.openapi.options.newEditor.OptionsEditor;
|
||||
import com.intellij.ui.ClickListener;
|
||||
import com.intellij.ui.components.JBLabel;
|
||||
@@ -41,7 +42,7 @@ public class PyConfigureInterpretersLinkPanel extends JPanel {
|
||||
if (clickCount == 1) {
|
||||
final OptionsEditor optionsEditor = OptionsEditor.KEY.getData(DataManager.getInstance().getDataContext(parentPanel));
|
||||
if (optionsEditor != null) {
|
||||
PythonSdkConfigurable configurable = optionsEditor.findConfigurable(PythonSdkConfigurable.class);
|
||||
SearchableConfigurable configurable = optionsEditor.findConfigurableById(PyActiveSdkModuleConfigurable.class.getName());
|
||||
if (configurable != null) {
|
||||
optionsEditor.clearSearchAndSelect(configurable);
|
||||
}
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.jetbrains.python.configuration.PythonSdkConfigurable">
|
||||
<grid id="27dc6" binding="myPanel" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<xy x="20" y="20" width="611" height="400"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<grid id="feff7" binding="mySplitterHolder" layout-manager="BorderLayout" hgap="0" vgap="0">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="2" vsize-policy="7" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<grid id="6feb9" binding="myNotificationsPlaceholder" layout-manager="BorderLayout" hgap="0" vgap="0">
|
||||
<constraints border-constraint="South"/>
|
||||
<properties>
|
||||
<background swing-color="ArrowButton.background"/>
|
||||
<minimumSize width="6" height="6"/>
|
||||
<preferredSize width="6" height="23"/>
|
||||
</properties>
|
||||
<border type="none"/>
|
||||
<children/>
|
||||
</grid>
|
||||
</children>
|
||||
</grid>
|
||||
</children>
|
||||
</grid>
|
||||
</form>
|
||||
+153
-265
@@ -15,41 +15,31 @@
|
||||
*/
|
||||
package com.jetbrains.python.configuration;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.intellij.CommonBundle;
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleManager;
|
||||
import com.intellij.openapi.options.Configurable;
|
||||
import com.intellij.openapi.options.ConfigurationException;
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.projectRoots.*;
|
||||
import com.intellij.openapi.projectRoots.impl.ProjectJdkImpl;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.projectRoots.SdkModel;
|
||||
import com.intellij.openapi.projectRoots.SdkModificator;
|
||||
import com.intellij.openapi.projectRoots.impl.SdkConfigurationUtil;
|
||||
import com.intellij.openapi.roots.ModuleRootManager;
|
||||
import com.intellij.openapi.roots.OrderRootType;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.ProjectSdksModel;
|
||||
import com.intellij.openapi.ui.DialogBuilder;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.ui.Splitter;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.remotesdk.RemoteCredentials;
|
||||
import com.intellij.ui.*;
|
||||
import com.intellij.ui.components.JBList;
|
||||
import com.intellij.ui.components.JBTabbedPane;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.NullableConsumer;
|
||||
import com.intellij.util.NullableFunction;
|
||||
import com.intellij.util.containers.FactoryMap;
|
||||
import com.intellij.webcore.packaging.PackagesNotificationPanel;
|
||||
import com.jetbrains.python.packaging.ui.PyInstalledPackagesPanel;
|
||||
import com.jetbrains.python.packaging.ui.PyPackageManagementService;
|
||||
import com.jetbrains.python.remote.PythonRemoteInterpreterManager;
|
||||
import com.jetbrains.python.sdk.*;
|
||||
import com.jetbrains.python.sdk.flavors.PythonSdkFlavor;
|
||||
@@ -63,19 +53,12 @@ import java.awt.*;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
|
||||
public class PythonSdkConfigurable implements Configurable, Configurable.NoScroll {
|
||||
private JPanel myPanel;
|
||||
public class PythonSdkDetailsDialog extends DialogWrapper {
|
||||
private JPanel myMainPanel;
|
||||
private JList mySdkList;
|
||||
private JPanel mySplitterHolder;
|
||||
private PackagesNotificationPanel myNotificationsArea;
|
||||
private JPanel myNotificationsPlaceholder;
|
||||
private PythonPathEditor myPathEditor;
|
||||
private boolean mySdkListChanged = false;
|
||||
private boolean myMakeActiveAdded = false;
|
||||
private Sdk myAddedSdk;
|
||||
private final PyConfigurableInterpreterList myInterpreterList;
|
||||
private final ProjectSdksModel myProjectSdksModel;
|
||||
private final PyInstalledPackagesPanel myPackagesPanel;
|
||||
|
||||
private Map<Sdk, SdkModificator> myModificators = new FactoryMap<Sdk, SdkModificator>() {
|
||||
@Override
|
||||
@@ -84,25 +67,43 @@ public class PythonSdkConfigurable implements Configurable, Configurable.NoScrol
|
||||
}
|
||||
};
|
||||
private Set<SdkModificator> myModifiedModificators = new HashSet<SdkModificator>();
|
||||
private Sdk myPreviousSelection;
|
||||
private boolean myFirstReset;
|
||||
private final Project myProject;
|
||||
|
||||
private boolean myNewProject = false;
|
||||
private boolean myShowOtherProjectVirtualenvs = false;
|
||||
private boolean myShowOtherProjectVirtualenvs = true;
|
||||
private final Module myModule;
|
||||
private NullableConsumer<Sdk> myShowMoreCallback;
|
||||
|
||||
public void setNewProject(final boolean newProject) {
|
||||
myNewProject = newProject;
|
||||
}
|
||||
public PythonSdkDetailsDialog(Project project, NullableConsumer<Sdk> showMoreCallback) {
|
||||
super(project);
|
||||
myModule = null;
|
||||
|
||||
public PythonSdkConfigurable(Project project) {
|
||||
setTitle("Project Interpreters");
|
||||
myShowMoreCallback = showMoreCallback;
|
||||
myProject = project;
|
||||
myInterpreterList = PyConfigurableInterpreterList.getInstance(myProject);
|
||||
myProjectSdksModel = myInterpreterList.getModel();
|
||||
myFirstReset = true;
|
||||
init();
|
||||
updateOkButton();
|
||||
}
|
||||
|
||||
public PythonSdkDetailsDialog(Module module, NullableConsumer<Sdk> showMoreCallback) {
|
||||
super(module.getProject());
|
||||
myModule = module;
|
||||
|
||||
setTitle("Project Interpreters");
|
||||
myShowMoreCallback = showMoreCallback;
|
||||
myProject = module.getProject();
|
||||
myInterpreterList = PyConfigurableInterpreterList.getInstance(myProject);
|
||||
myProjectSdksModel = myInterpreterList.getModel();
|
||||
init();
|
||||
updateOkButton();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected JComponent createCenterPanel() {
|
||||
mySdkList = new JBList();
|
||||
//noinspection unchecked
|
||||
mySdkList.setCellRenderer(new PySdkListCellRenderer("", myModificators));
|
||||
mySdkList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||
|
||||
@@ -111,65 +112,32 @@ public class PythonSdkConfigurable implements Configurable, Configurable.NoScrol
|
||||
@Override
|
||||
public void run(AnActionButton button) {
|
||||
addSdk(button);
|
||||
updateOkButton();
|
||||
}
|
||||
})
|
||||
.setEditAction(new AnActionButtonRunnable() {
|
||||
@Override
|
||||
public void run(AnActionButton button) {
|
||||
editSdk();
|
||||
updateOkButton();
|
||||
}
|
||||
})
|
||||
.setRemoveAction(new AnActionButtonRunnable() {
|
||||
@Override
|
||||
public void run(AnActionButton button) {
|
||||
removeSdk();
|
||||
updateOkButton();
|
||||
}
|
||||
})
|
||||
.addExtraAction(new CreateVirtualEnvButton())
|
||||
.addExtraAction(new ToggleVirtualEnvFilterButton());
|
||||
|
||||
|
||||
final Splitter splitter = new Splitter(true);
|
||||
/*
|
||||
final JScrollPane sdkListPane = ScrollPaneFactory.createScrollPane(mySdkList,
|
||||
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
|
||||
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
||||
sdkListPane.setPreferredSize(new Dimension(10, 10));
|
||||
*/
|
||||
splitter.setFirstComponent(decorator.createPanel());
|
||||
|
||||
myPathEditor =
|
||||
new PythonPathEditor("Classes", OrderRootType.CLASSES, FileChooserDescriptorFactory.createAllButJarContentsDescriptor()) {
|
||||
@Override
|
||||
protected void onReloadButtonClicked() {
|
||||
reloadSdk();
|
||||
}
|
||||
};
|
||||
|
||||
myNotificationsArea = new PackagesNotificationPanel(project);
|
||||
myNotificationsPlaceholder.add(myNotificationsArea.getComponent(), BorderLayout.CENTER);
|
||||
|
||||
final JBTabbedPane tabbedPane = new JBTabbedPane(SwingConstants.TOP);
|
||||
myPackagesPanel = new PyInstalledPackagesPanel(project, myNotificationsArea);
|
||||
tabbedPane.addTab("Packages", myPackagesPanel);
|
||||
|
||||
JPanel panel1 = new JPanel(new GridBagLayout());
|
||||
Insets anInsets1 = new Insets(2, 2, 2, 2);
|
||||
JScrollPane scrollPane1 = ScrollPaneFactory.createScrollPane(myPathEditor.createComponent(),
|
||||
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
|
||||
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
||||
scrollPane1.setPreferredSize(new Dimension(500, 500));
|
||||
panel1.add(scrollPane1, new GridBagConstraints(0, 0, 1, 8, 1.0, 1.0,
|
||||
GridBagConstraints.CENTER,
|
||||
GridBagConstraints.BOTH,
|
||||
anInsets1, 0, 0));
|
||||
|
||||
tabbedPane.addTab("Paths", panel1);
|
||||
|
||||
splitter.setSecondComponent(tabbedPane);
|
||||
mySplitterHolder.add(splitter, BorderLayout.CENTER);
|
||||
.addExtraAction(new ToggleVirtualEnvFilterButton())
|
||||
.addExtraAction(new ShowPathButton())
|
||||
.addExtraAction(new GenerateSkeletonsButton());
|
||||
|
||||
decorator.setPreferredSize(new Dimension(600, 500));
|
||||
myMainPanel = decorator.createPanel();
|
||||
refreshSdkList();
|
||||
addListeners();
|
||||
return myMainPanel;
|
||||
}
|
||||
|
||||
private void addListeners() {
|
||||
@@ -191,99 +159,49 @@ public class PythonSdkConfigurable implements Configurable, Configurable.NoScrol
|
||||
public void sdkHomeSelected(Sdk sdk, String newSdkHome) {
|
||||
}
|
||||
});
|
||||
myPackagesPanel.addPathChangedListener(new Consumer<Sdk>() {
|
||||
@Override
|
||||
public void consume(Sdk sdk) {
|
||||
updateSdkPaths(sdk);
|
||||
}
|
||||
});
|
||||
|
||||
myNotificationsArea.addLinkHandler(PyInstalledPackagesPanel.CREATE_VENV, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
createVirtualEnv(getSelectedSdk());
|
||||
}
|
||||
});
|
||||
mySdkList.addListSelectionListener(new ListSelectionListener() {
|
||||
public void valueChanged(ListSelectionEvent event) {
|
||||
updateOkButton();
|
||||
updateUI(getSelectedSdk());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void updateUI(final Sdk selectedSdk) {
|
||||
if (myPreviousSelection != null) {
|
||||
saveSdkPaths(myPreviousSelection);
|
||||
}
|
||||
myProjectSdksModel.setProjectSdk(selectedSdk);
|
||||
updateSdkPaths(selectedSdk);
|
||||
myPreviousSelection = selectedSdk;
|
||||
myPackagesPanel.updatePackages(selectedSdk == null ? null : new PyPackageManagementService(myProject, selectedSdk));
|
||||
|
||||
if (selectedSdk != null) {
|
||||
myPackagesPanel.updateNotifications(selectedSdk);
|
||||
}
|
||||
}
|
||||
|
||||
private void createVirtualEnv(Sdk sdk) {
|
||||
CreateVirtualEnvDialog.VirtualEnvCallback callback = new CreateVirtualEnvDialog.VirtualEnvCallback() {
|
||||
@Override
|
||||
public void virtualEnvCreated(Sdk sdk, boolean associateWithProject, boolean setAsProjectInterpreter) {
|
||||
PythonSdkType.setupSdkPaths(sdk, myProject, null);
|
||||
if (associateWithProject) {
|
||||
SdkAdditionalData additionalData = sdk.getSdkAdditionalData();
|
||||
if (additionalData == null) {
|
||||
additionalData = new PythonSdkAdditionalData(PythonSdkFlavor.getFlavor(sdk.getHomePath()));
|
||||
((ProjectJdkImpl)sdk).setSdkAdditionalData(additionalData);
|
||||
}
|
||||
if (myNewProject) {
|
||||
((PythonSdkAdditionalData)additionalData).associateWithNewProject();
|
||||
}
|
||||
else {
|
||||
((PythonSdkAdditionalData)additionalData).associateWithProject(myProject);
|
||||
}
|
||||
}
|
||||
myMakeActiveAdded = setAsProjectInterpreter;
|
||||
addCreatedSdk(sdk, true);
|
||||
}
|
||||
};
|
||||
final List<Sdk> allSdks = PyConfigurableInterpreterList.getInstance(myProject).getAllPythonSdks();
|
||||
final CreateVirtualEnvDialog dialog = new CreateVirtualEnvDialog(myProject, myNewProject, allSdks, sdk);
|
||||
dialog.show();
|
||||
if (dialog.isOK()) {
|
||||
dialog.createVirtualEnv(allSdks, callback);
|
||||
}
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Python Interpreters";
|
||||
}
|
||||
|
||||
public String getHelpTopic() {
|
||||
return "python_interpreter";
|
||||
}
|
||||
|
||||
public JComponent createComponent() {
|
||||
return myPanel;
|
||||
}
|
||||
|
||||
public boolean isModified() {
|
||||
return mySdkListChanged ||
|
||||
myProjectSdksModel.isModified() ||
|
||||
myPathEditor.isModified() ||
|
||||
!myModifiedModificators.isEmpty();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private String getSelectedSdkName() {
|
||||
final Sdk selectedSdk = (Sdk)mySdkList.getSelectedValue();
|
||||
return selectedSdk == null ? null : selectedSdk.getName();
|
||||
@Override
|
||||
public JComponent getPreferredFocusedComponent() {
|
||||
return mySdkList;
|
||||
}
|
||||
|
||||
public boolean isModified() {
|
||||
Sdk projectSdk = getSdk();
|
||||
if (projectSdk != null) {
|
||||
projectSdk = myProjectSdksModel.findSdk(projectSdk.getName());
|
||||
}
|
||||
return getSelectedSdk() != projectSdk || mySdkListChanged ||
|
||||
myProjectSdksModel.isModified() ||
|
||||
!myModifiedModificators.isEmpty();
|
||||
}
|
||||
|
||||
protected void updateOkButton() {
|
||||
super.setOKActionEnabled(isModified());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doOKAction() {
|
||||
try {
|
||||
apply();
|
||||
}
|
||||
catch (ConfigurationException ignored) {
|
||||
}
|
||||
super.doOKAction();
|
||||
}
|
||||
|
||||
public void apply() throws ConfigurationException {
|
||||
if (myPreviousSelection != null) {
|
||||
saveSdkPaths(myPreviousSelection);
|
||||
}
|
||||
for (SdkModificator modificator : myModifiedModificators) {
|
||||
modificator.commitChanges();
|
||||
}
|
||||
@@ -291,21 +209,7 @@ public class PythonSdkConfigurable implements Configurable, Configurable.NoScrol
|
||||
myModifiedModificators.clear();
|
||||
myProjectSdksModel.apply();
|
||||
mySdkListChanged = false;
|
||||
if (myMakeActiveAdded) {
|
||||
SdkConfigurationUtil.setDirectoryProjectSdk(myProject, myAddedSdk);
|
||||
myProjectSdksModel.setProjectSdk(myAddedSdk);
|
||||
myInterpreterList.setSelectedSdk(myAddedSdk);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the stable copy of the SDK currently selected in the SDK table.
|
||||
*
|
||||
* @return the selected SDK, or null if there's no selection
|
||||
*/
|
||||
@Nullable
|
||||
public Sdk getRealSelectedSdk() {
|
||||
return ProjectJdkTable.getInstance().findJdk(getSelectedSdkName());
|
||||
myShowMoreCallback.consume(getSelectedSdk());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -313,38 +217,17 @@ public class PythonSdkConfigurable implements Configurable, Configurable.NoScrol
|
||||
return (Sdk)mySdkList.getSelectedValue();
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
clearModificators();
|
||||
if (myFirstReset) {
|
||||
myFirstReset = false;
|
||||
}
|
||||
else {
|
||||
myProjectSdksModel.reset(null);
|
||||
}
|
||||
refreshSdkList();
|
||||
final Sdk selectedSdk = getRealSelectedSdk();
|
||||
if (selectedSdk != null) {
|
||||
myPackagesPanel.updateNotifications(selectedSdk);
|
||||
}
|
||||
}
|
||||
|
||||
private void clearModificators() {
|
||||
myModificators.clear();
|
||||
myModifiedModificators.clear();
|
||||
myPreviousSelection = null;
|
||||
}
|
||||
|
||||
private void refreshSdkList() {
|
||||
final List<Sdk> pythonSdks = myInterpreterList.getAllPythonSdks();
|
||||
Sdk projectSdk = myProjectSdksModel.getProjectSdk();
|
||||
final List<Sdk> pythonSdks = myInterpreterList.getAllPythonSdks(myProject);
|
||||
Sdk projectSdk = getSdk();
|
||||
if (!myShowOtherProjectVirtualenvs) {
|
||||
VirtualEnvProjectFilter.removeNotMatching(myProject, pythonSdks);
|
||||
}
|
||||
Collections.sort(pythonSdks, new PreferredSdkComparator());
|
||||
//noinspection unchecked
|
||||
mySdkList.setModel(new CollectionListModel<Sdk>(pythonSdks));
|
||||
|
||||
mySdkListChanged = false;
|
||||
if (projectSdk == null) projectSdk = getSdk();
|
||||
if (projectSdk != null) {
|
||||
projectSdk = myProjectSdksModel.findSdk(projectSdk.getName());
|
||||
mySdkList.clearSelection();
|
||||
@@ -352,24 +235,20 @@ public class PythonSdkConfigurable implements Configurable, Configurable.NoScrol
|
||||
mySdkList.updateUI();
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Sdk getSdk() {
|
||||
final Module[] modules = ModuleManager.getInstance(myProject).getModules();
|
||||
if (modules.length > 0) {
|
||||
final Module module = modules[0];
|
||||
final ModuleRootManager rootManager = ModuleRootManager.getInstance(module);
|
||||
return rootManager.getSdk();
|
||||
if (myModule == null) {
|
||||
return ProjectRootManager.getInstance(myProject).getProjectSdk();
|
||||
}
|
||||
return ProjectRootManager.getInstance(myProject).getProjectSdk();
|
||||
final ModuleRootManager rootManager = ModuleRootManager.getInstance(myModule);
|
||||
return rootManager.getSdk();
|
||||
}
|
||||
|
||||
private void addSdk(AnActionButton button) {
|
||||
InterpreterPathChooser
|
||||
.show(myProject, myProjectSdksModel.getSdks(), button.getPreferredPopupPoint(), false, new NullableConsumer<Sdk>() {
|
||||
PythonSdkDetailsStep
|
||||
.show(myProject, myProjectSdksModel.getSdks(), this, button.getPreferredPopupPoint(), false, new NullableConsumer<Sdk>() {
|
||||
@Override
|
||||
public void consume(Sdk sdk) {
|
||||
myMakeActiveAdded = false;
|
||||
addCreatedSdk(sdk, false);
|
||||
}
|
||||
});
|
||||
@@ -377,11 +256,9 @@ public class PythonSdkConfigurable implements Configurable, Configurable.NoScrol
|
||||
|
||||
private void addCreatedSdk(@Nullable final Sdk sdk, boolean newVirtualEnv) {
|
||||
if (sdk != null) {
|
||||
myAddedSdk = sdk;
|
||||
boolean isVirtualEnv = PythonSdkType.isVirtualEnv(sdk);
|
||||
boolean askSetAsProjectInterpreter = !myProject.isDefault() && !myNewProject;
|
||||
if (askSetAsProjectInterpreter && isVirtualEnv && !newVirtualEnv) {
|
||||
AddVEnvOptionsDialog dialog = new AddVEnvOptionsDialog(myPanel);
|
||||
if (isVirtualEnv && !newVirtualEnv) {
|
||||
AddVEnvOptionsDialog dialog = new AddVEnvOptionsDialog(myMainPanel);
|
||||
dialog.show();
|
||||
if (dialog.getExitCode() != DialogWrapper.OK_EXIT_CODE) {
|
||||
return;
|
||||
@@ -389,20 +266,13 @@ public class PythonSdkConfigurable implements Configurable, Configurable.NoScrol
|
||||
SdkModificator modificator = myModificators.get(sdk);
|
||||
setSdkAssociated(modificator, !dialog.makeAvailableToAll());
|
||||
myModifiedModificators.add(modificator);
|
||||
myMakeActiveAdded = dialog.useForThisProject();
|
||||
}
|
||||
myProjectSdksModel.addSdk(sdk);
|
||||
final Sdk oldSdk = myProjectSdksModel.findSdk(sdk);
|
||||
if (oldSdk == null)
|
||||
myProjectSdksModel.addSdk(sdk);
|
||||
refreshSdkList();
|
||||
mySdkList.setSelectedValue(sdk, true);
|
||||
mySdkListChanged = true;
|
||||
if (askSetAsProjectInterpreter && !isVirtualEnv && !PythonSdkType.isInvalid(sdk) && !PythonSdkType.isIncompleteRemote(sdk)) {
|
||||
//TODO: make native mac dialog work
|
||||
myMakeActiveAdded = Messages.showIdeaMessageDialog(myProject, "Do you want to set this interpreter as Project Interpreter?",
|
||||
"Project Interpreter",
|
||||
new String[]{CommonBundle.getYesButtonText(), CommonBundle.getNoButtonText()}, 0, null,
|
||||
null
|
||||
) == Messages.YES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -521,55 +391,6 @@ public class PythonSdkConfigurable implements Configurable, Configurable.NoScrol
|
||||
|
||||
private void reloadSdk(Sdk currentSdk) {
|
||||
PythonSdkType.setupSdkPaths(myProject, null, currentSdk, myModificators.get(currentSdk)); // or must it be a RunWriteAction?
|
||||
reloadSdkPaths(currentSdk);
|
||||
}
|
||||
|
||||
public void disposeUIResources() {
|
||||
myInterpreterList.disposeModel();
|
||||
clearModificators();
|
||||
myFirstReset = true;
|
||||
}
|
||||
|
||||
private void saveSdkPaths(Sdk selection) {
|
||||
SdkModificator modificator = myModificators.get(selection);
|
||||
if (myPathEditor.isModified()) {
|
||||
myPathEditor.apply(modificator);
|
||||
myModifiedModificators.add(modificator);
|
||||
}
|
||||
}
|
||||
|
||||
private void reloadSdkPaths(Sdk selection) {
|
||||
List<VirtualFile> rootPaths = Lists.newArrayList();
|
||||
if (selection != null) {
|
||||
Collections.addAll(rootPaths, selection.getRootProvider().getFiles(OrderRootType.CLASSES));
|
||||
myPathEditor.reload(myModificators.get(selection));
|
||||
}
|
||||
else {
|
||||
myPathEditor.reload(null);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateSdkPaths(final Sdk selection) {
|
||||
final List<VirtualFile> rootPaths = Lists.newArrayList();
|
||||
if (selection != null) {
|
||||
Collections.addAll(rootPaths, selection.getRootProvider().getFiles(OrderRootType.CLASSES));
|
||||
myPathEditor.reset(myModificators.get(selection));
|
||||
}
|
||||
else {
|
||||
myPathEditor.reset(null);
|
||||
}
|
||||
}
|
||||
|
||||
private class CreateVirtualEnvButton extends AnActionButton implements DumbAware {
|
||||
public CreateVirtualEnvButton() {
|
||||
super("Create Virtual Environment", PythonIcons.Python.Virtualenv);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
Sdk selectedSdk = getSelectedSdk();
|
||||
createVirtualEnv(selectedSdk);
|
||||
}
|
||||
}
|
||||
|
||||
private class ToggleVirtualEnvFilterButton extends ToggleActionButton implements DumbAware {
|
||||
@@ -586,6 +407,73 @@ public class PythonSdkConfigurable implements Configurable, Configurable.NoScrol
|
||||
public void setSelected(AnActionEvent e, boolean state) {
|
||||
myShowOtherProjectVirtualenvs = state;
|
||||
refreshSdkList();
|
||||
updateOkButton();
|
||||
}
|
||||
}
|
||||
|
||||
private class ShowPathButton extends AnActionButton implements DumbAware {
|
||||
public ShowPathButton() {
|
||||
super("Show path for the selected interpreter", AllIcons.Actions.ShowAsTree);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return !(getSelectedSdk() instanceof PyDetectedSdk);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
DialogBuilder dialog = new DialogBuilder(myProject);
|
||||
|
||||
final PythonPathEditor editor =
|
||||
new PythonPathEditor("Classes", OrderRootType.CLASSES, FileChooserDescriptorFactory.createAllButJarContentsDescriptor()) {
|
||||
@Override
|
||||
protected void onReloadButtonClicked() {
|
||||
reloadSdk();
|
||||
}
|
||||
};
|
||||
final JComponent component = editor.createComponent();
|
||||
component.setPreferredSize(new Dimension(600, 400));
|
||||
component.setBorder(IdeBorderFactory.createBorder(SideBorder.ALL));
|
||||
dialog.setCenterPanel(component);
|
||||
final Sdk sdk = getSelectedSdk();
|
||||
editor.reload(sdk != null ? sdk.getSdkModificator(): null);
|
||||
|
||||
dialog.setTitle("Interpreter Paths");
|
||||
dialog.show();
|
||||
updateOkButton();
|
||||
}
|
||||
}
|
||||
|
||||
private class GenerateSkeletonsButton extends AnActionButton implements DumbAware {
|
||||
public GenerateSkeletonsButton() {
|
||||
super("Generate skeletons for the selected interpreter", PythonIcons.Python.Skeleton);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return (getSelectedSdk() instanceof PyDetectedSdk);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
final Sdk sdk = getSelectedSdk();
|
||||
if (sdk instanceof PyDetectedSdk) {
|
||||
try {
|
||||
myProjectSdksModel.apply();
|
||||
}
|
||||
catch (ConfigurationException ignored) {
|
||||
}
|
||||
|
||||
final Sdk addedSdk = SdkConfigurationUtil.setupSdk(myProjectSdksModel.getSdks(), sdk.getHomeDirectory(),
|
||||
PythonSdkType.getInstance(), true,
|
||||
null, null);
|
||||
myProjectSdksModel.addSdk(addedSdk);
|
||||
myProjectSdksModel.removeSdk(sdk);
|
||||
refreshSdkList();
|
||||
mySdkList.setSelectedValue(addedSdk, true);
|
||||
updateOkButton();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -50,13 +50,14 @@ public class VirtualEnvProjectFilter implements Predicate<Sdk> {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void removeNotMatching(Project project, List<Sdk> sdks) {
|
||||
public static boolean removeNotMatching(Project project, List<Sdk> sdks) {
|
||||
if (project != null) {
|
||||
final String basePath = project.getBasePath();
|
||||
if (basePath != null) {
|
||||
Iterables.removeIf(sdks, new VirtualEnvProjectFilter(FileUtil.toSystemIndependentName(basePath)));
|
||||
return Iterables.removeIf(sdks, new VirtualEnvProjectFilter(FileUtil.toSystemIndependentName(basePath)));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void removeAllAssociated(List<Sdk> sdks) {
|
||||
|
||||
@@ -27,6 +27,7 @@ import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.platform.DirectoryProjectGenerator;
|
||||
import com.intellij.platform.NewDirectoryProjectAction;
|
||||
import com.jetbrains.python.sdk.PyDetectedSdk;
|
||||
import com.jetbrains.python.sdk.PythonSdkAdditionalData;
|
||||
import com.jetbrains.python.sdk.PythonSdkType;
|
||||
|
||||
@@ -48,6 +49,9 @@ public class PythonNewDirectoryProjectAction extends NewDirectoryProjectAction {
|
||||
dlg.show();
|
||||
if (dlg.getExitCode() != DialogWrapper.OK_EXIT_CODE) return;
|
||||
mySdk = dlg.getSdk();
|
||||
if (mySdk instanceof PyDetectedSdk) {
|
||||
mySdk = SdkConfigurationUtil.createAndAddSDK(mySdk.getName(), PythonSdkType.getInstance());
|
||||
}
|
||||
myInstallFramework = dlg.installFramework();
|
||||
Project newProject = generateProject(project, dlg);
|
||||
if (newProject != null) {
|
||||
|
||||
@@ -31,6 +31,7 @@ import com.intellij.ui.ComboboxWithBrowseButton;
|
||||
import com.intellij.ui.components.JBCheckBox;
|
||||
import com.intellij.ui.components.JBLabel;
|
||||
import com.jetbrains.python.PythonSdkChooserCombo;
|
||||
import com.jetbrains.python.configuration.PyConfigurableInterpreterList;
|
||||
import com.jetbrains.python.configuration.VirtualEnvProjectFilter;
|
||||
import com.jetbrains.python.packaging.PyExternalProcessException;
|
||||
import com.jetbrains.python.packaging.PyPackage;
|
||||
@@ -38,7 +39,6 @@ import com.jetbrains.python.packaging.PyPackageManager;
|
||||
import com.jetbrains.python.packaging.PyPackageManagerImpl;
|
||||
import com.jetbrains.python.remote.PythonRemoteInterpreterManager;
|
||||
import com.jetbrains.python.remote.RemoteProjectSettings;
|
||||
import com.jetbrains.python.sdk.PreferredSdkComparator;
|
||||
import com.jetbrains.python.sdk.PythonSdkType;
|
||||
import com.jetbrains.python.sdk.flavors.JythonSdkFlavor;
|
||||
import com.jetbrains.python.sdk.flavors.PyPySdkFlavor;
|
||||
@@ -53,7 +53,6 @@ import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -69,9 +68,8 @@ public class PythonNewDirectoryProjectDialog extends NewDirectoryProjectDialog {
|
||||
super(project);
|
||||
myProject = project;
|
||||
|
||||
final List<Sdk> sdks = PythonSdkType.getAllSdks();
|
||||
final List<Sdk> sdks = PyConfigurableInterpreterList.getInstance(myProject).getAllPythonSdks();
|
||||
VirtualEnvProjectFilter.removeAllAssociated(sdks);
|
||||
Collections.sort(sdks, PreferredSdkComparator.INSTANCE);
|
||||
final Sdk preferred = sdks.isEmpty() ? null : sdks.iterator().next();
|
||||
mySdkCombo = new PythonSdkChooserCombo(project, sdks, new Condition<Sdk>() {
|
||||
@Override
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
# Only has artwork and tips stuff
|
||||
skip: *
|
||||
skip: *.png
|
||||
skip: tips
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 509 B |
Binary file not shown.
|
After Width: | Height: | Size: 1019 B |
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 537 B |
Binary file not shown.
|
After Width: | Height: | Size: 622 B |
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
@@ -31,7 +31,6 @@
|
||||
|
||||
<projectAttachProcessor implementation="com.intellij.platform.ModuleAttachProcessor"/>
|
||||
|
||||
<!--<applicationConfigurable instance="com.jetbrains.python.configuration.PythonSdkConfigurable"/>-->
|
||||
<projectConfigurable instance="com.jetbrains.python.configuration.PythonContentEntriesConfigurable"/>
|
||||
<projectConfigurable instance="com.jetbrains.python.buildout.BuildoutModulesConfigurable"/>
|
||||
<projectConfigurable instance="com.jetbrains.python.configuration.PyActiveSdkModuleConfigurable"/>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.jetbrains.python.sdk.CreateVirtualEnvDialog">
|
||||
<grid id="cbd77" binding="myMainPanel" layout-manager="GridLayoutManager" row-count="7" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<grid id="cbd77" binding="myMainPanel" layout-manager="GridLayoutManager" row-count="6" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<xy x="48" y="54" width="550" height="342"/>
|
||||
@@ -16,7 +16,7 @@
|
||||
</component>
|
||||
<vspacer id="b277d">
|
||||
<constraints>
|
||||
<grid row="6" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
|
||||
<grid row="5" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
</vspacer>
|
||||
<component id="48fd" class="com.intellij.ui.components.JBLabel">
|
||||
@@ -60,30 +60,22 @@
|
||||
</component>
|
||||
<component id="41e08" class="com.intellij.ui.components.JBCheckBox" binding="myMakeAvailableToAllProjectsCheckbox">
|
||||
<constraints>
|
||||
<grid row="5" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="0" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||
<grid row="4" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="0" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<selected value="false"/>
|
||||
<text value="Make available to &all projects"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="9835d" class="com.intellij.ui.components.JBCheckBox" binding="mySitePackagesCheckBox">
|
||||
<component id="d10a9" class="com.intellij.ui.components.JBCheckBox" binding="mySitePackagesCheckBox">
|
||||
<constraints>
|
||||
<grid row="3" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
<grid row="3" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="0" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<selected value="false"/>
|
||||
<text value="&Inherit global site-packages"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="fd5f3" class="com.intellij.ui.components.JBCheckBox" binding="mySetAsProjectInterpreterCheckbox" default-binding="true">
|
||||
<constraints>
|
||||
<grid row="4" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="0" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<selected value="true"/>
|
||||
<text value="&Set as project interpreter for this project"/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
</form>
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package com.jetbrains.python.sdk;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.intellij.facet.ui.FacetEditorValidator;
|
||||
import com.intellij.facet.ui.FacetValidatorsManager;
|
||||
import com.intellij.openapi.application.Application;
|
||||
@@ -67,18 +69,16 @@ public class CreateVirtualEnvDialog extends IdeaDialog {
|
||||
private JTextField myName;
|
||||
private JBCheckBox mySitePackagesCheckBox;
|
||||
private JBCheckBox myMakeAvailableToAllProjectsCheckbox;
|
||||
private JBCheckBox mySetAsProjectInterpreterCheckbox;
|
||||
@Nullable private Project myProject;
|
||||
private String myInitialPath;
|
||||
|
||||
public interface VirtualEnvCallback {
|
||||
void virtualEnvCreated(Sdk sdk, boolean associateWithProject, boolean setAsProjectInterpreter);
|
||||
void virtualEnvCreated(Sdk sdk, boolean associateWithProject);
|
||||
}
|
||||
|
||||
private static void setupVirtualEnvSdk(List<Sdk> allSdks,
|
||||
private void setupVirtualEnvSdk(List<Sdk> allSdks,
|
||||
final String path,
|
||||
boolean associateWithProject,
|
||||
final boolean makeActive,
|
||||
VirtualEnvCallback callback) {
|
||||
final VirtualFile sdkHome =
|
||||
ApplicationManager.getApplication().runWriteAction(new Computable<VirtualFile>() {
|
||||
@@ -92,46 +92,45 @@ public class CreateVirtualEnvDialog extends IdeaDialog {
|
||||
SdkConfigurationUtil.createUniqueSdkName(PythonSdkType.getInstance(), sdkHome.getPath(), allSdks);
|
||||
final ProjectJdkImpl sdk = new ProjectJdkImpl(name, PythonSdkType.getInstance());
|
||||
sdk.setHomePath(sdkHome.getPath());
|
||||
callback.virtualEnvCreated(sdk, associateWithProject, makeActive);
|
||||
callback.virtualEnvCreated(sdk, associateWithProject);
|
||||
PythonSdkType.setupSdkPaths(sdk, myProject, null);
|
||||
}
|
||||
}
|
||||
|
||||
public CreateVirtualEnvDialog(Project project,
|
||||
boolean isNewProject,
|
||||
final List<Sdk> allSdks,
|
||||
@Nullable Sdk suggestedBaseSdk) {
|
||||
super(project);
|
||||
setupDialog(project, isNewProject, allSdks, suggestedBaseSdk);
|
||||
setupDialog(project, allSdks, suggestedBaseSdk);
|
||||
}
|
||||
|
||||
public CreateVirtualEnvDialog(Component owner,
|
||||
boolean isNewProject,
|
||||
final List<Sdk> allSdks,
|
||||
@Nullable Sdk suggestedBaseSdk) {
|
||||
super(owner);
|
||||
setupDialog(null, isNewProject, allSdks, suggestedBaseSdk);
|
||||
setupDialog(null, allSdks, suggestedBaseSdk);
|
||||
}
|
||||
|
||||
private void setupDialog(Project project, boolean isNewProject, List<Sdk> allSdks, @Nullable Sdk suggestedBaseSdk) {
|
||||
private void setupDialog(Project project, List<Sdk> allSdks, @Nullable Sdk suggestedBaseSdk) {
|
||||
myProject = project;
|
||||
init();
|
||||
setTitle("Create Virtual Environment");
|
||||
if (suggestedBaseSdk == null && allSdks.size() > 0) {
|
||||
Iterables.removeIf(allSdks, new Predicate<Sdk>() {
|
||||
@Override
|
||||
public boolean apply(Sdk s) {
|
||||
return PythonSdkType.isInvalid(s) || PythonSdkType.isVirtualEnv(s) || RemoteSdkDataHolder.isRemoteSdk(s.getHomePath());
|
||||
}
|
||||
});
|
||||
List<Sdk> sortedSdks = new ArrayList<Sdk>(allSdks);
|
||||
Collections.sort(sortedSdks, new PreferredSdkComparator());
|
||||
suggestedBaseSdk = sortedSdks.get(0);
|
||||
}
|
||||
updateSdkList(allSdks, suggestedBaseSdk);
|
||||
|
||||
myMakeAvailableToAllProjectsCheckbox.setBorder(BorderFactory.createEmptyBorder(8, 0, 0, 0));
|
||||
if (project == null || project.isDefault() || !PlatformUtils.isPyCharm()) {
|
||||
myMakeAvailableToAllProjectsCheckbox.setSelected(true);
|
||||
myMakeAvailableToAllProjectsCheckbox.setVisible(false);
|
||||
mySetAsProjectInterpreterCheckbox.setSelected(false);
|
||||
mySetAsProjectInterpreterCheckbox.setVisible(false);
|
||||
}
|
||||
else if (isNewProject) {
|
||||
mySetAsProjectInterpreterCheckbox.setText("Set as project interpreter for the project being created");
|
||||
}
|
||||
|
||||
setOKActionEnabled(false);
|
||||
@@ -238,17 +237,7 @@ public class CreateVirtualEnvDialog extends IdeaDialog {
|
||||
|
||||
private void updateSdkList(final List<Sdk> allSdks, @Nullable Sdk initialSelection) {
|
||||
mySdkCombo.setRenderer(new PySdkListCellRenderer());
|
||||
List<Sdk> baseSdks = new ArrayList<Sdk>();
|
||||
for (Sdk s : allSdks) {
|
||||
if (!PythonSdkType.isInvalid(s) && !PythonSdkType.isVirtualEnv(s) && !RemoteSdkDataHolder.isRemoteSdk(s.getHomePath())) {
|
||||
baseSdks.add(s);
|
||||
}
|
||||
else if (s.equals(initialSelection)){
|
||||
initialSelection = null;
|
||||
}
|
||||
}
|
||||
|
||||
mySdkCombo.setModel(new CollectionComboBoxModel(baseSdks, initialSelection));
|
||||
mySdkCombo.setModel(new CollectionComboBoxModel(allSdks, initialSelection));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -288,10 +277,6 @@ public class CreateVirtualEnvDialog extends IdeaDialog {
|
||||
return !myMakeAvailableToAllProjectsCheckbox.isSelected();
|
||||
}
|
||||
|
||||
public boolean setAsProjectInterpreter() {
|
||||
return mySetAsProjectInterpreterCheckbox.isSelected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JComponent getPreferredFocusedComponent() {
|
||||
return myName;
|
||||
@@ -326,7 +311,7 @@ public class CreateVirtualEnvDialog extends IdeaDialog {
|
||||
application.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
setupVirtualEnvSdk(allSdks, myPath, associateWithProject(), setAsProjectInterpreter(), callback);
|
||||
setupVirtualEnvSdk(allSdks, myPath, associateWithProject(), callback);
|
||||
}
|
||||
}, ModalityState.any());
|
||||
}
|
||||
|
||||
@@ -37,6 +37,12 @@ public class PreferredSdkComparator implements Comparator<Sdk> {
|
||||
if (remote1Weight != remote2Weight) {
|
||||
return remote2Weight - remote1Weight;
|
||||
}
|
||||
int detectedWeight1 = o1 instanceof PyDetectedSdk ? 0 : 1;
|
||||
int detectedWeight2 = o2 instanceof PyDetectedSdk ? 0 : 1;
|
||||
if (detectedWeight1 != detectedWeight2) {
|
||||
return detectedWeight2 - detectedWeight1;
|
||||
}
|
||||
|
||||
int venv1weight = PythonSdkType.isVirtualEnv(o1) ? 0 : 1;
|
||||
int venv2weight = PythonSdkType.isVirtualEnv(o2) ? 0 : 1;
|
||||
if (venv1weight != venv2weight) {
|
||||
@@ -47,6 +53,7 @@ public class PreferredSdkComparator implements Comparator<Sdk> {
|
||||
if (flavor1weight != flavor2weight) {
|
||||
return flavor2weight - flavor1weight;
|
||||
}
|
||||
|
||||
return -Comparing.compare(o1.getVersionString(), o2.getVersionString());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.jetbrains.python.sdk;
|
||||
|
||||
import com.intellij.openapi.projectRoots.impl.ProjectJdkImpl;
|
||||
|
||||
public class PyDetectedSdk extends ProjectJdkImpl {
|
||||
public PyDetectedSdk(String name) {
|
||||
super(name, PythonSdkType.getInstance());
|
||||
setHomePath(name);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,6 +19,7 @@ import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.projectRoots.SdkModificator;
|
||||
import com.intellij.openapi.projectRoots.SdkType;
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
import com.intellij.ui.LayeredIcon;
|
||||
import com.intellij.ui.ListCellRendererWrapper;
|
||||
import com.jetbrains.python.sdk.flavors.PythonSdkFlavor;
|
||||
@@ -27,9 +28,10 @@ import org.jetbrains.annotations.Nullable;
|
||||
import javax.swing.*;
|
||||
import java.util.Map;
|
||||
|
||||
public class PySdkListCellRenderer extends ListCellRendererWrapper<Sdk> {
|
||||
public class PySdkListCellRenderer extends ListCellRendererWrapper<Object> {
|
||||
private final String myNullText;
|
||||
private final Map<Sdk, SdkModificator> mySdkModifiers;
|
||||
public static final String SEPARATOR = "separator";
|
||||
|
||||
public PySdkListCellRenderer() {
|
||||
myNullText = "";
|
||||
@@ -42,8 +44,9 @@ public class PySdkListCellRenderer extends ListCellRendererWrapper<Sdk> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void customize(JList list, Sdk sdk, int index, boolean selected, boolean hasFocus) {
|
||||
if (sdk != null) {
|
||||
public void customize(JList list, Object item, int index, boolean selected, boolean hasFocus) {
|
||||
if (item instanceof Sdk) {
|
||||
Sdk sdk = (Sdk)item;
|
||||
final PythonSdkFlavor flavor = PythonSdkFlavor.getPlatformIndependentFlavor(sdk.getHomePath());
|
||||
final Icon icon = flavor != null ? flavor.getIcon() : ((SdkType)sdk.getSdkType()).getIcon();
|
||||
|
||||
@@ -54,7 +57,6 @@ public class PySdkListCellRenderer extends ListCellRendererWrapper<Sdk> {
|
||||
else {
|
||||
name = sdk.getName();
|
||||
}
|
||||
|
||||
if (PythonSdkType.isInvalid(sdk)) {
|
||||
setText("[invalid] " + name);
|
||||
setIcon(wrapIconWithWarningDecorator(icon));
|
||||
@@ -63,17 +65,22 @@ public class PySdkListCellRenderer extends ListCellRendererWrapper<Sdk> {
|
||||
setText("[incomplete] " + name);
|
||||
setIcon(wrapIconWithWarningDecorator(icon));
|
||||
}
|
||||
else if (sdk instanceof PyDetectedSdk){
|
||||
setText(name);
|
||||
setIcon(IconLoader.getTransparentIcon(icon));
|
||||
}
|
||||
else {
|
||||
setText(name);
|
||||
setIcon(icon);
|
||||
}
|
||||
}
|
||||
else {
|
||||
else if (SEPARATOR.equals(item))
|
||||
setSeparator();
|
||||
else if (item == null)
|
||||
setText(myNullText);
|
||||
}
|
||||
}
|
||||
|
||||
private LayeredIcon wrapIconWithWarningDecorator(Icon icon) {
|
||||
private static LayeredIcon wrapIconWithWarningDecorator(Icon icon) {
|
||||
final LayeredIcon layered = new LayeredIcon(2);
|
||||
layered.setIcon(icon, 0);
|
||||
// TODO: Create a separate invalid SDK overlay icon (DSGN-497)
|
||||
|
||||
+64
-78
@@ -21,102 +21,80 @@ import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.options.ShowSettingsUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.projectRoots.SdkAdditionalData;
|
||||
import com.intellij.openapi.projectRoots.impl.ProjectJdkImpl;
|
||||
import com.intellij.openapi.projectRoots.impl.SdkConfigurationUtil;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory;
|
||||
import com.intellij.openapi.ui.popup.ListPopup;
|
||||
import com.intellij.openapi.ui.popup.ListPopupStep;
|
||||
import com.intellij.openapi.ui.popup.PopupStep;
|
||||
import com.intellij.openapi.ui.popup.*;
|
||||
import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.util.NullableConsumer;
|
||||
import com.intellij.util.SystemProperties;
|
||||
import com.jetbrains.python.remote.PythonRemoteInterpreterManager;
|
||||
import com.jetbrains.python.sdk.flavors.PythonSdkFlavor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public class InterpreterPathChooser extends BaseListPopupStep<String> {
|
||||
public class PythonSdkDetailsStep extends BaseListPopupStep<String> {
|
||||
private static DialogWrapper myMore;
|
||||
private final Project myProject;
|
||||
private final Component myOwnerComponent;
|
||||
private final Sdk[] myExistingSdks;
|
||||
private final NullableConsumer<Sdk> myCallback;
|
||||
|
||||
private static final String LOCAL = "Local...";
|
||||
private static final String REMOTE = "Remote...";
|
||||
private static final String VIRTUALENV = "Create VirtualEnv...";
|
||||
private static final String LOCAL = "Add Local";
|
||||
private static final String REMOTE = "Add Remote";
|
||||
private static final String VIRTUALENV = "Create VirtualEnv";
|
||||
private static final String MORE = "More...";
|
||||
|
||||
public static void show(final Project project,
|
||||
final Sdk[] existingSdks,
|
||||
final RelativePoint popupPoint,
|
||||
final boolean showVirtualEnv,
|
||||
DialogWrapper component, final RelativePoint popupPoint,
|
||||
final boolean showMore,
|
||||
final NullableConsumer<Sdk> callback) {
|
||||
ListPopupStep sdkHomesStep = new InterpreterPathChooser(project, popupPoint.getComponent(), existingSdks, showVirtualEnv, callback);
|
||||
myMore = component;
|
||||
final ListPopupStep sdkHomesStep = new PythonSdkDetailsStep(project, popupPoint.getComponent(), existingSdks, showMore, callback);
|
||||
final ListPopup popup = JBPopupFactory.getInstance().createListPopup(sdkHomesStep);
|
||||
popup.show(popupPoint);
|
||||
}
|
||||
|
||||
public InterpreterPathChooser(Project project,
|
||||
Component ownerComponent,
|
||||
Sdk[] existingSdks,
|
||||
boolean showVirtualEnv,
|
||||
NullableConsumer<Sdk> callback) {
|
||||
super("Select Interpreter Path", getSuggestedPythonSdkPaths(existingSdks, showVirtualEnv));
|
||||
public PythonSdkDetailsStep(Project project,
|
||||
Component ownerComponent,
|
||||
Sdk[] existingSdks,
|
||||
boolean showMore,
|
||||
NullableConsumer<Sdk> callback) {
|
||||
super(null, getAvailableOptions(showMore));
|
||||
myProject = project;
|
||||
myOwnerComponent = ownerComponent;
|
||||
myExistingSdks = existingSdks;
|
||||
myCallback = callback;
|
||||
}
|
||||
|
||||
private static List<String> getSuggestedPythonSdkPaths(Sdk[] existingSdks, boolean showVirtualEnv) {
|
||||
List<String> paths = new ArrayList<String>();
|
||||
Collection<String> sdkHomes = PythonSdkType.getInstance().suggestHomePaths();
|
||||
for (String sdkHome : SdkConfigurationUtil.filterExistingPaths(PythonSdkType.getInstance(), sdkHomes, existingSdks)) {
|
||||
paths.add(FileUtil.getLocationRelativeToUserHome(sdkHome));
|
||||
}
|
||||
paths.add(LOCAL);
|
||||
private static List<String> getAvailableOptions(boolean showMore) {
|
||||
final List<String> options = new ArrayList<String>();
|
||||
options.add(LOCAL);
|
||||
if (PythonRemoteInterpreterManager.getInstance() != null) {
|
||||
paths.add(REMOTE);
|
||||
options.add(REMOTE);
|
||||
}
|
||||
if (showVirtualEnv) {
|
||||
paths.add(VIRTUALENV);
|
||||
options.add(VIRTUALENV);
|
||||
|
||||
if (showMore) {
|
||||
options.add(MORE);
|
||||
}
|
||||
return paths;
|
||||
return options;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Icon getIconFor(String aValue) {
|
||||
if (LOCAL.equals(aValue) || REMOTE.equals(aValue) || VIRTUALENV.equals(aValue)) return null;
|
||||
String filePath = aValue;
|
||||
if (StringUtil.startsWithChar(filePath, '~')) {
|
||||
String home = SystemProperties.getUserHome();
|
||||
filePath = home + filePath.substring(1);
|
||||
}
|
||||
final PythonSdkFlavor flavor = PythonSdkFlavor.getPlatformIndependentFlavor(filePath);
|
||||
return flavor != null ? flavor.getIcon() : PythonSdkType.getInstance().getIcon();
|
||||
public ListSeparator getSeparatorAbove(String value) {
|
||||
return MORE.equals(value) ? new ListSeparator() : null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getTextFor(String value) {
|
||||
return FileUtil.toSystemDependentName(value);
|
||||
}
|
||||
|
||||
private void sdkSelected(final String selectedValue) {
|
||||
private void optionSelected(final String selectedValue) {
|
||||
if (LOCAL.equals(selectedValue)) {
|
||||
createLocalSdk();
|
||||
}
|
||||
@@ -127,7 +105,7 @@ public class InterpreterPathChooser extends BaseListPopupStep<String> {
|
||||
createVirtualEnvSdk();
|
||||
}
|
||||
else {
|
||||
createSdkFromPath(selectedValue);
|
||||
myMore.show();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,7 +113,7 @@ public class InterpreterPathChooser extends BaseListPopupStep<String> {
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
SdkConfigurationUtil.createSdk(myProject, myExistingSdks, myCallback, PythonSdkType.getInstance());
|
||||
SdkConfigurationUtil.createSdk(myProject, myExistingSdks, myCallback, false, PythonSdkType.getInstance());
|
||||
}
|
||||
}, ModalityState.any());
|
||||
}
|
||||
@@ -152,35 +130,43 @@ public class InterpreterPathChooser extends BaseListPopupStep<String> {
|
||||
}
|
||||
}
|
||||
|
||||
private void createSdkFromPath(String selectedPath) {
|
||||
String filePath = selectedPath;
|
||||
if (StringUtil.startsWithChar(filePath, '~')) {
|
||||
String home = SystemProperties.getUserHome();
|
||||
filePath = home + filePath.substring(1);
|
||||
}
|
||||
Sdk sdk = SdkConfigurationUtil.setupSdk(myExistingSdks,
|
||||
LocalFileSystem.getInstance().findFileByPath(filePath),
|
||||
PythonSdkType.getInstance(), false, null, null);
|
||||
myCallback.consume(sdk);
|
||||
}
|
||||
|
||||
private void createVirtualEnvSdk() {
|
||||
CreateVirtualEnvDialog.VirtualEnvCallback callback = new CreateVirtualEnvDialog.VirtualEnvCallback() {
|
||||
@Override
|
||||
public void virtualEnvCreated(Sdk sdk, boolean associateWithProject) {
|
||||
PythonSdkType.setupSdkPaths(sdk, myProject, null);
|
||||
if (associateWithProject) {
|
||||
SdkAdditionalData additionalData = sdk.getSdkAdditionalData();
|
||||
if (additionalData == null) {
|
||||
additionalData = new PythonSdkAdditionalData(PythonSdkFlavor.getFlavor(sdk.getHomePath()));
|
||||
((ProjectJdkImpl)sdk).setSdkAdditionalData(additionalData);
|
||||
}
|
||||
((PythonSdkAdditionalData)additionalData).associateWithProject(myProject);
|
||||
}
|
||||
myCallback.consume(sdk);
|
||||
}
|
||||
};
|
||||
|
||||
final CreateVirtualEnvDialog dialog;
|
||||
final List<Sdk> allSdks = Arrays.asList(myExistingSdks);
|
||||
final List<Sdk> allSdks = Lists.newArrayList(myExistingSdks);
|
||||
|
||||
final List<PythonSdkFlavor> flavors = PythonSdkFlavor.getApplicableFlavors(false);
|
||||
for (PythonSdkFlavor flavor : flavors) {
|
||||
final Collection<String> strings = flavor.suggestHomePaths();
|
||||
for (String string : strings) {
|
||||
allSdks.add(new PyDetectedSdk(string));
|
||||
}
|
||||
}
|
||||
|
||||
if (myProject != null) {
|
||||
dialog = new CreateVirtualEnvDialog(myProject, false, allSdks, null);
|
||||
dialog = new CreateVirtualEnvDialog(myProject, allSdks, null);
|
||||
}
|
||||
else {
|
||||
dialog = new CreateVirtualEnvDialog(myOwnerComponent, false, allSdks, null);
|
||||
dialog = new CreateVirtualEnvDialog(myOwnerComponent, allSdks, null);
|
||||
}
|
||||
dialog.show();
|
||||
if (dialog.isOK()) {
|
||||
dialog.createVirtualEnv(allSdks, new CreateVirtualEnvDialog.VirtualEnvCallback() {
|
||||
@Override
|
||||
public void virtualEnvCreated(Sdk sdk, boolean associateWithProject, boolean setAsProjectInterpreter) {
|
||||
myCallback.consume(sdk);
|
||||
}
|
||||
});
|
||||
dialog.createVirtualEnv(allSdks, callback);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,7 +179,7 @@ public class InterpreterPathChooser extends BaseListPopupStep<String> {
|
||||
public PopupStep onChosen(final String selectedValue, boolean finalChoice) {
|
||||
return doFinalStep(new Runnable() {
|
||||
public void run() {
|
||||
sdkSelected(selectedValue);
|
||||
optionSelected(selectedValue);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -45,7 +45,10 @@ import com.intellij.openapi.util.io.FileSystemUtil;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.CharFilter;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.*;
|
||||
import com.intellij.openapi.vfs.JarFileSystem;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VfsUtilCore;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.reference.SoftReference;
|
||||
import com.intellij.remotesdk.RemoteSdkData;
|
||||
@@ -277,15 +280,16 @@ public class PythonSdkType extends SdkType {
|
||||
|
||||
public void showCustomCreateUI(SdkModel sdkModel, final JComponent parentComponent, final Consumer<Sdk> sdkCreatedCallback) {
|
||||
Project project = CommonDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext(parentComponent));
|
||||
InterpreterPathChooser.show(project, sdkModel.getSdks(), RelativePoint.getCenterOf(parentComponent), true, new NullableConsumer<Sdk>() {
|
||||
@Override
|
||||
public void consume(@Nullable Sdk sdk) {
|
||||
if (sdk != null) {
|
||||
sdk.putUserData(SDK_CREATOR_COMPONENT_KEY, new WeakReference<Component>(parentComponent));
|
||||
sdkCreatedCallback.consume(sdk);
|
||||
PythonSdkDetailsStep
|
||||
.show(project, sdkModel.getSdks(), null, RelativePoint.getCenterOf(parentComponent), true, new NullableConsumer<Sdk>() {
|
||||
@Override
|
||||
public void consume(@Nullable Sdk sdk) {
|
||||
if (sdk != null) {
|
||||
sdk.putUserData(SDK_CREATOR_COMPONENT_KEY, new WeakReference<Component>(parentComponent));
|
||||
sdkCreatedCallback.consume(sdk);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public static boolean isVirtualEnv(Sdk sdk) {
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package com.jetbrains.python.sdk.flavors;
|
||||
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VFileProperty;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.newvfs.NewVirtualFile;
|
||||
|
||||
@@ -57,7 +58,7 @@ public class MacPythonSdkFlavor extends CPythonSdkFlavor {
|
||||
if (binDir != null && binDir.isDirectory()) {
|
||||
for (String name : POSSIBLE_BINARY_NAMES) {
|
||||
final VirtualFile child = binDir.findChild(name);
|
||||
if (child != null) {
|
||||
if (child != null && !child.is(VFileProperty.SYMLINK)) {
|
||||
candidates.add(child.getPath());
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -72,6 +72,10 @@ public abstract class PythonSdkFlavor {
|
||||
}
|
||||
|
||||
public static List<PythonSdkFlavor> getApplicableFlavors() {
|
||||
return getApplicableFlavors(true);
|
||||
}
|
||||
|
||||
public static List<PythonSdkFlavor> getApplicableFlavors(boolean addPlatformIndependent) {
|
||||
List<PythonSdkFlavor> result = new ArrayList<PythonSdkFlavor>();
|
||||
|
||||
if (SystemInfo.isWindows) {
|
||||
@@ -84,7 +88,8 @@ public abstract class PythonSdkFlavor {
|
||||
result.add(UnixPythonSdkFlavor.INSTANCE);
|
||||
}
|
||||
|
||||
result.addAll(getPlatformIndependentFlavors());
|
||||
if (addPlatformIndependent)
|
||||
result.addAll(getPlatformIndependentFlavors());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package com.jetbrains.python.sdk.flavors;
|
||||
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VFileProperty;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.newvfs.NewVirtualFile;
|
||||
|
||||
@@ -47,14 +48,15 @@ public class UnixPythonSdkFlavor extends CPythonSdkFlavor {
|
||||
if (rootDir instanceof NewVirtualFile) {
|
||||
((NewVirtualFile)rootDir).markDirty();
|
||||
}
|
||||
rootDir.refresh(false, false);
|
||||
rootDir.refresh(true, false);
|
||||
VirtualFile[] suspects = rootDir.getChildren();
|
||||
for (VirtualFile child : suspects) {
|
||||
if (!child.isDirectory()) {
|
||||
final String childName = child.getName();
|
||||
for (String name : NAMES) {
|
||||
if (childName.startsWith(name)) {
|
||||
if (!childName.endsWith("-config") && !childName.startsWith("pythonw")) {
|
||||
if (!childName.endsWith("-config") && !childName.startsWith("pythonw") &&
|
||||
!childName.endsWith("m") && !child.is(VFileProperty.SYMLINK)) {
|
||||
candidates.add(child.getPath());
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -83,7 +83,7 @@ public class VirtualEnvSdkFlavor extends CPythonSdkFlavor {
|
||||
public static Collection<String> findInDirectory(VirtualFile rootDir) {
|
||||
List<String> candidates = new ArrayList<String>();
|
||||
if (rootDir != null) {
|
||||
rootDir.refresh(false, false);
|
||||
rootDir.refresh(true, false);
|
||||
VirtualFile[] suspects = rootDir.getChildren();
|
||||
for (VirtualFile child : suspects) {
|
||||
if (child.isDirectory()) {
|
||||
|
||||
@@ -32,6 +32,7 @@ public class PythonIcons {
|
||||
|
||||
}
|
||||
public static final Icon Dotnet = load("/icons/com/jetbrains/python/dotnet.png"); // 16x16
|
||||
public static final Icon InterpreterGear = load("/icons/com/jetbrains/python/interpreterGear.png"); // 16x16
|
||||
public static final Icon Jython = load("/icons/com/jetbrains/python/jython.png"); // 16x16
|
||||
|
||||
public static class Nodes {
|
||||
@@ -48,6 +49,7 @@ public class PythonIcons {
|
||||
public static final Icon Python_24 = load("/icons/com/jetbrains/python/python_24.png"); // 24x24
|
||||
public static final Icon PythonClosed = load("/icons/com/jetbrains/python/pythonClosed.png"); // 16x16
|
||||
public static final Icon PythonTests = load("/icons/com/jetbrains/python/pythonTests.png"); // 16x16
|
||||
public static final Icon Skeleton = load("/icons/com/jetbrains/python/skeleton.png"); // 16x16
|
||||
public static final Icon Virtualenv = load("/icons/com/jetbrains/python/virtualenv.png"); // 16x16
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user