/******************************************************************************* * Copyright (c) 2004, 2011 Tasktop Technologies and others. * 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 * * Contributors: * Tasktop Technologies - initial API and implementation *******************************************************************************/ package org.eclipse.mylyn.internal.tasks.ui.actions; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.IJobChangeEvent; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.core.runtime.jobs.JobChangeAdapter; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.dialogs.MessageDialogWithToggle; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.mylyn.commons.core.ICoreRunnable; import org.eclipse.mylyn.commons.core.StatusHandler; import org.eclipse.mylyn.commons.workbench.WorkbenchUtil; import org.eclipse.mylyn.internal.tasks.core.AbstractTask; import org.eclipse.mylyn.internal.tasks.core.AutomaticRepositoryTaskContainer; import org.eclipse.mylyn.internal.tasks.core.ITaskListRunnable; import org.eclipse.mylyn.internal.tasks.core.LocalTask; import org.eclipse.mylyn.internal.tasks.core.RepositoryQuery; import org.eclipse.mylyn.internal.tasks.core.TaskCategory; import org.eclipse.mylyn.internal.tasks.core.UncategorizedTaskContainer; import org.eclipse.mylyn.internal.tasks.core.UnmatchedTaskContainer; import org.eclipse.mylyn.internal.tasks.core.UnsubmittedTaskContainer; import org.eclipse.mylyn.internal.tasks.core.sync.DeleteTasksJob; import org.eclipse.mylyn.internal.tasks.ui.TasksUiPlugin; import org.eclipse.mylyn.internal.tasks.ui.util.TasksUiInternal; import org.eclipse.mylyn.tasks.core.AbstractRepositoryConnector; import org.eclipse.mylyn.tasks.core.IRepositoryElement; import org.eclipse.mylyn.tasks.core.IRepositoryQuery; import org.eclipse.mylyn.tasks.core.ITask; import org.eclipse.mylyn.tasks.core.TaskRepository; import org.eclipse.mylyn.tasks.ui.TasksUi; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.ui.ISharedImages; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.actions.BaseSelectionListenerAction; import org.eclipse.ui.internal.WorkbenchImages; import org.eclipse.ui.texteditor.IWorkbenchActionDefinitionIds; /** * @author Mik Kersten */ public class DeleteAction extends BaseSelectionListenerAction { public static final String ID = "org.eclipse.mylyn.tasklist.actions.delete"; //$NON-NLS-1$ public DeleteAction() { super(Messages.DeleteAction_Delete); setId(ID); setImageDescriptor(WorkbenchImages.getImageDescriptor(ISharedImages.IMG_TOOL_DELETE)); setActionDefinitionId(IWorkbenchActionDefinitionIds.DELETE); } @Override public void run() { doDelete(getStructuredSelection().toList()); } protected void doDelete(final List<?> toDelete) { boolean allLocalTasks = true; boolean allSupportRepositoryDeletion = true; boolean allElementsAreTasks = true; // determine what repository elements are to be deleted so that we can present the correct message to the user for (Object object : toDelete) { if (object instanceof ITask) { ITask task = (ITask) object; AbstractRepositoryConnector repositoryConnector = TasksUi .getRepositoryConnector(task.getConnectorKind()); TaskRepository repository = TasksUi.getRepositoryManager().getRepository(task.getConnectorKind(), task.getRepositoryUrl()); if (repository != null && repositoryConnector != null) { allSupportRepositoryDeletion &= repositoryConnector.canDeleteTask(repository, task); } else { allSupportRepositoryDeletion = false; } allLocalTasks &= task instanceof LocalTask; } else { allElementsAreTasks = false; } } String elements = buildElementListString(toDelete); String message = buildMessage(toDelete, elements, allElementsAreTasks); if (toDelete.isEmpty()) { MessageDialog.openError(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), Messages.DeleteAction_Delete_failed, Messages.DeleteAction_Nothing_selected); } else { boolean deleteConfirmed = false; boolean deleteOnServer = false; final boolean allTasksDeletable = allSupportRepositoryDeletion; if (allLocalTasks || !allElementsAreTasks) { deleteConfirmed = MessageDialog.openQuestion( PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), Messages.DeleteAction_Delete_Tasks, message); } else { String toggleMessage = Messages.DeleteAction_Also_delete_from_repository_X; if (allTasksDeletable) { toggleMessage = NLS.bind(toggleMessage, ""); //$NON-NLS-1$ } else { toggleMessage = NLS.bind(toggleMessage, Messages.DeleteAction_Not_supported); } final MessageDialogWithToggle dialog = new MessageDialogWithToggle(WorkbenchUtil.getShell(), Messages.DeleteAction_Delete_Tasks, null, message, MessageDialog.QUESTION, new String[] { IDialogConstants.YES_LABEL, IDialogConstants.NO_LABEL }, 0, toggleMessage, false) { @Override protected Control createContents(Composite parent) { Control createdControl = super.createContents(parent); getToggleButton().setEnabled(allTasksDeletable); return createdControl; } }; deleteConfirmed = dialog.open() == IDialogConstants.YES_ID; deleteOnServer = dialog.getToggleState() && allTasksDeletable; } if (deleteConfirmed) { deleteElements(toDelete, deleteOnServer); } } } private void deleteElements(final List<?> toDelete, final boolean deleteOnServer) { ICoreRunnable op = new ICoreRunnable() { public void run(IProgressMonitor monitor) throws CoreException { try { monitor.beginTask(Messages.DeleteAction_Delete_in_progress, IProgressMonitor.UNKNOWN); prepareDeletion(toDelete); TasksUiPlugin.getTaskList().run(new ITaskListRunnable() { public void execute(IProgressMonitor monitor) throws CoreException { performDeletion(toDelete); if (deleteOnServer) { performDeletionFromServer(toDelete); } } }, monitor); } finally { monitor.done(); } } }; try { WorkbenchUtil.runInUi(op, null); } catch (CoreException e) { Status status = new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN, NLS.bind("Problems encountered deleting task list elements: {0}", e.getMessage()), e); //$NON-NLS-1$ TasksUiInternal.logAndDisplayStatus(Messages.DeleteTaskRepositoryAction_Delete_Task_Repository_Failed, status); } catch (OperationCanceledException e) { // canceled } } private String buildMessage(final List<?> toDelete, String elements, boolean allElementsAreTasks) { String message; if (toDelete.size() == 1) { Object object = toDelete.get(0); if (object instanceof ITask) { if ((AbstractTask) object instanceof LocalTask) { message = Messages.DeleteAction_Permanently_delete_from_task_list; } else { message = Messages.DeleteAction_Delete_task_from_task_list_context_planning_deleted; } } else if (object instanceof TaskCategory) { message = Messages.DeleteAction_Permanently_delete_the_category; } else if (object instanceof IRepositoryQuery) { message = Messages.DeleteAction_Permanently_delete_the_query; } else if (object instanceof UnmatchedTaskContainer) { message = Messages.DeleteAction_Delete_the_planning_information_and_context_of_all_unmatched_tasks; } else if (object instanceof UnsubmittedTaskContainer) { message = Messages.DeleteAction_Delete_all_of_the_unsubmitted_tasks; } else { message = Messages.DeleteAction_Permanently_delete_the_element_listed_below; } } else { if (allElementsAreTasks) { message = Messages.DeleteAction_Delete_tasks_from_task_list_context_planning_deleted; } else { message = Messages.DeleteAction_Delete_elements_from_task_list_context_planning_deleted; } } message += "\n\n" + elements; //$NON-NLS-1$ return message; } private String buildElementListString(final List<?> toDelete) { String elements = ""; //$NON-NLS-1$ int i = 0; for (Object object : toDelete) { if (object instanceof UnmatchedTaskContainer) { continue; } i++; if (i < 20) { // TODO this action should be based on the action enablement and check if the container is user managed or not if (object instanceof IRepositoryElement) { elements += " " + ((IRepositoryElement) object).getSummary() + "\n"; //$NON-NLS-1$ //$NON-NLS-2$ } } else { elements += "..."; //$NON-NLS-1$ break; } } return elements; } public static void prepareDeletion(Collection<?> toDelete) { for (Object selectedObject : toDelete) { if (selectedObject instanceof AbstractTask) { AbstractTask task = (AbstractTask) selectedObject; TasksUi.getTaskActivityManager().deactivateTask(task); TasksUiInternal.closeTaskEditorInAllPages(task, false); } else if (selectedObject instanceof AutomaticRepositoryTaskContainer) { // support both the unmatched and the unsubmitted if (toDelete.size() == 1) { prepareDeletion(((AutomaticRepositoryTaskContainer) selectedObject).getChildren()); } } } } public static void performDeletion(Collection<?> toDelete) { for (Object selectedObject : toDelete) { if (selectedObject instanceof AbstractTask) { AbstractTask task = (AbstractTask) selectedObject; TasksUiInternal.deleteTask(task); } else if (selectedObject instanceof IRepositoryQuery) { TasksUiInternal.getTaskList().deleteQuery((RepositoryQuery) selectedObject); } else if (selectedObject instanceof TaskCategory) { TasksUiInternal.getTaskList().deleteCategory((TaskCategory) selectedObject); } else if (selectedObject instanceof AutomaticRepositoryTaskContainer) { // support both the unmatched and the unsubmitted if (toDelete.size() == 1) { // loop to ensure that all subtasks are deleted as well for (int i = 0; i < 5; i++) { Collection<ITask> children = ((AutomaticRepositoryTaskContainer) selectedObject).getChildren(); if (children.isEmpty()) { break; } performDeletion(children); } } } } } private void performDeletionFromServer(List<?> toDelete) { List<ITask> tasksToDelete = new ArrayList<ITask>(); for (Object element : toDelete) { if (element instanceof ITask) { tasksToDelete.add((ITask) element); } } final DeleteTasksJob deleteTaskJob = new DeleteTasksJob(Messages.DeleteAction_Deleting_tasks_from_repositories, tasksToDelete, TasksUi.getRepositoryManager()); deleteTaskJob.setPriority(Job.INTERACTIVE); deleteTaskJob.addJobChangeListener(new JobChangeAdapter() { @Override public void done(IJobChangeEvent event) { if (deleteTaskJob.getStatus() != null && !deleteTaskJob.getStatus().isOK()) { StatusHandler.log(deleteTaskJob.getStatus()); } } }); deleteTaskJob.setUser(true); deleteTaskJob.schedule(); } @Override protected boolean updateSelection(IStructuredSelection selection) { List<?> elements = (selection).toList(); for (Object object : elements) { if (object instanceof UncategorizedTaskContainer) { return false; } } return true; } }