PY-72994 Packages(refactor, feat): Update package actions

GitOrigin-RevId: 12d6e92f838717817b6b3a69ae7b844ba1724be3
This commit is contained in:
Nikita.Ashihmin
2024-08-21 00:19:39 +04:00
committed by intellij-monorepo-bot
parent 134376878d
commit 9fde169b6a
11 changed files with 78 additions and 70 deletions

View File

@@ -914,6 +914,13 @@ The Python plug-in provides smart editing for Python scripts. The feature set of
<add-to-group group-id="ToolsMenu" anchor="last"/>
</group>
<group id="PyPackageToolwindowContext">
<action id="PyInstallPackage" class="com.jetbrains.python.packaging.toolwindow.actions.InstallPackageAction"/>
<action id="PyDeletePackage" class="com.jetbrains.python.packaging.toolwindow.actions.DeletePackageAction"/>
<action id="PyChangeVersionPackage" class="com.jetbrains.python.packaging.toolwindow.actions.ChangeVersionPackageAction"/>
<action id="PyUpdateToLatestPackage" class="com.jetbrains.python.packaging.toolwindow.actions.UpdatePackageToLatestAction"/>
</group>
<action id="PythonGenerateDictionaries" class="com.jetbrains.python.spellchecker.PythonSpellcheckerGenerateDictionariesAction"
internal="true">
<add-to-group group-id="Internal"/>

View File

