[
Date Prev][
Date Next][
Thread Prev][
Thread Next][
Date Index][
Thread Index]
[
List Home]
[egit-dev] projectimport page
|
Hi,
I changed the project import wizardpage to use a filtered tree like is
custom in eclipse. I know I should file a bug for this but i will not
do that if you don't want it. I thought i could work on the
projectimport wizard as well to import projects after the repository
was imported. That does not seem to be available currently.
Best regards,
Wim Jongman
package org.eclipse.egit.ui.internal.clone;
/*******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation and others.
* Copyright (C) 2007, Martin Oberhuber (martin.oberhuber@xxxxxxxxxxxxx)
* Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@xxxxxxxxxx>
* Copyright (C) 2009, Mykola Nikishov <mn@xxxxxxxxx>
* Copyright (c) 2010, Wim Jongman <wim.jongman@xxxxxxxxxxxxxxxxxx>
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.egit.core.op.ConnectProviderOperation;
import org.eclipse.egit.ui.Activator;
import org.eclipse.egit.ui.UIText;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.actions.WorkspaceModifyOperation;
import org.eclipse.ui.dialogs.FilteredTree;
import org.eclipse.ui.dialogs.PatternFilter;
import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
import org.eclipse.ui.internal.ide.StatusUtil;
import org.eclipse.ui.internal.wizards.datatransfer.WizardProjectsImportPage;
import org.eclipse.ui.statushandlers.StatusManager;
import org.eclipse.ui.wizards.datatransfer.IImportStructureProvider;
/**
* The GitWizardProjectsImportPage is the page that allows the user to import
* projects from a particular location. This is a modified copy of
* {@link WizardProjectsImportPage}
*/
public class GitProjectsImportPage extends WizardPage {
/**
* The name of the folder containing metadata information for the workspace.
*/
public static final String METADATA_FOLDER = ".metadata"; //$NON-NLS-1$
/**
* The import structure provider.
*/
private IImportStructureProvider structureProvider;
class ProjectRecord {
File projectSystemFile;
String projectName;
Object parent;
int level;
IProjectDescription description;
/**
* Relative path to repository, '../.git' is by default. If you'll set
* it null you're on your own, no checks for null performed.
*/
File repository = new File("../.git"); //$NON-NLS-1$
/**
* Create a record for a project based on the info in the file.
*
* @param file
*/
ProjectRecord(File file) {
projectSystemFile = file;
setProjectName();
}
/**
* Create a record for a project based on the info in the file.
*
* @param file
* @param aRepository
* relative path to repository
*/
ProjectRecord(File file, File aRepository) {
projectSystemFile = file;
setProjectName();
repository = aRepository;
}
/**
* @param parent
* The parent folder of the .project file
* @param level
* The number of levels deep in the provider the file is
*/
ProjectRecord(Object parent, int level) {
this.parent = parent;
this.level = level;
setProjectName();
}
/**
* Set the name of the project based on the projectFile.
*/
private void setProjectName() {
try {
// If we don't have the project name try again
if (projectName == null) {
IPath path = new Path(projectSystemFile.getPath());
// if the file is in the default location, use the directory
// name as the project name
if (isDefaultLocation(path)) {
projectName = path.segment(path.segmentCount() - 2);
description = ResourcesPlugin.getWorkspace()
.newProjectDescription(projectName);
} else {
description = ResourcesPlugin.getWorkspace()
.loadProjectDescription(path);
projectName = description.getName();
}
}
} catch (CoreException e) {
// no good couldn't get the name
}
}
/**
* Returns whether the given project description file path is in the
* default location for a project
*
* @param path
* The path to examine
* @return Whether the given path is the default location for a project
*/
private boolean isDefaultLocation(IPath path) {
// The project description file must at least be within the project,
// which is within the workspace location
if (path.segmentCount() < 2)
return false;
return path.removeLastSegments(2).toFile().equals(
Platform.getLocation().toFile());
}
/**
* Get the name of the project
*
* @return String
*/
public String getProjectName() {
return projectName;
}
/**
* Gets the label to be used when rendering this project record in the
* UI.
*
* @return String the label
* @since 3.4
*/
public String getProjectLabel() {
if (description == null)
return projectName;
String path = projectSystemFile == null ? structureProvider
.getLabel(parent) : projectSystemFile.getParent();
return NLS.bind(UIText.WizardProjectsImportPage_projectLabel,
projectName, path);
}
}
private TreeViewer projectsList;
private ProjectRecord[] selectedProjects = new ProjectRecord[0];
final private HashSet<Object> checkedItems = new HashSet<Object>();
private IProject[] wsProjects;
// The last selected path to minimize searches
private String lastPath;
// The last time that the file or folder at the selected path was modified
// to mimize searches
private long lastModified;
private Button shareCheckBox;
private boolean share;
/**
* Creates a new project creation wizard page.
*
* @wbp.parser.constructor
*/
public GitProjectsImportPage() {
this("gitWizardExternalProjectsPage"); //$NON-NLS-1$
}
/**
* Create a new instance of the receiver.
*
* @param pageName
*/
public GitProjectsImportPage(String pageName) {
super(pageName);
setPageComplete(false);
setTitle(UIText.WizardProjectsImportPage_ImportProjectsTitle);
setDescription(UIText.WizardProjectsImportPage_ImportProjectsDescription);
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets
* .Composite)
*/
public void createControl(Composite parent) {
initializeDialogUnits(parent);
Composite workArea = new Composite(parent, SWT.NONE);
setControl(workArea);
workArea.setLayout(new GridLayout());
workArea.setLayoutData(new GridData(GridData.FILL_BOTH
| GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL));
createProjectsRoot(workArea);
createProjectsList(workArea);
createOptionsArea(workArea);
Dialog.applyDialogFont(workArea);
}
/**
* Create the area with the extra options.
*
* @param workArea
*/
private void createOptionsArea(Composite workArea) {
Composite optionsGroup = new Composite(workArea, SWT.NONE);
optionsGroup.setLayout(new GridLayout());
optionsGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
shareCheckBox = new Button(optionsGroup, SWT.CHECK);
shareCheckBox.setText(UIText.WizardProjectsImportPage_enableGit);
shareCheckBox.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
shareCheckBox.setSelection(share = true);
shareCheckBox.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
share = shareCheckBox.getSelection();
}
});
}
/**
* Create the checkbox list for the found projects.
*
* @param workArea
*/
private void createProjectsList(Composite workArea) {
checkedItems.clear();
Label title = new Label(workArea, SWT.NONE);
title.setText(UIText.WizardProjectsImportPage_ProjectsListTitle);
Composite listComposite = new Composite(workArea, SWT.NONE);
GridLayout layout = new GridLayout();
layout.numColumns = 2;
layout.marginWidth = 0;
layout.makeColumnsEqualWidth = false;
listComposite.setLayout(layout);
listComposite.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL
| GridData.GRAB_VERTICAL | GridData.FILL_BOTH));
PatternFilter filter = new PatternFilter() {
@Override
public boolean isElementVisible(Viewer viewer, Object element) {
if (checkedItems.contains(element)) {
return true;
}
return super.isElementVisible(viewer, element);
}
};
FilteredTree filteredTree = new FilteredTree(listComposite, SWT.CHECK
| SWT.BORDER, filter, true);
projectsList = filteredTree.getViewer();
GridData listData = new GridData(GridData.GRAB_HORIZONTAL
| GridData.GRAB_VERTICAL | GridData.FILL_BOTH);
projectsList.getControl().setLayoutData(listData);
projectsList.setLabelProvider(new ITableLabelProvider() {
public void removeListener(ILabelProviderListener listener) {
//
}
public boolean isLabelProperty(Object element, String property) {
//
return false;
}
public void dispose() {
//
}
public void addListener(ILabelProviderListener listener) {
//
}
public String getColumnText(Object element, int columnIndex) {
if (checkedItems.contains(element))
for (final TreeItem item : projectsList.getTree()
.getItems()) {
if (element == item.getData()) // not equals
item.setChecked(true);
}
return element.toString();
}
public Image getColumnImage(Object element, int columnIndex) {
//
return null;
}
});
projectsList.setContentProvider(new ITreeContentProvider() {
public Object[] getChildren(Object parentElement) {
return null;
}
public Object[] getElements(Object inputElement) {
return getValidProjects();
}
public boolean hasChildren(Object element) {
return false;
}
public Object getParent(Object element) {
return null;
}
public void dispose() {
// no dice
}
public void inputChanged(Viewer viewer, Object oldInput,
Object newInput) {
// no dice
}
});
projectsList.getTree().addMouseListener(new MouseAdapter() {
@Override
public void mouseUp(MouseEvent e) {
if (e.widget instanceof Tree) {
TreeItem item = ((Tree) e.widget).getItem(new Point(e.x,
e.y));
if (item != null) {
if (item.getChecked())
checkedItems.add(item.getData());
else
checkedItems.remove(item.getData());
setPageComplete(!checkedItems.isEmpty());
}
}
}
});
projectsList.setLabelProvider(new LabelProvider() {
public String getText(Object element) {
return ((ProjectRecord) element).getProjectLabel();
}
});
projectsList.setInput(this);
projectsList.setComparator(new ViewerComparator());
createSelectionButtons(listComposite);
}
/**
* Create the selection buttons in the listComposite.
*
* @param listComposite
*/
private void createSelectionButtons(Composite listComposite) {
Composite buttonsComposite = new Composite(listComposite, SWT.NONE);
GridLayout layout = new GridLayout();
layout.marginWidth = 0;
layout.marginHeight = 0;
buttonsComposite.setLayout(layout);
buttonsComposite.setLayoutData(new GridData(
GridData.VERTICAL_ALIGN_BEGINNING));
Button selectAll = new Button(buttonsComposite, SWT.PUSH);
selectAll.setText(UIText.WizardProjectsImportPage_selectAll);
selectAll.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
checkedItems.clear();
// only the root has children
for (final TreeItem item : projectsList.getTree().getItems()) {
item.setChecked(true);
checkedItems.add(item.getData());
}
setPageComplete(true);
}
});
Dialog.applyDialogFont(selectAll);
setButtonLayoutData(selectAll);
Button deselectAll = new Button(buttonsComposite, SWT.PUSH);
deselectAll.setText(UIText.WizardProjectsImportPage_deselectAll);
deselectAll.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
checkedItems.clear();
// only the root has children
for (final TreeItem item : projectsList.getTree().getItems()) {
item.setChecked(false);
}
setPageComplete(false);
}
});
Dialog.applyDialogFont(deselectAll);
setButtonLayoutData(deselectAll);
}
/**
* Create the area where you select the root directory for the projects.
*
* @param workArea
* Composite
*/
private void createProjectsRoot(Composite workArea) {
// project specification group
Composite projectGroup = new Composite(workArea, SWT.NONE);
GridLayout layout = new GridLayout();
layout.numColumns = 3;
layout.makeColumnsEqualWidth = false;
layout.marginWidth = 0;
projectGroup.setLayout(layout);
projectGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
}
/*
* (non-Javadoc) Method declared on IDialogPage. Set the focus on path
* fields when page becomes visible.
*/
public void setVisible(boolean visible) {
super.setVisible(visible);
}
/**
* Update the list of projects based on path. This will not check any
* projects.
*
* @param path
*/
void setProjectsList(final String path) {
// on an empty path empty selectedProjects
if (path == null || path.length() == 0) {
setMessage(UIText.WizardProjectsImportPage_ImportProjectsDescription);
selectedProjects = new ProjectRecord[0];
projectsList.refresh(true);
setPageComplete(false);
lastPath = path;
return;
}
final File directory = new File(path);
long modified = directory.lastModified();
if (path.equals(lastPath) && lastModified == modified) {
// since the file/folder was not modified and the path did not
// change, no refreshing is required
return;
}
lastPath = path;
lastModified = modified;
try {
getContainer().run(true, true, new IRunnableWithProgress() {
public void run(IProgressMonitor monitor) {
monitor.beginTask(
UIText.WizardProjectsImportPage_SearchingMessage,
100);
selectedProjects = new ProjectRecord[0];
Collection<File> files = new ArrayList<File>();
monitor.worked(10);
if (directory.isDirectory()) {
if (!collectProjectFilesFromDirectory(files, directory,
null, monitor)) {
return;
}
Iterator<File> filesIterator = files.iterator();
selectedProjects = new ProjectRecord[files.size()];
int index = 0;
monitor.worked(50);
monitor
.subTask(UIText.WizardProjectsImportPage_ProcessingMessage);
while (filesIterator.hasNext()) {
File file = filesIterator.next();
selectedProjects[index] = new ProjectRecord(file);
index++;
}
} else {
monitor.worked(60);
}
monitor.done();
}
});
} catch (InvocationTargetException e) {
IDEWorkbenchPlugin.log(e.getMessage(), e);
} catch (InterruptedException e) {
// Nothing to do if the user interrupts.
}
projectsList.refresh(true);
if (getValidProjects().length < selectedProjects.length) {
setMessage(UIText.WizardProjectsImportPage_projectsInWorkspace,
WARNING);
} else {
setMessage(UIText.WizardProjectsImportPage_ImportProjectsDescription);
}
}
/**
* Collect the list of .project files that are under directory into files.
*
* @param files
* @param directory
* @param directoriesVisited
* Set of canonical paths of directories, used as recursion guard
* @param monitor
* The monitor to report to
* @return boolean <code>true</code> if the operation was completed.
*/
private boolean collectProjectFilesFromDirectory(Collection<File> files,
File directory, Set<String> directoriesVisited,
IProgressMonitor monitor) {
if (monitor.isCanceled()) {
return false;
}
monitor.subTask(NLS.bind(
UIText.WizardProjectsImportPage_CheckingMessage, directory
.getPath()));
File[] contents = directory.listFiles();
if (contents == null)
return false;
// Initialize recursion guard for recursive symbolic links
if (directoriesVisited == null) {
directoriesVisited = new HashSet<String>();
try {
directoriesVisited.add(directory.getCanonicalPath());
} catch (IOException exception) {
StatusManager.getManager().handle(
StatusUtil.newStatus(IStatus.ERROR, exception
.getLocalizedMessage(), exception));
}
}
// first look for project description files
final String dotProject = IProjectDescription.DESCRIPTION_FILE_NAME;
for (int i = 0; i < contents.length; i++) {
File file = contents[i];
if (file.isFile() && file.getName().equals(dotProject)) {
files.add(file);
// don't search sub-directories since we can't have nested
// projects
return true;
}
}
// no project description found, so recurse into sub-directories
for (int i = 0; i < contents.length; i++) {
if (contents[i].isDirectory()) {
if (!contents[i].getName().equals(METADATA_FOLDER)) {
try {
String canonicalPath = contents[i].getCanonicalPath();
if (!directoriesVisited.add(canonicalPath)) {
// already been here --> do not recurse
continue;
}
} catch (IOException exception) {
StatusManager.getManager().handle(
StatusUtil.newStatus(IStatus.ERROR, exception
.getLocalizedMessage(), exception));
}
collectProjectFilesFromDirectory(files, contents[i],
directoriesVisited, monitor);
}
}
}
return true;
}
/**
* Create the selected projects
*
* @return boolean <code>true</code> if all project creations were
* successful.
*/
boolean createProjects() {
final Object[] selected = checkedItems.toArray();
WorkspaceModifyOperation op = new WorkspaceModifyOperation() {
protected void execute(IProgressMonitor monitor)
throws InvocationTargetException, InterruptedException {
try {
monitor.beginTask("", selected.length); //$NON-NLS-1$
if (monitor.isCanceled()) {
throw new OperationCanceledException();
}
for (int i = 0; i < selected.length; i++) {
createExistingProject((ProjectRecord) selected[i],
new SubProgressMonitor(monitor, 1));
}
} finally {
monitor.done();
}
}
};
// run the new project creation operation
try {
getContainer().run(true, true, op);
} catch (InterruptedException e) {
return false;
} catch (InvocationTargetException e) {
// one of the steps resulted in a core exception
Throwable t = e.getTargetException();
String message = UIText.WizardProjectImportPage_errorMessage;
IStatus status;
if (t instanceof CoreException) {
status = ((CoreException) t).getStatus();
} else {
status = new Status(IStatus.ERROR,
IDEWorkbenchPlugin.IDE_WORKBENCH, 1, message, t);
}
Activator.logError(message, t);
ErrorDialog.openError(getShell(), message, null, status);
return false;
}
return true;
}
/**
* Create the project described in record. If it is successful return true.
*
* @param record
* @param monitor
* @return boolean <code>true</code> if successful
* @throws InvocationTargetException
* @throws InterruptedException
*/
private boolean createExistingProject(final ProjectRecord record,
IProgressMonitor monitor) throws InvocationTargetException,
InterruptedException {
String projectName = record.getProjectName();
final IWorkspace workspace = ResourcesPlugin.getWorkspace();
final IProject project = workspace.getRoot().getProject(projectName);
if (record.description == null) {
// error case
record.description = workspace.newProjectDescription(projectName);
IPath locationPath = new Path(record.projectSystemFile
.getAbsolutePath());
// If it is under the root use the default location
if (Platform.getLocation().isPrefixOf(locationPath)) {
record.description.setLocation(null);
} else {
record.description.setLocation(locationPath);
}
} else {
record.description.setName(projectName);
}
try {
monitor.beginTask(
UIText.WizardProjectsImportPage_CreateProjectsTask, 100);
project.create(record.description, new SubProgressMonitor(monitor,
30));
int openTicks = share ? 50 : 70;
project.open(IResource.BACKGROUND_REFRESH, new SubProgressMonitor(
monitor, openTicks));
if (share) {
ConnectProviderOperation connectProviderOperation = new
ConnectProviderOperation(
project, record.repository);
connectProviderOperation
.run(new SubProgressMonitor(monitor, 20));
}
} catch (CoreException e) {
throw new InvocationTargetException(e);
} finally {
monitor.done();
}
return true;
}
/**
* Method used for test suite.
*
* @return CheckboxTreeViewer the viewer containing all the projects found
*/
public TreeViewer getProjectsList() {
return projectsList;
}
/**
* Retrieve all the projects in the current workspace.
*
* @return IProject[] array of IProject in the current workspace
*/
private IProject[] getProjectsInWorkspace() {
if (wsProjects == null) {
wsProjects = IDEWorkbenchPlugin.getPluginWorkspace().getRoot()
.getProjects();
}
return wsProjects;
}
/**
* Get the array of valid project records that can be imported from the
* source workspace or archive, selected by the user. If a project with the
* same name exists in both the source workspace and the current workspace,
* it will not appear in the list of projects to import and thus cannot be
* selected for import.
*
* Method declared public for test suite.
*
* @return ProjectRecord[] array of projects that can be imported into the
* workspace
*/
public ProjectRecord[] getValidProjects() {
List<ProjectRecord> validProjects = new ArrayList<ProjectRecord>();
for (int i = 0; i < selectedProjects.length; i++) {
if (!isProjectInWorkspace(selectedProjects[i].getProjectName())) {
validProjects.add(selectedProjects[i]);
}
}
return validProjects.toArray(new ProjectRecord[validProjects.size()]);
}
/**
* Determine if the project with the given name is in the current workspace.
*
* @param projectName
* String the project name to check
* @return boolean true if the project with the given name is in this
* workspace
*/
private boolean isProjectInWorkspace(String projectName) {
if (projectName == null) {
return false;
}
IProject[] workspaceProjects = getProjectsInWorkspace();
for (int i = 0; i < workspaceProjects.length; i++) {
if (projectName.equals(workspaceProjects[i].getName())) {
return true;
}
}
return false;
}
}