added "Learn Python" action to the Welcome screen

This commit is contained in:
Ekaterina Tuzova
2014-08-19 18:59:08 +04:00
parent 401e1b1882
commit 7ad6b7bcc6
6 changed files with 207 additions and 126 deletions
+1
View File
@@ -15,6 +15,7 @@
<orderEntry type="module" module-name="lang-impl" />
<orderEntry type="library" name="gson" level="project" />
<orderEntry type="library" name="JUnit4" level="project" />
<orderEntry type="module" module-name="python-ide-community" />
</component>
</module>
@@ -59,6 +59,11 @@
description="show hint">
<add-to-group group-id="MainToolBar" anchor="last"/>
</action>
<action id="WelcomeScreen.LearnPython" class="com.jetbrains.python.edu.actions.StudyNewProject" icon="StudyIcons.EducationalProjectType">
<add-to-group group-id="WelcomeScreen.QuickStart" anchor="first"/>
</action>
</actions>
<extensions defaultExtensionNs="com.intellij">
@@ -0,0 +1,34 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jetbrains.python.edu.actions;
import com.jetbrains.python.edu.StudyDirectoryProjectGenerator;
import com.jetbrains.python.newProject.actions.GenerateProjectCallback;
import com.jetbrains.python.newProject.actions.ProjectSpecificAction;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class StudyNewProject extends ProjectSpecificAction {
public StudyNewProject(@NotNull final String name, @Nullable final Runnable runnable) {
super(new GenerateProjectCallback(runnable), new StudyDirectoryProjectGenerator(), name);
}
public StudyNewProject() {
this("Learn Python", null);
}
}
@@ -0,0 +1,159 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jetbrains.python.newProject.actions;
import com.intellij.ide.GeneralSettings;
import com.intellij.ide.util.projectWizard.WebProjectTemplate;
import com.intellij.internal.statistic.UsageTrigger;
import com.intellij.internal.statistic.beans.ConvertUsagesUtil;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.projectRoots.ProjectJdkTable;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.SdkAdditionalData;
import com.intellij.openapi.projectRoots.impl.SdkConfigurationUtil;
import com.intellij.openapi.roots.ui.configuration.projectRoot.ProjectSdksModel;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.platform.DirectoryProjectGenerator;
import com.intellij.platform.PlatformProjectOpenProcessor;
import com.intellij.projectImport.ProjectOpenedCallback;
import com.intellij.util.NullableConsumer;
import com.jetbrains.python.configuration.PyConfigurableInterpreterList;
import com.jetbrains.python.newProject.PyNewProjectSettings;
import com.jetbrains.python.newProject.PythonProjectGenerator;
import com.jetbrains.python.sdk.PyDetectedSdk;
import com.jetbrains.python.sdk.PySdkService;
import com.jetbrains.python.sdk.PythonSdkAdditionalData;
import com.jetbrains.python.sdk.PythonSdkType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.util.List;
public class GenerateProjectCallback implements NullableConsumer<AbstractProjectSettingsStep> {
private static final Logger LOG = Logger.getInstance(GenerateProjectCallback.class);
@Nullable private final Runnable myRunnable;
public GenerateProjectCallback(@Nullable final Runnable runnable) {
myRunnable = runnable;
}
@Override
public void consume(@Nullable AbstractProjectSettingsStep settingsStep) {
if (myRunnable != null) {
myRunnable.run();
}
if (settingsStep == null) return;
Sdk sdk = settingsStep.getSdk();
final Project project = ProjectManager.getInstance().getDefaultProject();
final ProjectSdksModel model = PyConfigurableInterpreterList.getInstance(project).getModel();
if (sdk instanceof PyDetectedSdk) {
final String name = sdk.getName();
VirtualFile sdkHome = ApplicationManager.getApplication().runWriteAction(new Computable<VirtualFile>() {
@Override
public VirtualFile compute() {
return LocalFileSystem.getInstance().refreshAndFindFileByPath(name);
}
});
PySdkService.getInstance().solidifySdk(sdk);
sdk = SdkConfigurationUtil.setupSdk(ProjectJdkTable.getInstance().getAllJdks(), sdkHome, PythonSdkType.getInstance(), true, null,
null);
model.addSdk(sdk);
settingsStep.setSdk(sdk);
try {
model.apply();
}
catch (ConfigurationException exception) {
LOG.error("Error adding detected python interpreter " + exception.getMessage());
}
}
Project newProject = generateProject(project, settingsStep);
if (newProject != null) {
SdkConfigurationUtil.setDirectoryProjectSdk(newProject, sdk);
final List<Sdk> sdks = PythonSdkType.getAllSdks();
for (Sdk s : sdks) {
final SdkAdditionalData additionalData = s.getSdkAdditionalData();
if (additionalData instanceof PythonSdkAdditionalData) {
((PythonSdkAdditionalData)additionalData).reassociateWithCreatedProject(newProject);
}
}
}
}
@Nullable
private Project generateProject(@NotNull final Project project, @NotNull final AbstractProjectSettingsStep settings) {
final DirectoryProjectGenerator generator = settings.getProjectGenerator();
final File location = new File(settings.getProjectLocation());
if (!location.exists() && !location.mkdirs()) {
Messages.showErrorDialog(project, "Cannot create directory '" + location + "'", "Create Project");
return null;
}
final VirtualFile baseDir = ApplicationManager.getApplication().runWriteAction(new Computable<VirtualFile>() {
public VirtualFile compute() {
return LocalFileSystem.getInstance().refreshAndFindFileByIoFile(location);
}
});
LOG.assertTrue(baseDir != null, "Couldn't find '" + location + "' in VFS");
baseDir.refresh(false, true);
if (baseDir.getChildren().length > 0) {
int rc = Messages.showYesNoDialog(project,
"The directory '" + location +
"' is not empty. Would you like to create a project from existing sources instead?",
"Create New Project", Messages.getQuestionIcon());
if (rc == Messages.YES) {
return PlatformProjectOpenProcessor.getInstance().doOpenProject(baseDir, null, false);
}
}
String generatorName = generator == null ? "empty" : ConvertUsagesUtil.ensureProperKey(generator.getName());
UsageTrigger.trigger("NewDirectoryProjectAction." + generatorName);
GeneralSettings.getInstance().setLastProjectCreationLocation(location.getParent());
return PlatformProjectOpenProcessor.doOpenProject(baseDir, null, false, -1, new ProjectOpenedCallback() {
@Override
public void projectOpened(Project project, Module module) {
if (generator != null) {
Object projectSettings = null;
if (generator instanceof PythonProjectGenerator) {
projectSettings = ((PythonProjectGenerator)generator).getProjectSettings();
}
else if (generator instanceof WebProjectTemplate) {
projectSettings = ((WebProjectTemplate)generator).getPeer().getSettings();
}
if (projectSettings instanceof PyNewProjectSettings) {
((PyNewProjectSettings)projectSettings).setSdk(settings.getSdk());
((PyNewProjectSettings)projectSettings).setInstallFramework(settings.installFramework());
}
//noinspection unchecked
generator.generateProject(project, baseDir, projectSettings, module);
}
}
}, false);
}
}
@@ -29,7 +29,13 @@ public class ProjectSpecificAction extends DefaultActionGroup implements DumbAwa
public ProjectSpecificAction(@NotNull final NullableConsumer<AbstractProjectSettingsStep> callback,
@NotNull final DirectoryProjectGenerator projectGenerator) {
super(projectGenerator.getName(), true);
this(callback, projectGenerator, projectGenerator.getName());
}
public ProjectSpecificAction(@NotNull final NullableConsumer<AbstractProjectSettingsStep> callback,
@NotNull final DirectoryProjectGenerator projectGenerator,
@NotNull final String name) {
super(name, true);
getTemplatePresentation().setIcon(projectGenerator.getLogo());
mySettings = new ProjectSpecificSettingsStep(projectGenerator, callback);
add(mySettings);
@@ -16,151 +16,27 @@
package com.jetbrains.python.newProject.actions;
import com.google.common.collect.Lists;
import com.intellij.ide.GeneralSettings;
import com.intellij.ide.util.projectWizard.WebProjectTemplate;
import com.intellij.internal.statistic.UsageTrigger;
import com.intellij.internal.statistic.beans.ConvertUsagesUtil;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.projectRoots.ProjectJdkTable;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.SdkAdditionalData;
import com.intellij.openapi.projectRoots.impl.SdkConfigurationUtil;
import com.intellij.openapi.roots.ui.configuration.projectRoot.ProjectSdksModel;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.platform.DirectoryProjectGenerator;
import com.intellij.platform.PlatformProjectOpenProcessor;
import com.intellij.projectImport.ProjectOpenedCallback;
import com.intellij.util.NullableConsumer;
import com.jetbrains.python.configuration.PyConfigurableInterpreterList;
import com.jetbrains.python.newProject.PyFrameworkProjectGenerator;
import com.jetbrains.python.newProject.PyNewProjectSettings;
import com.jetbrains.python.newProject.PythonBaseProjectGenerator;
import com.jetbrains.python.newProject.PythonProjectGenerator;
import com.jetbrains.python.sdk.PyDetectedSdk;
import com.jetbrains.python.sdk.PySdkService;
import com.jetbrains.python.sdk.PythonSdkAdditionalData;
import com.jetbrains.python.sdk.PythonSdkType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
public class PyCharmNewProjectStep extends DefaultActionGroup implements DumbAware {
private static final Logger LOG = Logger.getInstance(PyCharmNewProjectStep.class);
public PyCharmNewProjectStep(@NotNull final String name, @Nullable final Runnable runnable) {
super(name, true);
final NullableConsumer<AbstractProjectSettingsStep> callback = new NullableConsumer<AbstractProjectSettingsStep>() {
@Override
public void consume(@Nullable AbstractProjectSettingsStep settingsStep) {
if (runnable != null)
runnable.run();
if (settingsStep == null) return;
Sdk sdk = settingsStep.getSdk();
final Project project = ProjectManager.getInstance().getDefaultProject();
final ProjectSdksModel model = PyConfigurableInterpreterList.getInstance(project).getModel();
if (sdk instanceof PyDetectedSdk) {
final String name = sdk.getName();
VirtualFile sdkHome = ApplicationManager.getApplication().runWriteAction(new Computable<VirtualFile>() {
@Override
public VirtualFile compute() {
return LocalFileSystem.getInstance().refreshAndFindFileByPath(name);
}
});
PySdkService.getInstance().solidifySdk(sdk);
sdk = SdkConfigurationUtil.setupSdk(ProjectJdkTable.getInstance().getAllJdks(), sdkHome, PythonSdkType.getInstance(), true, null,
null);
model.addSdk(sdk);
settingsStep.setSdk(sdk);
try {
model.apply();
}
catch (ConfigurationException exception) {
LOG.error("Error adding detected python interpreter " + exception.getMessage());
}
}
Project newProject = generateProject(project, settingsStep);
if (newProject != null) {
SdkConfigurationUtil.setDirectoryProjectSdk(newProject, sdk);
final List<Sdk> sdks = PythonSdkType.getAllSdks();
for (Sdk s : sdks) {
final SdkAdditionalData additionalData = s.getSdkAdditionalData();
if (additionalData instanceof PythonSdkAdditionalData) {
((PythonSdkAdditionalData)additionalData).reassociateWithCreatedProject(newProject);
}
}
}
}
@Nullable
private Project generateProject(@NotNull final Project project, @NotNull final AbstractProjectSettingsStep settings) {
final DirectoryProjectGenerator generator = settings.getProjectGenerator();
final File location = new File(settings.getProjectLocation());
if (!location.exists() && !location.mkdirs()) {
Messages.showErrorDialog(project, "Cannot create directory '" + location + "'", "Create Project");
return null;
}
final VirtualFile baseDir = ApplicationManager.getApplication().runWriteAction(new Computable<VirtualFile>() {
public VirtualFile compute() {
return LocalFileSystem.getInstance().refreshAndFindFileByIoFile(location);
}
});
LOG.assertTrue(baseDir != null, "Couldn't find '" + location + "' in VFS");
baseDir.refresh(false, true);
if (baseDir.getChildren().length > 0) {
int rc = Messages.showYesNoDialog(project,
"The directory '" + location +
"' is not empty. Would you like to create a project from existing sources instead?",
"Create New Project", Messages.getQuestionIcon());
if (rc == Messages.YES) {
return PlatformProjectOpenProcessor.getInstance().doOpenProject(baseDir, null, false);
}
}
String generatorName = generator == null ? "empty" : ConvertUsagesUtil.ensureProperKey(generator.getName());
UsageTrigger.trigger("NewDirectoryProjectAction." + generatorName);
GeneralSettings.getInstance().setLastProjectCreationLocation(location.getParent());
return PlatformProjectOpenProcessor.doOpenProject(baseDir, null, false, -1, new ProjectOpenedCallback() {
@Override
public void projectOpened(Project project, Module module) {
if (generator != null) {
Object projectSettings = null;
if (generator instanceof PythonProjectGenerator)
projectSettings = ((PythonProjectGenerator)generator).getProjectSettings();
else if (generator instanceof WebProjectTemplate) {
projectSettings = ((WebProjectTemplate)generator).getPeer().getSettings();
}
if (projectSettings instanceof PyNewProjectSettings) {
((PyNewProjectSettings)projectSettings).setSdk(settings.getSdk());
((PyNewProjectSettings)projectSettings).setInstallFramework(settings.installFramework());
}
//noinspection unchecked
generator.generateProject(project, baseDir, projectSettings, module);
}
}
}, false);
}
};
final NullableConsumer<AbstractProjectSettingsStep> callback = new GenerateProjectCallback(runnable);
final ProjectSpecificAction action = new ProjectSpecificAction(callback, new PythonBaseProjectGenerator());
add(action);