diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/core/MakeBuilder.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/core/MakeBuilder.java index cecc4d8c73f..4a1f2df4d7d 100644 --- a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/core/MakeBuilder.java +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/core/MakeBuilder.java @@ -9,6 +9,7 @@ * QNX Software Systems - Initial API and implementation * Tianchao Li (tianchao.li@gmail.com) - arbitrary build directory (bug #136136) * Dmitry Kozlov (CodeSourcery) - Build error highlighting and navigation + * Save build output *******************************************************************************/ package org.eclipse.cdt.make.core; @@ -29,6 +30,7 @@ import org.eclipse.cdt.core.ICommandLauncher; import org.eclipse.cdt.core.model.ICModelMarker; import org.eclipse.cdt.core.resources.ACBuilder; import org.eclipse.cdt.core.resources.IConsole; +import org.eclipse.cdt.internal.core.BuildOutputLogger; import org.eclipse.cdt.internal.core.ConsoleOutputSniffer; import org.eclipse.cdt.make.internal.core.MakeMessages; import org.eclipse.cdt.make.internal.core.StreamMonitor; @@ -208,7 +210,8 @@ public class MakeBuilder extends ACBuilder { } ErrorParserManager epm = new ErrorParserManager(getProject(), workingDirectoryURI, this, info.getErrorParsers()); epm.setOutputStream(cos); - StreamMonitor streamMon = new StreamMonitor(new SubProgressMonitor(monitor, 100), epm, last.intValue()); + BuildOutputLogger bol = new BuildOutputLogger(getProject(), epm.getOutputStream()); + StreamMonitor streamMon = new StreamMonitor(new SubProgressMonitor(monitor, 100), bol, last.intValue()); OutputStream stdout = streamMon; OutputStream stderr = streamMon; // Sniff console output for scanner info diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IConfiguration.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IConfiguration.java index baf1bbba51f..fd0dbce1657 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IConfiguration.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IConfiguration.java @@ -1,4 +1,5 @@ /******************************************************************************* + * Copyright (c) 2003, 2010 IBM Corporation 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 @@ -6,6 +7,7 @@ * * Contributors: * IBM - Initial API and implementation + * Dmitry Kozlov (CodeSourcery) - Save build output preferences *******************************************************************************/ package org.eclipse.cdt.managedbuilder.core; @@ -624,4 +626,33 @@ public interface IConfiguration extends IBuildObject, IBuildObjectPropertiesCont IBuildPropertyValue getBuildArtefactType(); void setBuildArtefactType(String id) throws BuildException; + + /** + * Set name of file to save build log + * @param fileName full file name where to build log file + * @since 7.0 + */ + public void setBuildLogFilename(String fileName); + + /** + * Get name of file to which build log is saved + * @return full filename where to save build log file + * @since 7.0 + */ + public String getBuildLogFilename(); + + /** + * Set whether to save build log + * @param saveBuildLog whether to save build log + * @since 7.0 + */ + public void setSavingBuildLog(boolean saveBuildLog); + + /** + * Test if build log saving is turned on + * @return true if saving build log is enabled + * @since 7.0 + */ + public boolean isSavingBuildLog(); + } diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/CommonBuilder.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/CommonBuilder.java index 513dc41b037..b111ba85edb 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/CommonBuilder.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/CommonBuilder.java @@ -9,6 +9,7 @@ * Intel Corporation - Initial API and implementation * IBM Corporation * Dmitry Kozlov (CodeSourcery) - Build error highlighting and navigation + * Save build output *******************************************************************************/ package org.eclipse.cdt.managedbuilder.internal.core; @@ -42,6 +43,7 @@ import org.eclipse.cdt.core.resources.IConsole; import org.eclipse.cdt.core.settings.model.ICConfigurationDescription; import org.eclipse.cdt.core.settings.model.ICProjectDescription; import org.eclipse.cdt.core.settings.model.util.ListComparator; +import org.eclipse.cdt.internal.core.BuildOutputLogger; import org.eclipse.cdt.internal.core.ConsoleOutputSniffer; import org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo2; import org.eclipse.cdt.make.core.scannerconfig.IScannerInfoCollector; @@ -903,6 +905,7 @@ public class CommonBuilder extends ACBuilder { ConsoleOutputStream consoleOutStream = null; IConsole console = null; OutputStream epmOutputStream = null; + BuildOutputLogger bol = null; try { int flags = 0; IResourceDelta delta = getDelta(currentProject); @@ -944,10 +947,19 @@ public class CommonBuilder extends ACBuilder { buf.append(System.getProperty("line.separator", "\n")); //$NON-NLS-1$ //$NON-NLS-2$ buf.append(System.getProperty("line.separator", "\n")); //$NON-NLS-1$ //$NON-NLS-2$ } - consoleOutStream.write(buf.toString().getBytes()); - consoleOutStream.flush(); IBuildDescription des = BuildDescriptionManager.createBuildDescription(cfg, cBS, delta, flags); + // Hook up an error parser manager + String[] errorParsers = builder.getErrorParsers(); + ErrorParserManager epm = new ErrorParserManager(currentProject, des.getDefaultBuildDirLocationURI(), this, errorParsers); + epm.setOutputStream(consoleOutStream); + // This variable is necessary to ensure that the EPM stream stay open + // until we explicitly close it. See bug#123302. + epmOutputStream = epm.getOutputStream(); + bol = new BuildOutputLogger(getProject(), epmOutputStream); + + bol.write(buf.toString().getBytes()); + bol.flush(); DescriptionBuilder dBuilder = null; if (!isParallel) @@ -957,21 +969,13 @@ public class CommonBuilder extends ACBuilder { // Remove all markers for this project removeAllMarkers(currentProject); - // Hook up an error parser manager - String[] errorParsers = builder.getErrorParsers(); - ErrorParserManager epm = new ErrorParserManager(currentProject, des.getDefaultBuildDirLocationURI(), this, errorParsers); - epm.setOutputStream(consoleOutStream); - // This variable is necessary to ensure that the EPM stream stay open - // until we explicitly close it. See bug#123302. - epmOutputStream = epm.getOutputStream(); - int status = 0; long t1 = System.currentTimeMillis(); if (isParallel) - status = ParallelBuilder.build(des, null, null, epmOutputStream, epmOutputStream, monitor, resumeOnErr, buildIncrementaly); + status = ParallelBuilder.build(des, null, null, bol, bol, monitor, resumeOnErr, buildIncrementaly); else - status = dBuilder.build(epmOutputStream, epmOutputStream, monitor); + status = dBuilder.build(bol, bol, monitor); long t2 = System.currentTimeMillis(); // Report either the success or failure of our mission @@ -1011,22 +1015,20 @@ public class CommonBuilder extends ACBuilder { } buf.append(System.getProperty("line.separator", "\n")); //$NON-NLS-1$ //$NON-NLS-2$ // Write message on the console - consoleOutStream.write(buf.toString().getBytes()); - consoleOutStream.flush(); - epmOutputStream.close(); - epmOutputStream = null; + bol.write(buf.toString().getBytes()); + bol.flush(); + // Generate any error markers that the build has discovered monitor.subTask(ManagedMakeMessages .getResourceString(MARKERS)); -//TODO: addBuilderMarkers(epm); bsMngr.setProjectBuildState(currentProject, pBS); } else { buf = new StringBuffer(); buf.append(ManagedMakeMessages.getFormattedString(NOTHING_BUILT, currentProject.getName())); buf.append(System.getProperty("line.separator", "\n")); //$NON-NLS-1$//$NON-NLS-2$ - consoleOutStream.write(buf.toString().getBytes()); - consoleOutStream.flush(); + bol.write(buf.toString().getBytes()); + bol.flush(); } } catch (Exception e) { @@ -1047,6 +1049,12 @@ public class CommonBuilder extends ACBuilder { } forgetLastBuiltState(); } finally { + if ( bol != null ) { + try { + bol.close(); + } catch (IOException e) { + } + } if(epmOutputStream != null){ try { epmOutputStream.close(); @@ -1059,7 +1067,6 @@ public class CommonBuilder extends ACBuilder { } catch (IOException e) { } } -// getGenerationProblems().clear(); monitor.done(); } return false; @@ -1897,7 +1904,8 @@ public class CommonBuilder extends ACBuilder { } ErrorParserManager epm = new ErrorParserManager(currProject, workingDirectoryURI, this, builder.getErrorParsers()); epm.setOutputStream(cos); - StreamMonitor streamMon = new StreamMonitor(new SubProgressMonitor(monitor, 100), epm, last.intValue()); + BuildOutputLogger bol = new BuildOutputLogger(getProject(), epm.getOutputStream()); + StreamMonitor streamMon = new StreamMonitor(new SubProgressMonitor(monitor, 100), bol, last.intValue()); OutputStream stdout = streamMon; OutputStream stderr = streamMon; // Sniff console output for scanner info diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Configuration.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Configuration.java index 070fcf41748..ab33b0bd53b 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Configuration.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Configuration.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2003, 2009 IBM Corporation and others. + * Copyright (c) 2003, 2010 IBM Corporation 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 @@ -8,6 +8,7 @@ * Contributors: * IBM - Initial API and implementation * James Blackburn (Broadcom Corp.) + * Dmitry Kozlov (CodeSourcery) - Save build output preferences *******************************************************************************/ package org.eclipse.cdt.managedbuilder.internal.core; @@ -157,6 +158,8 @@ public class Configuration extends BuildObject implements IConfiguration, IBuild private static final String RC_CHANGE_STATE = "rcState"; //$NON-NLS-1$ //resource change state private int resourceChangeState = -1; + private String buildLogFilename = null; + private boolean savingBuildLog = false; //Internal Builder state //NOTE: these are temporary properties @@ -3055,4 +3058,33 @@ public class Configuration extends BuildObject implements IConfiguration, IBuild public boolean isExtensionBuildObject() { return isExtensionElement(); } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IConfiguration#setBuildLogFilename() + */ + public void setBuildLogFilename(String fileName) { + buildLogFilename = fileName; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IConfiguration#getBuildLogFilename() + */ + public String getBuildLogFilename() { + return buildLogFilename; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IConfiguration#setSavingBuildLog() + */ + public void setSavingBuildLog(boolean save) { + savingBuildLog = save; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IConfiguration#isSavingBuildLog() + */ + public boolean isSavingBuildLog() { + return savingBuildLog; + } + } diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/MultiConfiguration.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/MultiConfiguration.java index c003cebdb66..1632ae16203 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/MultiConfiguration.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/MultiConfiguration.java @@ -7,6 +7,7 @@ * * Contributors: * Intel Corporation - Initial API and implementation + * Dmitry Kozlov (CodeSourcery) - Save build output preferences *******************************************************************************/ package org.eclipse.cdt.managedbuilder.internal.core; @@ -1253,4 +1254,39 @@ public class MultiConfiguration extends MultiItemsHolder implements } return res; } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IConfiguration#setBuildLogFilename() + * Multiconfiguration implementation is not provided + * since the control is disabled in properties in this mode. + */ + public String getBuildLogFilename() { + return ""; //$NON-NLS-1$ + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IConfiguration#isSavingBuildLog() + * Multiconfiguration implementation is not provided + * since the control is disabled in properties in this mode. + */ + public boolean isSavingBuildLog() { + return false; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IConfiguration#setBuildLogFilename() + * Multiconfiguration implementation is not provided + * since the control is disabled in properties in this mode. + */ + public void setBuildLogFilename(String fileName) { + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IConfiguration#setSavingBuildLog() + * Multiconfiguration implementation is not provided + * since the control is disabled in properties in this mode. + */ + public void setSavingBuildLog(boolean saveBuildLog) { + } + } diff --git a/build/org.eclipse.cdt.managedbuilder.ui.tests/src/org/eclipse/cdt/managedbuilder/ui/tests/util/TestConfiguration.java b/build/org.eclipse.cdt.managedbuilder.ui.tests/src/org/eclipse/cdt/managedbuilder/ui/tests/util/TestConfiguration.java index 57926250ceb..d35334cb7a6 100644 --- a/build/org.eclipse.cdt.managedbuilder.ui.tests/src/org/eclipse/cdt/managedbuilder/ui/tests/util/TestConfiguration.java +++ b/build/org.eclipse.cdt.managedbuilder.ui.tests/src/org/eclipse/cdt/managedbuilder/ui/tests/util/TestConfiguration.java @@ -559,5 +559,22 @@ public class TestConfiguration implements IConfiguration { } + public String getBuildLogFilename() { + // TODO Auto-generated method stub + return null; + } + + public boolean isSavingBuildLog() { + // TODO Auto-generated method stub + return false; + } + + public void setBuildLogFilename(String fileName) { + // TODO Auto-generated method stub + } + + public void setSavingBuildLog(boolean saveBuildLog) { + // TODO Auto-generated method stub + } } diff --git a/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/ui/properties/BuilderSettingsTab.java b/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/ui/properties/BuilderSettingsTab.java index e8b7de650c2..9f6a1e1ebff 100644 --- a/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/ui/properties/BuilderSettingsTab.java +++ b/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/ui/properties/BuilderSettingsTab.java @@ -8,16 +8,23 @@ * Contributors: * Intel Corporation - Initial API and implementation * IBM Corporation + * Dmitry Kozlov (CodeSourcery) - save build output preferences *******************************************************************************/ package org.eclipse.cdt.managedbuilder.ui.properties; +import org.eclipse.cdt.core.settings.model.ICConfigurationDescription; +import org.eclipse.cdt.core.settings.model.ICProjectDescription; import org.eclipse.cdt.core.settings.model.ICResourceDescription; +import org.eclipse.cdt.internal.core.BuildOutputLogger; import org.eclipse.cdt.managedbuilder.core.IBuilder; import org.eclipse.cdt.managedbuilder.core.IConfiguration; import org.eclipse.cdt.managedbuilder.core.IMultiConfiguration; +import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; import org.eclipse.cdt.managedbuilder.internal.core.Configuration; import org.eclipse.cdt.managedbuilder.internal.core.MultiConfiguration; import org.eclipse.cdt.ui.newui.AbstractCPropertyTab; +import org.eclipse.cdt.ui.newui.CDTPropertyManager; +import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; @@ -30,6 +37,7 @@ import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.FileDialog; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Text; @@ -55,11 +63,16 @@ public class BuilderSettingsTab extends AbstractCBuildPropertyTab { private Button b_dirFile; private Button b_dirVars; private Group group_dir; - + private Text saveBuildFilename; + private Button saveBuildFileButton; + private Button saveBuildCheckbox; + private Group buildOutputGroup; + private IBuilder bldr; private IConfiguration icfg; private boolean canModify = true; + @Override public void createControls(Composite parent) { super.createControls(parent); usercomp.setLayout(new GridLayout(1, false)); @@ -72,9 +85,10 @@ public class BuilderSettingsTab extends AbstractCBuildPropertyTab { c_builderType.add(Messages.getString("BuilderSettingsTab.2")); //$NON-NLS-1$ c_builderType.add(Messages.getString("BuilderSettingsTab.3")); //$NON-NLS-1$ c_builderType.addSelectionListener(new SelectionAdapter() { - public void widgetSelected(SelectionEvent event) { + @Override + public void widgetSelected(SelectionEvent event) { enableInternalBuilder(c_builderType.getSelectionIndex() == 1); - updateButtons(); + updateButtons(); }}); b_useDefault = setupCheck(g1, Messages.getString("BuilderSettingsTab.4"), 3, GridData.BEGINNING); //$NON-NLS-1$ @@ -119,6 +133,46 @@ public class BuilderSettingsTab extends AbstractCBuildPropertyTab { b_dirWsp = setupBottomButton(c, WORKSPACEBUTTON_NAME); b_dirFile = setupBottomButton(c, FILESYSTEMBUTTON_NAME); b_dirVars = setupBottomButton(c, VARIABLESBUTTON_NAME); + + // Save build output group + if ( page.isForProject() ) { + buildOutputGroup = setupGroup(usercomp, + Messages.getString("BuilderSettingsTab.23"), //$NON-NLS-1$ + 3, GridData.FILL_HORIZONTAL); + @SuppressWarnings("unused") + Label l = setupLabel(buildOutputGroup, Messages.getString("BuilderSettingsTab.24"), 1, GridData.BEGINNING); //$NON-NLS-1$ + saveBuildFilename = setupText(buildOutputGroup, 1, GridData.FILL_HORIZONTAL); + saveBuildFilename.addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent e) { + if ( BuildOutputLogger.canWriteToFile(saveBuildFilename.getText())) { + saveBuildCheckbox.setEnabled(true); + //saveBuildCheckbox.setSelection(true); + } else { + saveBuildCheckbox.setEnabled(false); + saveBuildCheckbox.setSelection(false); + } + icfg.setBuildLogFilename(saveBuildFilename.getText()); + icfg.setSavingBuildLog(saveBuildCheckbox.getSelection()); + }} ); + saveBuildFileButton = new Button(buildOutputGroup, SWT.PUSH); + saveBuildFileButton.setText(Messages.getString("BuilderSettingsTab.25")); //$NON-NLS-1$ + saveBuildFileButton.setData(saveBuildFilename); + saveBuildFileButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent event) { + buttonVarPressed(event); + }}); + saveBuildCheckbox = new Button(buildOutputGroup, SWT.CHECK); + saveBuildCheckbox.setText(Messages.getString("BuilderSettingsTab.26")); //$NON-NLS-1$ + saveBuildCheckbox.setEnabled(false); + saveBuildCheckbox.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent event) { + if ( ((Control)event.widget) == saveBuildCheckbox ) { + icfg.setSavingBuildLog(!icfg.isSavingBuildLog()); + } + }}); + } } private void setManagedBuild(boolean enable) { @@ -130,6 +184,7 @@ public class BuilderSettingsTab extends AbstractCBuildPropertyTab { /** * sets widgets states */ + @Override protected void updateButtons() { bldr = icfg.getEditableBuilder(); @@ -191,6 +246,30 @@ public class BuilderSettingsTab extends AbstractCBuildPropertyTab { if (external) { // just set relatet text widget state, checkPressed(b_useDefault, false); // do not update } + + if ( page.isForProject() ) { + if ( page.isMultiCfg() ) { + buildOutputGroup.setVisible(false); + } else { + boolean b = icfg.isSavingBuildLog(); + buildOutputGroup.setVisible(true); + String s = icfg.getBuildLogFilename(); + if ( s != null ) { + saveBuildFilename.setText(s); + } else { + saveBuildFilename.setText(""); //$NON-NLS-1$ + } + + if ( s != null && BuildOutputLogger.canWriteToFile(s) ) { + saveBuildCheckbox.setSelection(b); + icfg.setSavingBuildLog(b); + } else { + saveBuildCheckbox.setEnabled(false); + saveBuildCheckbox.setSelection(false); + icfg.setSavingBuildLog(false); + } + } + } canModify = true; } @@ -202,9 +281,10 @@ public class BuilderSettingsTab extends AbstractCBuildPropertyTab { b.setLayoutData(fd); b.setData(t_dir); b.addSelectionListener(new SelectionAdapter() { - public void widgetSelected(SelectionEvent event) { - buttonVarPressed(event); - }}); + @Override + public void widgetSelected(SelectionEvent event) { + buttonVarPressed(event); + }}); return b; } @@ -218,7 +298,8 @@ public class BuilderSettingsTab extends AbstractCBuildPropertyTab { b.setData(t); // to get know which text is affected t.setData(b); // to get know which button to enable/disable b.addSelectionListener(new SelectionAdapter() { - public void widgetSelected(SelectionEvent event) { + @Override + public void widgetSelected(SelectionEvent event) { buttonVarPressed(event); }}); if (check != null) check.setData(t); @@ -239,6 +320,11 @@ public class BuilderSettingsTab extends AbstractCBuildPropertyTab { } else if (b.equals(b_dirFile)) { x = getFileSystemDirDialog(usercomp.getShell(), EMPTY_STR); if (x != null) ((Text)b.getData()).setText(x); + } else if (b.equals(saveBuildFileButton)) { + FileDialog dialog = new FileDialog(usercomp.getShell(), SWT.SAVE); + dialog.setText(FILESYSTEM_FILE_DIALOG_TITLE); + x = dialog.open(); + if (x != null) ((Text)b.getData()).setText(x); } else { x = AbstractCPropertyTab.getVariableDialog(usercomp.getShell(), getResDesc().getConfiguration()); if (x != null) ((Text)b.getData()).insert(x); @@ -246,10 +332,11 @@ public class BuilderSettingsTab extends AbstractCBuildPropertyTab { } } - public void checkPressed(SelectionEvent e) { - checkPressed((Control)e.widget, true); - updateButtons(); - } + @Override + public void checkPressed(SelectionEvent e) { + checkPressed((Control)e.widget, true); + updateButtons(); + } private void checkPressed(Control b, boolean needUpdate) { if (b == null) return; @@ -296,15 +383,65 @@ public class BuilderSettingsTab extends AbstractCBuildPropertyTab { * (Copy from config to widgets) * @param cfgd - */ - + @Override public void updateData(ICResourceDescription cfgd) { if (cfgd == null) return; icfg = getCfg(cfgd.getConfiguration()); + if (icfg.getBuildLogFilename() == null) { + // In this case this tab is loaded for the first time, + // and we need to populate configuration with values stored + // in Preferences. This is horrible workaround because we need + // to use this settings in build console which is in cdt ui, + // hence IConfiguration is not accessible there and this values + // have be stored separately. + // That is why we have convention that IConfiguration have + // buildLogFilename set to null this means that it is not loaded. + // Otherwise it is loaded and doesn't require reloading. + // performOk, performApply and performDefaults shouldn't never write + // null values to Preferences to distinct this case from overs. + // + // To properly fix this problem without this workaround we need + // to make IConfiguration accessible for buildconsole package + loadBuildLogSettings(page.getProject(), icfg); + } updateButtons(); } + private static void loadBuildLogSettings(IProject project, IConfiguration icfg) { + BuildOutputLogger.SaveBuildOutputPreferences bp = BuildOutputLogger.readSaveBuildOutputPreferences(project, icfg.getName()); + icfg.setBuildLogFilename(bp.fileName); + icfg.setSavingBuildLog(bp.isSaving); + } + + @Override public void performApply(ICResourceDescription src, ICResourceDescription dst) { BuildBehaviourTab.apply(src, dst, page.isMultiCfg()); + BuildOutputLogger.SaveBuildOutputPreferences bp = new BuildOutputLogger.SaveBuildOutputPreferences(); + bp.fileName = icfg.getBuildLogFilename(); + bp.isSaving = icfg.isSavingBuildLog(); + BuildOutputLogger.writeSaveBuildOutputPreferences(page.getProject(), icfg.getName(), bp); + } + + @Override + public void performOK() { + if ( page.isForProject() ) { + // Saving for all configurations + ICProjectDescription pd = CDTPropertyManager.getProjectDescription(page.getProject()); + if ( pd != null ) { + ICConfigurationDescription cfgs[] = pd.getConfigurations(); + if ( cfgs != null ) { + for (ICConfigurationDescription cd : cfgs) { + IConfiguration c = ManagedBuildManager.getConfigurationForDescription(cd); + BuildOutputLogger.SaveBuildOutputPreferences bp = new BuildOutputLogger.SaveBuildOutputPreferences(); + bp.fileName = c.getBuildLogFilename(); + bp.isSaving = c.isSavingBuildLog(); + BuildOutputLogger.writeSaveBuildOutputPreferences(page.getProject(), c.getName(), bp); + c.setBuildLogFilename(null); + c.setSavingBuildLog(false); + } + } + } + } } /* (non-Javadoc) @@ -321,23 +458,29 @@ public class BuilderSettingsTab extends AbstractCBuildPropertyTab { } // This page can be displayed for project only + @Override public boolean canBeVisible() { return page.isForProject() || page.isForPrefs(); } + @Override public void setVisible (boolean b) { super.setVisible(b); } + @Override protected void performDefaults() { + icfg.setBuildLogFilename(""); //$NON-NLS-1$ + icfg.setSavingBuildLog(false); if (icfg instanceof IMultiConfiguration) { IConfiguration[] cfs = (IConfiguration[])((IMultiConfiguration)icfg).getItems(); for (int i=0; i 0 ) { + // Check path exists in filesystem + File f = new File(fileName); + if ( f.getParentFile() != null && + f.getParentFile().exists() && + f.getParentFile().isDirectory() && + ( !f.exists() || (f.exists() && f.canWrite()) ) ) { + // File can be written + return true; + } + } + return false; + } + + public static String getFileNameKey(IProject project, String cfgName) { + // Make this preference key to be per project + return SAVE_CONSOLE_FILE_ID + "." + project.getName() + "." + cfgName; //$NON-NLS-1$ //$NON-NLS-2$ + } + + public static String getIsSavingKey(IProject project, String cfgName) { + // Make this preference key to be per project + return SAVE_CONSOLE_STATE_ID + "." + project.getName() + "." + cfgName; //$NON-NLS-1$ //$NON-NLS-2$ + } + +} diff --git a/core/org.eclipse.cdt.ui/icons/dlcl16/save_console.gif b/core/org.eclipse.cdt.ui/icons/dlcl16/save_console.gif new file mode 100644 index 00000000000..bdae776216b Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/dlcl16/save_console.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/elcl16/save_console.gif b/core/org.eclipse.cdt.ui/icons/elcl16/save_console.gif new file mode 100644 index 00000000000..555182cacd0 Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/elcl16/save_console.gif differ diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CPluginImages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CPluginImages.java index 4d1ee006855..c89cda61fb3 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CPluginImages.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CPluginImages.java @@ -11,6 +11,7 @@ * Markus Schorn (Wind River Systems) * Anton Leherbauer (Wind River Systems) * Sergey Prigogin (Google) + * Dmitry Kozlov (CodeSourcery) *******************************************************************************/ package org.eclipse.cdt.internal.ui; @@ -139,13 +140,15 @@ public class CPluginImages { // build console public static final String IMG_VIEW_BUILD = NAME_PREFIX + "buildconsole.gif"; //$NON-NLS-1$ - public static final String IMG_VIEW_MENU = NAME_PREFIX + "view_menu.gif"; //$NON-NLS-1$ + public static final String IMG_VIEW_MENU = NAME_PREFIX + "view_menu.gif"; //$NON-NLS-1$ + public static final String IMG_SAVE_CONSOLE = NAME_PREFIX + "save_console.gif"; //$NON-NLS-1$ // unknown type public static final String IMG_OBJS_UNKNOWN = NAME_PREFIX + "unknown_obj.gif"; //$NON-NLS-1$ - public static final ImageDescriptor DESC_BUILD_CONSOLE = createManaged(T_VIEW, IMG_VIEW_BUILD); - public static final ImageDescriptor IMG_VIEW_MENU_DESC = createManaged(T_VIEW, IMG_VIEW_MENU); + public static final ImageDescriptor DESC_BUILD_CONSOLE = createManaged(T_VIEW, IMG_VIEW_BUILD); + public static final ImageDescriptor IMG_VIEW_MENU_DESC = createManaged(T_VIEW, IMG_VIEW_MENU); + public static final ImageDescriptor IMG_SAVE_CONSOLE_DESC = createManaged(T_VIEW, IMG_SAVE_CONSOLE); public static final ImageDescriptor DESC_OBJS_VARIABLE= createManaged(T_OBJ, IMG_OBJS_VARIABLE); public static final ImageDescriptor DESC_OBJS_LOCAL_VARIABLE= createManaged(T_OBJ, IMG_OBJS_LOCAL_VARIABLE); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/buildconsole/BuildConsolePage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/buildconsole/BuildConsolePage.java index 4c137a6b5f8..d24c3626aa5 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/buildconsole/BuildConsolePage.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/buildconsole/BuildConsolePage.java @@ -8,7 +8,8 @@ * Contributors: * QNX Software Systems - initial API and implementation * Red Hat Inc. - multiple build console support - * Dmitry Kozlov (CodeSourcery) - Build error highlighting and navigation + * Dmitry Kozlov (CodeSourcery) - Build error highlighting and navigation + * Save build output *******************************************************************************/ package org.eclipse.cdt.internal.ui.buildconsole; @@ -25,6 +26,10 @@ import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.preferences.IEclipsePreferences; +import org.eclipse.core.runtime.preferences.InstanceScope; +import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener; +import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent; import org.eclipse.jface.action.GroupMarker; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.IMenuListener; @@ -81,14 +86,22 @@ import org.eclipse.ui.texteditor.FindReplaceAction; import org.eclipse.ui.texteditor.ITextEditorActionConstants; import org.eclipse.ui.texteditor.IUpdate; +import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.ProblemMarkerInfo; +import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.model.ICModelMarker; import org.eclipse.cdt.core.resources.IConsole; +import org.eclipse.cdt.core.settings.model.CProjectDescriptionEvent; +import org.eclipse.cdt.core.settings.model.ICConfigurationDescription; +import org.eclipse.cdt.core.settings.model.ICProjectDescription; +import org.eclipse.cdt.core.settings.model.ICProjectDescriptionListener; import org.eclipse.cdt.ui.CUIPlugin; import org.eclipse.cdt.ui.IBuildConsoleEvent; import org.eclipse.cdt.ui.IBuildConsoleListener; import org.eclipse.cdt.ui.IBuildConsoleManager; +import org.eclipse.cdt.internal.core.BuildOutputLogger; + import org.eclipse.cdt.internal.ui.preferences.BuildConsolePreferencePage; public class BuildConsolePage extends Page @@ -96,8 +109,10 @@ public class BuildConsolePage extends Page ISelectionListener, IPropertyChangeListener, IBuildConsoleListener, - ITextListener, - IAdaptable { + ITextListener, + IAdaptable, + IPreferenceChangeListener, + ICProjectDescriptionListener { static final int POSITION_NEXT = -1; static final int POSITION_PREV = -2; @@ -121,6 +136,7 @@ public class BuildConsolePage extends Page private ClearOutputAction fClearOutputAction; private Map fGlobalActions = new HashMap(10); private List fSelectionActions = new ArrayList(3); + SaveConsoleAction fSaveConsoleAction; // menus private Menu fMenu; @@ -140,10 +156,26 @@ public class BuildConsolePage extends Page fConsole = console; fConsoleView = view; fContextMenuId = contextId; + IEclipsePreferences pref = new InstanceScope().getNode(CCorePlugin.PLUGIN_ID); + pref.addPreferenceChangeListener(this); + CoreModel.getDefault().addCProjectDescriptionListener(this, CProjectDescriptionEvent.DATA_APPLIED ); } protected void setProject(IProject project) { - fProject = project; + if (fProject != project && project.isAccessible()) { + fProject = project; + ICProjectDescription projDesc = CoreModel.getDefault().getProjectDescription(project); + fSaveConsoleAction.setChecked(false); + ICConfigurationDescription configDesc = projDesc.getActiveConfiguration(); + // Read save console log preferences + try { + IEclipsePreferences pref = new InstanceScope().getNode(CCorePlugin.PLUGIN_ID); + boolean b = pref.getBoolean(BuildOutputLogger.getIsSavingKey(project, configDesc.getName()),false); + fSaveConsoleAction.setChecked(b); + } catch (Exception e) { + CUIPlugin.log(e); + } + } } protected IProject getProject() { @@ -288,11 +320,13 @@ public class BuildConsolePage extends Page protected void createActions() { fClearOutputAction = new ClearOutputAction(getViewer()); fScrollLockAction = new ScrollLockAction(getViewer()); + fScrollLockAction.setChecked(fIsLocked); fNextErrorAction = new NextErrorAction(this); fPreviousErrorAction = new PreviousErrorAction(this); fShowErrorAction = new ShowErrorAction(this); + fSaveConsoleAction = new SaveConsoleAction(this); + fSaveConsoleAction.setChecked(false); - fScrollLockAction.setChecked(fIsLocked); getViewer().setAutoScroll(!fIsLocked); // In order for the clipboard actions to accessible via their shortcuts // (e.g., Ctrl-C, Ctrl-V), we *must* set a global action handler for @@ -346,7 +380,7 @@ public class BuildConsolePage extends Page mgr.appendToGroup(BuildConsole.ERROR_GROUP, fNextErrorAction); mgr.appendToGroup(BuildConsole.ERROR_GROUP, fPreviousErrorAction); mgr.appendToGroup(BuildConsole.ERROR_GROUP, fShowErrorAction); - + mgr.appendToGroup(IConsoleConstants.OUTPUT_GROUP, fSaveConsoleAction); mgr.appendToGroup(IConsoleConstants.OUTPUT_GROUP, fScrollLockAction); mgr.appendToGroup(IConsoleConstants.OUTPUT_GROUP, fClearOutputAction); } @@ -626,4 +660,33 @@ public class BuildConsolePage extends Page } } + public void preferenceChange(PreferenceChangeEvent event) { + if (fProject != null) { + ICProjectDescription projDesc = CoreModel.getDefault().getProjectDescription(fProject); + ICConfigurationDescription configDesc = projDesc.getActiveConfiguration(); + String sk = BuildOutputLogger.getIsSavingKey(fProject, configDesc.getName()); + String fk = BuildOutputLogger.getFileNameKey(fProject, configDesc.getName()); + if ( sk.equals(event.getKey()) || fk.equals(event.getKey()) ) { + IBuildConsoleManager consoleManager = CUIPlugin.getDefault().getConsoleManager(); + IConsole console = consoleManager.getConsole(fProject); + if (console != null && console instanceof BuildConsolePartitioner) { + BuildOutputLogger.SaveBuildOutputPreferences bp = BuildOutputLogger.readSaveBuildOutputPreferences(fProject); + fSaveConsoleAction.setChecked(bp.isSaving); + } + } + } + } + + public void handleEvent(CProjectDescriptionEvent event) { + ICProjectDescription newPd = event.getNewCProjectDescription(); + ICProjectDescription oldPd = event.getOldCProjectDescription(); + if ( fProject != null && fProject.equals(event.getProject()) && + newPd != null && oldPd != null && + newPd.getActiveConfiguration() != null && + newPd.getActiveConfiguration() != oldPd.getActiveConfiguration() ) { + BuildOutputLogger.SaveBuildOutputPreferences bp = BuildOutputLogger.readSaveBuildOutputPreferences(fProject); + fSaveConsoleAction.setChecked(bp.isSaving); + } + + } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/buildconsole/ConsoleMessages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/buildconsole/ConsoleMessages.java index 0f5dcfafb62..fb9bb6deeb3 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/buildconsole/ConsoleMessages.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/buildconsole/ConsoleMessages.java @@ -8,6 +8,7 @@ * Contributors: * QNX Software Systems - Initial API and implementation * Dmitry Kozlov (CodeSourcery) - Build error highlighting and navigation + * Save build output *******************************************************************************/ package org.eclipse.cdt.internal.ui.buildconsole; @@ -33,6 +34,7 @@ public final class ConsoleMessages extends NLS { public static String PreviousErrorAction_Tooltip; public static String NextErrorAction_Tooltip; public static String ShowErrorAction_Tooltip; + public static String SaveConsole_ActionTooltip; static { NLS.initializeMessages(BUNDLE_NAME, ConsoleMessages.class); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/buildconsole/ConsoleMessages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/buildconsole/ConsoleMessages.properties index a461e0535e1..48cdd5bab37 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/buildconsole/ConsoleMessages.properties +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/buildconsole/ConsoleMessages.properties @@ -24,3 +24,4 @@ ScrollLockAction_Scroll_Lock_1=Scroll Lock NextErrorAction_Tooltip=&Next Error PreviousErrorAction_Tooltip=&Previous Error ShowErrorAction_Tooltip=&Show Error In Editor +SaveConsole_ActionTooltip=Save Console Output To File \ No newline at end of file diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/buildconsole/SaveConsoleAction.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/buildconsole/SaveConsoleAction.java new file mode 100644 index 00000000000..e4523053329 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/buildconsole/SaveConsoleAction.java @@ -0,0 +1,71 @@ +/******************************************************************************* + * Copyright (c) 2010 CodeSourcery 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: + * Dmitry Kozlov (CodeSourcery) - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.internal.ui.buildconsole; + +import org.eclipse.core.resources.IProject; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.preference.PreferenceDialog; +import org.eclipse.jface.window.Window; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.dialogs.PreferencesUtil; + +import org.eclipse.cdt.core.resources.IConsole; +import org.eclipse.cdt.ui.CUIPlugin; +import org.eclipse.cdt.ui.IBuildConsoleManager; + +import org.eclipse.cdt.internal.core.BuildOutputLogger; + +import org.eclipse.cdt.internal.ui.CPluginImages; + +/** + * Save console content to a file + */ +public class SaveConsoleAction extends Action { + + private BuildConsolePage fConsolePage; + + public SaveConsoleAction(BuildConsolePage page) { + super(); + setToolTipText(ConsoleMessages.SaveConsole_ActionTooltip); + setChecked(false); + CPluginImages.setImageDescriptors(this, CPluginImages.T_LCL, CPluginImages.IMG_SAVE_CONSOLE); + fConsolePage = page; + } + + @Override + public void run() { + IProject project = fConsolePage.getProject(); + if ( ! project.isAccessible() ) return; + IBuildConsoleManager consoleManager = CUIPlugin.getDefault().getConsoleManager(); + IConsole console = consoleManager.getConsole(project); + // If state is switched to save build log, but log file is not set + // in project properties, show project properties dialog. + if ( console != null && console instanceof BuildConsolePartitioner ) { + BuildOutputLogger.SaveBuildOutputPreferences bp = + BuildOutputLogger.readSaveBuildOutputPreferences(project); + if ( isChecked() ) { + if ( bp.fileName == null || bp.fileName.trim().length() == 0 ) { + Shell shell = fConsolePage.getControl().getShell(); + String id = "org.eclipse.cdt.managedbuilder.ui.properties.Page_head_build"; //$NON-NLS-1$ + PreferenceDialog d = PreferencesUtil.createPropertyDialogOn(shell, project, id, new String[] { id }, null); + int result = d.open(); + if ( result == Window.CANCEL ) { + setChecked(false); + } + } + } + bp.isSaving = isChecked(); + BuildOutputLogger.writeSaveBuildOutputPreferences(project,bp); + } + } + +}