diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/pluginsAdvertisement/PluginAdvertiserService.kt b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/pluginsAdvertisement/PluginAdvertiserService.kt index 8bafbaa15dbe..de5b764be162 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/pluginsAdvertisement/PluginAdvertiserService.kt +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/pluginsAdvertisement/PluginAdvertiserService.kt @@ -79,7 +79,7 @@ sealed interface PluginAdvertiserService { @Suppress("HardCodedStringLiteral", "DialogTitleCapitalization") val pyCharmProfessional: SuggestedIde = SuggestedIde( - name = "PyCharm", + name = "PyCharm Pro", productCode = "PY", defaultDownloadUrl = "https://www.jetbrains.com/pycharm/download/", platformSpecificDownloadUrlTemplate = "https://www.jetbrains.com/pycharm/download/download-thanks.html?platform={type}", diff --git a/platform/platform-tests/testSrc/com/intellij/ide/plugins/advertiser/PluginsAdvertiserTest.kt b/platform/platform-tests/testSrc/com/intellij/ide/plugins/advertiser/PluginsAdvertiserTest.kt index f5b9415516fa..8347ee06a284 100644 --- a/platform/platform-tests/testSrc/com/intellij/ide/plugins/advertiser/PluginsAdvertiserTest.kt +++ b/platform/platform-tests/testSrc/com/intellij/ide/plugins/advertiser/PluginsAdvertiserTest.kt @@ -61,7 +61,7 @@ class PluginsAdvertiserTest { fun suggestedIdeInPyCharmCommunity() = runBlocking { preparePluginCache("*.js" to PluginData("JavaScript")) val suggestion = getSuggestionData(projectRule.project, "PC", "foo.js", PlainTextFileType.INSTANCE) - assertEquals(listOf("PyCharm"), suggestion!!.suggestedIdes.map { it.name }) + assertEquals(listOf("PyCharm Pro"), suggestion!!.suggestedIdes.map { it.name }) } @Test diff --git a/python/ide/customization.shared/BUILD.bazel b/python/ide/customization.shared/BUILD.bazel index f9a0b99b0f6b..c7b274bce458 100644 --- a/python/ide/customization.shared/BUILD.bazel +++ b/python/ide/customization.shared/BUILD.bazel @@ -9,11 +9,15 @@ jvm_resources( jvm_library( name = "customization.shared", + module_name = "intellij.pycharm.community.customization.shared", visibility = ["//visibility:public"], - srcs = glob([], allow_empty = True), + srcs = glob(["src/**/*.kt", "src/**/*.java", "src/**/*.form"], allow_empty = True), + deps = [ + "//python/ide/impl", + "//platform/platform-impl:ide-impl", + ], runtime_deps = [ ":customization.shared_resources", - "//python/ide/impl", "//python/ide/implTraining/intellij.pycharm.community.ide.implTraining:pycharm-community-ide-implTraining", "//platform/whatsNew", ] diff --git a/python/ide/customization.shared/intellij.pycharm.community.customization.shared.iml b/python/ide/customization.shared/intellij.pycharm.community.customization.shared.iml index 6be4b843f212..57f1d319c855 100644 --- a/python/ide/customization.shared/intellij.pycharm.community.customization.shared.iml +++ b/python/ide/customization.shared/intellij.pycharm.community.customization.shared.iml @@ -4,11 +4,13 @@ + - + + \ No newline at end of file diff --git a/python/ide/customization.shared/src/com/intellij/pycharm/community/customization/shared/djangoPromoFeatureList.kt b/python/ide/customization.shared/src/com/intellij/pycharm/community/customization/shared/djangoPromoFeatureList.kt new file mode 100644 index 000000000000..34d7bd58a831 --- /dev/null +++ b/python/ide/customization.shared/src/com/intellij/pycharm/community/customization/shared/djangoPromoFeatureList.kt @@ -0,0 +1,11 @@ +// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package com.intellij.pycharm.community.customization.shared // Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +import com.intellij.icons.AllIcons +import com.intellij.openapi.updateSettings.impl.pluginsAdvertisement.PromoFeatureListItem +import com.intellij.pycharm.community.ide.impl.PyCharmCommunityCustomizationBundle + +val djangoPromoFeatureList: List = listOf( + PromoFeatureListItem(AllIcons.Actions.ReformatCode, PyCharmCommunityCustomizationBundle.message("feature.django.code")), + PromoFeatureListItem(AllIcons.FileTypes.Html, PyCharmCommunityCustomizationBundle.message("feature.django.djangoTemplates")), + PromoFeatureListItem(AllIcons.General.Web, PyCharmCommunityCustomizationBundle.message("feature.django.endpoints")) +) \ No newline at end of file diff --git a/python/ide/customization.shared/src/com/intellij/pycharm/community/customization/shared/javaScriptPromoFeatureList.kt b/python/ide/customization.shared/src/com/intellij/pycharm/community/customization/shared/javaScriptPromoFeatureList.kt new file mode 100644 index 000000000000..ed27823d253e --- /dev/null +++ b/python/ide/customization.shared/src/com/intellij/pycharm/community/customization/shared/javaScriptPromoFeatureList.kt @@ -0,0 +1,12 @@ +// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package com.intellij.pycharm.community.customization.shared // Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +import com.intellij.icons.AllIcons +import com.intellij.openapi.updateSettings.impl.pluginsAdvertisement.FeaturePromoBundle +import com.intellij.openapi.updateSettings.impl.pluginsAdvertisement.PromoFeatureListItem + +val javaScriptPromoFeatureList: List = listOf( + PromoFeatureListItem(AllIcons.Actions.ReformatCode, FeaturePromoBundle.message("feature.javascript.code")), + PromoFeatureListItem(AllIcons.Actions.SuggestedRefactoringBulb, FeaturePromoBundle.message("feature.javascript.refactor")), + @Suppress("DialogTitleCapitalization") // Properly capitalized, React and Vue are names. + PromoFeatureListItem(AllIcons.FileTypes.UiForm, FeaturePromoBundle.message("feature.javascript.frameworks")) +) \ No newline at end of file diff --git a/python/ide/impl/intellij.pycharm.community.ide.impl.promotion/BUILD.bazel b/python/ide/impl/intellij.pycharm.community.ide.impl.promotion/BUILD.bazel index 3c7392afdbea..48886254c52f 100644 --- a/python/ide/impl/intellij.pycharm.community.ide.impl.promotion/BUILD.bazel +++ b/python/ide/impl/intellij.pycharm.community.ide.impl.promotion/BUILD.bazel @@ -25,6 +25,7 @@ jvm_library( "//platform/statistics", "@lib//:http-client", "//platform/core-ui", + "//python/ide/customization.shared", ], runtime_deps = [":pycharm-community-ide-impl-promotion_resources"] ) diff --git a/python/ide/impl/intellij.pycharm.community.ide.impl.promotion/intellij.pycharm.community.ide.impl.promotion.iml b/python/ide/impl/intellij.pycharm.community.ide.impl.promotion/intellij.pycharm.community.ide.impl.promotion.iml index 90e38dc9c626..621f1f51abe6 100644 --- a/python/ide/impl/intellij.pycharm.community.ide.impl.promotion/intellij.pycharm.community.ide.impl.promotion.iml +++ b/python/ide/impl/intellij.pycharm.community.ide.impl.promotion/intellij.pycharm.community.ide.impl.promotion.iml @@ -20,5 +20,6 @@ + \ No newline at end of file diff --git a/python/ide/impl/intellij.pycharm.community.ide.impl.promotion/src/com/intellij/pycharm/community/ide/impl/promotion/djangoProject.kt b/python/ide/impl/intellij.pycharm.community.ide.impl.promotion/src/com/intellij/pycharm/community/ide/impl/promotion/djangoProject.kt index ccc8e6dcc8d5..f953a49fcfe2 100644 --- a/python/ide/impl/intellij.pycharm.community.ide.impl.promotion/src/com/intellij/pycharm/community/ide/impl/promotion/djangoProject.kt +++ b/python/ide/impl/intellij.pycharm.community.ide.impl.promotion/src/com/intellij/pycharm/community/ide/impl/promotion/djangoProject.kt @@ -8,6 +8,7 @@ import com.intellij.openapi.updateSettings.impl.pluginsAdvertisement.PluginAdver import com.intellij.openapi.updateSettings.impl.pluginsAdvertisement.PromoFeaturePage import com.intellij.openapi.updateSettings.impl.pluginsAdvertisement.PromoPages import com.intellij.openapi.util.NlsSafe +import com.intellij.pycharm.community.customization.shared.djangoPromoFeatureList import com.intellij.pycharm.community.ide.impl.PyCharmCommunityCustomizationBundle import com.jetbrains.python.icons.PythonIcons import com.jetbrains.python.newProjectWizard.promotion.PromoProjectGenerator diff --git a/python/ide/impl/intellij.pycharm.community.ide.impl.promotion/src/com/intellij/pycharm/community/ide/impl/promotion/featurePages.kt b/python/ide/impl/intellij.pycharm.community.ide.impl.promotion/src/com/intellij/pycharm/community/ide/impl/promotion/featurePages.kt index d5468dcfdbcf..393469eb83af 100644 --- a/python/ide/impl/intellij.pycharm.community.ide.impl.promotion/src/com/intellij/pycharm/community/ide/impl/promotion/featurePages.kt +++ b/python/ide/impl/intellij.pycharm.community.ide.impl.promotion/src/com/intellij/pycharm/community/ide/impl/promotion/featurePages.kt @@ -4,13 +4,17 @@ package com.intellij.pycharm.community.ide.impl.promotion import com.intellij.icons.AllIcons import com.intellij.openapi.updateSettings.impl.pluginsAdvertisement.* import com.intellij.openapi.util.NlsContexts +import com.intellij.pycharm.community.customization.shared.djangoPromoFeatureList +import com.intellij.pycharm.community.customization.shared.javaScriptPromoFeatureList import com.intellij.pycharm.community.ide.impl.PyCharmCommunityCustomizationBundle import com.jetbrains.python.icons.PythonIcons import javax.swing.JComponent -private fun featurePage(@NlsContexts.Label title: String, items: List, - source: PromoEventSource, - topic: PromoTopic): JComponent { +private fun featurePage( + @NlsContexts.Label title: String, items: List, + source: PromoEventSource, + topic: PromoTopic, +): JComponent { val page = PromoFeaturePage( productIcon = PythonIcons.Python.Pycharm, suggestedIde = PluginAdvertiserService.pyCharmProfessional, @@ -39,7 +43,6 @@ internal fun databaseFeatures(source: PromoEventSource): JComponent = featurePag ) internal fun javascriptFeatures(source: PromoEventSource, promoTopic: PromoTopic): JComponent { - @Suppress("DialogTitleCapitalization") return featurePage( FeaturePromoBundle.message("feature.javascript.description.html", "https://www.jetbrains.com/help/pycharm/javascript-specific-guidelines.html"), @@ -59,7 +62,6 @@ internal fun djangoFeatures(source: PromoEventSource): JComponent { ) } - internal fun jupyterFeatures(source: PromoEventSource): JComponent { return featurePage( PyCharmCommunityCustomizationBundle.message("feature.jupyter.description.html", @@ -87,16 +89,4 @@ internal fun sshFeatures(source: PromoEventSource): JComponent { source, PromoTopic.RemoteSSH ) -} - -internal val djangoPromoFeatureList = listOf( - PromoFeatureListItem(AllIcons.Actions.ReformatCode, PyCharmCommunityCustomizationBundle.message("feature.django.code")), - PromoFeatureListItem(AllIcons.FileTypes.Html, PyCharmCommunityCustomizationBundle.message("feature.django.djangoTemplates")), - PromoFeatureListItem(AllIcons.General.Web, PyCharmCommunityCustomizationBundle.message("feature.django.endpoints")) -) - -internal val javaScriptPromoFeatureList = listOf( - PromoFeatureListItem(AllIcons.Actions.ReformatCode, FeaturePromoBundle.message("feature.javascript.code")), - PromoFeatureListItem(AllIcons.Actions.SuggestedRefactoringBulb, FeaturePromoBundle.message("feature.javascript.refactor")), - PromoFeatureListItem(AllIcons.FileTypes.UiForm, FeaturePromoBundle.message("feature.javascript.frameworks")) -) \ No newline at end of file +} \ No newline at end of file diff --git a/python/ide/impl/intellij.pycharm.community.ide.impl.promotion/src/com/intellij/pycharm/community/ide/impl/promotion/javaScriptProject.kt b/python/ide/impl/intellij.pycharm.community.ide.impl.promotion/src/com/intellij/pycharm/community/ide/impl/promotion/javaScriptProject.kt index c6a42934af2a..cae2a9ed0f14 100644 --- a/python/ide/impl/intellij.pycharm.community.ide.impl.promotion/src/com/intellij/pycharm/community/ide/impl/promotion/javaScriptProject.kt +++ b/python/ide/impl/intellij.pycharm.community.ide.impl.promotion/src/com/intellij/pycharm/community/ide/impl/promotion/javaScriptProject.kt @@ -8,6 +8,7 @@ import com.intellij.openapi.updateSettings.impl.pluginsAdvertisement.PluginAdver import com.intellij.openapi.updateSettings.impl.pluginsAdvertisement.PromoFeaturePage import com.intellij.openapi.updateSettings.impl.pluginsAdvertisement.PromoPages import com.intellij.openapi.util.NlsSafe +import com.intellij.pycharm.community.customization.shared.javaScriptPromoFeatureList import com.jetbrains.python.icons.PythonIcons import com.jetbrains.python.newProjectWizard.promotion.PromoProjectGenerator import javax.swing.Icon diff --git a/python/ide/impl/src/com/intellij/pycharm/community/ide/impl/newProjectWizard/impl/PyV3NewProjectStepAction.kt b/python/ide/impl/src/com/intellij/pycharm/community/ide/impl/newProjectWizard/impl/PyV3NewProjectStepAction.kt index 14ac16e4ad9a..6aa8afaddddb 100644 --- a/python/ide/impl/src/com/intellij/pycharm/community/ide/impl/newProjectWizard/impl/PyV3NewProjectStepAction.kt +++ b/python/ide/impl/src/com/intellij/pycharm/community/ide/impl/newProjectWizard/impl/PyV3NewProjectStepAction.kt @@ -32,7 +32,6 @@ internal class PyV3NewProjectStepAction : AbstractNewProjectStep ProjectSettingsStepBase(projectGenerator, callback) } - override fun getActions( generators: List>, callback: AbstractCallback, diff --git a/python/pluginResources/messages/PyBundle.properties b/python/pluginResources/messages/PyBundle.properties index 13269d9896dc..c0dd996de414 100644 --- a/python/pluginResources/messages/PyBundle.properties +++ b/python/pluginResources/messages/PyBundle.properties @@ -1695,7 +1695,7 @@ python.uv.lockfile.out.of.sync=The lock file at `uv.lock` is out of sync python.uv.update.lock=Update uv lock pycharm.free.mode.upgrade.title=Upgrade to PyCharm Pro -pycharm.free.mode.upgrade.body=Unlock the full potential of your IDE! Boost productivity,
work faster, and be more efficient with powerful development tools.
  • Support for JavaScript, TypeScript, React and others
  • Advances support for Django, Flask and FastAPI
  • Remote development
  • Local and remote full-scale Jupyter notebooks
+pycharm.free.mode.upgrade.body=Unlock the full potential of your IDE! Boost productivity,
work faster and be more efficient with powerful development tools.
  • Support for JavaScript, TypeScript, React and others
  • Advances support for Django, Flask and FastAPI
  • Remote development
  • Local and remote full-scale Jupyter notebooks
pycharm.free.mode.upgrade.button=Purchase Subscription python.packaging.sync.packages=Syncing project dependencies python.sdk.read.only=Python SDK ''{0}'' is read only and operation cannot be performed. diff --git a/python/src/com/jetbrains/python/createPromoPanel.kt b/python/src/com/jetbrains/python/createPromoPanel.kt index f03e5fafb403..fc2a10244948 100644 --- a/python/src/com/jetbrains/python/createPromoPanel.kt +++ b/python/src/com/jetbrains/python/createPromoPanel.kt @@ -1,19 +1,24 @@ // Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.jetbrains.python +import com.intellij.ide.BrowserUtil import com.intellij.ide.browsers.BrowserLauncher import com.intellij.ide.ui.laf.darcula.ui.DarculaButtonUI +import com.intellij.openapi.updateSettings.impl.pluginsAdvertisement.PromoFeatureListItem import com.intellij.ui.dsl.builder.* import com.intellij.util.concurrency.annotations.RequiresEdt import com.intellij.util.ui.JBFont import com.jetbrains.python.icons.PythonIcons +import org.jetbrains.annotations.Nls import javax.swing.JPanel /** - * Panel that suggests user to buy Pro version + * Panel that suggests user to buy a Pro version. + * By default, it shows a "pycharm.free.mode.upgrade.body" promo text. + * Could be customized by passing descriptionHtml and features list. In this case, default text will be substituted to features list. */ @RequiresEdt -internal fun createPromoPanel(): JPanel = panel { +fun createPromoPanel(@Nls descriptionHtml: String? = null, features: List? = null): JPanel = panel { row { icon(PythonIcons.Python.Pycharm32).resizableColumn().align(AlignX.RIGHT + AlignY.TOP) panel { @@ -22,10 +27,30 @@ internal fun createPromoPanel(): JPanel = panel { text(PyBundle.message("pycharm.free.mode.upgrade.title")).align(AlignY.BOTTOM).applyToComponent { font = JBFont.h1() } + }.topGap(TopGap.SMALL) + + if (descriptionHtml != null) { + row { + text(descriptionHtml) { BrowserUtil.browse(it.url.toExternalForm()) } + } } - row { - text(PyBundle.message("pycharm.free.mode.upgrade.body")).align(AlignY.TOP).applyToComponent { putClientProperty(DslComponentProperty.VERTICAL_COMPONENT_GAP, VerticalComponentGap(top = false, bottom = false)) } + + if (features == null) { + row { + text(PyBundle.message("pycharm.free.mode.upgrade.body")).align(AlignY.TOP).applyToComponent { + putClientProperty(DslComponentProperty.VERTICAL_COMPONENT_GAP, VerticalComponentGap(top = true, bottom = false)) + } + }.topGap(TopGap.SMALL) } + else { + features.forEach { feature -> + row { + icon(feature.icon).gap(RightGap.SMALL).align(AlignY.TOP) + text(feature.title) + } + } + } + row { button(PyBundle.message("pycharm.free.mode.upgrade.button")) { BrowserLauncher.instance.open("https://www.jetbrains.com/pycharm/buy/?utm_source=product&utm_medium=referral&utm_campaign=pycharm&utm_content=pro_upgrade§ion=commercial&billing=yearly")