001/* 002 * Copyright 2010-2015 Institut Pasteur. 003 * 004 * This file is part of Icy. 005 * 006 * Icy is free software: you can redistribute it and/or modify 007 * it under the terms of the GNU General Public License as published by 008 * the Free Software Foundation, either version 3 of the License, or 009 * (at your option) any later version. 010 * 011 * Icy is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 * GNU General Public License for more details. 015 * 016 * You should have received a copy of the GNU General Public License 017 * along with Icy. If not, see <http://www.gnu.org/licenses/>. 018 */ 019package icy.gui.preferences; 020 021import icy.gui.dialog.ConfirmDialog; 022import icy.plugin.PluginDescriptor; 023import icy.plugin.PluginInstaller; 024import icy.plugin.PluginInstaller.PluginInstallerListener; 025import icy.plugin.PluginLoader; 026import icy.plugin.PluginLoader.PluginLoaderEvent; 027import icy.plugin.PluginLoader.PluginLoaderListener; 028import icy.plugin.PluginRepositoryLoader; 029import icy.plugin.PluginRepositoryLoader.PluginRepositoryLoaderListener; 030import icy.plugin.PluginUpdater; 031 032import java.util.ArrayList; 033import java.util.List; 034 035/** 036 * @author Stephane 037 */ 038public class PluginLocalPreferencePanel extends PluginListPreferencePanel implements PluginLoaderListener, 039 PluginInstallerListener, PluginRepositoryLoaderListener 040{ 041 private enum PluginLocalState 042 { 043 NULL, UPDATING, REMOVING, HAS_UPDATE, NO_UPDATE, CHECKING_UPDATE 044 } 045 046 /** 047 * 048 */ 049 private static final long serialVersionUID = -6732331255351202922L; 050 051 public static final String NODE_NAME = "Local Plugin"; 052 053 PluginLocalPreferencePanel(PreferenceFrame parent) 054 { 055 super(parent, NODE_NAME, PluginPreferencePanel.NODE_NAME); 056 057 PluginRepositoryLoader.addListener(this); 058 PluginLoader.addListener(this); 059 PluginInstaller.addListener(this); 060 061 // remove last column not used here 062 table.removeColumn(table.getColumn(columnIds[4])); 063 064 action1Button.setText("Delete"); 065 action1Button.setVisible(true); 066 action2Button.setText("Check update"); 067 action2Button.setVisible(true); 068 069 pluginsChanged(); 070 } 071 072 @Override 073 protected void closed() 074 { 075 super.closed(); 076 077 PluginRepositoryLoader.removeListener(this); 078 PluginInstaller.removeListener(this); 079 PluginLoader.removeListener(this); 080 } 081 082 private PluginLocalState getPluginLocalState(PluginDescriptor plugin) 083 { 084 if (plugin != null) 085 { 086 if (!PluginRepositoryLoader.isLoaded()) 087 return PluginLocalState.CHECKING_UPDATE; 088 089 if ((PluginInstaller.isDesinstallingPlugin(plugin))) 090 return PluginLocalState.REMOVING; 091 092 // get online version 093 final PluginDescriptor onlinePlugin = PluginUpdater.getUpdate(plugin); 094 095 // update available ? 096 if (onlinePlugin != null) 097 { 098 if (PluginInstaller.isInstallingPlugin(onlinePlugin)) 099 return PluginLocalState.UPDATING; 100 101 return PluginLocalState.HAS_UPDATE; 102 } 103 104 if (plugin.isInstalled()) 105 return PluginLocalState.NO_UPDATE; 106 107 // here the plugin has just been removed but plugin list is not yet updated 108 return PluginLocalState.REMOVING; 109 } 110 111 return PluginLocalState.NULL; 112 } 113 114 @Override 115 protected void doAction1() 116 { 117 final List<PluginDescriptor> selectedPlugins = getSelectedPlugins(); 118 final List<PluginDescriptor> toRemove = new ArrayList<PluginDescriptor>(); 119 120 for (PluginDescriptor plugin : selectedPlugins) 121 if (!PluginInstaller.isDesinstallingPlugin(plugin) && plugin.isInstalled()) 122 toRemove.add(plugin); 123 124 // nothing to remove 125 if (toRemove.isEmpty()) 126 return; 127 128 // get dependants plugins 129 final List<PluginDescriptor> dependants = PluginInstaller.getLocalDependenciesFrom(toRemove); 130 // delete the one we plan to remove 131 dependants.removeAll(toRemove); 132 133 String message = "<html>"; 134 135 if (!dependants.isEmpty()) 136 { 137 message = message + "The following plugin(s) won't work anymore :<br>"; 138 139 for (PluginDescriptor depPlug : dependants) 140 message = message + depPlug.getName() + " " + depPlug.getVersion() + "<br>"; 141 142 message = message + "<br>"; 143 } 144 145 message = message + "Are you sure you want to remove selected plugin(s) ?</html>"; 146 147 if (ConfirmDialog.confirm(message)) 148 { 149 // remove plugins 150 for (PluginDescriptor plugin : toRemove) 151 PluginInstaller.desinstall(plugin, false, true); 152 } 153 154 // refresh state 155 refreshTableData(); 156 } 157 158 @Override 159 protected void doAction2() 160 { 161 final List<PluginDescriptor> selectedPlugins = getSelectedPlugins(); 162 163 for (PluginDescriptor plugin : selectedPlugins) 164 { 165 final PluginDescriptor onlinePlugin = PluginUpdater.getUpdate(plugin); 166 // install update 167 if (onlinePlugin != null) 168 PluginInstaller.install(onlinePlugin, true); 169 } 170 171 // refresh state 172 refreshTableData(); 173 } 174 175 @Override 176 protected void repositoryChanged() 177 { 178 // do nothing here 179 } 180 181 @Override 182 protected void reloadPlugins() 183 { 184 PluginLoader.reloadAsynch(); 185 // so we display the empty list during reload 186 pluginsChanged(); 187 } 188 189 @Override 190 protected String getStateValue(PluginDescriptor plugin) 191 { 192 if (plugin == null) 193 return ""; 194 195 switch (getPluginLocalState(plugin)) 196 { 197 case REMOVING: 198 return "removing..."; 199 200 case CHECKING_UPDATE: 201 return "checking..."; 202 203 case UPDATING: 204 return "updating..."; 205 206 case HAS_UPDATE: 207 return "update available"; 208 209 case NO_UPDATE: 210 return ""; 211 } 212 213 return ""; 214 } 215 216 @Override 217 protected List<PluginDescriptor> getPlugins() 218 { 219 // loading... 220 if (PluginLoader.isLoading()) 221 return new ArrayList<PluginDescriptor>(); 222 223 final List<PluginDescriptor> result = PluginLoader.getPlugins(false); 224 225 // only display installed plugins (this hide inner or dev plugins) 226 for (int i = result.size() - 1; i >= 0; i--) 227 if (!result.get(i).isInstalled()) 228 result.remove(i); 229 230 return result; 231 } 232 233 @Override 234 protected void updateButtonsStateInternal() 235 { 236 super.updateButtonsStateInternal(); 237 238 final List<PluginDescriptor> selectedPlugins = getSelectedPlugins(); 239 final boolean selected = (selectedPlugins.size() > 0); 240 241 if (PluginLoader.isLoading()) 242 { 243 refreshButton.setText("Reloading..."); 244 refreshButton.setEnabled(false); 245 } 246 else 247 { 248 refreshButton.setText("Reload list"); 249 refreshButton.setEnabled(true); 250 } 251 252 if (!selected) 253 { 254 action1Button.setEnabled(false); 255 action2Button.setEnabled(false); 256 return; 257 } 258 259 boolean removing = true; 260 for (PluginDescriptor plugin : selectedPlugins) 261 { 262 if (!PluginInstaller.isDesinstallingPlugin(plugin)) 263 { 264 removing = false; 265 break; 266 } 267 } 268 269 // special case where plugins are currently begin removed 270 if (removing) 271 { 272 action1Button.setText("Removing..."); 273 action1Button.setEnabled(false); 274 } 275 else 276 { 277 action1Button.setText("Remove"); 278 action1Button.setEnabled(true); 279 } 280 281 PluginLocalState state = PluginLocalState.NULL; 282 283 for (PluginDescriptor plugin : selectedPlugins) 284 { 285 switch (getPluginLocalState(plugin)) 286 { 287 case CHECKING_UPDATE: 288 if ((state == PluginLocalState.NULL) || (state == PluginLocalState.NO_UPDATE)) 289 state = PluginLocalState.CHECKING_UPDATE; 290 break; 291 292 case UPDATING: 293 if ((state == PluginLocalState.NULL) || (state == PluginLocalState.NO_UPDATE) 294 || (state == PluginLocalState.CHECKING_UPDATE)) 295 state = PluginLocalState.UPDATING; 296 break; 297 298 case HAS_UPDATE: 299 state = PluginLocalState.HAS_UPDATE; 300 break; 301 302 case NO_UPDATE: 303 if (state == PluginLocalState.NULL) 304 state = PluginLocalState.NO_UPDATE; 305 break; 306 } 307 } 308 309 switch (state) 310 { 311 case CHECKING_UPDATE: 312 action1Button.setEnabled(false); 313 action2Button.setText("Checking..."); 314 action2Button.setEnabled(false); 315 break; 316 317 case UPDATING: 318 action1Button.setEnabled(false); 319 action2Button.setText("Updating..."); 320 action2Button.setEnabled(false); 321 break; 322 323 case HAS_UPDATE: 324 action2Button.setText("Update"); 325 action2Button.setEnabled(true); 326 break; 327 328 case NO_UPDATE: 329 action2Button.setText("No update"); 330 action2Button.setEnabled(false); 331 break; 332 333 case NULL: 334 action1Button.setEnabled(false); 335 action2Button.setEnabled(false); 336 break; 337 } 338 339 // keep delete button enabled only if we can actually delete the plugin 340 if (action1Button.isEnabled()) 341 { 342 boolean canDelete = false; 343 for (PluginDescriptor plugin : selectedPlugins) 344 { 345 if (plugin.isInstalled()) 346 { 347 canDelete = true; 348 break; 349 } 350 } 351 352 action1Button.setEnabled(canDelete); 353 } 354 } 355 356 @Override 357 public void pluginLoaderChanged(PluginLoaderEvent e) 358 { 359 pluginsChanged(); 360 } 361 362 @Override 363 public void pluginInstalled(PluginDescriptor plugin, boolean success) 364 { 365 updateButtonsState(); 366 } 367 368 @Override 369 public void pluginRemoved(PluginDescriptor plugin, boolean success) 370 { 371 updateButtonsState(); 372 } 373 374 @Override 375 public void pluginRepositeryLoaderChanged(PluginDescriptor plugin) 376 { 377 refreshTableData(); 378 } 379}