Commit 1e64d9f9 authored by Friedemann Kleint's avatar Friedemann Kleint

Version control: Replace per-VCS output panes with a single one.

...and give it some color and formatting.
parent 12981d0c
......@@ -11,7 +11,6 @@ include(../../libs/utils/utils.pri)
HEADERS += annotationhighlighter.h \
cvsplugin.h \
cvscontrol.h \
cvsoutputwindow.h \
settingspage.h \
cvseditor.h \
cvssubmiteditor.h \
......@@ -24,7 +23,6 @@ HEADERS += annotationhighlighter.h \
SOURCES += annotationhighlighter.cpp \
cvsplugin.cpp \
cvscontrol.cpp \
cvsoutputwindow.cpp \
settingspage.cpp \
cvseditor.cpp \
cvssubmiteditor.cpp \
......
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://www.qtsoftware.com/contact.
**
**************************************************************************/
#include "cvsoutputwindow.h"
#include "cvsplugin.h"
#include <QtGui/QListWidget>
#include <QtCore/QDebug>
using namespace CVS::Internal;
CVSOutputWindow::CVSOutputWindow(CVSPlugin *cvsPlugin)
: m_cvsPlugin(cvsPlugin)
{
m_outputListWidget = new QListWidget;
m_outputListWidget->setFrameStyle(QFrame::NoFrame);
m_outputListWidget->setWindowTitle(tr("CVS Output"));
m_outputListWidget->setSelectionMode(QAbstractItemView::ExtendedSelection);
}
CVSOutputWindow::~CVSOutputWindow()
{
delete m_outputListWidget;
}
QWidget *CVSOutputWindow::outputWidget(QWidget *parent)
{
m_outputListWidget->setParent(parent);
return m_outputListWidget;
}
QString CVSOutputWindow::name() const
{
return tr("CVS");
}
void CVSOutputWindow::clearContents()
{
m_outputListWidget->clear();
}
int CVSOutputWindow::priorityInStatusBar() const
{
return -1;
}
void CVSOutputWindow::visibilityChanged(bool b)
{
if (b)
m_outputListWidget->setFocus();
}
void CVSOutputWindow::append(const QString &txt, bool doPopup)
{
const QStringList lines = txt.split(QLatin1Char('\n'));
foreach (const QString &s, lines)
m_outputListWidget->addItem(s);
m_outputListWidget->scrollToBottom();
if (doPopup)
popup();
}
bool CVSOutputWindow::canFocus()
{
return false;
}
bool CVSOutputWindow::hasFocus()
{
return m_outputListWidget->hasFocus();
}
void CVSOutputWindow::setFocus()
{
}
bool CVSOutputWindow::canNext()
{
return false;
}
bool CVSOutputWindow::canPrevious()
{
return false;
}
void CVSOutputWindow::goToNext()
{
}
void CVSOutputWindow::goToPrev()
{
}
bool CVSOutputWindow::canNavigate()
{
return false;
}
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://www.qtsoftware.com/contact.
**
**************************************************************************/
#ifndef CVSOUTPUTWINDOW_H
#define CVSOUTPUTWINDOW_H
#include <coreplugin/ioutputpane.h>
QT_BEGIN_NAMESPACE
class QListWidget;
QT_END_NAMESPACE
namespace CVS {
namespace Internal {
class CVSPlugin;
class CVSOutputWindow : public Core::IOutputPane
{
Q_OBJECT
public:
CVSOutputWindow(CVSPlugin *cvsPlugin);
~CVSOutputWindow();
QWidget *outputWidget(QWidget *parent);
QList<QWidget*> toolBarWidgets() const {
return QList<QWidget *>();
}
QString name() const;
void clearContents();
int priorityInStatusBar() const;
void visibilityChanged(bool visible);
bool canFocus();
bool hasFocus();
void setFocus();
bool canNext();
bool canPrevious();
void goToNext();
void goToPrev();
bool canNavigate();
public slots:
void append(const QString &txt, bool popup = false);
private:
CVSPlugin *m_cvsPlugin;
QListWidget *m_outputListWidget;
};
} // namespace CVS
} // namespace Internal
#endif // CVSOUTPUTWINDOW_H
......@@ -30,7 +30,6 @@
#include "cvsplugin.h"
#include "settingspage.h"
#include "cvseditor.h"
#include "cvsoutputwindow.h"
#include "cvssubmiteditor.h"
#include "cvsconstants.h"
#include "cvscontrol.h"
......@@ -39,6 +38,7 @@
#include <vcsbase/basevcseditorfactory.h>
#include <vcsbase/vcsbaseeditor.h>
#include <vcsbase/basevcssubmiteditorfactory.h>
#include <vcsbase/vcsbaseoutputwindow.h>
#include <utils/synchronousprocess.h>
#include <utils/parameteraction.h>
......@@ -152,7 +152,6 @@ CVSPlugin *CVSPlugin::m_cvsPluginInstance = 0;
CVSPlugin::CVSPlugin() :
m_versionControl(0),
m_changeTmpFile(0),
m_cvsOutputWindow(0),
m_projectExplorer(0),
m_addAction(0),
m_deleteAction(0),
......@@ -239,9 +238,6 @@ bool CVSPlugin::initialize(const QStringList &arguments, QString *errorMessage)
for (int i = 0; i < editorCount; i++)
addAutoReleasedObject(new CVSEditorFactory(editorParameters + i, this, describeSlotC));
m_cvsOutputWindow = new CVSOutputWindow(this);
addAutoReleasedObject(m_cvsOutputWindow);
addAutoReleasedObject(new CheckoutWizard);
//register actions
......@@ -644,14 +640,14 @@ void CVSPlugin::startCommit(const QString &source)
if (VCSBase::VCSBaseSubmitEditor::raiseSubmitEditor())
return;
if (m_changeTmpFile) {
showOutput(tr("Another commit is currently being executed."));
VCSBase::VCSBaseOutputWindow::instance()->appendWarning(tr("Another commit is currently being executed."));
return;
}
const QFileInfo sourceFi(source);
const QString sourceDir = sourceFi.isDir() ? source : sourceFi.absolutePath();
const QString topLevel = findTopLevelForDirectory(sourceDir);
if (topLevel.isEmpty()) {
showOutput(msgCannotFindTopLevel(source), true);
VCSBase::VCSBaseOutputWindow::instance()->appendError(msgCannotFindTopLevel(source));
return;
}
// We need the "Examining <subdir>" stderr output to tell
......@@ -673,7 +669,7 @@ void CVSPlugin::startCommit(const QString &source)
qDebug() << Q_FUNC_INFO << '\n' << source << "top" << topLevel;
if (statusOutput.empty()) {
showOutput(tr("There are no modified files."), true);
VCSBase::VCSBaseOutputWindow::instance()->append(tr("There are no modified files."));
return;
}
......@@ -681,7 +677,7 @@ void CVSPlugin::startCommit(const QString &source)
QTemporaryFile *changeTmpFile = new QTemporaryFile(this);
changeTmpFile->setAutoRemove(true);
if (!changeTmpFile->open()) {
showOutput(tr("Cannot create temporary file: %1").arg(changeTmpFile->errorString()));
VCSBase::VCSBaseOutputWindow::instance()->appendError(tr("Cannot create temporary file: %1").arg(changeTmpFile->errorString()));
delete changeTmpFile;
return;
}
......@@ -807,7 +803,7 @@ void CVSPlugin::slotDescribe(const QString &source, const QString &changeNr)
{
QString errorMessage;
if (!describe(source, changeNr, &errorMessage))
showOutput(errorMessage, true);
VCSBase::VCSBaseOutputWindow::instance()->appendError(errorMessage);
}
bool CVSPlugin::describe(const QString &file, const QString &changeNr, QString *errorMessage)
......@@ -1034,12 +1030,11 @@ static inline QString fixFileArgs(QStringList *files)
// Format log entry for command
static inline QString msgExecutionLogEntry(const QString &workingDir, const QString &executable, const QStringList &arguments)
{
const QString timeStamp = QTime::currentTime().toString(QLatin1String("HH:mm"));
//: <timestamp> Executing: <executable> <arguments>
//: Executing: <executable> <arguments>
const QString args = arguments.join(QString(QLatin1Char(' ')));
if (workingDir.isEmpty())
return CVSPlugin::tr("%1 Executing: %2 %3\n").arg(timeStamp, executable, args);
return CVSPlugin::tr("%1 Executing in %2: %3 %4\n").arg(timeStamp, workingDir, executable, args);
return CVSPlugin::tr("Executing: %2 %3\n").arg(executable, args);
return CVSPlugin::tr("Executing in %2: %3 %4\n").arg(workingDir, executable, args);
}
// Figure out a working directory for the process,
......@@ -1075,7 +1070,7 @@ CVSResponse CVSPlugin::runCVS(const QString &workingDirectory,
const QStringList allArgs = m_settings.addOptions(arguments);
const QString outputText = msgExecutionLogEntry(response.workingDirectory, executable, allArgs);
showOutput(outputText, false);
VCSBase::VCSBaseOutputWindow::instance()->appendCommand(outputText);
if (CVS::Constants::debug)
qDebug() << "runCVS" << timeOut << outputText;
......@@ -1092,12 +1087,13 @@ CVSResponse CVSPlugin::runCVS(const QString &workingDirectory,
process.setStdOutCodec(outputCodec);
process.setStdErrBufferedSignalsEnabled(true);
connect(&process, SIGNAL(stdErrBuffered(QString,bool)), m_cvsOutputWindow, SLOT(append(QString,bool)));
VCSBase::VCSBaseOutputWindow *outputWindow = VCSBase::VCSBaseOutputWindow::instance();
connect(&process, SIGNAL(stdErrBuffered(QString,bool)), outputWindow, SLOT(append(QString)));
// connect stdout to the output window if desired
if (showStdOutInOutputWindow) {
process.setStdOutBufferedSignalsEnabled(true);
connect(&process, SIGNAL(stdOutBuffered(QString,bool)), m_cvsOutputWindow, SLOT(append(QString,bool)));
connect(&process, SIGNAL(stdOutBuffered(QString,bool)), outputWindow, SLOT(append(QString)));
}
const Core::Utils::SynchronousProcessResponse sp_resp = process.run(executable, allArgs);
......@@ -1123,18 +1119,11 @@ CVSResponse CVSPlugin::runCVS(const QString &workingDirectory,
break;
}
if (response.result != CVSResponse::Ok)
m_cvsOutputWindow->append(response.message, true);
VCSBase::VCSBaseOutputWindow::instance()->appendError(response.message);
return response;
}
void CVSPlugin::showOutput(const QString &output, bool bringToForeground)
{
m_cvsOutputWindow->append(output);
if (bringToForeground)
m_cvsOutputWindow->popup();
}
Core::IEditor * CVSPlugin::showOutputInEditor(const QString& title, const QString &output,
int editorType, const QString &source,
QTextCodec *codec)
......
......@@ -58,7 +58,6 @@ namespace ProjectExplorer {
namespace CVS {
namespace Internal {
class CVSOutputWindow;
class CVSSubmitEditor;
struct CVSResponse
......@@ -141,7 +140,6 @@ private:
bool showStdOutInOutputWindow, QTextCodec *outputCodec = 0,
bool mergeStderr = false);
void showOutput(const QString &output, bool bringToForeground = true);
void annotate(const QString &file);
bool describe(const QString &source, const QString &changeNr, QString *errorMessage);
bool describe(const QString &repository, QList<CVS_LogEntry> entries, QString *errorMessage);
......@@ -157,7 +155,6 @@ private:
Core::IVersionControl *m_versionControl;
QTemporaryFile *m_changeTmpFile;
CVSOutputWindow *m_cvsOutputWindow;
ProjectExplorer::ProjectExplorerPlugin *m_projectExplorer;
Core::Utils::ParameterAction *m_addAction;
......
......@@ -8,7 +8,6 @@ include(../../plugins/vcsbase/vcsbase.pri)
include(../../libs/utils/utils.pri)
HEADERS += gitplugin.h \
gitconstants.h \
gitoutputwindow.h \
gitclient.h \
changeselectiondialog.h \
commitdata.h \
......@@ -25,7 +24,6 @@ HEADERS += gitplugin.h \
clonewizard.h \
clonewizardpage.h
SOURCES += gitplugin.cpp \
gitoutputwindow.cpp \
gitclient.cpp \
changeselectiondialog.cpp \
commitdata.cpp \
......
......@@ -46,6 +46,7 @@
#include <texteditor/itexteditor.h>
#include <utils/qtcassert.h>
#include <vcsbase/vcsbaseeditor.h>
#include <vcsbase/vcsbaseoutputwindow.h>
#include <QtCore/QRegExp>
#include <QtCore/QTemporaryFile>
......@@ -89,9 +90,8 @@ static inline QString msgParseFilesFailed()
// Format a command for the status window
static QString formatCommand(const QString &binary, const QStringList &args)
{
const QString timeStamp = QTime::currentTime().toString(QLatin1String("HH:mm"));
//: <timestamp> Executing: <executable> <arguments>
return GitClient::tr("%1 Executing: %2 %3\n").arg(timeStamp, binary, args.join(QString(QLatin1Char(' '))));
//: Executing: <executable> <arguments>
return GitClient::tr("Executing: %1 %2\n").arg(binary, args.join(QString(QLatin1Char(' '))));
}
// ---------------- GitClient
......@@ -210,20 +210,20 @@ void GitClient::diff(const QString &workingDirectory,
if (unstagedFileNames.empty() && stagedFileNames.empty()) {
QStringList arguments(commonDiffArgs);
arguments << diffArgs;
m_plugin->outputWindow()->append(formatCommand(binary, arguments));
VCSBase::VCSBaseOutputWindow::instance()->appendCommand(formatCommand(binary, arguments));
command->addJob(arguments, m_settings.timeout);
} else {
// Files diff.
if (!unstagedFileNames.empty()) {
QStringList arguments(commonDiffArgs);
arguments << QLatin1String("--") << unstagedFileNames;
m_plugin->outputWindow()->append(formatCommand(binary, arguments));
VCSBase::VCSBaseOutputWindow::instance()->appendCommand(formatCommand(binary, arguments));
command->addJob(arguments, m_settings.timeout);
}
if (!stagedFileNames.empty()) {
QStringList arguments(commonDiffArgs);
arguments << QLatin1String("--cached") << diffArgs << QLatin1String("--") << stagedFileNames;
m_plugin->outputWindow()->append(formatCommand(binary, arguments));
VCSBase::VCSBaseOutputWindow::instance()->appendCommand(formatCommand(binary, arguments));
command->addJob(arguments, m_settings.timeout);
}
}
......@@ -360,8 +360,7 @@ bool GitClient::synchronousAdd(const QString &workingDirectory, const QStringLis
if (!rc) {
const QString errorMessage = tr("Unable to add %n file(s) to %1: %2", 0, files.size()).
arg(workingDirectory, QString::fromLocal8Bit(errorText));
m_plugin->outputWindow()->append(errorMessage);
m_plugin->outputWindow()->popup(false);
VCSBase::VCSBaseOutputWindow::instance()->appendError(errorMessage);
}
return rc;
}
......@@ -371,10 +370,8 @@ bool GitClient::synchronousReset(const QString &workingDirectory,
{
QString errorMessage;
const bool rc = synchronousReset(workingDirectory, files, &errorMessage);
if (!rc) {
m_plugin->outputWindow()->append(errorMessage);
m_plugin->outputWindow()->popup(false);
}
if (!rc)
VCSBase::VCSBaseOutputWindow::instance()->appendError(errorMessage);
return rc;
}
......@@ -390,8 +387,7 @@ bool GitClient::synchronousReset(const QString &workingDirectory,
arguments << QLatin1String("reset") << QLatin1String("HEAD") << QLatin1String("--") << files;
const bool rc = synchronousGit(workingDirectory, arguments, &outputText, &errorText);
const QString output = QString::fromLocal8Bit(outputText);
m_plugin->outputWindow()->popup(false);
m_plugin->outputWindow()->append(output);
VCSBase::VCSBaseOutputWindow::instance()->append(output);
// Note that git exits with 1 even if the operation is successful
// Assume real failure if the output does not contain "foo.cpp modified"
if (!rc && !output.contains(QLatin1String("modified"))) {
......@@ -478,12 +474,11 @@ GitCommand *GitClient::createCommand(const QString &workingDirectory,
if (Git::Constants::debug)
qDebug() << Q_FUNC_INFO << workingDirectory << editor;
GitOutputWindow *outputWindow = m_plugin->outputWindow();
VCSBase::VCSBaseOutputWindow *outputWindow = VCSBase::VCSBaseOutputWindow::instance();
GitCommand* command = new GitCommand(binary(), workingDirectory, processEnvironment());
if (outputToWindow) {
if (!editor) { // assume that the commands output is the important thing
connect(command, SIGNAL(outputData(QByteArray)), this, SLOT(appendDataAndPopup(QByteArray)));
if (editor) { // assume that the commands output is the important thing
connect(command, SIGNAL(outputData(QByteArray)), outputWindow, SLOT(appendDataSilently(QByteArray)));
} else {
connect(command, SIGNAL(outputData(QByteArray)), outputWindow, SLOT(appendData(QByteArray)));
}
......@@ -493,7 +488,7 @@ GitCommand *GitClient::createCommand(const QString &workingDirectory,
}
if (outputWindow)
connect(command, SIGNAL(errorText(QString)), this, SLOT(appendAndPopup(QString)));
connect(command, SIGNAL(errorText(QString)), outputWindow, SLOT(appendError(QString)));
return command;
}
......@@ -504,25 +499,13 @@ void GitClient::executeGit(const QString &workingDirectory,
bool outputToWindow,
GitCommand::TerminationReportMode tm)
{
m_plugin->outputWindow()->append(formatCommand(QLatin1String(Constants::GIT_BINARY), arguments));
VCSBase::VCSBaseOutputWindow::instance()->appendCommand(formatCommand(QLatin1String(Constants::GIT_BINARY), arguments));
GitCommand *command = createCommand(workingDirectory, editor, outputToWindow);
command->addJob(arguments, m_settings.timeout);
command->setTerminationReportMode(tm);
command->execute();
}
void GitClient::appendDataAndPopup(const QByteArray &data)
{
m_plugin->outputWindow()->appendData(data);
m_plugin->outputWindow()->popup(false);
}
void GitClient::appendAndPopup(const QString &text)
{
m_plugin->outputWindow()->append(text);
m_plugin->outputWindow()->popup(false);
}
// Return fixed arguments required to run
QStringList GitClient::binary() const
{
......@@ -553,7 +536,7 @@ bool GitClient::synchronousGit(const QString &workingDirectory,
qDebug() << "synchronousGit" << workingDirectory << arguments;
if (logCommandToWindow)
m_plugin->outputWindow()->append(formatCommand(m_binaryPath, arguments));
VCSBase::VCSBaseOutputWindow::instance()->appendCommand(formatCommand(m_binaryPath, arguments));
QProcess process;
process.setWorkingDirectory(workingDirectory);
......@@ -602,10 +585,8 @@ GitClient::StashResult GitClient::ensureStash(const QString &workingDirectory)
{
QString errorMessage;
const StashResult sr = ensureStash(workingDirectory, &errorMessage);
if (sr == StashFailed) {
m_plugin->outputWindow()->append(errorMessage);
m_plugin->outputWindow()->popup();
}
if (sr == StashFailed)
VCSBase::VCSBaseOutputWindow::instance()->appendError(errorMessage);
return sr;
}
......@@ -810,12 +791,11 @@ bool GitClient::addAndCommit(const QString &repositoryDirectory,
QByteArray outputText;
QByteArray errorText;
const bool rc = synchronousGit(repositoryDirectory, args, &outputText, &errorText);
const QString message = rc ?
tr("Committed %n file(s).\n", 0, checkedFiles.size()) :
tr("Unable to commit %n file(s): %1\n", 0, checkedFiles.size()).arg(QString::fromLocal8Bit(errorText));
m_plugin->outputWindow()->append(message);
m_plugin->outputWindow()->popup(false);
if (rc) {
VCSBase::VCSBaseOutputWindow::instance()->append(tr("Committed %n file(s).\n", 0, checkedFiles.size()));
} else {
VCSBase::VCSBaseOutputWindow::instance()->appendError(tr("Unable to commit %n file(s): %1\n", 0, checkedFiles.size()).arg(QString::fromLocal8Bit(errorText)));
}
return rc;
}
......@@ -919,13 +899,11 @@ void GitClient::revert(const QStringList &files)
break;
case RevertUnchanged: {
const QString msg = (isDirectory || files.size() > 1) ? msgNoChangedFiles() : tr("The file is not modified.");
m_plugin->outputWindow()->append(msg);
m_plugin->outputWindow()->popup();
VCSBase::VCSBaseOutputWindow::instance()->append(msg);
}
break;
case RevertFailed:
m_plugin->outputWindow()->append(errorMessage);
m_plugin->outputWindow()->popup();
VCSBase::VCSBaseOutputWindow::instance()->append(errorMessage);
break;
}
}
......@@ -954,12 +932,10 @@ void GitClient::stash(const QString &workingDirectory)
executeGit(workingDirectory, QStringList(QLatin1String("stash")), 0, true);
break;
case StatusUnchanged:
m_plugin->outputWindow()->append(msgNoChangedFiles());
m_plugin->outputWindow()->popup();
VCSBase::VCSBaseOutputWindow::instance()->append(msgNoChangedFiles());
break;
case StatusFailed:
m_plugin->outputWindow()->append(errorMessage);
m_plugin->outputWindow()->popup();
VCSBase::VCSBaseOutputWindow::instance()->append(errorMessage);
break;
}
}
......
......@@ -145,10 +145,6 @@ public:
public slots:
void show(const QString &source, const QString &id);
private slots:
void appendAndPopup(const QString &text);
void appendDataAndPopup(const QByteArray &data);