/******************************************************************************* * Copyright (c) 2003 - 2006 University Of British Columbia 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: University Of British Columbia - initial API and implementation *******************************************************************************/ /******************************************************************************* * Copyright (c) 2007 - 2007 IT Solutions, Inc. 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: Chris Hane - adapted Trac implementation for Mantis *******************************************************************************/ package com.itsolut.mantis.ui.wizard; import static com.itsolut.mantis.ui.util.MantisUIUtil.newEnhancedFilteredTree; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.jface.dialogs.DialogPage; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.mylyn.commons.workbench.EnhancedFilteredTree; import org.eclipse.mylyn.commons.workbench.forms.SectionComposite; import org.eclipse.mylyn.tasks.core.IRepositoryQuery; import org.eclipse.mylyn.tasks.core.TaskRepository; import org.eclipse.mylyn.tasks.ui.wizards.AbstractRepositoryQueryPage2; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.List; import org.eclipse.swt.widgets.Text; import com.itsolut.mantis.core.IMantisClient; import com.itsolut.mantis.core.IMantisClientManager; import com.itsolut.mantis.core.MantisCache; import com.itsolut.mantis.core.exception.MantisException; import com.itsolut.mantis.core.model.MantisProject; import com.itsolut.mantis.core.model.MantisProjectFilter; import com.itsolut.mantis.core.model.MantisSearch; import com.itsolut.mantis.core.util.MantisUtils; import com.itsolut.mantis.ui.MantisUIPlugin; /** * Mantis search page. Provides a form similar to the one the Bugzilla connector uses. * * @author Steffen Pingel * @author Chris Hane * * Dave Carver - 20070806 [ 1729675 ] Internal errors when project or filter not selected */ public class MantisCustomQueryPage extends AbstractRepositoryQueryPage2 { private static final String NO_FILTERS_AVAILABLE = "No filters available for this project. Make sure they are created and that you have the right to access them."; private static final String TITLE = "Enter query parameters"; private static final String DESCRIPTION = "Select a project and a filter to populate the task list. Custom filters can be created from the web interface."; private static final String MAX_SEARCH_RESULTS = "Maximum results"; private Text searchLimit; private TaskRepository repository; protected List projectFilters; private EnhancedFilteredTree tree; private final Map<FilterKey, String> filterKeyToUrl = new HashMap<FilterKey, String>(); private final IMantisClientManager clientManager; public MantisCustomQueryPage(TaskRepository repository, IRepositoryQuery query, IMantisClientManager clientManager) { super(TITLE, repository, query); this.repository = repository; this.clientManager = clientManager; setTitle(TITLE); setDescription(DESCRIPTION); } public MantisCustomQueryPage(TaskRepository repository, IMantisClientManager clientManager) { this(repository, null, clientManager); } protected void createPageContent(SectionComposite sectionComposite) { Composite parent = sectionComposite.getContent(); Composite control = new Composite(parent, SWT.NONE); GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true); control.setLayoutData(gd); GridLayout layout = new GridLayout(2, true); control.setLayout(layout); Label projectLabel = new Label(control, SWT.NONE); projectLabel.setLayoutData(new GridData(SWT.NONE, SWT.TOP, true, false)); projectLabel.setText("Select project"); Label comboLabel = new Label(control, SWT.NONE); comboLabel.setLayoutData(new GridData(SWT.NONE, SWT.TOP, true, false)); comboLabel.setText("Select filter"); createProjectTree(control); projectFilters = new List(control, SWT.SINGLE | SWT.BORDER | SWT.V_SCROLL); projectFilters.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); projectFilters.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { updateButtonsIfNeeded(); List combo = (List) e.getSource(); updateDescription(combo); String text = getSelected(combo); if ( text == null ) return; // set suggestion if (!inSearchContainer()) setQueryTitle(text); updateButtonsIfNeeded(); } private void updateDescription(List combo) { if (combo.getItemCount() > 1) setMessage(null, DialogPage.WARNING); else if (getSelectedProject() == null) setMessage(NO_FILTERS_AVAILABLE, DialogPage.WARNING); } }); Composite searchLimitComposite = new Composite(parent, SWT.NONE); GridLayoutFactory.fillDefaults().numColumns(2).applyTo(searchLimitComposite); Label titleLabel = new Label(searchLimitComposite, SWT.NONE); titleLabel.setText(MAX_SEARCH_RESULTS); searchLimit = new Text(searchLimitComposite, SWT.BORDER); searchLimit.setText(MantisSearch.DEFAULT_SEARCH_LIMIT_STRING); } private IMantisClient getMantisClient() throws MantisException { return clientManager.getRepository(repository); } private void createProjectTree(Composite control) { tree = newEnhancedFilteredTree(control); TreeViewer projectTreeViewer = tree.getViewer(); projectTreeViewer.setLabelProvider(new MantisProjectLabelProvider()); projectTreeViewer.setContentProvider(new MantisProjectITreeContentProvider()); projectTreeViewer.addPostSelectionChangedListener(new ISelectionChangedListener() { public void selectionChanged(SelectionChangedEvent event) { if (getSelectedProject() == null) { setErrorMessage("Please select a project."); } else { setErrorMessage(null); } refreshFilterCombo(); } }); } private void refreshProjectTree() { tree.getViewer().setInput(getProjects()); } private MantisProject[] getProjects() { try { final ArrayList<MantisProject> projects = new ArrayList<MantisProject>(); projects.add(MantisProject.ALL_PROJECTS); projects.addAll(getMantisClient().getCache(new NullProgressMonitor()).getProjects()); return projects.toArray(new MantisProject[projects.size()]); } catch (MantisException e) { String message = "Failed loading projects : " + e.getMessage(); MantisUIPlugin.handleError(e, message, false); setErrorMessage(message); return new MantisProject[0]; } } public MantisProject getSelectedProject() { IStructuredSelection selection = (IStructuredSelection) tree.getViewer().getSelection(); return (MantisProject) selection.getFirstElement(); } @Override public boolean canFlipToNextPage() { return false; } private static void select(org.eclipse.swt.widgets.List list, String text) { for ( int i = 0 ; i < list.getItemCount(); i++ ) if ( list.getItem(i).equals(text) ) list.setSelection(i); } private static String getSelected(org.eclipse.swt.widgets.List list) { String[] selection = list.getSelection(); if ( selection.length == 0 ) return null; return selection[0]; } public TaskRepository getRepository() { return repository; } public void setRepository(TaskRepository repository) { this.repository = repository; } @Override public boolean isPageComplete() { return validate(); } @Override public void setPageComplete(boolean complete) { super.setPageComplete(complete); if (getSearchContainer() != null) getSearchContainer().setPerformActionEnabled(complete); } private boolean validate() { if (getSearchContainer() == null) { if (getQueryTitle() == null) return false; if (getQueryTitle().length() == 0) return false; } if (tree == null || getSelectedProject() == null) return false; if (projectFilters == null || getSelected(projectFilters) == null ) return false; try { if (searchLimit != null) Integer.parseInt(searchLimit.getText()); } catch (NumberFormatException e) { return false; } return true; } @Override public void applyTo(IRepositoryQuery query) { query.setSummary(getQueryTitle()); query.setUrl(filterKeyToUrl.get(new FilterKey(getSelectedProject().getValue(), getSelected(projectFilters)))); // possibly null query.setAttribute(IMantisClient.SEARCH_LIMIT, searchLimit.getText()); query.setAttribute(IMantisClient.PROJECT_NAME, getSelectedProject().getName()); query.setAttribute(IMantisClient.FILTER_NAME, getSelected(projectFilters)); } private void refreshFilterCombo() { try { MantisCache cache = getMantisClient().getCache(new NullProgressMonitor()); String valueToSet = getSelected(projectFilters); projectFilters.removeAll(); if (getSelectedProject() == null) return; int selectedProjectId = getSelectedProject().getValue(); for (MantisProjectFilter pd : cache.getProjectFilters(selectedProjectId)) { projectFilters.add(pd.getName()); filterKeyToUrl.put(new FilterKey(selectedProjectId, pd.getName()), pd.getUrl()); } if (valueToSet != null) select(projectFilters, valueToSet); } catch (MantisException e) { setErrorMessage("Failed updating attributes " + e.getMessage() + " ."); } updateButtonsIfNeeded(); } @Override protected boolean restoreState(IRepositoryQuery query) { try { MantisCache cache = getMantisClient().getCache(new NullProgressMonitor()); MantisSearch search = MantisUtils.getMantisSearch(query); tree.getViewer().setSelection(new StructuredSelection(cache.getProjectByName(search.getProjectName()))); select(projectFilters, search.getFilterName()); searchLimit.setText(String.valueOf(search.getLimit())); return true; } catch (MantisException e) { MantisUIPlugin.handleError(e, "Failed restoring query page state from query " + query, false); return false; } } private void updateButtonsIfNeeded() { if (getContainer() != null) getContainer().updateButtons(); setPageComplete(isPageComplete()); } @Override protected void doRefreshControls() { refreshProjectTree(); refreshFilterCombo(); } @Override protected boolean hasRepositoryConfiguration() { try { return getMantisClient().getCacheData().hasBeenRefreshed(); } catch (MantisException e) { return false; } } private static final class FilterKey { private int projectId; private String filterName; public FilterKey(int projectId, String filterName) { this.projectId = projectId; this.filterName = filterName; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((filterName == null) ? 0 : filterName.hashCode()); result = prime * result + projectId; return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; FilterKey other = (FilterKey) obj; if (filterName == null) { if (other.filterName != null) return false; } else if (!filterName.equals(other.filterName)) return false; if (projectId != other.projectId) return false; return true; } } }