blob: 4e5c5c365f6f363e6637f9280c783a517b99d4f3 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2011 Tasktop Technologies and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* https://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*
* 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;
}
}