initial python project interpreters page

This commit is contained in:
Ekaterina Tuzova
2014-02-06 20:16:08 +04:00
parent 7fd991d1a7
commit 057c5f3329
9 changed files with 189 additions and 179 deletions
@@ -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,37 @@ 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();
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));
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);
myPackagesTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
@Override
@@ -107,16 +106,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 +151,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() {
@@ -322,43 +306,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
@@ -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>
@@ -32,52 +32,133 @@ 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.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.PySdkListCellRenderer;
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.List;
/**
* @author yole
*/
public class PyActiveSdkConfigurable implements UnnamedConfigurable {
private JPanel myPanel;
private final Project myProject;
@Nullable private final Module myModule;
private JComboBox mySdkCombo;
private JPanel myConfigureInterpretersPanel;
private PyConfigurableInterpreterList myInterpreterList;
private ProjectSdksModel myProjectSdksModel;
private MyListener myListener;
public PyActiveSdkConfigurable(Project project) {
private PyConfigurableInterpreterList myInterpreterList;
private ProjectSdksModel myProjectSdksModel;
private ComboBox mySdkCombo;
private PyInstalledPackagesPanel myPackagesPanel;
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() {
mySdkCombo.setRenderer(new SdkListCellRenderer("<None>"));
private void initContent() {
myInterpreterList = PyConfigurableInterpreterList.getInstance(myProject);
myInterpreterList.setSdkCombo(mySdkCombo);
myProjectSdksModel = myInterpreterList.getModel();
myListener = new MyListener(this);
myProjectSdksModel.addListener(myListener);
myConfigureInterpretersPanel.add(new PyConfigureInterpretersLinkPanel(myPanel), BorderLayout.CENTER);
myInterpreterList.setSdkCombo(mySdkCombo);
mySdkCombo.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
final Sdk selectedSdk = (Sdk)mySdkCombo.getSelectedItem();
myPackagesPanel.updatePackages(selectedSdk == null ? null : new PyPackageManagementService(myProject, selectedSdk));
}
});
}
private void layoutPanel() {
final GridBagLayout layout = new GridBagLayout();
myPanel = new JPanel(layout);
final JLabel label = new JLabel("Project Interpreter:");
final JLabel label1 = new JLabel(" ");
mySdkCombo = new ComboBox();
mySdkCombo.setRenderer(new SdkListCellRenderer("<None>"));
PackagesNotificationPanel notificationsArea = new PackagesNotificationPanel(myProject);
final JComponent notificationsComponent = notificationsArea.getComponent();
notificationsComponent.setPreferredSize(new Dimension(500, 29));
JButton detailsButton = new JButton();
detailsButton.setIcon(PythonIcons.Python.InterpreterGear);
detailsButton.setIconTextGap(0);
detailsButton.setPreferredSize(new Dimension(29, 29));
if (((UIUtil.isUnderAquaLookAndFeel())) || UIUtil.isUnderIntelliJLaF() || UIUtil.isUnderDarcula()) {
detailsButton.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;
myPanel.add(label, c);
c.gridx = 1;
c.gridy = 0;
c.weightx = 0.1;
myPanel.add(mySdkCombo, c);
c.insets = new Insets(0,5,0,2);
c.gridx = 2;
c.gridy = 0;
c.weightx = 0.0;
myPanel.add(detailsButton, c);
c.insets = new Insets(2,2,2,2);
c.gridx = 0;
c.gridy = 1;
c.gridwidth = 3;
myPanel.add(label1, c);
c.gridx = 0;
c.gridy = 2;
c.weighty = 0.5;
c.gridwidth = 3;
c.gridheight = GridBagConstraints.RELATIVE;
c.fill = GridBagConstraints.BOTH;
myPanel.add(myPackagesPanel, c);
c.gridheight = GridBagConstraints.REMAINDER;
c.gridx = 0;
c.gridy = 3;
c.gridwidth = 3;
c.fill = GridBagConstraints.HORIZONTAL;
c.anchor = GridBagConstraints.SOUTH;
myPanel.add(notificationsComponent, c);
}
@Override
@@ -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 };
}
}
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

+1
View File
@@ -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 {