mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
PY-22830 Improve UI for remote notebooks
This commit is contained in:
@@ -26,5 +26,6 @@
|
||||
</orderEntry>
|
||||
<orderEntry type="library" name="markdown4j-2.2" level="project" />
|
||||
<orderEntry type="library" name="http-client" level="project" />
|
||||
<orderEntry type="module" module-name="python-community-configure" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.plugins.ipnb.configuration.IpnbConfigurable">
|
||||
<grid id="27dc6" binding="myMainPanel" layout-manager="GridLayoutManager" row-count="5" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<grid id="27dc6" binding="myMainPanel" 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="657" height="302"/>
|
||||
@@ -8,7 +8,7 @@
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<grid id="6ed7f" layout-manager="GridLayoutManager" row-count="3" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<grid id="6ed7f" layout-manager="GridLayoutManager" row-count="2" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="1" fill="1" indent="0" use-parent-layout="false"/>
|
||||
@@ -21,18 +21,18 @@
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="Jupyter Notebook URL:"/>
|
||||
<text value="&URL:"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="5a5b" class="com.intellij.ui.components.JBTextField" binding="myFieldUrl">
|
||||
<component id="5a5b" class="com.intellij.ui.components.JBTextField" binding="myUrlField">
|
||||
<constraints>
|
||||
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
</component>
|
||||
<component id="24f12" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myWorkingDirField">
|
||||
<component id="24f12" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myNotebookDirectoryField">
|
||||
<constraints>
|
||||
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||
<grid row="1" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
</component>
|
||||
@@ -42,103 +42,36 @@
|
||||
</constraints>
|
||||
<properties>
|
||||
<labelFor value="24f12"/>
|
||||
<text value="&Working directory:"/>
|
||||
<text value="&Notebook directory:"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="97534" class="com.intellij.ui.components.JBTextField" binding="myArgumentsField">
|
||||
<component id="8a71c" class="com.intellij.ui.components.JBLabel" binding="myWarningIcon">
|
||||
<constraints>
|
||||
<grid row="2" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||
<grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="0" indent="0" use-parent-layout="false">
|
||||
<minimum-size width="18" height="18"/>
|
||||
</grid>
|
||||
</constraints>
|
||||
<properties/>
|
||||
</component>
|
||||
<component id="83e21" class="com.intellij.ui.components.JBLabel">
|
||||
<constraints>
|
||||
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="Arguments:"/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
<grid id="18b6b" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<grid id="18b6b" binding="mySpecificNotebookSettingsPanel" custom-create="true" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="true" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="2" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
<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">
|
||||
<font/>
|
||||
<color color="-4539718"/>
|
||||
</border>
|
||||
<children>
|
||||
<component id="85ddd" class="com.intellij.ui.components.JBLabel">
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<labelFor value="39ad9"/>
|
||||
<text value="&Password:"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="5fd16" 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="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="&Username:"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="39ad9" class="javax.swing.JPasswordField" binding="myPasswordField">
|
||||
<constraints>
|
||||
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
|
||||
<preferred-size width="150" height="-1"/>
|
||||
</grid>
|
||||
</constraints>
|
||||
<properties/>
|
||||
</component>
|
||||
<component id="a47cd" class="com.intellij.ui.components.JBTextField" binding="myUsernameField">
|
||||
<constraints>
|
||||
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
</component>
|
||||
</children>
|
||||
<children/>
|
||||
</grid>
|
||||
<vspacer id="9a11e">
|
||||
<constraints>
|
||||
<grid row="4" column="0" row-span="1" col-span="2" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
|
||||
<grid row="2" column="0" row-span="1" col-span="2" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
</vspacer>
|
||||
<component id="b88d4" class="com.intellij.ui.TitledSeparator">
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="Remote notebook credentials"/>
|
||||
</properties>
|
||||
</component>
|
||||
<grid id="161aa" 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>
|
||||
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="9a652" class="com.intellij.ui.components.JBLabel" binding="myWarningLabel">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
</component>
|
||||
<hspacer id="cab57">
|
||||
<constraints>
|
||||
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
</hspacer>
|
||||
</children>
|
||||
</grid>
|
||||
</children>
|
||||
</grid>
|
||||
</form>
|
||||
|
||||
@@ -1,44 +1,56 @@
|
||||
package org.jetbrains.plugins.ipnb.configuration;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.ide.DataManager;
|
||||
import com.intellij.ide.IdeTooltipManager;
|
||||
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
|
||||
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
|
||||
import com.intellij.openapi.options.ConfigurationException;
|
||||
import com.intellij.openapi.options.SearchableConfigurable;
|
||||
import com.intellij.openapi.options.ex.Settings;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
|
||||
import com.intellij.openapi.ui.VerticalFlowLayout;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.ui.JBColor;
|
||||
import com.intellij.ui.ClickListener;
|
||||
import com.intellij.ui.TooltipWithClickableLinks;
|
||||
import com.intellij.ui.UI;
|
||||
import com.intellij.ui.components.JBLabel;
|
||||
import com.intellij.ui.components.JBPasswordField;
|
||||
import com.intellij.ui.components.JBRadioButton;
|
||||
import com.intellij.ui.components.JBTextField;
|
||||
import com.intellij.util.PlatformUtils;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.jetbrains.python.configuration.PyActiveSdkModuleConfigurable;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.FocusAdapter;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.*;
|
||||
|
||||
public class IpnbConfigurable implements SearchableConfigurable {
|
||||
private static final int DEFAULT_PADDING = 3;
|
||||
private JPanel myMainPanel;
|
||||
private JBTextField myFieldUrl;
|
||||
private TextFieldWithBrowseButton myWorkingDirField;
|
||||
private JBTextField myArgumentsField;
|
||||
private JPasswordField myPasswordField;
|
||||
private JBTextField myUsernameField;
|
||||
private JBLabel myWarningLabel;
|
||||
@NotNull private final Project myProject;
|
||||
private JBTextField myUrlField;
|
||||
private TextFieldWithBrowseButton myNotebookDirectoryField;
|
||||
private JBLabel myWarningIcon;
|
||||
private JPanel mySpecificNotebookSettingsPanel;
|
||||
private final Project myProject;
|
||||
|
||||
public IpnbConfigurable(@NotNull Project project) {
|
||||
myProject = project;
|
||||
myWarningLabel.setForeground(new JBColor(new Color(164, 145, 52), new Color(187, 181, 41)));
|
||||
|
||||
final FileChooserDescriptor fileChooserDescriptor = FileChooserDescriptorFactory.createSingleFolderDescriptor();
|
||||
myWorkingDirField.addBrowseFolderListener("Select Working Directory", null, myProject, fileChooserDescriptor);
|
||||
myFieldUrl.setText(IpnbSettings.getInstance(myProject).getURL());
|
||||
myFieldUrl.addFocusListener(createUrlProtocolValidationListener());
|
||||
myUsernameField.addFocusListener(createUrlProtocolValidationListener());
|
||||
myPasswordField.addFocusListener(createUrlProtocolValidationListener());
|
||||
myWorkingDirField.setText(IpnbSettings.getInstance(myProject).getWorkingDirectory());
|
||||
myArgumentsField.setText(IpnbSettings.getInstance(myProject).getArguments());
|
||||
myNotebookDirectoryField.addBrowseFolderListener("Select Working Directory", null, myProject, fileChooserDescriptor);
|
||||
|
||||
myUrlField.setText(IpnbSettings.getInstance(myProject).getURL());
|
||||
myUrlField.addFocusListener(createUrlProtocolValidationListener());
|
||||
|
||||
final String workingDirectory = IpnbSettings.getInstance(myProject).getWorkingDirectory();
|
||||
myNotebookDirectoryField.setText(workingDirectory.isEmpty() ? myProject.getBasePath() : workingDirectory);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -46,24 +58,27 @@ public class IpnbConfigurable implements SearchableConfigurable {
|
||||
return new FocusAdapter() {
|
||||
@Override
|
||||
public void focusLost(FocusEvent e) {
|
||||
setWarningLabelText();
|
||||
setWarningLabelIcon(IpnbSettings.getInstance(myProject).isRemote());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void setWarningLabelText() {
|
||||
final boolean isRemote = myPasswordField.getPassword().length > 0;
|
||||
final String url = myFieldUrl.getText();
|
||||
if (isRemote && !url.startsWith("https")) {
|
||||
myWarningLabel.setText("Only HTTPS urls are supported in remote notebooks");
|
||||
return;
|
||||
}
|
||||
if (!isRemote && url.startsWith("https")) {
|
||||
myWarningLabel.setText("Only HTTP urls are supported in local notebooks");
|
||||
private void setWarningLabelIcon(boolean isRemote) {
|
||||
if (myUrlField == null) return;
|
||||
final String url = myUrlField.getText();
|
||||
if (isRemote && !url.startsWith("https") || !isRemote && url.startsWith("https") ) {
|
||||
Dimension oldPreferredSize = myWarningIcon.getPreferredSize();
|
||||
myWarningIcon.setIcon(AllIcons.General.BalloonWarning);
|
||||
myWarningIcon.setPreferredSize(oldPreferredSize);
|
||||
myWarningIcon.setMinimumSize(oldPreferredSize);
|
||||
myWarningIcon.revalidate();
|
||||
String message = isRemote ? "Use HTTPS for remote notebooks" : "Use HTTP for local notebooks";
|
||||
IdeTooltipManager.getInstance().setCustomTooltip(myWarningIcon, new TooltipWithClickableLinks.ForBrowser(myWarningIcon, message));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
myWarningLabel.setText("");
|
||||
myWarningIcon.setIcon(AllIcons.Nodes.EmptyNode);
|
||||
}
|
||||
|
||||
@Nls
|
||||
@@ -86,55 +101,39 @@ public class IpnbConfigurable implements SearchableConfigurable {
|
||||
public boolean isModified() {
|
||||
final String oldUrl = IpnbSettings.getInstance(myProject).getURL();
|
||||
final String oldWorkingDirectory = IpnbSettings.getInstance(myProject).getWorkingDirectory();
|
||||
final String oldArguments = StringUtil.notNullize(IpnbSettings.getInstance(myProject).getArguments());
|
||||
|
||||
final String url = StringUtil.trimEnd(StringUtil.notNullize(myFieldUrl.getText()), "/");
|
||||
final String workingDirectory = StringUtil.notNullize(myWorkingDirField.getText());
|
||||
final String arguments = StringUtil.notNullize(myArgumentsField.getText());
|
||||
final String url = StringUtil.trimEnd(StringUtil.notNullize(myUrlField.getText()), "/");
|
||||
final String workingDirectory = StringUtil.notNullize(myNotebookDirectoryField.getText());
|
||||
|
||||
return !url.equals(oldUrl) || !workingDirectory.equals(oldWorkingDirectory) || !arguments.equals(oldArguments)
|
||||
|| isCredentialsModified();
|
||||
}
|
||||
|
||||
public boolean isCredentialsModified() {
|
||||
final String oldUsername = StringUtil.notNullize(IpnbSettings.getInstance(myProject).getUsername());
|
||||
final String oldPassword = IpnbSettings.getInstance(myProject).getPassword(myProject.getLocationHash());
|
||||
|
||||
final String username = StringUtil.notNullize(myUsernameField.getText());
|
||||
final String password = StringUtil.notNullize(String.valueOf(myPasswordField.getPassword()));
|
||||
|
||||
return !oldUsername.equals(username) || !oldPassword.equals(password);
|
||||
final boolean isBaseModified = !url.equals(oldUrl) || !workingDirectory.equals(oldWorkingDirectory);
|
||||
|
||||
return isBaseModified || ((SettingsPanel)mySpecificNotebookSettingsPanel).isModified();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply() throws ConfigurationException {
|
||||
IpnbSettings.getInstance(myProject).setWorkingDirectory(myWorkingDirField.getText());
|
||||
IpnbSettings.getInstance(myProject).setArguments(myArgumentsField.getText());
|
||||
final IpnbSettings ipnbSettings = IpnbSettings.getInstance(myProject);
|
||||
final String newNotebookDir = myNotebookDirectoryField.getText();
|
||||
ipnbSettings.setWorkingDirectory(newNotebookDir.isEmpty() ? myProject.getBasePath() : newNotebookDir);
|
||||
|
||||
String url = StringUtil.notNullize(myFieldUrl.getText());
|
||||
url = StringUtil.trimEnd(url, "/");
|
||||
final boolean urlModified = !url.equals(IpnbSettings.getInstance(myProject).getURL());
|
||||
if (urlModified) {
|
||||
String url = StringUtil.trimEnd(StringUtil.notNullize(myUrlField.getText()), "/");
|
||||
if (!url.equals(ipnbSettings.getURL())) {
|
||||
IpnbConnectionManager.getInstance(myProject).shutdownKernels();
|
||||
IpnbSettings.getInstance(myProject).setURL(url);
|
||||
}
|
||||
|
||||
if (isCredentialsModified()) {
|
||||
IpnbConnectionManager.getInstance(myProject).shutdownKernels();
|
||||
IpnbSettings.getInstance(myProject).setUsername(myUsernameField.getText());
|
||||
IpnbSettings.getInstance(myProject).setPassword(String.valueOf(myPasswordField.getPassword()), myProject.getLocationHash());
|
||||
ipnbSettings.setURL(url);
|
||||
}
|
||||
|
||||
((SettingsPanel)mySpecificNotebookSettingsPanel).apply();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
myFieldUrl.setText(IpnbSettings.getInstance(myProject).getURL());
|
||||
myWorkingDirField.setText(IpnbSettings.getInstance(myProject).getWorkingDirectory());
|
||||
myArgumentsField.setText(IpnbSettings.getInstance(myProject).getArguments());
|
||||
myUsernameField.setText(IpnbSettings.getInstance(myProject).getUsername());
|
||||
myPasswordField.setText(IpnbSettings.getInstance(myProject).getPassword(myProject.getLocationHash()));
|
||||
myUrlField.setText(IpnbSettings.getInstance(myProject).getURL());
|
||||
final String workingDirectory = IpnbSettings.getInstance(myProject).getWorkingDirectory();
|
||||
myNotebookDirectoryField.setText(workingDirectory.isEmpty() ? myProject.getBasePath() : workingDirectory);
|
||||
|
||||
((SettingsPanel)mySpecificNotebookSettingsPanel).reset();
|
||||
|
||||
setWarningLabelText();
|
||||
setWarningLabelIcon(IpnbSettings.getInstance(myProject).isRemote());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -142,5 +141,362 @@ public class IpnbConfigurable implements SearchableConfigurable {
|
||||
public String getId() {
|
||||
return "IpnbConfigurable";
|
||||
}
|
||||
|
||||
private void createUIComponents() {
|
||||
// TODO: remove this hack
|
||||
int gap = SystemInfo.isWindows ? 1 : 2;
|
||||
mySpecificNotebookSettingsPanel = PlatformUtils.isPyCharmPro() ? new SettingsPanelPro() : new LocalSettingsPanel(true, 0, gap);
|
||||
}
|
||||
|
||||
private abstract static class SettingsPanel extends JPanel {
|
||||
public abstract boolean isModified();
|
||||
|
||||
public abstract void apply();
|
||||
|
||||
public abstract void reset();
|
||||
}
|
||||
|
||||
private class SettingsPanelPro extends SettingsPanel {
|
||||
private final JBRadioButton myLocal;
|
||||
private final JBRadioButton myRemote;
|
||||
private final RemoteSettingsPanel myRemoteSettingsPanel;
|
||||
private final LocalSettingsPanel myLocalSettingsPanel;
|
||||
|
||||
public SettingsPanelPro() {
|
||||
final boolean isRemote = IpnbSettings.getInstance(myProject).isRemote();
|
||||
|
||||
myLocal = createModeRadioButton("Local");
|
||||
myLocal.addItemListener(createRadioButtonListener(myLocal));
|
||||
|
||||
myRemote = createModeRadioButton("Remote");
|
||||
|
||||
myRemoteSettingsPanel = new RemoteSettingsPanel(isRemote);
|
||||
myLocalSettingsPanel = new LocalSettingsPanel(!isRemote, DEFAULT_PADDING, 1);
|
||||
|
||||
final ButtonGroup group = new ButtonGroup();
|
||||
myLocal.setSelected(!isRemote);
|
||||
myRemote.setSelected(isRemote);
|
||||
group.add(myLocal);
|
||||
group.add(myRemote);
|
||||
|
||||
final JPanel localPanel = new JPanel(new BorderLayout(10, 1));
|
||||
localPanel.add(myLocal, BorderLayout.NORTH);
|
||||
localPanel.add(myLocalSettingsPanel, BorderLayout.CENTER);
|
||||
|
||||
final JPanel remotePanel = new JPanel(new BorderLayout(10, 1));
|
||||
remotePanel.add(myRemote, BorderLayout.NORTH);
|
||||
remotePanel.add(myRemoteSettingsPanel, BorderLayout.CENTER);
|
||||
|
||||
setLayout(new VerticalFlowLayout(VerticalFlowLayout.MIDDLE, 0, 1, true, false));
|
||||
add(localPanel);
|
||||
add(remotePanel);
|
||||
|
||||
setWarningLabelIcon(isRemote);
|
||||
}
|
||||
|
||||
public boolean isModified() {
|
||||
final boolean wasRemote = IpnbSettings.getInstance(myProject).isRemote();
|
||||
final boolean isRemote = myRemote.isSelected();
|
||||
|
||||
if (wasRemote != isRemote) return true;
|
||||
|
||||
if (wasRemote) {
|
||||
return myRemoteSettingsPanel.isModified();
|
||||
}
|
||||
else {
|
||||
return myLocalSettingsPanel.isModified();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply() {
|
||||
final boolean isRemote = myRemote.isSelected();
|
||||
final boolean wasRemote = IpnbSettings.getInstance(myProject).isRemote();
|
||||
|
||||
if (isRemote != wasRemote) {
|
||||
IpnbConnectionManager.getInstance(myProject).shutdownKernels();
|
||||
IpnbSettings.getInstance(myProject).setRemote(isRemote);
|
||||
}
|
||||
|
||||
if (isRemote) {
|
||||
myRemoteSettingsPanel.apply();
|
||||
}
|
||||
else {
|
||||
myLocalSettingsPanel.apply();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
final boolean isRemote = IpnbSettings.getInstance(myProject).isRemote();
|
||||
myRemote.setSelected(isRemote);
|
||||
myLocal.setSelected(!isRemote);
|
||||
|
||||
if (isRemote) {
|
||||
myRemoteSettingsPanel.reset();
|
||||
}
|
||||
else {
|
||||
myLocalSettingsPanel.reset();
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private ItemListener createRadioButtonListener(@NotNull JBRadioButton local) {
|
||||
return new ItemListener() {
|
||||
@Override
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
if (local.isSelected()) {
|
||||
myLocalSettingsPanel.enablePanel();
|
||||
myRemoteSettingsPanel.disablePanel();
|
||||
setWarningLabelIcon(false);
|
||||
}
|
||||
else {
|
||||
myLocalSettingsPanel.disablePanel();
|
||||
myRemoteSettingsPanel.enablePanel();
|
||||
setWarningLabelIcon(true);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static JBRadioButton createModeRadioButton(@NotNull String text) {
|
||||
final JBRadioButton local = new JBRadioButton(text);
|
||||
local.setFocusable(false);
|
||||
local.setBorder(null);
|
||||
return local;
|
||||
}
|
||||
|
||||
private class LocalSettingsPanel extends SettingsPanel {
|
||||
private static final String PARAMETERS_TEXT = "Additional options:";
|
||||
private static final String DEFAULT_PARAMETERS_TEXT = "for example: --profile=nbserver";
|
||||
private JBTextField myAdditionalOptions;
|
||||
private final JLabel myParametersLabel;
|
||||
|
||||
public LocalSettingsPanel(boolean enabled, int leftPadding, int gap) {
|
||||
myParametersLabel = new JLabel(PARAMETERS_TEXT);
|
||||
myAdditionalOptions = new JBTextField();
|
||||
myAdditionalOptions.addFocusListener(createInitialTextFocusAdapter(myAdditionalOptions, DEFAULT_PARAMETERS_TEXT));
|
||||
initFields();
|
||||
|
||||
setLayout(new MigLayout("insets 0", leftPadding + "unrel[]" + gap + "unrel[grow]", "[][]"));
|
||||
add(myParametersLabel);
|
||||
add(myAdditionalOptions, "growx");
|
||||
if (enabled) {
|
||||
enablePanel();
|
||||
}
|
||||
else {
|
||||
disablePanel();
|
||||
}
|
||||
}
|
||||
|
||||
public void enablePanel() {
|
||||
myParametersLabel.setEnabled(true);
|
||||
myParametersLabel.setForeground(UIUtil.getActiveTextColor());
|
||||
myAdditionalOptions.setEnabled(true);
|
||||
}
|
||||
|
||||
public void disablePanel() {
|
||||
myParametersLabel.setEnabled(false);
|
||||
myParametersLabel.setForeground(UIUtil.getInactiveTextColor());
|
||||
myAdditionalOptions.setEnabled(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply() {
|
||||
final String parameters = myAdditionalOptions.getText();
|
||||
if (!parameters.equals(DEFAULT_PARAMETERS_TEXT)) {
|
||||
IpnbSettings.getInstance(myProject).setArguments(parameters);
|
||||
}
|
||||
else {
|
||||
IpnbSettings.getInstance(myProject).setArguments("");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
initFields();
|
||||
}
|
||||
|
||||
private void initFields() {
|
||||
final String arguments = IpnbSettings.getInstance(myProject).getArguments();
|
||||
setInitialText(myAdditionalOptions, arguments, DEFAULT_PARAMETERS_TEXT);
|
||||
}
|
||||
|
||||
public boolean isModified() {
|
||||
final IpnbSettings ipnbSettings = IpnbSettings.getInstance(myProject);
|
||||
final String arguments = ipnbSettings.getArguments();
|
||||
final String text = StringUtil.trim(StringUtil.notNullize(myAdditionalOptions.getText()));
|
||||
|
||||
return !text.equals(arguments);
|
||||
}
|
||||
}
|
||||
|
||||
private class RemoteSettingsPanel extends SettingsPanel {
|
||||
private static final String DEFAULT_USERNAME_TEXT = "Leave empty for a single-user notebook";
|
||||
|
||||
private JBTextField myUsernameField;
|
||||
private JBPasswordField myPasswordField;
|
||||
private JLabel myInterpreterSetupLinkLabel;
|
||||
private JBLabel myPasswordLabel;
|
||||
private JBLabel myUsernameLabel;
|
||||
private boolean myIsEnabled;
|
||||
|
||||
|
||||
public RemoteSettingsPanel(boolean enabled) {
|
||||
myIsEnabled = enabled;
|
||||
myInterpreterSetupLinkLabel = new JLabel("Configure remote interpreter");
|
||||
myInterpreterSetupLinkLabel.setForeground(UI.getColor("link.foreground"));
|
||||
myInterpreterSetupLinkLabel.setCursor(new Cursor(Cursor.HAND_CURSOR));
|
||||
createNavigateToInterpreterSettingsListener().installOn(myInterpreterSetupLinkLabel);
|
||||
|
||||
|
||||
setLayout(new MigLayout("insets 0", DEFAULT_PADDING + "unrel[]5unrel[grow]", "[][][]"));
|
||||
myUsernameLabel = new JBLabel("Username:");
|
||||
myUsernameField = new JBTextField();
|
||||
myUsernameField.addFocusListener(createInitialTextFocusAdapter(myUsernameField, DEFAULT_USERNAME_TEXT));
|
||||
setInitialText(myUsernameField, IpnbSettings.getInstance(myProject).getUsername(), DEFAULT_USERNAME_TEXT);
|
||||
myPasswordLabel = new JBLabel("Password:");
|
||||
myPasswordField = new JBPasswordField();
|
||||
|
||||
|
||||
add(myUsernameLabel);
|
||||
add(myUsernameField, "cell 1 0, growx, wrap");
|
||||
add(myPasswordLabel);
|
||||
add(myPasswordField, "cell 1 1, growx, wrap");
|
||||
add(myInterpreterSetupLinkLabel, "cell 1 2, align right");
|
||||
|
||||
if (myIsEnabled) {
|
||||
enablePanel();
|
||||
}
|
||||
else {
|
||||
disablePanel();
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private ClickListener createNavigateToInterpreterSettingsListener() {
|
||||
return new ClickListener() {
|
||||
@Override
|
||||
public boolean onClick(@NotNull MouseEvent event, int clickCount) {
|
||||
if (myIsEnabled) {
|
||||
final Settings settings = Settings.KEY.getData(DataManager.getInstance().getDataContext(RemoteSettingsPanel.this));
|
||||
if (settings != null) {
|
||||
settings.select(settings.find(PyActiveSdkModuleConfigurable.class.getName()));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public void enablePanel() {
|
||||
myIsEnabled = true;
|
||||
myUsernameField.setEnabled(true);
|
||||
myUsernameLabel.setEnabled(true);
|
||||
myUsernameLabel.setForeground(UIUtil.getActiveTextColor());
|
||||
if (DEFAULT_USERNAME_TEXT.equals(myUsernameField.getText())) {
|
||||
myUsernameField.setForeground(UIUtil.getInactiveTextColor());
|
||||
}
|
||||
|
||||
myPasswordField.setEnabled(true);
|
||||
myPasswordLabel.setEnabled(true);
|
||||
myPasswordLabel.setForeground(UIUtil.getActiveTextColor());
|
||||
|
||||
myInterpreterSetupLinkLabel.setEnabled(true);
|
||||
myInterpreterSetupLinkLabel.setForeground(UI.getColor("link.foreground"));
|
||||
myInterpreterSetupLinkLabel.setCursor(new Cursor(Cursor.HAND_CURSOR));
|
||||
}
|
||||
|
||||
public void disablePanel() {
|
||||
myIsEnabled = false;
|
||||
myUsernameField.setEnabled(false);
|
||||
myUsernameLabel.setEnabled(false);
|
||||
myUsernameLabel.setForeground(UIUtil.getInactiveTextColor());
|
||||
|
||||
myPasswordField.setEnabled(false);
|
||||
myPasswordLabel.setEnabled(false);
|
||||
myPasswordLabel.setForeground(UIUtil.getInactiveTextColor());
|
||||
|
||||
myInterpreterSetupLinkLabel.setEnabled(false);
|
||||
myInterpreterSetupLinkLabel.setForeground(UIUtil.getInactiveTextColor());
|
||||
myInterpreterSetupLinkLabel.setCursor(Cursor.getDefaultCursor());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply() {
|
||||
final IpnbSettings ipnbSettings = IpnbSettings.getInstance(myProject);
|
||||
|
||||
final String oldUsername = ipnbSettings.getUsername();
|
||||
final String oldPassword = ipnbSettings.getPassword(myProject.getLocationHash());
|
||||
|
||||
final String newUsername = myUsernameField.getText().equals(DEFAULT_USERNAME_TEXT) ? "" : myUsernameField.getText();
|
||||
final String newPassword = String.valueOf(myPasswordField.getPassword());
|
||||
|
||||
if (!oldUsername.equals(newUsername) || !oldPassword.equals(newPassword)) {
|
||||
IpnbConnectionManager.getInstance(myProject).shutdownKernels();
|
||||
ipnbSettings.setUsername(newUsername);
|
||||
ipnbSettings.setPassword(newPassword, myProject.getLocationHash());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
final IpnbSettings ipnbSettings = IpnbSettings.getInstance(myProject);
|
||||
|
||||
final String savedUsername = ipnbSettings.getUsername();
|
||||
setInitialText(myUsernameField, savedUsername, DEFAULT_USERNAME_TEXT);
|
||||
|
||||
final String savedPassword = ipnbSettings.getPassword(myProject.getLocationHash());
|
||||
myPasswordField.setText(savedPassword);
|
||||
}
|
||||
|
||||
public boolean isModified() {
|
||||
final IpnbSettings ipnbSettings = IpnbSettings.getInstance(myProject);
|
||||
final String oldUsername = ipnbSettings.getUsername();
|
||||
final String oldPassword = ipnbSettings.getPassword(myProject.getLocationHash());
|
||||
|
||||
final String newPassword = String.valueOf(myPasswordField.getPassword());
|
||||
final String newUsername = myUsernameField.getText();
|
||||
|
||||
return !oldPassword.equals(newPassword) || !oldUsername.equals(newUsername);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static FocusAdapter createInitialTextFocusAdapter(@NotNull JBTextField field, @NotNull String initialText) {
|
||||
return new FocusAdapter() {
|
||||
@Override
|
||||
public void focusGained(FocusEvent e) {
|
||||
if (field.getText().equals(initialText)) {
|
||||
field.setForeground(UIUtil.getActiveTextColor());
|
||||
field.setText("");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void focusLost(FocusEvent e) {
|
||||
if (field.getText().isEmpty()) {
|
||||
field.setForeground(UIUtil.getInactiveTextColor());
|
||||
field.setText(initialText);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static void setInitialText(@NotNull JBTextField field,
|
||||
@NotNull String savedValue,
|
||||
@NotNull String defaultText) {
|
||||
if (savedValue.isEmpty()) {
|
||||
field.setForeground(UIUtil.getInactiveTextColor());
|
||||
field.setText(defaultText);
|
||||
}
|
||||
else {
|
||||
field.setForeground(UIUtil.getActiveTextColor());
|
||||
field.setText(savedValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -105,7 +105,7 @@ public final class IpnbConnectionManager implements ProjectComponent {
|
||||
@NotNull final String path) {
|
||||
final String url = getURL();
|
||||
if (connectToIpythonServer(codePanel, fileEditor, path, url)) return;
|
||||
final boolean isRemote = IpnbSettings.getInstance(myProject).isRemote(myProject.getLocationHash());
|
||||
final boolean isRemote = IpnbSettings.getInstance(myProject).isRemote();
|
||||
if (!isRemote) {
|
||||
ApplicationManager.getApplication().executeOnPooledThread(() -> {
|
||||
final boolean serverStarted = startIpythonServer(url, fileEditor);
|
||||
@@ -122,7 +122,7 @@ public final class IpnbConnectionManager implements ProjectComponent {
|
||||
@NotNull final String path,
|
||||
@NotNull final String url) {
|
||||
final IpnbSettings ipnbSettings = IpnbSettings.getInstance(myProject);
|
||||
final boolean isRemote = ipnbSettings.isRemote(myProject.getLocationHash());
|
||||
final boolean isRemote = ipnbSettings.isRemote();
|
||||
if (!isRemote) {
|
||||
if (myToken != null) return startConnection(codePanel, path, url, true);
|
||||
final Module module = ProjectFileIndex.SERVICE.getInstance(myProject).getModuleForFile(fileEditor.getVirtualFile());
|
||||
|
||||
@@ -19,6 +19,15 @@ public class IpnbSettings implements PersistentStateComponent<IpnbSettings> {
|
||||
private String myWorkingDirectory;
|
||||
private String myArguments = "";
|
||||
private String myUsername;
|
||||
private boolean myIsRemote;
|
||||
|
||||
public boolean isRemote() {
|
||||
return myIsRemote;
|
||||
}
|
||||
|
||||
public void setRemote(boolean remote) {
|
||||
myIsRemote = remote;
|
||||
}
|
||||
|
||||
public static IpnbSettings getInstance(@NotNull Project project) {
|
||||
return ServiceManager.getService(project, IpnbSettings.class);
|
||||
@@ -77,11 +86,6 @@ public class IpnbSettings implements PersistentStateComponent<IpnbSettings> {
|
||||
final String accountName = createAccountName(username, url, projectPathHash);
|
||||
PasswordSafe.getInstance().setPassword(IpnbSettings.class, accountName, password);
|
||||
}
|
||||
|
||||
public boolean isRemote(String locationHash) {
|
||||
final String password = getPassword(locationHash);
|
||||
return !password.isEmpty();
|
||||
}
|
||||
|
||||
private static String createAccountName(@NotNull String username, @NotNull String url, @NotNull String projectPath) {
|
||||
return IPNB_PASSWORD_KEY + url + username + projectPath;
|
||||
|
||||
@@ -94,7 +94,7 @@ public class IpnbConnection {
|
||||
myProject = project;
|
||||
myCookieManager = new CookieManager();
|
||||
CookieHandler.setDefault(myCookieManager);
|
||||
if (!IpnbSettings.getInstance(project).isRemote(project.getLocationHash())) {
|
||||
if (!IpnbSettings.getInstance(project).isRemote()) {
|
||||
if (!"http".equals(myURI.getScheme())) {
|
||||
throw new UnsupportedOperationException("Only http urls are supported for local notebooks");
|
||||
}
|
||||
@@ -103,7 +103,7 @@ public class IpnbConnection {
|
||||
throw new UnsupportedOperationException("Only https urls are supported for remote notebooks");
|
||||
}
|
||||
|
||||
if (IpnbSettings.getInstance(project).isRemote(project.getLocationHash())) {
|
||||
if (IpnbSettings.getInstance(project).isRemote()) {
|
||||
String loginUrl = getLoginUrl();
|
||||
initXSRF(myURI.toString() + loginUrl);
|
||||
myIsHubServer = isHubServer(loginUrl);
|
||||
|
||||
Reference in New Issue
Block a user