### Eclipse Workspace Patch 1.0 #P org.eclipse.equinox.p2.ui Index: src/org/eclipse/equinox/internal/provisional/p2/ui/dialogs/InstalledIUGroup.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.equinox/p2/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/provisional/p2/ui/dialogs/InstalledIUGroup.java,v retrieving revision 1.7 diff -u -r1.7 InstalledIUGroup.java --- src/org/eclipse/equinox/internal/provisional/p2/ui/dialogs/InstalledIUGroup.java 8 May 2008 22:19:28 -0000 1.7 +++ src/org/eclipse/equinox/internal/provisional/p2/ui/dialogs/InstalledIUGroup.java 21 May 2008 22:55:15 -0000 @@ -98,6 +98,8 @@ Object getInput() { ProfileElement element = new ProfileElement(profileId); element.setQueryProvider(getQueryProvider()); + // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=232413 + element.preloadIUNamesWhileCollecting(); return element; } Index: src/org/eclipse/equinox/internal/provisional/p2/ui/model/ProfileElement.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.equinox/p2/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/provisional/p2/ui/model/ProfileElement.java,v retrieving revision 1.4 diff -u -r1.4 ProfileElement.java --- src/org/eclipse/equinox/internal/provisional/p2/ui/model/ProfileElement.java 7 Apr 2008 22:53:49 -0000 1.4 +++ src/org/eclipse/equinox/internal/provisional/p2/ui/model/ProfileElement.java 21 May 2008 22:55:15 -0000 @@ -10,6 +10,7 @@ *******************************************************************************/ package org.eclipse.equinox.internal.provisional.p2.ui.model; +import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.equinox.internal.p2.ui.ProvUIMessages; import org.eclipse.equinox.internal.p2.ui.model.RemoteQueriedElement; import org.eclipse.equinox.internal.provisional.p2.core.ProvisionException; @@ -18,6 +19,8 @@ import org.eclipse.equinox.internal.provisional.p2.ui.ProvUIImages; import org.eclipse.equinox.internal.provisional.p2.ui.operations.ProvisioningUtil; import org.eclipse.equinox.internal.provisional.p2.ui.policy.IQueryProvider; +import org.eclipse.equinox.internal.provisional.p2.ui.query.ElementQueryDescriptor; +import org.eclipse.equinox.internal.provisional.p2.ui.query.InstalledIUCollector; import org.eclipse.osgi.util.NLS; /** @@ -29,6 +32,9 @@ public class ProfileElement extends RemoteQueriedElement { String profileId; + // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=232413 + private boolean queryChildNames = false; + public ProfileElement(String profileId) { this.profileId = profileId; } @@ -83,4 +89,27 @@ public boolean isContainer() { return super.getChildren(this).length > 0; } + + // Make these two methods public to fix + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=232413 + public Object[] fetchChildren(Object o, IProgressMonitor monitor) { + if (queryChildNames) { + if (getQueryProvider() == null) + return new Object[0]; + ElementQueryDescriptor queryDescriptor = getQueryProvider().getQueryDescriptor(this, getQueryType()); + if (queryDescriptor == null || !isSufficientForQuery(queryDescriptor)) + return new Object[0]; + if (queryDescriptor.collector instanceof InstalledIUCollector) + ((InstalledIUCollector) queryDescriptor.collector).fetchNamePropertyWhileCollecting(); + queryDescriptor.queryable.query(queryDescriptor.query, queryDescriptor.collector, monitor); + return queryDescriptor.collector.toArray(Object.class); + + } + return super.fetchChildren(o, monitor); + } + + public void preloadIUNamesWhileCollecting() { + queryChildNames = true; + } + } Index: src/org/eclipse/equinox/internal/p2/ui/messages.properties =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.equinox/p2/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/messages.properties,v retrieving revision 1.60 diff -u -r1.60 messages.properties --- src/org/eclipse/equinox/internal/p2/ui/messages.properties 21 May 2008 22:39:50 -0000 1.60 +++ src/org/eclipse/equinox/internal/p2/ui/messages.properties 21 May 2008 22:55:15 -0000 @@ -140,6 +140,8 @@ AvailableIUGroup_RefreshOperationLabel=Refresh AvailableIUGroup_ViewByToolTipText=View by DeferredFetchFilteredTree_RetrievingList=Retrieving List +DeferredQueryContentProvider_FetchJobName=Fetching install information +DeferredQueryContentProvider_Pending=Pending... Label_Profiles=All Software Profiles Label_Repositories=Known Repositories MetadataRepositoryElement_NotFound=This repository is currently not available. Index: src/org/eclipse/equinox/internal/p2/ui/ProvUIMessages.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.equinox/p2/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ProvUIMessages.java,v retrieving revision 1.51 diff -u -r1.51 ProvUIMessages.java --- src/org/eclipse/equinox/internal/p2/ui/ProvUIMessages.java 21 May 2008 22:39:50 -0000 1.51 +++ src/org/eclipse/equinox/internal/p2/ui/ProvUIMessages.java 21 May 2008 22:55:15 -0000 @@ -124,6 +124,8 @@ public static String AvailableIUGroup_RefreshOperationLabel; public static String AvailableIUGroup_ViewByToolTipText; public static String DeferredFetchFilteredTree_RetrievingList; + public static String DeferredQueryContentProvider_FetchJobName; + public static String DeferredQueryContentProvider_Pending; public static String Label_Profiles; public static String Label_Repositories; public static String MetadataRepositoryElement_NotFound; Index: src/org/eclipse/equinox/internal/provisional/p2/ui/query/InstalledIUCollector.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.equinox/p2/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/provisional/p2/ui/query/InstalledIUCollector.java,v retrieving revision 1.4 diff -u -r1.4 InstalledIUCollector.java --- src/org/eclipse/equinox/internal/provisional/p2/ui/query/InstalledIUCollector.java 18 Apr 2008 15:12:03 -0000 1.4 +++ src/org/eclipse/equinox/internal/provisional/p2/ui/query/InstalledIUCollector.java 21 May 2008 22:55:15 -0000 @@ -24,6 +24,9 @@ */ public class InstalledIUCollector extends QueriedElementCollector { + // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=232413 + private boolean queryNameProperty = false; + public InstalledIUCollector(IQueryProvider queryProvider, IProfile profile, QueryContext queryContext) { super(queryProvider, profile, queryContext); } @@ -38,10 +41,19 @@ public boolean accept(Object match) { if (!(match instanceof IInstallableUnit)) return true; - if (queryable instanceof IProfile) + if (queryNameProperty && queryable instanceof IProfile) { + // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=232413 + // access the IU's name while collecting to prevent a later lockup in the UI thread. + IUPropertyUtils.getIUProperty((IInstallableUnit) match, IInstallableUnit.PROP_NAME); return super.accept(new InstalledIUElement(((IProfile) queryable).getProfileId(), (IInstallableUnit) match)); + } // shouldn't happen, but is possible if a client reset the queryable to a non-profile. return super.accept(match); } + // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=232413 + public void fetchNamePropertyWhileCollecting() { + this.queryNameProperty = true; + } + } Index: src/org/eclipse/equinox/internal/provisional/p2/ui/viewers/DeferredQueryContentProvider.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.equinox/p2/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/provisional/p2/ui/viewers/DeferredQueryContentProvider.java,v retrieving revision 1.6 diff -u -r1.6 DeferredQueryContentProvider.java --- src/org/eclipse/equinox/internal/provisional/p2/ui/viewers/DeferredQueryContentProvider.java 9 Apr 2008 17:52:06 -0000 1.6 +++ src/org/eclipse/equinox/internal/provisional/p2/ui/viewers/DeferredQueryContentProvider.java 21 May 2008 22:55:15 -0000 @@ -13,14 +13,18 @@ import java.util.HashMap; import java.util.HashSet; -import org.eclipse.core.runtime.ListenerList; +import org.eclipse.core.runtime.*; +import org.eclipse.core.runtime.jobs.*; +import org.eclipse.equinox.internal.p2.ui.ProvUIMessages; import org.eclipse.equinox.internal.p2.ui.model.ProvElement; import org.eclipse.equinox.internal.p2.ui.model.RemoteQueriedElement; import org.eclipse.equinox.internal.p2.ui.viewers.DeferredQueryTreeContentManager; import org.eclipse.equinox.internal.p2.ui.viewers.DeferredQueryTreeListener; +import org.eclipse.equinox.internal.provisional.p2.ui.model.ProfileElement; import org.eclipse.equinox.internal.provisional.p2.ui.policy.IQueryProvider; import org.eclipse.equinox.internal.provisional.p2.ui.query.QueriedElement; import org.eclipse.jface.viewers.*; +import org.eclipse.swt.widgets.Display; /** * Content provider that retrieves children asynchronously where @@ -40,6 +44,11 @@ AbstractTreeViewer viewer = null; ListenerList listeners = new ListenerList(); boolean synchronous = false; + TableViewer tableViewer = null; + Job profileFetchJob = null; + Display display = null; + String placeholder; + Object[] realChildren; public DeferredQueryContentProvider(IQueryProvider queryProvider) { this.queryProvider = queryProvider; @@ -54,8 +63,14 @@ } public void inputChanged(Viewer v, Object oldInput, Object newInput) { + // cache display while in UI thread + display = v.getControl().getDisplay(); if (manager != null) manager.cancel(oldInput); + if (profileFetchJob != null) { + profileFetchJob.cancel(); + profileFetchJob = null; + } if (v instanceof AbstractTreeViewer) { manager = new DeferredQueryTreeContentManager((AbstractTreeViewer) v); viewer = (AbstractTreeViewer) v; @@ -69,8 +84,11 @@ queryCompleted.add(parent); } }); - } else + } else { viewer = null; + if (v instanceof TableViewer) + tableViewer = (TableViewer) v; + } alreadyQueried = new HashMap(); queryCompleted = new HashSet(); currentInput = newInput; @@ -81,7 +99,48 @@ } - public Object[] getElements(Object input) { + public Object[] getElements(final Object input) { + if (input instanceof ProfileElement) { + if (profileFetchJob == null && tableViewer != null) { + final ProfileElement element = (ProfileElement) input; + element.setQueryProvider(queryProvider); + placeholder = ProvUIMessages.DeferredQueryContentProvider_Pending; + profileFetchJob = new Job(ProvUIMessages.DeferredQueryContentProvider_FetchJobName) { + public IStatus run(IProgressMonitor monitor) { + if (monitor.isCanceled()) + return Status.CANCEL_STATUS; + realChildren = element.fetchChildren(input, monitor); + return Status.OK_STATUS; + } + }; + profileFetchJob.addJobChangeListener(new JobChangeAdapter() { + public void done(IJobChangeEvent event) { + // whether finished or cancelled, get rid of the placeholder. + if (display == null || placeholder == null) + return; + final boolean addChildren = event.getResult().isOK(); + display.asyncExec(new Runnable() { + public void run() { + if (!tableViewer.getControl().isDisposed()) { + tableViewer.remove(placeholder); + if (addChildren) { + tableViewer.add(realChildren); + // Set the selection explicitly so listeners can + // change their validation + tableViewer.setSelection(StructuredSelection.EMPTY); + } + } + placeholder = null; + } + }); + } + }); + profileFetchJob.schedule(); + realChildren = new Object[] {placeholder}; + } + // realChildren could contain the placeholder or the real stuff + return realChildren; + } if (input instanceof QueriedElement) { QueriedElement element = (QueriedElement) input; element.setQueryProvider(queryProvider); @@ -94,6 +153,10 @@ if (manager != null) { manager.cancel(currentInput); } + if (profileFetchJob != null) { + profileFetchJob.cancel(); + profileFetchJob = null; + } } public Object getParent(Object child) {