@@ -1357,9 +1357,8 @@ python.toolwindow.packages.documentation.link=Documentation
python.toolwindow.packages.no.interpreter.text=Select an interpreter to see the installed packages
python.toolwindow.packages.latest.version.label=latest
python.toolwindow.packages.delete.package=Uninstall
python.toolwindow.packages.update.package=Change Version
python.toolwindow.packages.update.package.version=Update {0} -> {1}
python.toolwindow.packages.install.link=Install
action.python.packages.install.text=Install
python.toolwindow.packages.search.text.placeholder=Search for more packages
python.toolwindow.packages.description.panel.placeholder=Select a package to view documentation
python.toolwindow.packages.no.description.placeholder=<html><head></head><body><p class="empty_description">Package author did not provide a description.</p></body></html>
@@ -1526,3 +1525,8 @@ param.info.show.more.n.overloads=Show {0} more {1, choice, 0#overloads|1#overloa
# Advertising
advertiser.package.supported.by.pro={0} is supported by PyCharm Professional
advertiser.code.cells.supported.by.pro=Code cells are supported by PyCharm Professional
action.PyInstallPackage.text=Install
action.PyDeletePackage.text=Uninstall
action.PyUpdateToLatestPackage.text=Update to Latest
action.PyChangeVersionPackage.text=Change Version

View File

@@ -6,6 +6,7 @@ import com.intellij.ide.BrowserUtil
import com.intellij.openapi.Disposable
import com.intellij.openapi.actionSystem.ActionManager
import com.intellij.openapi.actionSystem.ActionPlaces
import com.intellij.openapi.actionSystem.DataSink
import com.intellij.openapi.actionSystem.DefaultActionGroup
import com.intellij.openapi.actionSystem.impl.ActionButton
import com.intellij.openapi.application.ModalityState
@@ -242,6 +243,12 @@ class PyPackagingToolWindowPanel(private val project: Project, toolWindow: ToolW
trackOrientation(service)
}
override fun uiDataSnapshot(sink: DataSink) {
sink[PyPackagesUiComponents.SELECTED_PACKAGE_DATA_CONTEXT] = selectedPackage
super.uiDataSnapshot(sink)
}
private fun initOrientation(service: PyPackagingToolWindowService, horizontal: Boolean) {
val second = if (splitter?.secondComponent == rightPanel) rightPanel else noPackagePanel
val proportionKey = if (horizontal) HORIZONTAL_SPLITTER_KEY else VERTICAL_SPLITTER_KEY

View File

@@ -51,8 +51,8 @@ import org.jetbrains.annotations.Nls
@Service(Service.Level.PROJECT)
class PyPackagingToolWindowService(val project: Project, val serviceScope: CoroutineScope) : Disposable {
private var toolWindowPanel: PyPackagingToolWindowPanel? = null
var toolWindowPanel: PyPackagingToolWindowPanel? = null
private set
lateinit var manager: PythonPackageManager
private var installedPackages: Map<String, InstalledPackage> = emptyMap()
internal var currentSdk: Sdk? = null
@@ -231,10 +231,12 @@ class PyPackagingToolWindowService(val project: Project, val serviceScope: Corou
}
}
private fun sortPackagesForRepo(packageNames: List<String>,
private fun sortPackagesForRepo(
packageNames: List<String>,
query: String,
repository: PyPackageRepository,
skipItems: Int = 0): PyPackagesViewData {
skipItems: Int = 0,
): PyPackagesViewData {
val comparator = createNameComparator(query, repository.repositoryUrl ?: "")
@@ -384,6 +386,9 @@ class PyPackagingToolWindowService(val project: Project, val serviceScope: Corou
companion object {
private const val PACKAGES_LIMIT = 50
fun getInstance(project: Project) = project.service<PyPackagingToolWindowService>()
private fun createNameComparator(query: String, url: String): Comparator<String> {
val nameComparator = Comparator<String> { name1, name2 ->
val queryLowerCase = query.lowercase()

View File

@@ -4,39 +4,39 @@ package com.jetbrains.python.packaging.toolwindow.actions
import com.intellij.openapi.actionSystem.ActionUpdateThread
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.application.EDT
import com.intellij.openapi.components.service
import com.intellij.openapi.project.DumbAwareAction
import com.intellij.ui.awt.RelativePoint
import com.jetbrains.python.PyBundle
import com.jetbrains.python.packaging.toolwindow.PyPackagingToolWindowService
import com.jetbrains.python.packaging.toolwindow.model.InstalledPackage
import com.jetbrains.python.packaging.toolwindow.ui.PyPackagesTable
import com.jetbrains.python.packaging.toolwindow.ui.PyPackagesUiComponents
import com.jetbrains.python.packaging.toolwindow.ui.PyPackagesUiComponents.selectedPackage
import com.jetbrains.python.packaging.utils.PyPackageCoroutine
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.awt.event.MouseEvent
internal class ChangeVersionPackageAction(val table: PyPackagesTable<*>) : DumbAwareAction(PyBundle.message("python.toolwindow.packages.update.package")) {
internal class ChangeVersionPackageAction : DumbAwareAction() {
override fun actionPerformed(e: AnActionEvent) {
val project = e.project ?: return
val pkg = table.selectedItem() as? InstalledPackage ?: return
val pkg = e.selectedPackage as? InstalledPackage ?: return
val service = PyPackagingToolWindowService.getInstance(project)
val controller = service.toolWindowPanel ?: return
PyPackageCoroutine.getIoScope(project).launch {
val service = project.service<PyPackagingToolWindowService>()
val details = service.detailsForPackage(pkg)
withContext(Dispatchers.EDT) {
PyPackagesUiComponents.createAvailableVersionsPopup(pkg, details, project, table.controller).show(
PyPackagesUiComponents.createAvailableVersionsPopup(pkg, details, project, controller).show(
RelativePoint(e.inputEvent as MouseEvent))
}
}
}
override fun update(e: AnActionEvent) {
val pkg = table.selectedItem() as? InstalledPackage
val pkg = e.selectedPackage as? InstalledPackage
e.presentation.isEnabledAndVisible = pkg != null
}
override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.BGT
}

View File

@@ -5,17 +5,16 @@ import com.intellij.openapi.actionSystem.ActionUpdateThread
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.components.service
import com.intellij.openapi.project.DumbAwareAction
import com.jetbrains.python.PyBundle
import com.jetbrains.python.packaging.toolwindow.PyPackagingToolWindowService
import com.jetbrains.python.packaging.toolwindow.model.InstalledPackage
import com.jetbrains.python.packaging.toolwindow.ui.PyPackagesTable
import com.jetbrains.python.packaging.toolwindow.ui.PyPackagesUiComponents.selectedPackage
import com.jetbrains.python.packaging.utils.PyPackageCoroutine
import kotlinx.coroutines.Dispatchers
internal class DeletePackageAction(val table: PyPackagesTable<*>) : DumbAwareAction(PyBundle.message("python.toolwindow.packages.delete.package")) {
internal class DeletePackageAction : DumbAwareAction() {
override fun actionPerformed(e: AnActionEvent) {
val project = e.project ?: return
val pkg = table.selectedItem() as? InstalledPackage ?: return
val pkg = e.selectedPackage as? InstalledPackage ?: return
val service = project.service<PyPackagingToolWindowService>()
@@ -25,7 +24,7 @@ internal class DeletePackageAction(val table: PyPackagesTable<*>) : DumbAwareAct
}
override fun update(e: AnActionEvent) {
e.presentation.isEnabledAndVisible = table.selectedItem() is InstalledPackage
e.presentation.isEnabledAndVisible = e.selectedPackage is InstalledPackage
}
override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.BGT

View File

@@ -3,36 +3,36 @@ package com.jetbrains.python.packaging.toolwindow.actions
import com.intellij.openapi.actionSystem.ActionUpdateThread
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.components.service
import com.intellij.openapi.project.DumbAwareAction
import com.intellij.ui.awt.RelativePoint
import com.jetbrains.python.PyBundle
import com.jetbrains.python.packaging.toolwindow.PyPackagingToolWindowService
import com.jetbrains.python.packaging.toolwindow.model.InstallablePackage
import com.jetbrains.python.packaging.toolwindow.ui.PyPackagesTable
import com.jetbrains.python.packaging.toolwindow.ui.PyPackagesUiComponents
import com.jetbrains.python.packaging.toolwindow.ui.PyPackagesUiComponents.selectedPackage
import com.jetbrains.python.packaging.utils.PyPackageCoroutine
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.awt.event.MouseEvent
internal class InstallPackageAction(val table: PyPackagesTable<*>) : DumbAwareAction(PyBundle.message("python.toolwindow.packages.install.link")) {
internal class InstallPackageAction : DumbAwareAction() {
override fun actionPerformed(e: AnActionEvent) {
val project = e.project ?: return
val service = project.service<PyPackagingToolWindowService>()
val pkg = table.selectedItem() as? InstallablePackage ?: return
val pkg = e.selectedPackage as? InstallablePackage ?: return
val service = PyPackagingToolWindowService.getInstance(project)
val controller = service.toolWindowPanel ?: return
PyPackageCoroutine.launch(project, Dispatchers.IO) {
val details = service.detailsForPackage(pkg)
withContext(Dispatchers.Main) {
val popup = PyPackagesUiComponents.createAvailableVersionsPopup(pkg, details, project, table.controller)
val popup = PyPackagesUiComponents.createAvailableVersionsPopup(pkg, details, project, controller)
popup.show(RelativePoint(e.inputEvent as MouseEvent))
}
}
}
override fun update(e: AnActionEvent) {
e.presentation.isEnabledAndVisible = table.selectedItem() is InstallablePackage
e.presentation.isEnabledAndVisible = e.selectedPackage is InstallablePackage
}
override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.BGT

View File

@@ -3,47 +3,29 @@ package com.jetbrains.python.packaging.toolwindow.actions
import com.intellij.openapi.actionSystem.ActionUpdateThread
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.application.EDT
import com.intellij.openapi.components.service
import com.intellij.openapi.project.DumbAwareAction
import com.intellij.ui.awt.RelativePoint
import com.jetbrains.python.PyBundle
import com.jetbrains.python.packaging.toolwindow.PyPackagingToolWindowService
import com.jetbrains.python.packaging.toolwindow.model.InstallablePackage
import com.jetbrains.python.packaging.toolwindow.model.InstalledPackage
import com.jetbrains.python.packaging.toolwindow.ui.PyPackagesTable
import com.jetbrains.python.packaging.toolwindow.ui.PyPackagesUiComponents
import com.jetbrains.python.packaging.toolwindow.ui.PyPackagesUiComponents.selectedPackage
import com.jetbrains.python.packaging.utils.PyPackageCoroutine
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.awt.event.MouseEvent
internal class UpdatePackageToLatestAction(val table: PyPackagesTable<*>) : DumbAwareAction(PyBundle.message("python.toolwindow.packages.update.package")) {
internal class UpdatePackageToLatestAction : DumbAwareAction() {
override fun actionPerformed(e: AnActionEvent) {
val project = e.project ?: return
val pkg = table.selectedItem()
val pkg = e.selectedPackage as? InstalledPackage ?: return
val service = PyPackagingToolWindowService.getInstance(project)
val service = project.service<PyPackagingToolWindowService>()
if (pkg is InstalledPackage && pkg.canBeUpdated) {
PyPackageCoroutine.getIoScope(project).launch {
val specification = pkg.repository.createPackageSpecification(pkg.name, pkg.nextVersion!!.presentableText)
service.updatePackage(specification)
}
}
else if (pkg is InstallablePackage) {
PyPackageCoroutine.getIoScope(project).launch {
val details = service.detailsForPackage(pkg)
withContext(Dispatchers.EDT) {
PyPackagesUiComponents.createAvailableVersionsPopup(pkg, details, project, table.controller).show(
RelativePoint(e.inputEvent as MouseEvent))
}
}
}
}
override fun update(e: AnActionEvent) {
val pkg = table.selectedItem() as? InstalledPackage
val pkg = e.selectedPackage as? InstalledPackage
val currentVersion = pkg?.currentVersion?.presentableText
val nextVersion = pkg?.nextVersion?.presentableText

View File

@@ -1,7 +1,8 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.jetbrains.python.packaging.toolwindow.ui
import com.intellij.openapi.actionSystem.DefaultActionGroup
import com.intellij.openapi.actionSystem.ActionGroup
import com.intellij.openapi.actionSystem.ActionManager
import com.intellij.openapi.components.service
import com.intellij.openapi.project.Project
import com.intellij.ui.DoubleClickListener
@@ -15,10 +16,6 @@ import com.intellij.util.ui.NamedColorUtil
import com.jetbrains.python.packaging.toolwindow.PyPackagingTablesView
import com.jetbrains.python.packaging.toolwindow.PyPackagingToolWindowPanel
import com.jetbrains.python.packaging.toolwindow.PyPackagingToolWindowService
import com.jetbrains.python.packaging.toolwindow.actions.ChangeVersionPackageAction
import com.jetbrains.python.packaging.toolwindow.actions.DeletePackageAction
import com.jetbrains.python.packaging.toolwindow.actions.InstallPackageAction
import com.jetbrains.python.packaging.toolwindow.actions.UpdatePackageToLatestAction
import com.jetbrains.python.packaging.toolwindow.model.DisplayablePackage
import com.jetbrains.python.packaging.toolwindow.model.ExpandResultNode
import com.jetbrains.python.packaging.toolwindow.model.InstallablePackage
@@ -127,12 +124,7 @@ internal class PyPackagesTable<T : DisplayablePackage>(
}
}.installOn(this)
val packageActionGroup = DefaultActionGroup(
DeletePackageAction(this),
InstallPackageAction(this),
UpdatePackageToLatestAction(this),
ChangeVersionPackageAction(this),
)
val packageActionGroup = ActionManager.getInstance().getAction("PyPackageToolwindowContext") as ActionGroup
PopupHandler.installPopupMenu(this, packageActionGroup, "PackagePopup")
}

View File

@@ -2,6 +2,9 @@
package com.jetbrains.python.packaging.toolwindow.ui
import com.intellij.icons.AllIcons
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.actionSystem.DataKey
import com.intellij.openapi.components.service
import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.popup.JBPopupFactory
@@ -25,6 +28,15 @@ import java.awt.event.MouseEvent
import javax.swing.*
object PyPackagesUiComponents {
val SELECTED_PACKAGE_DATA_CONTEXT = DataKey.create<DisplayablePackage>("SELECTED_PACKAGE_DATA_CONTEXT")
val DataContext.selectedPackage: DisplayablePackage?
get() = getData(SELECTED_PACKAGE_DATA_CONTEXT)
val AnActionEvent.selectedPackage: DisplayablePackage?
get() = dataContext.selectedPackage
fun createAvailableVersionsPopup(selectedPackage: DisplayablePackage, details: PythonPackageDetails, project: Project, controller: PyPackagingToolWindowPanel): ListPopup {
return JBPopupFactory.getInstance().createListPopup(object : BaseListPopupStep<String>(null, details.availableVersions) {
override fun onChosen(selectedValue: String?, finalChoice: Boolean): PopupStep<*>? {

View File

@@ -21,7 +21,7 @@ import javax.swing.table.DefaultTableCellRenderer
internal class PyPaginationAwareRenderer : DefaultTableCellRenderer() {
private val nameLabel = JLabel().apply { border = JBUI.Borders.empty(0, 12) }
private val versionLabel = JLabel().apply { border = JBUI.Borders.emptyRight(12) }
private val linkLabel = JLabel(PyBundle.message("python.toolwindow.packages.install.link")).apply {
private val linkLabel = JLabel(PyBundle.message("action.python.packages.install.text")).apply {
border = JBUI.Borders.emptyRight(12)
foreground = JBUI.CurrentTheme.Link.Foreground.ENABLED
}
@@ -67,7 +67,7 @@ internal class PyPaginationAwareRenderer : DefaultTableCellRenderer() {
versionPanel.removeAll()
if (value is InstallablePackage) {
linkLabel.text = PyBundle.message("python.toolwindow.packages.install.link")
linkLabel.text = PyBundle.message("action.python.packages.install.text")
linkLabel.updateUnderline(table, row)
if (rowSelected || TableHoverListener.getHoveredRow(table) == row) {
versionPanel.add(linkLabel)