Home | History | Annotate | Download | only in ui
      1 /*******************************************************************************
      2  * Copyright (c) 2000, 2009 IBM Corporation and others.
      3  * All rights reserved. This program and the accompanying materials
      4  * are made available under the terms of the Eclipse Public License v1.0
      5  * which accompanies this distribution, and is available at
      6  * http://www.eclipse.org/legal/epl-v10.html
      7  *
      8  * Contributors:
      9  *     IBM Corporation - initial API and implementation
     10  *******************************************************************************/
     11 package org.eclipse.test.internal.performance.results.ui;
     12 
     13 
     14 import java.io.File;
     15 import java.io.PrintWriter;
     16 import java.io.StringWriter;
     17 import java.lang.reflect.InvocationTargetException;
     18 import java.util.Comparator;
     19 
     20 import org.eclipse.core.runtime.IProgressMonitor;
     21 import org.eclipse.core.runtime.IStatus;
     22 import org.eclipse.core.runtime.preferences.InstanceScope;
     23 import org.eclipse.jface.action.Action;
     24 import org.eclipse.jface.action.IMenuManager;
     25 import org.eclipse.jface.action.Separator;
     26 import org.eclipse.jface.dialogs.MessageDialog;
     27 import org.eclipse.jface.dialogs.ProgressMonitorDialog;
     28 import org.eclipse.jface.operation.IRunnableWithProgress;
     29 import org.eclipse.jface.resource.JFaceResources;
     30 import org.eclipse.jface.viewers.IStructuredSelection;
     31 import org.eclipse.jface.viewers.LabelProvider;
     32 import org.eclipse.jface.viewers.SelectionChangedEvent;
     33 import org.eclipse.jface.viewers.TreeViewer;
     34 import org.eclipse.jface.viewers.Viewer;
     35 import org.eclipse.jface.viewers.ViewerSorter;
     36 import org.eclipse.swt.SWT;
     37 import org.eclipse.swt.graphics.Color;
     38 import org.eclipse.swt.graphics.Font;
     39 import org.eclipse.swt.graphics.FontData;
     40 import org.eclipse.swt.widgets.Composite;
     41 import org.eclipse.test.internal.performance.results.db.DB_Results;
     42 import org.eclipse.test.internal.performance.results.model.BuildResultsElement;
     43 import org.eclipse.test.internal.performance.results.model.ResultsElement;
     44 import org.eclipse.test.internal.performance.results.utils.IPerformancesConstants;
     45 import org.eclipse.test.internal.performance.results.utils.Util;
     46 import org.eclipse.test.performance.ui.GenerateResults;
     47 import org.eclipse.ui.PlatformUI;
     48 import org.eclipse.ui.dialogs.ElementListSelectionDialog;
     49 import org.eclipse.ui.model.WorkbenchContentProvider;
     50 import org.eclipse.ui.model.WorkbenchLabelProvider;
     51 
     52 
     53 /**
     54  * View to see all the builds which have performance results stored in the database.
     55  * <p>
     56  * Typical actions from this view are update local data files with builds results
     57  * and generated the HTML pages.
     58  * </p>
     59  */
     60 public class BuildsView extends PerformancesView {
     61 
     62 	/**
     63 	 * Action to generate results.
     64 	 */
     65 	final class GenerateAction extends Action {
     66 		IStatus status;
     67 
     68 		public void run() {
     69 
     70 			// Ask for output directory
     71 			String resultGenerationDir = BuildsView.this.preferences.get(IPerformancesConstants.PRE_RESULTS_GENERATION_DIR, "");
     72 			String pathFilter = (BuildsView.this.outputDir == null) ? resultGenerationDir : BuildsView.this.outputDir.getPath();
     73 			File dir = changeDir(pathFilter, "Select directory to write comparison files");
     74 			if (dir == null) {
     75 				return;
     76 			}
     77 			BuildsView.this.outputDir = dir;
     78 			BuildsView.this.preferences.put(IPerformancesConstants.PRE_RESULTS_GENERATION_DIR, dir.getAbsolutePath());
     79 
     80 			// Select the reference
     81 			String[] baselines = BuildsView.this.results.getBaselines();
     82 			int bLength = baselines.length;
     83 			String selectedBaseline;
     84 			switch (bLength) {
     85 				case 0:
     86 					// no baseline, nothing to do...
     87 					selectedBaseline = BuildsView.this.results.getPerformanceResults().getBaselineName();
     88 					break;
     89 				case 1:
     90 					// only one baseline, no selection to do
     91 					selectedBaseline = baselines[0];
     92 					break;
     93 				default:
     94 					// select the baseline from list
     95 					ElementListSelectionDialog dialog = new ElementListSelectionDialog(getSite().getShell(), new LabelProvider());
     96 					dialog.setTitle(getTitleToolTip());
     97 					dialog.setMessage("Select the baseline to use while generating results:");
     98 					String[] defaultBaseline = new String[] { baselines[baselines.length - 1] };
     99 					dialog.setInitialSelections(defaultBaseline);
    100 					dialog.setElements(baselines);
    101 					dialog.open();
    102 					Object[] selected = dialog.getResult();
    103 					if (selected == null)
    104 						return;
    105 					selectedBaseline = (String) selected[0];
    106 					break;
    107 			}
    108 			final String baselineName = selectedBaseline;
    109 			BuildsView.this.results.getPerformanceResults().setBaselineName(baselineName);
    110 
    111 			// Ask for fingerprints
    112 			final boolean fingerprints = MessageDialog.openQuestion(BuildsView.this.shell, getTitleToolTip(), "Generate only fingerprints?");
    113 
    114 			// Generate all selected builds
    115 			int length = BuildsView.this.buildsResults.length;
    116 			for (int i = 0; i < length; i++) {
    117 				generate(i, baselineName, fingerprints);
    118 			}
    119 		}
    120 
    121 		/*
    122 		 * Generate the HTML pages.
    123 		 */
    124 		private void generate(int i, final String baselineName, final boolean fingerprints) {
    125 			// Create output directory
    126 			final String buildName = BuildsView.this.buildsResults[i].getName();
    127 			final File genDir = new File(BuildsView.this.outputDir, buildName);
    128 			if (!genDir.exists() && !genDir.mkdir()) {
    129 				MessageDialog.openError(BuildsView.this.shell, getTitleToolTip(), "Cannot create " + genDir.getPath() + " to generate results!");
    130 				return;
    131 			}
    132 
    133 			// Create runnable
    134 			IRunnableWithProgress runnable = new IRunnableWithProgress() {
    135 
    136 				public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
    137 					try {
    138 						monitor.beginTask("Generate performance results", 10000);
    139 						GenerateResults generation = new GenerateResults(BuildsView.this.results.getPerformanceResults(),
    140 						    buildName,
    141 						    baselineName,
    142 						    fingerprints,
    143 						    BuildsView.this.dataDir,
    144 						    genDir);
    145 						GenerateAction.this.status = generation.run(monitor);
    146 						monitor.done();
    147 					} catch (Exception e) {
    148 						e.printStackTrace();
    149 					}
    150 				}
    151 			};
    152 
    153 			// Run with progress monitor
    154 			ProgressMonitorDialog readProgress = new ProgressMonitorDialog(getSite().getShell());
    155 			try {
    156 				readProgress.run(true, true, runnable);
    157 			} catch (InvocationTargetException e) {
    158 				// skip
    159 			} catch (InterruptedException e) {
    160 				// skip
    161 			}
    162 
    163 			// Results
    164 			if (!this.status.isOK()) {
    165 				StringWriter swriter = new StringWriter();
    166 				PrintWriter pwriter = new PrintWriter(swriter);
    167 				swriter.write(this.status.getMessage());
    168 				Throwable ex = this.status.getException();
    169 				if (ex != null) {
    170 					swriter.write(": ");
    171 					swriter.write(ex.getMessage());
    172 					swriter.write('\n');
    173 					ex.printStackTrace(pwriter);
    174 				}
    175 				MessageDialog.open(this.status.getSeverity(),
    176 				    BuildsView.this.shell,
    177 				    getTitleToolTip(),
    178 				    swriter.toString(),
    179 				    SWT.NONE);
    180 			}
    181 		}
    182 	}
    183 
    184 	/**
    185 	 * Action to update local data files with the performance results of a build.
    186 	 *
    187 	 * This may be done lazily (i.e. not done if the local data already knows
    188 	 * the build) or forced (i.e. done whatever the local data files contain).
    189 	 */
    190 	class UpdateBuildAction extends Action {
    191 
    192 		boolean force;
    193 
    194 		UpdateBuildAction(boolean force) {
    195 			super();
    196 			this.force = force;
    197 		}
    198 
    199 		public void run() {
    200 
    201 			// Verify that directories are set
    202 			if (BuildsView.this.dataDir == null) {
    203 				if (changeDataDir() == null) {
    204 					if (!MessageDialog.openConfirm(BuildsView.this.shell, getTitleToolTip(), "No local files directory is set, hence the update could not be written! OK to continue?")) {
    205 						return;
    206 					}
    207 				}
    208 			}
    209 
    210 			// Progress dialog
    211 			IRunnableWithProgress runnable = new IRunnableWithProgress() {
    212 
    213 				public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
    214 					try {
    215 						updateBuilds(monitor);
    216 					} catch (Exception e) {
    217 						e.printStackTrace();
    218 					}
    219 				}
    220 			};
    221 			ProgressMonitorDialog readProgress = new ProgressMonitorDialog(getSite().getShell());
    222 			try {
    223 				readProgress.run(true, true, runnable);
    224 			} catch (InvocationTargetException e) {
    225 				return;
    226 			} catch (InterruptedException e) {
    227 				return;
    228 			}
    229 
    230 			// Reset Components and Builds views input
    231 			refreshInput();
    232 			getSiblingView().refreshInput();
    233 		}
    234 
    235 		void updateBuilds(IProgressMonitor monitor) {
    236 			BuildsView.this.updateBuilds(monitor, this.force);
    237 		}
    238 	}
    239 
    240 	/**
    241 	 * Action to update local data files with the performance results of all builds.
    242 	 *
    243 	 * This may be done lazily (i.e. not done if the local data already knows
    244 	 * the build) or forced (i.e. done whatever the local data files contain).
    245 	 */
    246 	class UpdateAllBuildsAction extends UpdateBuildAction {
    247 
    248 		UpdateAllBuildsAction(boolean force) {
    249 			super(force);
    250 		}
    251 //
    252 //		public boolean isEnabled() {
    253 //			String[] elements = buildsToUpdate();
    254 //			return elements != null;
    255 //		}
    256 
    257 		void updateBuilds(IProgressMonitor monitor) {
    258 			BuildsView.this.updateAllBuilds(monitor, this.force);
    259 		}
    260 	}
    261 
    262 	/**
    263 	 * Class to compare builds regarding their date instead of their name.
    264 	 *
    265 	 * @see Util#getBuildDate(String)
    266 	 */
    267 	class BuildDateComparator implements Comparator {
    268 		public int compare(Object o1, Object o2) {
    269 	        String s1 = (String) o1;
    270 	        String s2 = (String) o2;
    271 	        return Util.getBuildDate(s1).compareTo(Util.getBuildDate(s2));
    272 	    }
    273 	}
    274 
    275 	// Views
    276 	PerformancesView componentsView;
    277 
    278 	// Results model
    279 	BuildResultsElement[] buildsResults;
    280 
    281 	// Generation info
    282 	File outputDir;
    283 
    284 	// Actions
    285 	Action generate;
    286 	UpdateBuildAction updateBuild, updateAllBuilds;
    287 //	UpdateBuildAction forceUpdateBuild, forceUpdateAllBuilds;
    288 
    289 	// SWT resources
    290 	Font italicFont;
    291 
    292 /*
    293  * Default constructor.
    294  */
    295 public BuildsView() {
    296 	this.preferences = new InstanceScope().getNode(IPerformancesConstants.PLUGIN_ID);
    297 	this.preferences.addPreferenceChangeListener(this);
    298 }
    299 
    300 /*
    301  * Compute the list of builds to update based on their status.
    302  */
    303 String[] buildsToUpdate() {
    304 	Object[] elements = this.results.getBuilds();
    305 	int length = elements.length;
    306 	String[] buildsToUpdate = new String[length];
    307 	int count = 0;
    308 	for (int i=0; i<length; i++) {
    309 		BuildResultsElement element = (BuildResultsElement) elements[i];
    310 		if (element.getStatus() == 0) {
    311 	        buildsToUpdate[count++] = element.getName();
    312 		}
    313 	}
    314 	if (count == 0) return null;
    315 	if (count < length) {
    316 		System.arraycopy(buildsToUpdate, 0, buildsToUpdate = new String[count], 0, count);
    317 	}
    318 	return buildsToUpdate;
    319 }
    320 
    321 /* (non-Javadoc)
    322  * @see org.eclipse.test.internal.performance.results.ui.PerformancesView#createPartControl(org.eclipse.swt.widgets.Composite)
    323  */
    324 public void createPartControl(Composite parent) {
    325 	super.createPartControl(parent);
    326 
    327 	// Create the viewer
    328 	this.viewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
    329 
    330 	// Set the content provider: first level is builds list
    331 	WorkbenchContentProvider contentProvider = new WorkbenchContentProvider() {
    332 		public Object[] getElements(Object o) {
    333 			return getBuilds();
    334 		}
    335 	};
    336 	this.viewer.setContentProvider(contentProvider);
    337 
    338 	// Set the label provider
    339 	WorkbenchLabelProvider labelProvider = new WorkbenchLabelProvider() {
    340 
    341 		// Set an italic font when no local data have been read
    342 		public Font getFont(Object element) {
    343 			Font font = super.getFont(element);
    344 			if (element instanceof BuildResultsElement) {
    345 				if (((BuildResultsElement) element).isUnknown()) {
    346 					if (BuildsView.this.italicFont == null) {
    347 						FontData[] defaultFont = JFaceResources.getDefaultFont().getFontData();
    348 						FontData italicFontData = new FontData(defaultFont[0].getName(), defaultFont[0].getHeight(), SWT.ITALIC);
    349 						BuildsView.this.italicFont = new Font(DEFAULT_DISPLAY, italicFontData);
    350 					}
    351 					return BuildsView.this.italicFont;
    352 				}
    353 			}
    354 			return font;
    355 		}
    356 
    357 		// Set font in gray when no local data is available (i.e. local data needs to be updated)
    358 		public Color getForeground(Object element) {
    359 			Color color = super.getForeground(element);
    360 			if (element instanceof BuildResultsElement) {
    361 				if (!((BuildResultsElement) element).isRead()) {
    362 					color = DARK_GRAY;
    363 				}
    364 			}
    365 			return color;
    366 		}
    367 	};
    368 	this.viewer.setLabelProvider(labelProvider);
    369 
    370 	// Set the children sorter
    371 	ViewerSorter nameSorter = new ViewerSorter() {
    372 
    373 		// Sort children using specific comparison (see the implementation
    374 		// of the #compareTo(Object) in the ResultsElement hierarchy
    375 		public int compare(Viewer view, Object e1, Object e2) {
    376 			if (e2 instanceof ResultsElement) {
    377 				return ((ResultsElement) e2).compareTo(e1);
    378 			}
    379 			return super.compare(view, e1, e2);
    380 		}
    381 	};
    382 	this.viewer.setSorter(nameSorter);
    383 
    384 	// Finalize viewer initialization
    385 	PlatformUI.getWorkbench().getHelpSystem().setHelp(this.viewer.getControl(), "org.eclipse.test.performance.ui.builds");
    386 	finalizeViewerCreation();
    387 }
    388 
    389 /* (non-Javadoc)
    390  * @see org.eclipse.ui.part.WorkbenchPart#dispose()
    391  */
    392 public void dispose() {
    393 	if (this.italicFont != null) {
    394 		this.italicFont.dispose();
    395 	}
    396 	super.dispose();
    397 }
    398 
    399 /*
    400  * (non-Javadoc)
    401  * @see org.eclipse.test.internal.performance.results.ui.PerformancesView#fillContextMenu(org.eclipse.jface.action.IMenuManager)
    402  */
    403 void fillContextMenu(IMenuManager manager) {
    404 	super.fillContextMenu(manager);
    405 	manager.add(this.generate);
    406 	manager.add(this.updateBuild);
    407 //	manager.add(this.forceUpdateBuild);
    408 }
    409 
    410 /*
    411  * (non-Javadoc)
    412  * @see org.eclipse.test.internal.performance.results.ui.PerformancesView#fillLocalPullDown(org.eclipse.jface.action.IMenuManager)
    413  */
    414 void fillFiltersDropDown(IMenuManager manager) {
    415 	super.fillFiltersDropDown(manager);
    416 	manager.add(this.filterLastBuilds);
    417 }
    418 
    419 /*
    420  * Fill the local data drop-down menu
    421  */
    422 void fillLocalDataDropDown(IMenuManager manager) {
    423 	super.fillLocalDataDropDown(manager);
    424 	manager.add(new Separator());
    425 	manager.add(this.updateAllBuilds);
    426 //	manager.add(this.forceUpdateAllBuilds);
    427 }
    428 
    429 /*
    430  * Get all builds from the model.
    431  */
    432 Object[] getBuilds() {
    433 	if (this.results == null) {
    434 		initResults();
    435 	}
    436 	return this.results.getBuilds();
    437 }
    438 
    439 /*
    440  * Return the components view.
    441  */
    442 PerformancesView getSiblingView() {
    443 	if (this.componentsView == null) {
    444 		this.componentsView = (PerformancesView) getWorkbenchView("org.eclipse.test.internal.performance.results.ui.ComponentsView");
    445 	}
    446 	return this.componentsView;
    447 }
    448 
    449 /*
    450  * (non-Javadoc)
    451  * @see org.eclipse.test.internal.performance.results.ui.PerformancesView#makeActions()
    452  */
    453 void makeActions() {
    454 
    455 	super.makeActions();
    456 
    457 	// Generate action
    458 	this.generate = new GenerateAction();
    459 	this.generate.setText("&Generate");
    460 
    461 	// Update build actions
    462 	boolean connected = this.preferences.getBoolean(IPerformancesConstants.PRE_DATABASE_CONNECTION, IPerformancesConstants.DEFAULT_DATABASE_CONNECTION);
    463 	this.updateBuild = new UpdateBuildAction(false);
    464 	this.updateBuild.setText("&Update from DB");
    465 	this.updateBuild.setEnabled(connected);
    466 //	this.forceUpdateBuild = new UpdateBuildAction(true);
    467 //	this.forceUpdateBuild.setText("Force Update");
    468 
    469 	// Update build action
    470 	this.updateAllBuilds = new UpdateAllBuildsAction(false);
    471 	this.updateAllBuilds.setText("&Update from DB (all)");
    472 	this.updateAllBuilds.setEnabled(connected);
    473 //	this.forceUpdateAllBuilds = new UpdateAllBuildsAction(true);
    474 //	this.forceUpdateAllBuilds.setText("Force Update all");
    475 
    476 	// Set filters default
    477 	this.filterBaselineBuilds.setChecked(false);
    478 	this.filterNightlyBuilds.setChecked(false);
    479 }
    480 
    481 /**
    482  * Reset the views.
    483  */
    484 public void resetView() {
    485 
    486 	boolean debug = true;
    487 
    488 	// Look whether database constants has changed or not
    489 	int eclipseVersion = this.preferences.getInt(IPerformancesConstants.PRE_ECLIPSE_VERSION, IPerformancesConstants.DEFAULT_ECLIPSE_VERSION);
    490 	boolean connected = this.preferences.getBoolean(IPerformancesConstants.PRE_DATABASE_CONNECTION, IPerformancesConstants.DEFAULT_DATABASE_CONNECTION);
    491 	String databaseLocation = this.preferences.get(IPerformancesConstants.PRE_DATABASE_LOCATION, IPerformancesConstants.NETWORK_DATABASE_LOCATION);
    492 	String lastBuild = this.preferences.get(IPerformancesConstants.PRE_LAST_BUILD, null);
    493 	boolean noLastBuild = lastBuild.length() == 0;
    494 	if (debug) {
    495 		System.out.println("Reset View:");
    496 		System.out.println("	- eclispe version = "+eclipseVersion);
    497 		System.out.println("	- connected       = "+connected);
    498 		System.out.println("	- db location     = "+databaseLocation);
    499 		System.out.println("	- last build      = "+(noLastBuild?"<none>":lastBuild));
    500 	}
    501 	final boolean sameVersion = DB_Results.getDbVersion().endsWith(Integer.toString(eclipseVersion));
    502 	final boolean sameConnection = connected == DB_Results.DB_CONNECTION;
    503 	final boolean sameDB = sameVersion && databaseLocation.equals(DB_Results.getDbLocation());
    504 	boolean sameLastBuild = (noLastBuild && LAST_BUILD == null) || lastBuild.equals(LAST_BUILD);
    505 	if (debug) {
    506 		System.out.println("	- same version:    "+sameVersion);
    507 		System.out.println("	- same connection: "+sameConnection);
    508 		System.out.println("	- same DB:         "+sameDB);
    509 		System.out.println("	- same last build: "+sameLastBuild);
    510 	}
    511 	final PerformancesView siblingView = getSiblingView();
    512 	if (sameConnection && sameDB) {
    513 		if (!sameLastBuild) {
    514 			// Set last build
    515 			LAST_BUILD = noLastBuild ? null : lastBuild;
    516 			this.results.setLastBuildName(LAST_BUILD);
    517 			siblingView.results.setLastBuildName(LAST_BUILD);
    518 
    519 			// Reset views content
    520 			resetInput();
    521 			siblingView.resetInput();
    522 
    523 			// May be read local data now
    524 			File newDataDir = changeDataDir();
    525 			if (newDataDir == null) {
    526 				this.dataDir = null;
    527 				siblingView.dataDir = null;
    528 			}
    529 		}
    530 		// No database preferences has changed do nothing
    531 		return;
    532 	}
    533 
    534 	// Update database constants
    535 	boolean updated = DB_Results.updateDbConstants(connected, eclipseVersion, databaseLocation);
    536 	if (debug) {
    537 		System.out.println("	- updated:         "+updated);
    538 	}
    539 	if (!connected) {
    540 		if (!updated) {
    541 			MessageDialog.openError(this.shell, getTitleToolTip(), "Error while updating database results constants!\nOpen error log to see more details on this error");
    542 		}
    543 	} else if (updated) {
    544 		StringBuffer message = new StringBuffer("Database connection has been correctly ");
    545 		message.append( connected ? "opened." : "closed.");
    546 		MessageDialog.openInformation(this.shell, getTitleToolTip(), message.toString());
    547 	} else {
    548 		MessageDialog.openError(this.shell, getTitleToolTip(), "The database connection cannot be established!\nOpen error log to see more details on this error");
    549 		DB_Results.updateDbConstants(false, eclipseVersion, databaseLocation);
    550 	}
    551 	setTitleToolTip();
    552 	siblingView.setTitleToolTip();
    553 
    554 	// Refresh view
    555 	if (sameVersion && sameLastBuild) {
    556 		// Refresh only builds view as the sibling view (Components) contents is based on local data files contents
    557 		this.results.resetBuildNames();
    558 		refreshInput();
    559 	} else {
    560 		// Reset views content
    561 		resetInput();
    562 		siblingView.resetInput();
    563 
    564 		// May be read local data now
    565 		if (MessageDialog.openQuestion(this.shell, getTitleToolTip(), "Do you want to read local data right now?")) {
    566 			changeDataDir();
    567 		} else {
    568 			this.dataDir = null;
    569 			siblingView.dataDir = null;
    570 		}
    571 	}
    572 
    573 	// Update actions
    574 	this.updateBuild.setEnabled(connected);
    575 	this.updateAllBuilds.setEnabled(connected);
    576 }
    577 
    578 /*
    579  * (non-Javadoc)
    580  * @see org.eclipse.test.internal.performance.results.ui.PerformancesView#selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent)
    581  */
    582 public void selectionChanged(SelectionChangedEvent event) {
    583 	super.selectionChanged(event);
    584 
    585 	// Update selected element
    586 	Object selection = this.viewer.getSelection();
    587 	int length = 0;
    588 	if (selection instanceof IStructuredSelection) {
    589 		Object[] elements = ((IStructuredSelection)selection).toArray();
    590 		length = elements == null ? 0 : elements.length;
    591 		this.buildsResults = new BuildResultsElement[length];
    592 		if (length == 0) {
    593 			this.updateAllBuilds.setText("&Update from DB (all)");
    594 			return;
    595 		}
    596 		for (int i=0; i<length; i++) {
    597 			this.buildsResults[i] = (BuildResultsElement) elements[i];
    598 		}
    599 	} else {
    600 		return;
    601 	}
    602 
    603 	// Update update build action
    604 //	boolean enableUpdateBuild = true;
    605 //	boolean enableGenerate = true;
    606 	int readBuilds = 0;
    607 	for (int i=0; i<length; i++) {
    608 		if (this.buildsResults[i].isRead()) {
    609 //			enableUpdateBuild = false;
    610 			readBuilds++;
    611 		} else {
    612 //			enableGenerate = false;
    613 		}
    614 	}
    615 //	this.updateBuild.setEnabled(enableUpdateBuild);
    616 //	this.forceUpdateBuild.setEnabled(!enableUpdateBuild);
    617 	final boolean force = readBuilds < length;
    618 	this.updateBuild.force = force;
    619 	this.updateAllBuilds.force = force;
    620 	this.updateAllBuilds.setText("&Update from DB");
    621 
    622 	// Update generate action
    623 	boolean enableGenerate = true;
    624 	if (enableGenerate) {
    625 		for (int i=0; i<length; i++) {
    626 			if (this.buildsResults[i].getName().startsWith(DB_Results.getDbBaselinePrefix())) {
    627 				enableGenerate = false;
    628 				break;
    629 			}
    630 		}
    631 	}
    632 	this.generate.setEnabled(enableGenerate);
    633 }
    634 
    635 void updateAllBuilds(IProgressMonitor monitor, boolean force) {
    636 	if (this.dataDir == null) {
    637 		changeDataDir();
    638 	}
    639 	String[] builds = buildsToUpdate();
    640 	if (builds == null) {
    641 		this.results.updateBuild(null, true, this.dataDir, monitor);
    642 	} else {
    643 		this.results.updateBuilds(builds, force, this.dataDir, monitor);
    644 	}
    645 }
    646 
    647 void updateBuilds(IProgressMonitor monitor, boolean force) {
    648 	if (this.dataDir == null) {
    649 		changeDataDir();
    650 	}
    651 	int length = this.buildsResults.length;
    652 	String[] builds = new String[length];
    653 	for (int i = 0; i < length; i++) {
    654 		builds[i] = this.buildsResults[i].getName();
    655 	}
    656 	this.results.updateBuilds(builds, force, this.dataDir, monitor);
    657 }
    658 
    659 }