1 /******************************************************************************* 2 * Copyright (c) 2007, 2018 IBM Corporation and others. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * IBM Corporation - initial API and implementation 13 * EclipseSource - ongoing development 14 * Sonatype, Inc. - ongoing development 15 * Red Hat, Inc. - support for remediation page 16 *******************************************************************************/ 17 package org.eclipse.equinox.internal.p2.ui.dialogs; 18 19 import java.util.Collection; 20 import org.eclipse.core.runtime.IStatus; 21 import org.eclipse.core.runtime.Status; 22 import org.eclipse.equinox.internal.p2.ui.*; 23 import org.eclipse.equinox.internal.p2.ui.model.*; 24 import org.eclipse.equinox.internal.p2.ui.viewers.*; 25 import org.eclipse.equinox.p2.engine.IProvisioningPlan; 26 import org.eclipse.equinox.p2.metadata.IInstallableUnit; 27 import org.eclipse.equinox.p2.operations.ProfileChangeOperation; 28 import org.eclipse.equinox.p2.operations.ProvisioningJob; 29 import org.eclipse.equinox.p2.query.IQueryable; 30 import org.eclipse.equinox.p2.ui.ProvisioningUI; 31 import org.eclipse.jface.dialogs.Dialog; 32 import org.eclipse.jface.dialogs.IDialogConstants; 33 import org.eclipse.jface.viewers.*; 34 import org.eclipse.swt.SWT; 35 import org.eclipse.swt.custom.SashForm; 36 import org.eclipse.swt.graphics.Image; 37 import org.eclipse.swt.layout.*; 38 import org.eclipse.swt.widgets.*; 39 import org.eclipse.ui.statushandlers.StatusManager; 40 41 /** 42 * A wizard page that shows detailed information about a resolved install 43 * operation. It allows drill down into the elements that will be installed. 44 * 45 * @since 3.4 46 * 47 */ 48 public abstract class ResolutionResultsWizardPage extends ResolutionStatusPage { 49 50 private static final String DIALOG_SETTINGS_SECTION = "ResolutionResultsPage"; //$NON-NLS-1$ 51 52 protected IUElementListRoot input; 53 ProfileChangeOperation resolvedOperation; 54 TreeViewer treeViewer; 55 ProvElementContentProvider contentProvider; 56 IUDetailsLabelProvider labelProvider; 57 protected Display display; 58 private IUDetailsGroup iuDetailsGroup; 59 SashForm sashForm; 60 ResolutionResultsWizardPage(ProvisioningUI ui, ProvisioningOperationWizard wizard, IUElementListRoot input, ProfileChangeOperation operation)61 protected ResolutionResultsWizardPage(ProvisioningUI ui, ProvisioningOperationWizard wizard, IUElementListRoot input, ProfileChangeOperation operation) { 62 super("ResolutionPage", ui, wizard); //$NON-NLS-1$ 63 this.resolvedOperation = operation; 64 if (input == null) 65 this.input = new IUElementListRoot(ui); 66 else 67 this.input = input; 68 } 69 70 @Override createControl(Composite parent)71 public void createControl(Composite parent) { 72 display = parent.getDisplay(); 73 sashForm = new SashForm(parent, SWT.VERTICAL); 74 FillLayout layout = new FillLayout(); 75 sashForm.setLayout(layout); 76 GridData data = new GridData(GridData.FILL_BOTH); 77 sashForm.setLayoutData(data); 78 initializeDialogUnits(sashForm); 79 80 Composite composite = new Composite(sashForm, SWT.NONE); 81 GridLayout gridLayout = new GridLayout(); 82 gridLayout.marginWidth = 0; 83 gridLayout.marginHeight = 0; 84 composite.setLayout(gridLayout); 85 86 treeViewer = createTreeViewer(composite); 87 data = new GridData(GridData.FILL_BOTH); 88 data.heightHint = convertHeightInCharsToPixels(ILayoutConstants.DEFAULT_TABLE_HEIGHT); 89 data.widthHint = convertWidthInCharsToPixels(ILayoutConstants.DEFAULT_TABLE_WIDTH); 90 Tree tree = treeViewer.getTree(); 91 tree.setLayoutData(data); 92 tree.setHeaderVisible(true); 93 activateCopy(tree); 94 TreeViewerColumn nameColumn = new TreeViewerColumn(treeViewer, SWT.LEFT); 95 nameColumn.getColumn().setText(ProvUIMessages.ProvUI_NameColumnTitle); 96 nameColumn.getColumn().setWidth(400); 97 nameColumn.getColumn().setMoveable(true); 98 nameColumn.setLabelProvider(new ColumnLabelProvider() { 99 @Override 100 public String getText(Object element) { 101 IInstallableUnit iu = ProvUI.getAdapter(element, IInstallableUnit.class); 102 String label = iu.getProperty(IInstallableUnit.PROP_NAME, null); 103 if (label == null) 104 label = iu.getId(); 105 return label; 106 } 107 108 @Override 109 public Image getImage(Object element) { 110 if (element instanceof ProvElement) 111 return ((ProvElement) element).getImage(element); 112 if (ProvUI.getAdapter(element, IInstallableUnit.class) != null) 113 return ProvUIImages.getImage(ProvUIImages.IMG_IU); 114 return null; 115 } 116 117 @Override 118 public String getToolTipText(Object element) { 119 if (element instanceof AvailableIUElement && ((AvailableIUElement) element).getImageOverlayId(null) == ProvUIImages.IMG_INFO) 120 return ProvUIMessages.RemedyElementNotHighestVersion; 121 return super.getToolTipText(element); 122 } 123 }); 124 TreeViewerColumn versionColumn = new TreeViewerColumn(treeViewer, SWT.LEFT); 125 versionColumn.getColumn().setText(ProvUIMessages.ProvUI_VersionColumnTitle); 126 versionColumn.getColumn().setWidth(200); 127 versionColumn.setLabelProvider(new ColumnLabelProvider() { 128 @Override 129 public String getText(Object element) { 130 IInstallableUnit iu = ProvUI.getAdapter(element, IInstallableUnit.class); 131 if (element instanceof IIUElement) { 132 if (((IIUElement) element).shouldShowVersion()) 133 return iu.getVersion().toString(); 134 return ""; //$NON-NLS-1$ 135 } 136 return iu.getVersion().toString(); 137 } 138 }); 139 TreeViewerColumn idColumn = new TreeViewerColumn(treeViewer, SWT.LEFT); 140 idColumn.getColumn().setText(ProvUIMessages.ProvUI_IdColumnTitle); 141 idColumn.getColumn().setWidth(200); 142 143 idColumn.setLabelProvider(new ColumnLabelProvider() { 144 @Override 145 public String getText(Object element) { 146 IInstallableUnit iu = ProvUI.getAdapter(element, IInstallableUnit.class); 147 return iu.getId(); 148 } 149 }); 150 151 // Filters and sorters before establishing content, so we don't refresh unnecessarily. 152 IUComparator comparator = new IUComparator(IUComparator.IU_NAME); 153 comparator.useColumnConfig(getColumnConfig()); 154 treeViewer.setComparator(comparator); 155 treeViewer.setComparer(new ProvElementComparer()); 156 ColumnViewerToolTipSupport.enableFor(treeViewer); 157 contentProvider = new ProvElementContentProvider(); 158 treeViewer.setContentProvider(contentProvider); 159 // labelProvider = new IUDetailsLabelProvider(null, getColumnConfig(), getShell()); 160 // treeViewer.setLabelProvider(labelProvider); 161 162 // Optional area to show the size 163 createSizingInfo(composite); 164 165 // The text area shows a description of the selected IU, or error detail if applicable. 166 iuDetailsGroup = new IUDetailsGroup(sashForm, treeViewer, convertWidthInCharsToPixels(ILayoutConstants.DEFAULT_TABLE_WIDTH), true); 167 168 setControl(sashForm); 169 sashForm.setWeights(getSashWeights()); 170 Dialog.applyDialogFont(sashForm); 171 172 // Controls for filtering/presentation/site selection 173 Composite controlsComposite = new Composite(composite, SWT.NONE); 174 gridLayout = new GridLayout(); 175 gridLayout.marginWidth = 0; 176 gridLayout.marginHeight = 0; 177 gridLayout.numColumns = 2; 178 gridLayout.makeColumnsEqualWidth = true; 179 gridLayout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING); 180 controlsComposite.setLayout(layout); 181 GridData gd = new GridData(SWT.FILL, SWT.FILL, true, false); 182 controlsComposite.setLayoutData(gd); 183 184 final Runnable runnable = () -> { 185 treeViewer.addSelectionChangedListener(event -> setDetailText(resolvedOperation)); 186 setDrilldownElements(input, resolvedOperation); 187 treeViewer.setInput(input); 188 }; 189 190 if (resolvedOperation != null && !resolvedOperation.hasResolved()) { 191 try { 192 getContainer().run(true, false, monitor -> { 193 resolvedOperation.resolveModal(monitor); 194 display.asyncExec(runnable); 195 }); 196 } catch (Exception e) { 197 StatusManager.getManager().handle(new Status(IStatus.ERROR, ProvUIActivator.PLUGIN_ID, e.getMessage(), e)); 198 } 199 } else { 200 runnable.run(); 201 } 202 } 203 204 @Override updateStatus(IUElementListRoot newRoot, ProfileChangeOperation op)205 public void updateStatus(IUElementListRoot newRoot, ProfileChangeOperation op) { 206 super.updateStatus(newRoot, op); 207 } 208 createSizingInfo(Composite parent)209 protected void createSizingInfo(Composite parent) { 210 // Default is to do nothing 211 } 212 performFinish()213 public boolean performFinish() { 214 if (resolvedOperation.getResolutionResult().getSeverity() != IStatus.ERROR) { 215 getProvisioningUI().schedule(resolvedOperation.getProvisioningJob(null), StatusManager.SHOW | StatusManager.LOG); 216 return true; 217 } 218 return false; 219 } 220 getTreeViewer()221 protected TreeViewer getTreeViewer() { 222 return treeViewer; 223 } 224 getCurrentPlan()225 public IProvisioningPlan getCurrentPlan() { 226 if (resolvedOperation != null) 227 return resolvedOperation.getProvisioningPlan(); 228 return null; 229 } 230 231 @Override getSelectedElements()232 protected Object[] getSelectedElements() { 233 return treeViewer.getStructuredSelection().toArray(); 234 } 235 236 @Override getSelectedIU()237 protected IInstallableUnit getSelectedIU() { 238 java.util.List<IInstallableUnit> units = ElementUtils.elementsToIUs(getSelectedElements()); 239 if (units.size() == 0) 240 return null; 241 return units.get(0); 242 } 243 244 @Override shouldCompleteOnCancel()245 protected boolean shouldCompleteOnCancel() { 246 return false; 247 } 248 getIUs()249 protected Collection<IInstallableUnit> getIUs() { 250 return ElementUtils.elementsToIUs(input.getChildren(input)); 251 } 252 setDrilldownElements(IUElementListRoot root, ProfileChangeOperation operation)253 void setDrilldownElements(IUElementListRoot root, ProfileChangeOperation operation) { 254 if (operation == null || operation.getProvisioningPlan() == null) 255 return; 256 Object[] elements = root.getChildren(root); 257 for (Object element : elements) { 258 if (element instanceof QueriedElement) { 259 ((QueriedElement) element).setQueryable(getQueryable(operation.getProvisioningPlan())); 260 } 261 } 262 } 263 getOperationLabel()264 protected abstract String getOperationLabel(); 265 266 /** 267 * Returns the restart policy for this operation. 268 * 269 * @return an integer constant describing whether the running profile 270 * needs to be restarted. 271 * 272 * @see ProvisioningJob#RESTART_NONE 273 * @see ProvisioningJob#RESTART_ONLY 274 * @see ProvisioningJob#RESTART_OR_APPLY 275 * 276 */ getRestartPolicy()277 protected int getRestartPolicy() { 278 return ProvisioningJob.RESTART_OR_APPLY; 279 } 280 281 /** 282 * Returns the task name for this operation, or <code>null</code> to display 283 * a generic task name. 284 */ getOperationTaskName()285 protected String getOperationTaskName() { 286 return null; 287 } 288 createTreeViewer(Composite parent)289 protected TreeViewer createTreeViewer(Composite parent) { 290 return new TreeViewer(parent, SWT.BORDER | SWT.MULTI | SWT.FULL_SELECTION); 291 } 292 getQueryable(IProvisioningPlan plan)293 protected abstract IQueryable<IInstallableUnit> getQueryable(IProvisioningPlan plan); 294 295 @Override getClipboardText(Control control)296 protected String getClipboardText(Control control) { 297 return CopyUtils.getIndentedClipboardText(getSelectedElements(), labelProvider); 298 } 299 300 @Override getDetailsGroup()301 protected IUDetailsGroup getDetailsGroup() { 302 return iuDetailsGroup; 303 } 304 305 @Override isCreated()306 protected boolean isCreated() { 307 return treeViewer != null; 308 } 309 310 @Override updateCaches(IUElementListRoot newRoot, ProfileChangeOperation op)311 protected void updateCaches(IUElementListRoot newRoot, ProfileChangeOperation op) { 312 resolvedOperation = op; 313 if (newRoot != null) { 314 setDrilldownElements(newRoot, resolvedOperation); 315 if (treeViewer != null) { 316 if (input != newRoot) 317 treeViewer.setInput(newRoot); 318 else 319 treeViewer.refresh(); 320 } 321 input = newRoot; 322 } 323 } 324 325 @Override getDialogSettingsName()326 protected String getDialogSettingsName() { 327 return getWizard().getClass().getName() + "." + DIALOG_SETTINGS_SECTION; //$NON-NLS-1$ 328 } 329 330 @Override getColumnWidth(int index)331 protected int getColumnWidth(int index) { 332 return treeViewer.getTree().getColumn(index).getWidth(); 333 } 334 335 @Override getSashForm()336 protected SashForm getSashForm() { 337 return sashForm; 338 } 339 }