plugins: highlight ready to update plugins

This commit is contained in:
anna
2011-10-14 14:01:27 +02:00
parent 5bf73ebcbc
commit bbb02580e9
8 changed files with 147 additions and 107 deletions
@@ -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;
@@ -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<IdeaPluginDescriptor> 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<IdeaPluginDescriptor> 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<IdeaPluginDescriptor> list) {
installed.modifyPluginsList(list); //propagate updates
}
private class MyFilterCategoryAction extends ComboBoxAction {
@@ -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<IdeaPluginDescriptor> 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));
}
@@ -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 {
@@ -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 {
@@ -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<IdeaPluginDescriptor> 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<IdeaPluginDescriptor> 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<IdeaPluginDescriptor> list);
protected void setDownloadStatus(boolean status) {
pluginTable.setPaintBusy(status);
}
protected void loadAvailablePlugins() {
ArrayList<IdeaPluginDescriptor> 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<PluginNode> plugins, final List<IdeaPluginDescriptor> 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 += "<h4>Vendor</h4>";
//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 +="<h4>Version</h4>" + version;
description += "<h4>Version</h4>" + 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("");
}
}
}
@@ -168,12 +168,14 @@ public final class UpdateChecker {
if (!toUpdate.isEmpty()) {
try {
final UpdateSettings updateSettings = UpdateSettings.getInstance();
final ArrayList<IdeaPluginDescriptor> 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);
@@ -53,6 +53,8 @@ public class UpdateSettings implements PersistentStateComponent<Element>, 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;