From bbb02580e9da709a574c9c06c750b35891bdc694 Mon Sep 17 00:00:00 2001 From: anna Date: Fri, 14 Oct 2011 12:55:52 +0200 Subject: [PATCH] plugins: highlight ready to update plugins --- .../plugins/AvailablePluginColumnInfo.java | 8 +- .../plugins/AvailablePluginsManagerMain.java | 97 ++------------ .../plugins/InstalledPluginsManagerMain.java | 10 +- .../plugins/InstalledPluginsTableModel.java | 13 +- .../plugins/PluginManagerConfigurable.java | 2 +- .../ide/plugins/PluginManagerMain.java | 120 ++++++++++++++++-- .../updateSettings/impl/UpdateChecker.java | 2 + .../updateSettings/impl/UpdateSettings.java | 2 + 8 files changed, 147 insertions(+), 107 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/AvailablePluginColumnInfo.java b/platform/platform-impl/src/com/intellij/ide/plugins/AvailablePluginColumnInfo.java index ee27e544d01b..c9f8de4709f2 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/AvailablePluginColumnInfo.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/AvailablePluginColumnInfo.java @@ -18,6 +18,7 @@ package com.intellij.ide.plugins; import com.intellij.ide.IdeBundle; import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.vcs.FileStatus; +import com.intellij.ui.LightColors; import com.intellij.ui.SideBorder; import com.intellij.util.text.DateFormatUtil; import com.intellij.util.ui.UIUtil; @@ -144,9 +145,12 @@ class AvailablePluginColumnInfo extends PluginManagerColumnInfo { myPanel.setToolTipText(IdeBundle.message("plugin.download.status.tooltip")); } else if (pluginNode.getStatus() == PluginNode.STATUS_INSTALLED) { + final boolean hasNewerVersion = InstalledPluginsTableModel.hasNewerVersion(pluginNode.getPluginId()); if (!isSelected) myNameLabel.setForeground(FileStatus.COLOR_MODIFIED); - myStatusLabel.setText("[Installed]"); - myPanel.setToolTipText(IdeBundle.message("plugin.is.already.installed.status.tooltip")); + if (hasNewerVersion) { + if (!isSelected) myPanel.setBackground(LightColors.BLUE); + } + myStatusLabel.setText("[Installed" + (hasNewerVersion ? ": Ready to update" : "") + "]"); } } return myPanel; diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/AvailablePluginsManagerMain.java b/platform/platform-impl/src/com/intellij/ide/plugins/AvailablePluginsManagerMain.java index 81a240426563..33d1eddcf3bc 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/AvailablePluginsManagerMain.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/AvailablePluginsManagerMain.java @@ -15,26 +15,21 @@ */ package com.intellij.ide.plugins; -import com.intellij.CommonBundle; import com.intellij.ide.IdeBundle; -import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.actionSystem.ActionGroup; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.DefaultActionGroup; import com.intellij.openapi.actionSystem.ex.ComboBoxAction; -import com.intellij.openapi.application.PathManager; -import com.intellij.openapi.ui.Messages; -import com.intellij.openapi.util.IconLoader; import com.intellij.ui.ScrollPaneFactory; import com.intellij.util.net.HTTPProxySettingsDialog; -import com.intellij.util.ui.UIUtil; import com.intellij.util.ui.update.UiNotifyConnector; import org.jetbrains.annotations.NotNull; import javax.swing.*; -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.io.File; import java.util.ArrayList; import java.util.LinkedHashSet; @@ -43,12 +38,11 @@ import java.util.LinkedHashSet; */ public class AvailablePluginsManagerMain extends PluginManagerMain { private PluginManagerMain installed; - private PluginManagerUISettings myUISettings; private JButton myHttpProxySettingsButton = new JButton(IdeBundle.message("button.http.proxy.settings")); public AvailablePluginsManagerMain(PluginManagerMain installed, PluginManagerUISettings uiSettings) { + super(uiSettings); this.installed = installed; - myUISettings = uiSettings; init(); } @@ -90,13 +84,7 @@ public class AvailablePluginsManagerMain extends PluginManagerMain { if (!inToolbar) { actionGroup.add(new ActionInstallPlugin(this, installed)); } - actionGroup.add(new AnAction("Reload list of plugins", "Reload list of plugins", IconLoader.getIcon("/vcs/refresh.png")) { - @Override - public void actionPerformed(AnActionEvent e) { - loadAvailablePlugins(); - myFilter.setFilter(""); - } - }); + actionGroup.add(new RefreshAction()); if (inToolbar) { actionGroup.add(new MyFilterCategoryAction()); actionGroup.add(new SortByNameAction()); @@ -104,76 +92,9 @@ public class AvailablePluginsManagerMain extends PluginManagerMain { return actionGroup; } - /** - * Start a new thread which downloads new list of plugins from the site in - * the background and updates a list of plugins in the table. - */ - private void loadPluginsFromHostInBackground() { - setDownloadStatus(true); - - new com.intellij.util.concurrency.SwingWorker() { - ArrayList list = null; - Exception error; - - public Object construct() { - try { - list = RepositoryHelper.process(null); - } - catch (Exception e) { - error = e; - } - return list; - } - - public void finished() { - UIUtil.invokeLaterIfNeeded(new Runnable() { - public void run() { - if (list != null) { - modifyPluginsList(list); - setDownloadStatus(false); - pluginsModel.setSortMode(myUISettings.AVAILABLE_SORT_MODE); - } - else if (error != null) { - LOG.info(error); - setDownloadStatus(false); - if (0 == Messages.showOkCancelDialog( - IdeBundle.message("error.list.of.plugins.was.not.loaded", error.getMessage()), - IdeBundle.message("title.plugins"), - CommonBundle.message("button.retry"), CommonBundle.getCancelButtonText(), Messages.getErrorIcon())) { - loadPluginsFromHostInBackground(); - } - } - } - }); - } - }.start(); - } - - private void setDownloadStatus(boolean status) { - pluginTable.setPaintBusy(status); - } - - private void loadAvailablePlugins() { - ArrayList list; - try { - // If we already have a file with downloaded plugins from the last time, - // then read it, load into the list and start the updating process. - // Otherwise just start the process of loading the list and save it - // into the persistent config file for later reading. - File file = new File(PathManager.getPluginsPath(), RepositoryHelper.extPluginsFile); - if (file.exists()) { - RepositoryContentHandler handler = new RepositoryContentHandler(); - SAXParser parser = SAXParserFactory.newInstance().newSAXParser(); - parser.parse(file, handler); - list = handler.getPluginsList(); - modifyPluginsList(list); - } - } - catch (Exception ex) { - // Nothing to do, just ignore - if nothing can be read from the local - // file just start downloading of plugins' list from the site. - } - loadPluginsFromHostInBackground(); + @Override + protected void propagateUpdates(ArrayList list) { + installed.modifyPluginsList(list); //propagate updates } private class MyFilterCategoryAction extends ComboBoxAction { diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/InstalledPluginsManagerMain.java b/platform/platform-impl/src/com/intellij/ide/plugins/InstalledPluginsManagerMain.java index 8e743e960989..c04cb0d7df8f 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/InstalledPluginsManagerMain.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/InstalledPluginsManagerMain.java @@ -43,7 +43,8 @@ import java.util.Set; */ public class InstalledPluginsManagerMain extends PluginManagerMain { - public InstalledPluginsManagerMain() { + public InstalledPluginsManagerMain(PluginManagerUISettings uiSettings) { + super(uiSettings); init(); final JButton button = new JButton("Browse JetBrains repository"); button.setMnemonic('b'); @@ -56,6 +57,10 @@ public class InstalledPluginsManagerMain extends PluginManagerMain { myActionsPanel.add(button, BorderLayout.NORTH); } + @Override + protected void propagateUpdates(ArrayList list) { + } + private PluginManagerConfigurable createAvailableConfigurable() { return new PluginManagerConfigurable(PluginManagerUISettings.getInstance(), true) { @Override @@ -97,7 +102,8 @@ public class InstalledPluginsManagerMain extends PluginManagerMain { @Override protected ActionGroup getActionGroup(boolean inToolbar) { - DefaultActionGroup actionGroup = new DefaultActionGroup(); + final DefaultActionGroup actionGroup = new DefaultActionGroup(); + actionGroup.add(new RefreshAction()); if (!inToolbar) { actionGroup.add(new ActionUninstallPlugin(this, pluginTable)); } diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/InstalledPluginsTableModel.java b/platform/platform-impl/src/com/intellij/ide/plugins/InstalledPluginsTableModel.java index 72581c6fe5d6..e9d2715c7bb3 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/InstalledPluginsTableModel.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/InstalledPluginsTableModel.java @@ -21,6 +21,7 @@ import com.intellij.openapi.application.ex.ApplicationInfoEx; import com.intellij.openapi.extensions.PluginId; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.updateSettings.impl.UpdateSettings; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.util.text.StringUtil; @@ -191,8 +192,10 @@ public class InstalledPluginsTableModel extends PluginTableModel { private static void updateExistingPluginInfo(IdeaPluginDescriptor descr, IdeaPluginDescriptor existing) { int state = StringUtil.compareVersionNumbers(descr.getVersion(), existing.getVersion()); + final PluginId pluginId = existing.getPluginId(); if (state > 0 && !PluginManager.isIncompatible(descr) && !updatedPlugins.contains(descr.getPluginId())) { - NewVersions2Plugins.put(existing.getPluginId(), 1); + NewVersions2Plugins.put(pluginId, 1); + UpdateSettings.getInstance().myOutdatedPlugins.add(pluginId.getIdString()); final IdeaPluginDescriptorImpl plugin = (IdeaPluginDescriptorImpl)existing; plugin.setDownloadsCount(descr.getDownloads()); @@ -202,8 +205,9 @@ public class InstalledPluginsTableModel extends PluginTableModel { plugin.setUrl(descr.getUrl()); } else { - if (NewVersions2Plugins.remove(existing.getPluginId()) != null) { - updatedPlugins.add(existing.getPluginId()); + UpdateSettings.getInstance().myOutdatedPlugins.remove(pluginId.getIdString()); + if (NewVersions2Plugins.remove(pluginId) != null) { + updatedPlugins.add(pluginId); } } } @@ -401,7 +405,8 @@ public class InstalledPluginsTableModel extends PluginTableModel { if (descriptor.isDeleted()) { myNameLabel.setIcon(IconLoader.getIcon("/actions/clean.png")); } - else if (hasNewerVersion(myPluginDescriptor.getPluginId())) { + else if (hasNewerVersion(myPluginDescriptor.getPluginId()) || + UpdateSettings.getInstance().myOutdatedPlugins.contains(myPluginDescriptor.getPluginId().getIdString())) { myNameLabel.setIcon(IconLoader.getIcon("/nodes/pluginobsolete.png")); } else { diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerConfigurable.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerConfigurable.java index e8877e8e8ae8..0ef315736b76 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerConfigurable.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerConfigurable.java @@ -97,7 +97,7 @@ public class PluginManagerConfigurable extends BaseConfigurable implements Searc } protected PluginManagerMain createPanel() { - return new InstalledPluginsManagerMain(); + return new InstalledPluginsManagerMain(myUISettings); } public void apply() throws ConfigurationException { diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java index 23ca3156c127..ded066268f39 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java @@ -15,21 +15,24 @@ */ package com.intellij.ide.plugins; +import com.intellij.CommonBundle; import com.intellij.ide.BrowserUtil; import com.intellij.ide.IdeBundle; import com.intellij.ide.ui.search.SearchUtil; import com.intellij.ide.ui.search.SearchableOptionsRegistrar; import com.intellij.openapi.Disposable; -import com.intellij.openapi.actionSystem.ActionGroup; -import com.intellij.openapi.actionSystem.ActionManager; -import com.intellij.openapi.actionSystem.ActionToolbar; +import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.application.PathManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.FilterComponent; import com.intellij.ui.PopupHandler; import com.intellij.ui.SpeedSearchBase; import com.intellij.ui.TableUtil; +import com.intellij.util.ui.UIUtil; import com.intellij.util.ui.update.UiNotifyConnector; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.Nullable; @@ -41,7 +44,10 @@ import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import javax.swing.text.html.HTMLDocument; import javax.swing.text.html.HTMLFrameHyperlinkEvent; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; import java.awt.*; +import java.io.File; import java.io.IOException; import java.net.URL; import java.util.*; @@ -82,6 +88,12 @@ public abstract class PluginManagerMain implements Disposable { private ActionToolbar myActionToolbar; protected final MyPluginsFilter myFilter = new MyPluginsFilter(); + protected PluginManagerUISettings myUISettings; + + public PluginManagerMain( + PluginManagerUISettings uiSettings) { + myUISettings = uiSettings; + } protected void init() { myDescriptionTextArea.addHyperlinkListener(new MyHyperlinkListener()); @@ -148,7 +160,7 @@ public abstract class PluginManagerMain implements Disposable { return pluginsModel.dependent(pluginDescriptor); } - + protected void modifyPluginsList(ArrayList list) { IdeaPluginDescriptor[] selected = pluginTable.getSelectedObjects(); if (pluginsList == null) { @@ -169,6 +181,81 @@ public abstract class PluginManagerMain implements Disposable { return main; } + /** + * Start a new thread which downloads new list of plugins from the site in + * the background and updates a list of plugins in the table. + */ + protected void loadPluginsFromHostInBackground() { + setDownloadStatus(true); + + new com.intellij.util.concurrency.SwingWorker() { + ArrayList list = null; + Exception error; + + public Object construct() { + try { + list = RepositoryHelper.process(null); + } + catch (Exception e) { + error = e; + } + return list; + } + + public void finished() { + UIUtil.invokeLaterIfNeeded(new Runnable() { + public void run() { + if (list != null) { + modifyPluginsList(list); + propagateUpdates(list); + setDownloadStatus(false); + pluginsModel.setSortMode(myUISettings.AVAILABLE_SORT_MODE); + } + else if (error != null) { + LOG.info(error); + setDownloadStatus(false); + if (0 == Messages.showOkCancelDialog( + IdeBundle.message("error.list.of.plugins.was.not.loaded", error.getMessage()), + IdeBundle.message("title.plugins"), + CommonBundle.message("button.retry"), CommonBundle.getCancelButtonText(), Messages.getErrorIcon())) { + loadPluginsFromHostInBackground(); + } + } + } + }); + } + }.start(); + } + + protected abstract void propagateUpdates(ArrayList list); + + protected void setDownloadStatus(boolean status) { + pluginTable.setPaintBusy(status); + } + + protected void loadAvailablePlugins() { + ArrayList list; + try { + // If we already have a file with downloaded plugins from the last time, + // then read it, load into the list and start the updating process. + // Otherwise just start the process of loading the list and save it + // into the persistent config file for later reading. + File file = new File(PathManager.getPluginsPath(), RepositoryHelper.extPluginsFile); + if (file.exists()) { + RepositoryContentHandler handler = new RepositoryContentHandler(); + SAXParser parser = SAXParserFactory.newInstance().newSAXParser(); + parser.parse(file, handler); + list = handler.getPluginsList(); + modifyPluginsList(list); + } + } + catch (Exception ex) { + // Nothing to do, just ignore - if nothing can be read from the local + // file just start downloading of plugins' list from the site. + } + loadPluginsFromHostInBackground(); + } + public static boolean downloadPlugins(final List plugins, final List allPlugins) throws IOException { final boolean[] result = new boolean[1]; try { @@ -180,7 +267,7 @@ public abstract class PluginManagerMain implements Disposable { } catch (RuntimeException e) { if (e.getCause() != null && e.getCause() instanceof IOException) { - throw(IOException)e.getCause(); + throw (IOException)e.getCause(); } else { throw e; @@ -224,7 +311,6 @@ public abstract class PluginManagerMain implements Disposable { if (!pluginDescriptor.isBundled()) { description += "

Vendor

"; - //todo vendor section String vendor = pluginDescriptor.getVendor(); if (!StringUtil.isEmpty(vendor)) { description += vendor; @@ -249,7 +335,7 @@ public abstract class PluginManagerMain implements Disposable { String version = pluginDescriptor.getVersion(); if (!StringUtil.isEmpty(version)) { - description +="

Version

" + version; + description += "

Version

" + version; } String size = plugin instanceof PluginNode ? ((PluginNode)plugin).getSize() : null; @@ -260,7 +346,8 @@ public abstract class PluginManagerMain implements Disposable { setTextValue(description, myDescriptionTextArea); - } else { + } + else { setTextValue(null, myDescriptionTextArea); } } @@ -297,8 +384,9 @@ public abstract class PluginManagerMain implements Disposable { } else { URL url = e.getURL(); - if( url != null ) - BrowserUtil.launchBrowser( url.toString() ); + if (url != null) { + BrowserUtil.launchBrowser(url.toString()); + } } } } @@ -392,4 +480,16 @@ public abstract class PluginManagerMain implements Disposable { } } } + + protected class RefreshAction extends AnAction { + public RefreshAction() { + super("Reload list of plugins", "Reload list of plugins", IconLoader.getIcon("/vcs/refresh.png")); + } + + @Override + public void actionPerformed(AnActionEvent e) { + loadAvailablePlugins(); + myFilter.setFilter(""); + } + } } diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java index a69f8e691188..8a16fe9bf2d1 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java @@ -168,12 +168,14 @@ public final class UpdateChecker { if (!toUpdate.isEmpty()) { try { + final UpdateSettings updateSettings = UpdateSettings.getInstance(); final ArrayList process = RepositoryHelper.process(null); for (IdeaPluginDescriptor loadedPlugin : process) { final String idString = loadedPlugin.getPluginId().getIdString(); final IdeaPluginDescriptor installedPlugin = toUpdate.get(idString); if (installedPlugin != null) { if (StringUtil.compareVersionNumbers(loadedPlugin.getVersion(), installedPlugin.getVersion()) > 0) { + updateSettings.myOutdatedPlugins.add(idString); final PluginDownloader downloader = PluginDownloader.createDownloader(loadedPlugin); if (downloader.prepareToInstall()) { downloaded.add(downloader); diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateSettings.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateSettings.java index 1784b6ce1402..2dc1fe7bc3c9 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateSettings.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateSettings.java @@ -53,6 +53,8 @@ public class UpdateSettings implements PersistentStateComponent, UserUp @SuppressWarnings({"WeakerAccess", "CanBeFinal"}) public JDOMExternalizableStringList myIgnoredBuildNumbers = new JDOMExternalizableStringList(); + public JDOMExternalizableStringList myOutdatedPlugins = new JDOMExternalizableStringList(); + public boolean CHECK_NEEDED = true; public long LAST_TIME_CHECKED = 0; public String UPDATE_CHANNEL_TYPE = ChannelStatus.RELEASE_CODE;