From c7d29290dd5caf38a2cea99af024813249b76a97 Mon Sep 17 00:00:00 2001 From: Andrew Gvozdev Date: Fri, 21 May 2010 13:53:29 +0000 Subject: [PATCH] bug 306222: Further enhancement of Save Build Console feature --- core/org.eclipse.cdt.ui/plugin.properties | 2 + core/org.eclipse.cdt.ui/plugin.xml | 12 + .../ui/buildconsole/BuildConsoleManager.java | 52 +++- .../ui/buildconsole/BuildConsolePage.java | 74 +----- .../buildconsole/BuildConsolePartitioner.java | 227 +++++++++++++++--- .../ui/buildconsole/BuildOutputStream.java | 4 +- .../ui/buildconsole/ConsoleMessages.java | 10 +- .../buildconsole/ConsoleMessages.properties | 11 +- .../ui/buildconsole/CopyBuildLogAction.java | 107 +++++++++ .../ui/buildconsole/SaveConsoleAction.java | 71 ------ .../preferences/BuildLogPreferencePage.java | 169 +++++++++++++ .../ui/preferences/PreferencesMessages.java | 4 + .../PreferencesMessages.properties | 6 + 13 files changed, 565 insertions(+), 184 deletions(-) create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/buildconsole/CopyBuildLogAction.java delete mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/buildconsole/SaveConsoleAction.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/BuildLogPreferencePage.java diff --git a/core/org.eclipse.cdt.ui/plugin.properties b/core/org.eclipse.cdt.ui/plugin.properties index ff429f60ca7..a839fb9edf6 100644 --- a/core/org.eclipse.cdt.ui/plugin.properties +++ b/core/org.eclipse.cdt.ui/plugin.properties @@ -216,6 +216,8 @@ DeleteRcConfigAction.label=Reset to Default... ExcludeAction.label=Exclude from Build... BuildConfigurationActionSet.descr=Build active configuration for the current project +BuildLoggingPreferencePage.name=Logging + # Common Editor ruler actions AddTask.label=Add &Task... AddTask.tooltip=Add Task... diff --git a/core/org.eclipse.cdt.ui/plugin.xml b/core/org.eclipse.cdt.ui/plugin.xml index bdcafb55510..b1f6fa1a17d 100644 --- a/core/org.eclipse.cdt.ui/plugin.xml +++ b/core/org.eclipse.cdt.ui/plugin.xml @@ -2632,6 +2632,18 @@ + + + + + + + + fGlobalActions = new HashMap(10); private List fSelectionActions = new ArrayList(3); - SaveConsoleAction fSaveConsoleAction; + private CopyBuildLogAction fSaveLogAction; // menus private Menu fMenu; @@ -156,33 +142,11 @@ 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) { if (fProject != project && project.isAccessible()) { fProject = project; - - ICProjectDescription projDesc = CoreModel.getDefault().getProjectDescription(project); - if (projDesc == null) { - // don't support logging for non-C/C++ projects - fSaveConsoleAction.setChecked(false); - fSaveConsoleAction.setEnabled(false); - } else { - fSaveConsoleAction.setEnabled(true); - 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); - } - } } } @@ -332,8 +296,7 @@ public class BuildConsolePage extends Page fNextErrorAction = new NextErrorAction(this); fPreviousErrorAction = new PreviousErrorAction(this); fShowErrorAction = new ShowErrorAction(this); - fSaveConsoleAction = new SaveConsoleAction(this); - fSaveConsoleAction.setChecked(false); + fSaveLogAction = new CopyBuildLogAction(this); getViewer().setAutoScroll(!fIsLocked); // In order for the clipboard actions to accessible via their shortcuts @@ -388,7 +351,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, fSaveLogAction); mgr.appendToGroup(IConsoleConstants.OUTPUT_GROUP, fScrollLockAction); mgr.appendToGroup(IConsoleConstants.OUTPUT_GROUP, fClearOutputAction); } @@ -668,33 +631,4 @@ 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/BuildConsolePartitioner.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/buildconsole/BuildConsolePartitioner.java index 85869562a1c..35917f5b559 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/buildconsole/BuildConsolePartitioner.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/buildconsole/BuildConsolePartitioner.java @@ -8,16 +8,25 @@ * Contributors: * QNX Software Systems - initial API and implementation * Dmitry Kozlov (CodeSourcery) - Build error highlighting and navigation + * Andrew Gvozdev (Quoin Inc.) - Copy build log (bug 306222) *******************************************************************************/ package org.eclipse.cdt.internal.ui.buildconsole; +import java.io.IOException; +import java.io.OutputStream; +import java.net.URI; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Vector; +import org.eclipse.core.filesystem.EFS; +import org.eclipse.core.filesystem.IFileStore; +import org.eclipse.core.filesystem.URIUtil; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.DocumentEvent; import org.eclipse.jface.text.IDocument; @@ -30,6 +39,7 @@ import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.console.ConsolePlugin; +import org.osgi.service.prefs.Preferences; import org.eclipse.cdt.core.ConsoleOutputStream; import org.eclipse.cdt.core.ProblemMarkerInfo; @@ -45,6 +55,8 @@ public class BuildConsolePartitioner IConsole, IPropertyChangeListener { + private IProject fProject; + /** * List of partitions */ @@ -61,7 +73,6 @@ public class BuildConsolePartitioner DocumentMarkerManager fDocumentMarkerManager; boolean killed; BuildConsoleManager fManager; - Boolean outputStreamClosed = new Boolean(false); /** * A queue of stream entries written to standard out and standard err. @@ -71,21 +82,40 @@ public class BuildConsolePartitioner */ Vector fQueue = new Vector(5); - //private boolean fAppending; + private URI fLogURI; + private OutputStream fLogStream; - class StreamEntry { + private class StreamEntry { + static public final int EVENT_APPEND = 0; + static public final int EVENT_OPEN_LOG = 1; + static public final int EVENT_CLOSE_LOG = 2; /** Identifier of the stream written to. */ private BuildConsoleStreamDecorator fStream; /** The text written */ - private StringBuffer fText = null; + private StringBuffer fText = null; /** Problem marker corresponding to the line of text */ private ProblemMarkerInfo fMarker; + /** Type of event **/ + private int eventType; - StreamEntry(String text, BuildConsoleStreamDecorator stream, ProblemMarkerInfo marker) { + public StreamEntry(String text, BuildConsoleStreamDecorator stream, ProblemMarkerInfo marker) { fText = new StringBuffer(text); fStream = stream; fMarker = marker; + eventType = EVENT_APPEND; + } + + /** + * This constructor is used for special events such as clear console or close log. + * + * @param event - kind of event. + */ + public StreamEntry(int event) { + fText = null; + fStream = null; + fMarker = null; + eventType = event; } /** @@ -117,24 +147,73 @@ public class BuildConsolePartitioner return fMarker; } + /** + * Returns type of event + */ + public int getEventType() { + return eventType; + } + } - public BuildConsolePartitioner(BuildConsoleManager manager) { + public BuildConsolePartitioner(IProject project, BuildConsoleManager manager) { + fProject = project; fManager = manager; fMaxLines = BuildConsolePreferencePage.buildConsoleLines(); fDocument = new BuildConsoleDocument(); fDocument.setDocumentPartitioner(this); fDocumentMarkerManager = new DocumentMarkerManager(fDocument, this); connect(fDocument); + + fLogURI = null; + fLogStream = null; + } + + /** + * Sets the indicator that stream was opened so logging can be started. Should be called + * when opening the output stream. + */ + public void setStreamOpened() { + fQueue.add(new StreamEntry(StreamEntry.EVENT_OPEN_LOG)); + asyncProcessQueue(); + } + + /** + * Sets the indicator that stream was closed so logging should be stopped. Should be called when + * build process has finished. Note that there could still be unprocessed console + * stream entries in the queue being worked on in the background. + */ + public void setStreamClosed() { + fQueue.add(new StreamEntry(StreamEntry.EVENT_CLOSE_LOG)); + asyncProcessQueue(); + } + + /** + * @return {@link URI} of build log or {@code null} if not available. + */ + static private URI getLogURI(IProject project) { + URI logURI = null; + + Preferences prefs = BuildConsoleManager.getBuildLogPreferences(project); + boolean keepLog = prefs.getBoolean(BuildConsoleManager.KEY_KEEP_LOG, BuildConsoleManager.CONSOLE_KEEP_LOG_DEFAULT); + if (keepLog) { + String strLocation = prefs.get(BuildConsoleManager.KEY_LOG_LOCATION, BuildConsoleManager.getDefaultConsoleLogLocation(project)); + if (strLocation.trim().length()>0) { + logURI = URIUtil.toURI(strLocation); + } + if (logURI==null) { + IStatus status= new Status(IStatus.ERROR, CUIPlugin.PLUGIN_ID,"Can't determine URI for location=["+strLocation+"]"); //$NON-NLS-1$ //$NON-NLS-2$ + CUIPlugin.log(status); + } + } + return logURI; } /** * Adds the new text to the document. - * - * @param text - * the text to append - * @param stream - * the stream to append to + * + * @param text - the text to append. + * @param stream - the stream to append to. */ public void appendToDocument(String text, BuildConsoleStreamDecorator stream, ProblemMarkerInfo marker) { boolean addToQueue = true; @@ -144,7 +223,7 @@ public class BuildConsolePartitioner StreamEntry entry = fQueue.get(i - 1); // if last stream is the same and we have not exceeded our // display write limit, append. - if (entry.getStream() == stream && entry.size() < 10000 && entry.getMarker() == marker) { + if (entry.getStream()==stream && entry.getEventType()==StreamEntry.EVENT_APPEND && entry.getMarker()==marker && entry.size()<10000) { entry.appendText(text); addToQueue = false; } @@ -153,8 +232,18 @@ public class BuildConsolePartitioner fQueue.add(new StreamEntry(text, stream, marker)); } } - Runnable r = new Runnable() { + if (addToQueue) { + asyncProcessQueue(); + } + } + /** + * Asynchronous processing of stream entries to append to console. + * Note that all these are processed by the same by the user-interface thread + * as of {@link Display#asyncExec(Runnable)}. + */ + private void asyncProcessQueue() { + Runnable r = new Runnable() { public void run() { StreamEntry entry; try { @@ -162,24 +251,77 @@ public class BuildConsolePartitioner } catch (ArrayIndexOutOfBoundsException e) { return; } - fLastStream = entry.getStream(); - try { - warnOfContentChange(fLastStream); + switch (entry.getEventType()) { + case StreamEntry.EVENT_OPEN_LOG: + logOpen(); + break; + case StreamEntry.EVENT_APPEND: + fLastStream = entry.getStream(); + try { + warnOfContentChange(fLastStream); - if ( fLastStream == null ) { - // special case to empty document - fPartitions.clear(); - fDocumentMarkerManager.clear(); - fDocument.set(""); //$NON-NLS-1$ + if (fLastStream == null) { + // special case to empty document + fPartitions.clear(); + fDocumentMarkerManager.clear(); + fDocument.set(""); //$NON-NLS-1$ + } + addStreamEntryToDocument(entry); + log(entry.getText()); + checkOverflow(); + } catch (BadLocationException e) { } - addStreamEntryToDocument(entry); - checkOverflow(); - } catch (BadLocationException e) { + break; + case StreamEntry.EVENT_CLOSE_LOG: + logClose(); + break; } } + private void logOpen() { + fLogURI = getLogURI(fProject); + if (fLogURI!=null) { + try { + IFileStore logStore = EFS.getStore(fLogURI); + fLogStream = logStore.openOutputStream(EFS.NONE, null); + } catch (CoreException e) { + CUIPlugin.log(e); + } finally { + BuildConsoleManager.refreshWorkspaceFiles(fLogURI); + } + } + } + + private void log(String text) { + if (fLogStream!=null) { + try { + fLogStream.write(text.getBytes()); + if (fQueue.isEmpty()) { + fLogStream.flush(); + } + } catch (IOException e) { + CUIPlugin.log(e); + } finally { + BuildConsoleManager.refreshWorkspaceFiles(fLogURI); + } + } + } + + private void logClose() { + if (fLogStream!=null) { + try { + fLogStream.close(); + } catch (IOException e) { + CUIPlugin.log(e); + } finally { + BuildConsoleManager.refreshWorkspaceFiles(fLogURI); + } + fLogStream = null; + } + } + }; Display display = CUIPlugin.getStandardDisplay(); - if (addToQueue && display != null) { + if (display != null) { display.asyncExec(r); } } @@ -187,21 +329,21 @@ public class BuildConsolePartitioner private void addStreamEntryToDocument(StreamEntry entry) throws BadLocationException { if ( entry.getMarker() == null ) { // It is plain unmarkered console output - addPartition(new BuildConsolePartition(fLastStream, - fDocument.getLength(), + addPartition(new BuildConsolePartition(fLastStream, + fDocument.getLength(), entry.getText().length(), BuildConsolePartition.CONSOLE_PARTITION_TYPE)); } else { - // this text line in entry is markered with ProblemMarkerInfo, + // this text line in entry is markered with ProblemMarkerInfo, // create special partition for it. - addPartition(new BuildConsolePartition(fLastStream, - fDocument.getLength(), + addPartition(new BuildConsolePartition(fLastStream, + fDocument.getLength(), entry.getText().length(), BuildConsolePartition.ERROR_PARTITION_TYPE, entry.getMarker())); } fDocument.replace(fDocument.getLength(), 0, entry.getText()); } - + void warnOfContentChange(BuildConsoleStreamDecorator stream) { if (stream != null) { ConsolePlugin.getDefault().getConsoleManager().warnOfContentChange(stream.getConsole()); @@ -268,7 +410,7 @@ public class BuildConsolePartitioner ITypedRegion partition = fPartitions.get(i); int partitionStart = partition.getOffset(); int partitionEnd = partitionStart + partition.getLength(); - if ( (offset >= partitionStart && offset <= partitionEnd) || + if ( (offset >= partitionStart && offset <= partitionEnd) || (offset < partitionStart && end >= partitionStart)) { list.add(partition); } @@ -339,9 +481,9 @@ public class BuildConsolePartitioner int offset = region.getOffset(); if (offset < overflow) { int endOffset = offset + region.getLength(); - if (endOffset < overflow || + if (endOffset < overflow || messageConsolePartition.getType() == BuildConsolePartition.ERROR_PARTITION_TYPE ) { - // remove partition, + // remove partition, // partitions with problem markers can't be split - remove them too } else { // split partition @@ -410,13 +552,15 @@ public class BuildConsolePartitioner }); } + fLogURI = null; + fLogStream = null; + if (BuildConsolePreferencePage.isClearBuildConsole()) { appendToDocument("", null, null); //$NON-NLS-1$ } } public ConsoleOutputStream getOutputStream() throws CoreException { - outputStreamClosed = Boolean.FALSE; return new BuildOutputStream(this, fManager.getStreamDecorator(BuildConsoleManager.BUILD_STREAM_TYPE_OUTPUT)); } @@ -427,7 +571,7 @@ public class BuildConsolePartitioner public ConsoleOutputStream getErrorStream() throws CoreException { return new BuildOutputStream(this, fManager.getStreamDecorator(BuildConsoleManager.BUILD_STREAM_TYPE_ERROR)); } - + /** This method is useful for future debugging and bugfixing */ @SuppressWarnings("unused") private void printDocumentPartitioning() { @@ -451,8 +595,15 @@ public class BuildConsolePartitioner if (text.endsWith("\n")) { //$NON-NLS-1$ text = text.substring(0, text.length() - 1); } - System.out.println(" " + isError + " " + start + "-" + end + //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - ":[" + text + "]"); //$NON-NLS-1$ //$NON-NLS-2$ + System.out.println(" " + isError + " " + start + "-" + end + //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + ":[" + text + "]"); //$NON-NLS-1$ //$NON-NLS-2$ } } + + /** + * @return {@link URI} location of log file. + */ + public URI getLogURI() { + return fLogURI; + } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/buildconsole/BuildOutputStream.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/buildconsole/BuildOutputStream.java index c77a0dfbe7a..b61f1245f87 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/buildconsole/BuildOutputStream.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/buildconsole/BuildOutputStream.java @@ -31,7 +31,8 @@ public class BuildOutputStream extends ConsoleOutputStream implements IErrorMark public BuildOutputStream(BuildConsolePartitioner partitioner, BuildConsoleStreamDecorator stream) { fPartitioner = partitioner; - fStream = stream; + fPartitioner.setStreamOpened(); + fStream = stream; } @Override @@ -41,6 +42,7 @@ public class BuildOutputStream extends ConsoleOutputStream implements IErrorMark @Override public void close() throws IOException { flush(); + fPartitioner.setStreamClosed(); } @Override 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 fb9bb6deeb3..bfdc1ab9a92 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 @@ -34,7 +34,15 @@ 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; + public static String CopyLog_ActionTooltip; + public static String CopyLog_BuildNotLogged; + public static String CopyLog_ChooseDestination; + public static String CopyLog_ErrorCopyingFile; + public static String CopyLog_ErrorWhileCopyingLog; + public static String CopyLog_InvalidDestination; + public static String CopyLog_LogFileIsNotAvailable; + public static String CopyLog_UnableToAccess; + public static String CopyLog_UnavailableLog; 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 b5916fabd5c..996397476b8 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 @@ -20,9 +20,18 @@ BuildConsolePage_Copy_7=Copy BuildConsolePage_Select__All_Ctrl_A_12=Select &All@Ctrl+A BuildConsolePage_Select_All=Select All +CopyLog_ActionTooltip=Copy Build Log +CopyLog_BuildNotLogged=Last build was not logged. Check Logging page in project properties. +CopyLog_ChooseDestination=Choose Log File Destination +CopyLog_ErrorCopyingFile=Error Copying a File +CopyLog_ErrorWhileCopyingLog=Error while copying working log file: +CopyLog_InvalidDestination=Destination is not valid: +CopyLog_LogFileIsNotAvailable=Working log file is not available. +CopyLog_UnableToAccess=Unable to access build log at +CopyLog_UnavailableLog=Unavailable Log + 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/CopyBuildLogAction.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/buildconsole/CopyBuildLogAction.java new file mode 100644 index 00000000000..e0aed6a7802 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/buildconsole/CopyBuildLogAction.java @@ -0,0 +1,107 @@ +/******************************************************************************* + * Copyright (c) 2010 Andrew Gvozdev 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: + * Andrew Gvozdev (Quoin Inc.) - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.internal.ui.buildconsole; + +import java.net.URI; + +import org.eclipse.core.filesystem.EFS; +import org.eclipse.core.filesystem.IFileStore; +import org.eclipse.core.filesystem.URIUtil; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.Shell; + +import org.eclipse.cdt.core.resources.IConsole; +import org.eclipse.cdt.ui.CUIPlugin; +import org.eclipse.cdt.ui.IBuildConsoleManager; + +import org.eclipse.cdt.internal.ui.CPluginImages; + +/** + * Action to copy build log from working file to a user selected file. + */ +public class CopyBuildLogAction extends Action { + private BuildConsolePage fConsolePage; + + public CopyBuildLogAction(BuildConsolePage page) { + super(); + setToolTipText(ConsoleMessages.CopyLog_ActionTooltip); + 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 (console instanceof BuildConsolePartitioner) { + Shell shell = Display.getCurrent().getActiveShell(); + URI srcURI = ((BuildConsolePartitioner)console).getLogURI(); + if (srcURI==null) { + MessageDialog.openWarning(shell, ConsoleMessages.CopyLog_UnavailableLog, + ConsoleMessages.CopyLog_BuildNotLogged); + return; + } + + IFileStore srcStore = null; + try { + srcStore = EFS.getStore(srcURI); + } catch (CoreException e) { + CUIPlugin.log(e); + MessageDialog.openError(shell, ConsoleMessages.CopyLog_UnavailableLog, + ConsoleMessages.CopyLog_UnableToAccess+srcURI); + return; + } + + if (!srcStore.fetchInfo().exists()) { + MessageDialog.openError(shell, ConsoleMessages.CopyLog_UnavailableLog, + ConsoleMessages.CopyLog_LogFileIsNotAvailable); + return; + } + + // open file dialog + FileDialog dialog = new FileDialog(shell, SWT.NONE); + dialog.setText(ConsoleMessages.CopyLog_ChooseDestination); + + String destLocation = dialog.open(); + if (destLocation!=null) { + URI destURI = URIUtil.toURI(destLocation); + if (destURI==null) { + MessageDialog.openError(shell, ConsoleMessages.CopyLog_UnavailableLog, + ConsoleMessages.CopyLog_InvalidDestination+destLocation); + return; + } + try { + IFileStore destStore = EFS.getStore(destURI); + srcStore.copy(destStore, EFS.OVERWRITE, null); + } catch (CoreException e) { + CUIPlugin.log(e); + MessageDialog.openError(shell, ConsoleMessages.CopyLog_ErrorCopyingFile, + ConsoleMessages.CopyLog_ErrorWhileCopyingLog+e.getLocalizedMessage()); + } finally { + BuildConsoleManager.refreshWorkspaceFiles(destURI); + } + } + } + } + +} 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 deleted file mode 100644 index 553cb9005b6..00000000000 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/buildconsole/SaveConsoleAction.java +++ /dev/null @@ -1,71 +0,0 @@ -/******************************************************************************* - * 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.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); - d.open(); - BuildOutputLogger.SaveBuildOutputPreferences newBp = - BuildOutputLogger.readSaveBuildOutputPreferences(project); - setChecked(newBp.isSaving); - return; - } - } - bp.isSaving = isChecked(); - BuildOutputLogger.writeSaveBuildOutputPreferences(project,bp); - } - } - -} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/BuildLogPreferencePage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/BuildLogPreferencePage.java new file mode 100644 index 00000000000..f92add233e6 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/BuildLogPreferencePage.java @@ -0,0 +1,169 @@ +/******************************************************************************* + * Copyright (c) 2010 Andrew Gvozdev 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: + * Andrew Gvozdev (Quoin Inc.) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.preferences; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +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.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.dialogs.PropertyPage; +import org.osgi.service.prefs.BackingStoreException; +import org.osgi.service.prefs.Preferences; + +import org.eclipse.cdt.ui.CUIPlugin; +import org.eclipse.cdt.ui.dialogs.ICOptionContainer; +import org.eclipse.cdt.utils.ui.controls.ControlFactory; + +import org.eclipse.cdt.internal.ui.buildconsole.BuildConsoleManager; + +/** + * Preference page defining build log properties. + */ +public class BuildLogPreferencePage extends PropertyPage implements ICOptionContainer { + private boolean isProjectLevel; + private Button enableLoggingCheckbox; + private Button browseButton; + private Text logLocationText; + private Label logLocationLabel; + + @Override + protected Control createContents(Composite parent) { + IProject project = getProject(); + isProjectLevel= project != null; + if(isProjectLevel) { + Preferences prefs = BuildConsoleManager.getBuildLogPreferences(project); + + Composite contents = ControlFactory.createCompositeEx(parent, 3, GridData.FILL_BOTH); + ((GridLayout) contents.getLayout()).makeColumnsEqualWidth = false; + + ControlFactory.createEmptySpace(contents, 3); + + // [v] Enable Logging + enableLoggingCheckbox = ControlFactory.createCheckBox(contents, PreferencesMessages.BuildLogPreferencePage_EnableLogging); + boolean keepLog = prefs.getBoolean(BuildConsoleManager.KEY_KEEP_LOG, BuildConsoleManager.CONSOLE_KEEP_LOG_DEFAULT); + enableLoggingCheckbox.setSelection(keepLog); + enableLoggingCheckbox.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + updateEnablements(); + } + }); + + ControlFactory.createEmptySpace(contents, 3); + + // Log file location: [....................] + logLocationLabel = ControlFactory.createLabel(contents, PreferencesMessages.BuildLogPreferencePage_LogLocation); + ((GridData) logLocationLabel.getLayoutData()).grabExcessHorizontalSpace = false; + + logLocationText = ControlFactory.createTextField(contents, SWT.SINGLE | SWT.BORDER); + String logLocation = prefs.get(BuildConsoleManager.KEY_LOG_LOCATION, BuildConsoleManager.getDefaultConsoleLogLocation(project)); + logLocationText.setText(logLocation); + logLocationText.addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent e) { + } + }); + + // [Browse...] + browseButton = ControlFactory.createPushButton(contents, PreferencesMessages.BuildLogPreferencePage_Browse); + ((GridData) browseButton.getLayoutData()).horizontalAlignment = GridData.END; + browseButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent event) { + FileDialog dialog = new FileDialog(getShell(), SWT.NONE); + dialog.setText(PreferencesMessages.BuildLogPreferencePage_ChooseLogFile); + String fileName = logLocationText.getText(); + IPath logFolder = new Path(fileName).removeLastSegments(1); + dialog.setFilterPath(logFolder.toOSString()); + String chosenFile = dialog.open(); + if (chosenFile != null) { + logLocationText.setText(chosenFile); + } + } + + }); + + updateEnablements(); + } + return parent; + } + + @Override + protected void performDefaults() { + if(isProjectLevel) { + IProject project = getProject(); + Preferences prefs = BuildConsoleManager.getBuildLogPreferences(project); + prefs.put(BuildConsoleManager.KEY_LOG_LOCATION, BuildConsoleManager.getDefaultConsoleLogLocation(project)); + prefs.putBoolean(BuildConsoleManager.KEY_KEEP_LOG, BuildConsoleManager.CONSOLE_KEEP_LOG_DEFAULT); + try { + prefs.flush(); + } catch (BackingStoreException e) { + CUIPlugin.log(e); + } + logLocationText.setText(prefs.get(BuildConsoleManager.KEY_LOG_LOCATION, BuildConsoleManager.getDefaultConsoleLogLocation(project))); + enableLoggingCheckbox.setSelection(prefs.getBoolean(BuildConsoleManager.KEY_KEEP_LOG, BuildConsoleManager.CONSOLE_KEEP_LOG_DEFAULT)); + updateEnablements(); + } + super.performDefaults(); + } + + @Override + public boolean performOk() { + if(isProjectLevel) { + Preferences prefs = BuildConsoleManager.getBuildLogPreferences(getProject()); + prefs.put(BuildConsoleManager.KEY_LOG_LOCATION, logLocationText.getText()); + prefs.putBoolean(BuildConsoleManager.KEY_KEEP_LOG, enableLoggingCheckbox.getSelection()); + try { + prefs.flush(); + } catch (BackingStoreException e) { + CUIPlugin.log(e); + } + } + return true; + } + + public IProject getProject(){ + IProject project= null; + IAdaptable elem = getElement(); + if (elem instanceof IProject) { + project= (IProject) elem; + } else if (elem != null) { + project= (IProject) elem.getAdapter(IProject.class); + } + return project; + } + + public org.eclipse.core.runtime.Preferences getPreferences() { + throw new UnsupportedOperationException(); + } + + public void updateContainer() { + } + + private void updateEnablements() { + boolean isLoggingEnabled = enableLoggingCheckbox.getSelection(); + logLocationLabel.setEnabled(isLoggingEnabled); + logLocationText.setEnabled(isLoggingEnabled); + browseButton.setEnabled(isLoggingEnabled); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.java index dd61370bc7f..695a4789482 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.java @@ -145,6 +145,10 @@ public final class PreferencesMessages extends NLS { public static String AppearancePreferencePage_note; public static String AppearancePreferencePage_preferenceOnlyForNewViews; public static String AppearancePreferencePage_showSourceRootsAtTopOfProject_label; + public static String BuildLogPreferencePage_Browse; + public static String BuildLogPreferencePage_ChooseLogFile; + public static String BuildLogPreferencePage_EnableLogging; + public static String BuildLogPreferencePage_LogLocation; public static String CEditorPreferencePage_folding_title; public static String FoldingConfigurationBlock_enable; public static String FoldingConfigurationBlock_combo_caption; diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.properties index 9c2a47279bf..414cd5e5e72 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.properties +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.properties @@ -165,6 +165,12 @@ AppearancePreferencePage_preferenceOnlyForNewViews=This preference does not affe AppearancePreferencePage_outlineGroupMacros_label=Group macro definitions in the Outline view AppearancePreferencePage_showSourceRootsAtTopOfProject_label=Show source roots at top of project +#Build Logging +BuildLogPreferencePage_Browse=Browse... +BuildLogPreferencePage_ChooseLogFile=Choose Log File +BuildLogPreferencePage_EnableLogging=Enable logging +BuildLogPreferencePage_LogLocation=Log file location: + #Folding CEditorPreferencePage_folding_title= &Folding