From 7ad6b7bcc6819f90d4e64da1031f8cd7b9818832 Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Tue, 19 Aug 2014 18:59:08 +0400 Subject: [PATCH] added "Learn Python" action to the Welcome screen --- python/edu/learn-python/learn-python.iml | 1 + .../resources/META-INF/plugin.xml | 5 + .../python/edu/actions/StudyNewProject.java | 34 ++++ .../actions/GenerateProjectCallback.java | 159 ++++++++++++++++++ .../actions/ProjectSpecificAction.java | 8 +- .../actions/PyCharmNewProjectStep.java | 126 +------------- 6 files changed, 207 insertions(+), 126 deletions(-) create mode 100644 python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyNewProject.java create mode 100644 python/ide/src/com/jetbrains/python/newProject/actions/GenerateProjectCallback.java diff --git a/python/edu/learn-python/learn-python.iml b/python/edu/learn-python/learn-python.iml index bd539d1e2147..613d67594a7a 100644 --- a/python/edu/learn-python/learn-python.iml +++ b/python/edu/learn-python/learn-python.iml @@ -15,6 +15,7 @@ + diff --git a/python/edu/learn-python/resources/META-INF/plugin.xml b/python/edu/learn-python/resources/META-INF/plugin.xml index be379436157f..ed59420570ba 100644 --- a/python/edu/learn-python/resources/META-INF/plugin.xml +++ b/python/edu/learn-python/resources/META-INF/plugin.xml @@ -59,6 +59,11 @@ description="show hint"> + + + + + diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyNewProject.java b/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyNewProject.java new file mode 100644 index 000000000000..665cfd7a5dd3 --- /dev/null +++ b/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyNewProject.java @@ -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); + } + +} diff --git a/python/ide/src/com/jetbrains/python/newProject/actions/GenerateProjectCallback.java b/python/ide/src/com/jetbrains/python/newProject/actions/GenerateProjectCallback.java new file mode 100644 index 000000000000..2aa9a391512f --- /dev/null +++ b/python/ide/src/com/jetbrains/python/newProject/actions/GenerateProjectCallback.java @@ -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 { + 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() { + @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 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() { + 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); + } +} diff --git a/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificAction.java b/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificAction.java index 4397a090b253..85cf6d118d34 100644 --- a/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificAction.java +++ b/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificAction.java @@ -29,7 +29,13 @@ public class ProjectSpecificAction extends DefaultActionGroup implements DumbAwa public ProjectSpecificAction(@NotNull final NullableConsumer callback, @NotNull final DirectoryProjectGenerator projectGenerator) { - super(projectGenerator.getName(), true); + this(callback, projectGenerator, projectGenerator.getName()); + } + + public ProjectSpecificAction(@NotNull final NullableConsumer callback, + @NotNull final DirectoryProjectGenerator projectGenerator, + @NotNull final String name) { + super(name, true); getTemplatePresentation().setIcon(projectGenerator.getLogo()); mySettings = new ProjectSpecificSettingsStep(projectGenerator, callback); add(mySettings); diff --git a/python/ide/src/com/jetbrains/python/newProject/actions/PyCharmNewProjectStep.java b/python/ide/src/com/jetbrains/python/newProject/actions/PyCharmNewProjectStep.java index 4f9f1074df68..b15c20606ded 100644 --- a/python/ide/src/com/jetbrains/python/newProject/actions/PyCharmNewProjectStep.java +++ b/python/ide/src/com/jetbrains/python/newProject/actions/PyCharmNewProjectStep.java @@ -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 callback = new NullableConsumer() { - @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() { - @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 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() { - 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 callback = new GenerateProjectCallback(runnable); final ProjectSpecificAction action = new ProjectSpecificAction(callback, new PythonBaseProjectGenerator()); add(action); -- 2.32.0