Merge branch '0.9.1-beta' of git@scm.dev.nokia.troll.no:creator/mainline into 0.9.1-beta

This commit is contained in:
mae
2008-12-04 19:35:59 +01:00
93 changed files with 2533 additions and 979 deletions

26
.gitignore vendored
View File

@@ -68,8 +68,8 @@ src/corelib/lib
src/network/lib src/network/lib
src/xml/lib/ src/xml/lib/
# Files copied by syncIde # Binaries
# ----------------------- # --------
bin/Aggregation.dll bin/Aggregation.dll
bin/CodeModel.dll bin/CodeModel.dll
bin/ExtensionSystem.dll bin/ExtensionSystem.dll
@@ -77,24 +77,4 @@ bin/QtConcurrent.dll
bin/Utils.dll bin/Utils.dll
bin/qtcreator bin/qtcreator
bin/qtcreator.exe bin/qtcreator.exe
shared/help/bookmarkdialog.ui tests/manual/cplusplus/cplusplus0
shared/help/bookmarkmanager.cpp
shared/help/bookmarkmanager.h
shared/help/contentwindow.cpp
shared/help/contentwindow.h
shared/help/filternamedialog.cpp
shared/help/filternamedialog.h
shared/help/filternamedialog.ui
shared/help/helpviewer.cpp
shared/help/helpviewer.h
shared/help/indexwindow.cpp
shared/help/indexwindow.h
shared/help/topicchooser.cpp
shared/help/topicchooser.h
shared/help/topicchooser.ui
shared/proparser/abstractproitemvisitor.h
shared/proparser/profileevaluator.cpp
shared/proparser/profileevaluator.h
shared/proparser/proitems.cpp
shared/proparser/proitems.h
shared/proparser/proparserutils.h

View File

@@ -1191,6 +1191,11 @@ bool Parser::parseClassSpecifier(SpecifierAST *&node)
NameAST *name = 0; NameAST *name = 0;
parseName(name); parseName(name);
bool parsed = false;
const bool previousInFunctionBody = _inFunctionBody;
_inFunctionBody = false;
if (LA() == T_COLON || LA() == T_LBRACE) { if (LA() == T_COLON || LA() == T_LBRACE) {
BaseSpecifierAST *base_clause = 0; BaseSpecifierAST *base_clause = 0;
if (LA() == T_COLON) { if (LA() == T_COLON) {
@@ -1233,9 +1238,12 @@ bool Parser::parseClassSpecifier(SpecifierAST *&node)
} }
} }
node = ast; node = ast;
return true; parsed = true;
} }
return false;
_inFunctionBody = previousInFunctionBody;
return parsed;
} }
bool Parser::parseAccessSpecifier(SpecifierAST *&node) bool Parser::parseAccessSpecifier(SpecifierAST *&node)

View File

@@ -292,6 +292,7 @@ Use *Scope::useAt(unsigned index) const
void Scope::addUse(unsigned sourceOffset, Name *name) void Scope::addUse(unsigned sourceOffset, Name *name)
{ {
#ifdef CPLUSPLUS_WITH_USES
if (++_useCount == _allocatedUses) { if (++_useCount == _allocatedUses) {
_allocatedUses += 4; _allocatedUses += 4;
_uses = reinterpret_cast<Use *>(realloc(_uses, _allocatedUses * sizeof(Use))); _uses = reinterpret_cast<Use *>(realloc(_uses, _allocatedUses * sizeof(Use)));
@@ -303,6 +304,7 @@ void Scope::addUse(unsigned sourceOffset, Name *name)
else else
lastVisibleSymbol = _symbols[_symbolCount]; lastVisibleSymbol = _symbols[_symbolCount];
_uses[_useCount].init(sourceOffset, name, lastVisibleSymbol); _uses[_useCount].init(sourceOffset, name, lastVisibleSymbol);
#endif
} }
CPLUSPLUS_END_NAMESPACE CPLUSPLUS_END_NAMESPACE

View File

@@ -9,7 +9,8 @@ HEADERS += \
$$PWD/helpviewer.h \ $$PWD/helpviewer.h \
$$PWD/contentwindow.h \ $$PWD/contentwindow.h \
$$PWD/bookmarkmanager.h \ $$PWD/bookmarkmanager.h \
$$PWD/../namespace_global.h $$PWD/../namespace_global.h \
$$PWD/indexwindow.h
SOURCES += \ SOURCES += \
$$PWD/filternamedialog.cpp \ $$PWD/filternamedialog.cpp \
@@ -19,7 +20,7 @@ SOURCES += \
$$PWD/contentwindow.cpp \ $$PWD/contentwindow.cpp \
$$PWD/bookmarkmanager.cpp $$PWD/bookmarkmanager.cpp
FORMS += \ FORMS += \
$$PWD/filternamedialog.ui \ $$PWD/filternamedialog.ui \
$$PWD/topicchooser.ui \ $$PWD/topicchooser.ui \
$$PWD/bookmarkdialog.ui $$PWD/bookmarkdialog.ui

View File

@@ -153,6 +153,11 @@ void Document::appendMacro(const QByteArray &macroName, const QByteArray &text)
_definedMacros += text; _definedMacros += text;
} }
void Document::addMacroUse(unsigned offset, unsigned length)
{
_macroUses.append(Block(offset, offset + length));
}
TranslationUnit *Document::translationUnit() const TranslationUnit *Document::translationUnit() const
{ {
return _translationUnit; return _translationUnit;

View File

@@ -68,6 +68,8 @@ public:
void appendMacro(const QByteArray &macroName, const QByteArray &text); void appendMacro(const QByteArray &macroName, const QByteArray &text);
void addMacroUse(unsigned offset, unsigned length);
Control *control() const; Control *control() const;
TranslationUnit *translationUnit() const; TranslationUnit *translationUnit() const;
@@ -176,6 +178,9 @@ public:
QList<Block> skippedBlocks() const QList<Block> skippedBlocks() const
{ return _skippedBlocks; } { return _skippedBlocks; }
QList<Block> macroUses() const
{ return _macroUses; }
private: private:
Symbol *findSymbolAt(unsigned line, unsigned column, Scope *scope) const; Symbol *findSymbolAt(unsigned line, unsigned column, Scope *scope) const;
@@ -189,6 +194,7 @@ private:
QByteArray _definedMacros; QByteArray _definedMacros;
QSet<QByteArray> _macroNames; QSet<QByteArray> _macroNames;
QList<Block> _skippedBlocks; QList<Block> _skippedBlocks;
QList<Block> _macroUses;
}; };
} // end of namespace CPlusPlus } // end of namespace CPlusPlus

View File

@@ -235,9 +235,9 @@ bool ResolveExpression::visit(ExpressionListAST *)
return false; return false;
} }
bool ResolveExpression::visit(BinaryExpressionAST *) bool ResolveExpression::visit(BinaryExpressionAST *ast)
{ {
// nothing to do. accept(ast->left_expression);
return false; return false;
} }

View File

@@ -91,7 +91,8 @@ Document::Ptr TypeOfExpression::documentForExpression(const QString &expression)
{ {
// create the expression's AST. // create the expression's AST.
Document::Ptr doc = Document::create(QLatin1String("<completion>")); Document::Ptr doc = Document::create(QLatin1String("<completion>"));
doc->setSource(expression.toUtf8()); const QByteArray bytes = expression.toUtf8();
doc->setSource(bytes);
doc->parse(Document::ParseExpression); doc->parse(Document::ParseExpression);
return doc; return doc;
} }

View File

@@ -165,7 +165,7 @@ void runFileSearchRegExp(QFutureInterface<FileSearchResult> &future,
int numFilesSearched = 0; int numFilesSearched = 0;
int numMatches = 0; int numMatches = 0;
if (flags & QTextDocument::FindWholeWords) if (flags & QTextDocument::FindWholeWords)
searchTerm = QString("\b%1\b").arg(searchTerm); searchTerm = QString("\\b%1\\b").arg(searchTerm);
Qt::CaseSensitivity caseSensitivity = (flags & QTextDocument::FindCaseSensitively) ? Qt::CaseSensitive : Qt::CaseInsensitive; Qt::CaseSensitivity caseSensitivity = (flags & QTextDocument::FindCaseSensitively) ? Qt::CaseSensitive : Qt::CaseInsensitive;
QRegExp expression(searchTerm, caseSensitivity); QRegExp expression(searchTerm, caseSensitivity);

View File

@@ -44,6 +44,8 @@ FileWizardDialog::FileWizardDialog(QWidget *parent) :
m_filePage(new FileWizardPage) m_filePage(new FileWizardPage)
{ {
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
setOption(QWizard::NoCancelButton, false);
setOption(QWizard::NoDefaultButton, false);
setPixmap(QWizard::WatermarkPixmap, QPixmap(QLatin1String(":/qworkbench/images/qtwatermark.png"))); setPixmap(QWizard::WatermarkPixmap, QPixmap(QLatin1String(":/qworkbench/images/qtwatermark.png")));
addPage(m_filePage); addPage(m_filePage);
connect(m_filePage, SIGNAL(activated()), button(QWizard::FinishButton), SLOT(animateClick())); connect(m_filePage, SIGNAL(activated()), button(QWizard::FinishButton), SLOT(animateClick()));

View File

@@ -125,6 +125,7 @@ struct SynchronousProcessPrivate {
SynchronousProcessResponse m_result; SynchronousProcessResponse m_result;
int m_hangTimerCount; int m_hangTimerCount;
int m_maxHangTimerCount; int m_maxHangTimerCount;
bool m_startFailure;
ChannelBuffer m_stdOut; ChannelBuffer m_stdOut;
ChannelBuffer m_stdErr; ChannelBuffer m_stdErr;
@@ -133,7 +134,8 @@ struct SynchronousProcessPrivate {
SynchronousProcessPrivate::SynchronousProcessPrivate() : SynchronousProcessPrivate::SynchronousProcessPrivate() :
m_stdOutCodec(0), m_stdOutCodec(0),
m_hangTimerCount(0), m_hangTimerCount(0),
m_maxHangTimerCount(defaultMaxHangTimerCount) m_maxHangTimerCount(defaultMaxHangTimerCount),
m_startFailure(false)
{ {
} }
@@ -143,6 +145,7 @@ void SynchronousProcessPrivate::clearForRun()
m_stdOut.clearForRun(); m_stdOut.clearForRun();
m_stdErr.clearForRun(); m_stdErr.clearForRun();
m_result.clear(); m_result.clear();
m_startFailure = false;
} }
// ----------- SynchronousProcess // ----------- SynchronousProcess
@@ -221,23 +224,27 @@ SynchronousProcessResponse SynchronousProcess::run(const QString &binary,
qDebug() << '>' << Q_FUNC_INFO << binary << args; qDebug() << '>' << Q_FUNC_INFO << binary << args;
m_d->clearForRun(); m_d->clearForRun();
m_d->m_timer.start();
QApplication::setOverrideCursor(Qt::WaitCursor);
// On Windows, start failure is triggered immediately if the
// executable cannot be found in the path. Do not start the
// event loop in that case.
m_d->m_process.start(binary, args, QIODevice::ReadOnly); m_d->m_process.start(binary, args, QIODevice::ReadOnly);
m_d->m_eventLoop.exec(QEventLoop::ExcludeUserInputEvents); if (!m_d->m_startFailure) {
if (m_d->m_result.result == SynchronousProcessResponse::Finished || m_d->m_result.result == SynchronousProcessResponse::FinishedError) { m_d->m_timer.start();
processStdOut(false); QApplication::setOverrideCursor(Qt::WaitCursor);
processStdErr(false); m_d->m_eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
if (m_d->m_result.result == SynchronousProcessResponse::Finished || m_d->m_result.result == SynchronousProcessResponse::FinishedError) {
processStdOut(false);
processStdErr(false);
}
m_d->m_result.stdOut = convertStdOut(m_d->m_stdOut.data);
m_d->m_result.stdErr = convertStdErr(m_d->m_stdErr.data);
m_d->m_timer.stop();
QApplication::restoreOverrideCursor();
} }
m_d->m_result.stdOut = convertStdOut(m_d->m_stdOut.data);
m_d->m_result.stdErr = convertStdErr(m_d->m_stdErr.data);
m_d->m_timer.stop();
QApplication::restoreOverrideCursor();
if (debug) if (debug)
qDebug() << '<' << Q_FUNC_INFO << binary << m_d->m_result; qDebug() << '<' << Q_FUNC_INFO << binary << m_d->m_result;
return m_d->m_result; return m_d->m_result;
@@ -246,12 +253,14 @@ SynchronousProcessResponse SynchronousProcess::run(const QString &binary,
void SynchronousProcess::slotTimeout() void SynchronousProcess::slotTimeout()
{ {
if (++m_d->m_hangTimerCount > m_d->m_maxHangTimerCount) { if (++m_d->m_hangTimerCount > m_d->m_maxHangTimerCount) {
if (debug)
qDebug() << Q_FUNC_INFO << "HANG detected, killing";
m_d->m_process.kill(); m_d->m_process.kill();
m_d->m_result.result = SynchronousProcessResponse::Hang; m_d->m_result.result = SynchronousProcessResponse::Hang;
} else {
if (debug)
qDebug() << Q_FUNC_INFO << m_d->m_hangTimerCount;
} }
if (debug)
qDebug() << Q_FUNC_INFO << m_d->m_hangTimerCount;
} }
void SynchronousProcess::finished(int exitCode, QProcess::ExitStatus e) void SynchronousProcess::finished(int exitCode, QProcess::ExitStatus e)
@@ -265,7 +274,9 @@ void SynchronousProcess::finished(int exitCode, QProcess::ExitStatus e)
m_d->m_result.exitCode = exitCode; m_d->m_result.exitCode = exitCode;
break; break;
case QProcess::CrashExit: case QProcess::CrashExit:
m_d->m_result.result = SynchronousProcessResponse::TerminatedAbnormally; // Was hang detected before and killed?
if (m_d->m_result.result != SynchronousProcessResponse::Hang)
m_d->m_result.result = SynchronousProcessResponse::TerminatedAbnormally;
m_d->m_result.exitCode = -1; m_d->m_result.exitCode = -1;
break; break;
} }
@@ -277,7 +288,10 @@ void SynchronousProcess::error(QProcess::ProcessError e)
m_d->m_hangTimerCount = 0; m_d->m_hangTimerCount = 0;
if (debug) if (debug)
qDebug() << Q_FUNC_INFO << e; qDebug() << Q_FUNC_INFO << e;
m_d->m_result.result = SynchronousProcessResponse::StartFailed; // Was hang detected before and killed?
if (m_d->m_result.result != SynchronousProcessResponse::Hang)
m_d->m_result.result = SynchronousProcessResponse::StartFailed;
m_d->m_startFailure = true;
m_d->m_eventLoop.quit(); m_d->m_eventLoop.quit();
} }

View File

@@ -40,6 +40,7 @@ namespace Constants {
const char * const PROJECTCONTEXT = "CMakeProject.ProjectContext"; const char * const PROJECTCONTEXT = "CMakeProject.ProjectContext";
const char * const CMAKEMIMETYPE = "text/x-cmake"; // TOOD check that this is correct const char * const CMAKEMIMETYPE = "text/x-cmake"; // TOOD check that this is correct
const char * const CMAKESTEP = "CMakeProjectManager.CMakeStep"; const char * const CMAKESTEP = "CMakeProjectManager.CMakeStep";
const char * const MAKESTEP = "CMakeProjectManager.MakeStep";
} // namespace Constants } // namespace Constants

View File

@@ -7,10 +7,12 @@ HEADERS = cmakeproject.h \
cmakeprojectmanager.h \ cmakeprojectmanager.h \
cmakeprojectconstants.h \ cmakeprojectconstants.h \
cmakeprojectnodes.h \ cmakeprojectnodes.h \
cmakestep.h cmakestep.h \
makestep.h
SOURCES = cmakeproject.cpp \ SOURCES = cmakeproject.cpp \
cmakeprojectplugin.cpp \ cmakeprojectplugin.cpp \
cmakeprojectmanager.cpp \ cmakeprojectmanager.cpp \
cmakeprojectnodes.cpp \ cmakeprojectnodes.cpp \
cmakestep.cpp cmakestep.cpp \
makestep.cpp
RESOURCES += cmakeproject.qrc RESOURCES += cmakeproject.qrc

View File

@@ -1,3 +1,36 @@
/***************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Qt Software Information (qt-info@nokia.com)
**
**
** Non-Open Source Usage
**
** Licensees may use this file in accordance with the Qt Beta Version
** License Agreement, Agreement version 2.2 provided with the Software or,
** alternatively, in accordance with the terms contained in a written
** agreement between you and Nokia.
**
** GNU General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU General
** Public License versions 2.0 or 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the packaging
** of this file. Please review the following information to ensure GNU
** General Public Licensing requirements will be met:
**
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
** http://www.gnu.org/copyleft/gpl.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt GPL Exception
** version 1.2, included in the file GPL_EXCEPTION.txt in this package.
**
***************************************************************************/
#include "cmakestep.h" #include "cmakestep.h"
#include "cmakeprojectconstants.h" #include "cmakeprojectconstants.h"
#include "cmakeproject.h" #include "cmakeproject.h"
@@ -6,7 +39,7 @@ using namespace CMakeProjectManager;
using namespace CMakeProjectManager::Internal; using namespace CMakeProjectManager::Internal;
CMakeStep::CMakeStep(CMakeProject *pro) CMakeStep::CMakeStep(CMakeProject *pro)
: BuildStep(pro), m_pro(pro) : AbstractProcessStep(pro), m_pro(pro)
{ {
} }
@@ -18,14 +51,17 @@ CMakeStep::~CMakeStep()
bool CMakeStep::init(const QString &buildConfiguration) bool CMakeStep::init(const QString &buildConfiguration)
{ {
// TODO setEnabled(buildConfiguration, true);
return true; setWorkingDirectory(buildConfiguration, m_pro->buildDirectory(buildConfiguration));
setCommand(buildConfiguration, "cmake"); // TODO give full path here?
setArguments(buildConfiguration, QStringList()); // TODO
setEnvironment(buildConfiguration, m_pro->environment(buildConfiguration));
return AbstractProcessStep::init(buildConfiguration);
} }
void CMakeStep::run(QFutureInterface<bool> &fi) void CMakeStep::run(QFutureInterface<bool> &fi)
{ {
// TODO AbstractProcessStep::run(fi);
fi.reportResult(true);
} }
QString CMakeStep::name() QString CMakeStep::name()

View File

@@ -1,7 +1,41 @@
/***************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Qt Software Information (qt-info@nokia.com)
**
**
** Non-Open Source Usage
**
** Licensees may use this file in accordance with the Qt Beta Version
** License Agreement, Agreement version 2.2 provided with the Software or,
** alternatively, in accordance with the terms contained in a written
** agreement between you and Nokia.
**
** GNU General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU General
** Public License versions 2.0 or 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the packaging
** of this file. Please review the following information to ensure GNU
** General Public Licensing requirements will be met:
**
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
** http://www.gnu.org/copyleft/gpl.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt GPL Exception
** version 1.2, included in the file GPL_EXCEPTION.txt in this package.
**
***************************************************************************/
#ifndef CMAKESTEP_H #ifndef CMAKESTEP_H
#define CMAKESTEP_H #define CMAKESTEP_H
#include <projectexplorer/buildstep.h> #include <projectexplorer/buildstep.h>
#include <projectexplorer/abstractprocessstep.h>
namespace CMakeProjectManager { namespace CMakeProjectManager {
namespace Internal { namespace Internal {
@@ -10,7 +44,7 @@ class CMakeProject;
class CMakeBuildStepConfigWidget; class CMakeBuildStepConfigWidget;
class CMakeStep : public ProjectExplorer::BuildStep class CMakeStep : public ProjectExplorer::AbstractProcessStep
{ {
public: public:
CMakeStep(CMakeProject *pro); CMakeStep(CMakeProject *pro);

View File

@@ -0,0 +1,127 @@
/***************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Qt Software Information (qt-info@nokia.com)
**
**
** Non-Open Source Usage
**
** Licensees may use this file in accordance with the Qt Beta Version
** License Agreement, Agreement version 2.2 provided with the Software or,
** alternatively, in accordance with the terms contained in a written
** agreement between you and Nokia.
**
** GNU General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU General
** Public License versions 2.0 or 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the packaging
** of this file. Please review the following information to ensure GNU
** General Public Licensing requirements will be met:
**
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
** http://www.gnu.org/copyleft/gpl.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt GPL Exception
** version 1.2, included in the file GPL_EXCEPTION.txt in this package.
**
***************************************************************************/
#include "makestep.h"
#include "cmakeprojectconstants.h"
#include "cmakeproject.h"
using namespace CMakeProjectManager;
using namespace CMakeProjectManager::Internal;
MakeStep::MakeStep(CMakeProject *pro)
: AbstractProcessStep(pro), m_pro(pro)
{
}
MakeStep::~MakeStep()
{
}
bool MakeStep::init(const QString &buildConfiguration)
{
setEnabled(buildConfiguration, true);
setWorkingDirectory(buildConfiguration, m_pro->buildDirectory(buildConfiguration));
setCommand(buildConfiguration, "make"); // TODO give full path here?
setArguments(buildConfiguration, QStringList()); // TODO
setEnvironment(buildConfiguration, m_pro->environment(buildConfiguration));
return AbstractProcessStep::init(buildConfiguration);
}
void MakeStep::run(QFutureInterface<bool> &fi)
{
AbstractProcessStep::run(fi);
}
QString MakeStep::name()
{
return "Make";
}
QString MakeStep::displayName()
{
return Constants::CMAKESTEP;
}
ProjectExplorer::BuildStepConfigWidget *MakeStep::createConfigWidget()
{
return new MakeBuildStepConfigWidget();
}
bool MakeStep::immutable() const
{
return true;
}
//
// CMakeBuildStepConfigWidget
//
QString MakeBuildStepConfigWidget::displayName() const
{
return "Make";
}
void MakeBuildStepConfigWidget::init(const QString &buildConfiguration)
{
// TODO
}
//
// MakeBuildStepFactory
//
bool MakeBuildStepFactory::canCreate(const QString &name) const
{
return (Constants::MAKESTEP == name);
}
ProjectExplorer::BuildStep *MakeBuildStepFactory::create(ProjectExplorer::Project *project, const QString &name) const
{
Q_ASSERT(name == Constants::MAKESTEP);
CMakeProject *pro = qobject_cast<CMakeProject *>(project);
Q_ASSERT(pro);
return new MakeStep(pro);
}
QStringList MakeBuildStepFactory::canCreateForProject(ProjectExplorer::Project *pro) const
{
return QStringList();
}
QString MakeBuildStepFactory::displayNameForName(const QString &name) const
{
return "Make";
}

View File

@@ -0,0 +1,79 @@
/***************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Qt Software Information (qt-info@nokia.com)
**
**
** Non-Open Source Usage
**
** Licensees may use this file in accordance with the Qt Beta Version
** License Agreement, Agreement version 2.2 provided with the Software or,
** alternatively, in accordance with the terms contained in a written
** agreement between you and Nokia.
**
** GNU General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU General
** Public License versions 2.0 or 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the packaging
** of this file. Please review the following information to ensure GNU
** General Public Licensing requirements will be met:
**
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
** http://www.gnu.org/copyleft/gpl.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt GPL Exception
** version 1.2, included in the file GPL_EXCEPTION.txt in this package.
**
***************************************************************************/
#ifndef MAKESTEP_H
#define MAKESTEP_H
#include <projectexplorer/abstractprocessstep.h>
namespace CMakeProjectManager {
namespace Internal {
class CMakeProject;
class MakeStep : public ProjectExplorer::AbstractProcessStep
{
public:
MakeStep(CMakeProject *pro);
~MakeStep();
virtual bool init(const QString &buildConfiguration);
virtual void run(QFutureInterface<bool> &fi);
virtual QString name();
virtual QString displayName();
virtual ProjectExplorer::BuildStepConfigWidget *createConfigWidget();
virtual bool immutable() const;
private:
CMakeProject *m_pro;
};
class MakeBuildStepConfigWidget :public ProjectExplorer::BuildStepConfigWidget
{
public:
virtual QString displayName() const;
virtual void init(const QString &buildConfiguration);
};
class MakeBuildStepFactory : public ProjectExplorer::IBuildStepFactory
{
virtual bool canCreate(const QString &name) const;
virtual ProjectExplorer::BuildStep *create(ProjectExplorer::Project *pro, const QString &name) const;
virtual QStringList canCreateForProject(ProjectExplorer::Project *pro) const;
virtual QString displayNameForName(const QString &name) const;
};
}
}
#endif // MAKESTEP_H

View File

@@ -509,6 +509,8 @@ QPixmap BaseFileWizard::watermark()
void BaseFileWizard::setupWizard(QWizard *w) void BaseFileWizard::setupWizard(QWizard *w)
{ {
w->setPixmap(QWizard::WatermarkPixmap, watermark()); w->setPixmap(QWizard::WatermarkPixmap, watermark());
w->setOption(QWizard::NoCancelButton, false);
w->setOption(QWizard::NoDefaultButton, false);
} }
bool BaseFileWizard::postGenerateFiles(const GeneratedFiles &l, QString *errorMessage) bool BaseFileWizard::postGenerateFiles(const GeneratedFiles &l, QString *errorMessage)

View File

@@ -94,6 +94,7 @@ const char * const C_WELCOME_MODE = "Core.WelcomeMode";
const char * const C_EDIT_MODE = "Core.EditMode"; const char * const C_EDIT_MODE = "Core.EditMode";
const char * const C_EDITORMANAGER = "Core.EditorManager"; const char * const C_EDITORMANAGER = "Core.EditorManager";
const char * const C_NAVIGATION_PANE = "Core.NavigationPane"; const char * const C_NAVIGATION_PANE = "Core.NavigationPane";
const char * const C_PROBLEM_PANE = "Core.ProblemPane";
//default editor kind //default editor kind
const char * const K_DEFAULT_TEXT_EDITOR = "Plain Text Editor"; const char * const K_DEFAULT_TEXT_EDITOR = "Plain Text Editor";

View File

@@ -74,20 +74,6 @@ using namespace Core::Internal;
enum { debugEditorManager=0 }; enum { debugEditorManager=0 };
QString EditorManager::defaultExternalEditor() const
{
#ifdef Q_OS_MAC
return m_d->m_core->resourcePath()
+QLatin1String("/runInTerminal.command vi %f %l %c %W %H %x %y");
#elif defined(Q_OS_UNIX)
return QLatin1String("xterm -geom %Wx%H+%x+%y -e vi %f +%l +\"normal %c|\"");
#elif defined (Q_OS_WIN)
return QLatin1String("notepad %f");
#else
return QString();
#endif
}
//===================EditorManager===================== //===================EditorManager=====================
EditorManagerPlaceHolder *EditorManagerPlaceHolder::m_current = 0; EditorManagerPlaceHolder *EditorManagerPlaceHolder::m_current = 0;
@@ -388,6 +374,20 @@ QSize EditorManager::minimumSizeHint() const
return QSize(400, 300); return QSize(400, 300);
} }
QString EditorManager::defaultExternalEditor() const
{
#ifdef Q_OS_MAC
return m_d->m_core->resourcePath()
+QLatin1String("/runInTerminal.command vi %f %l %c %W %H %x %y");
#elif defined(Q_OS_UNIX)
return QLatin1String("xterm -geom %Wx%H+%x+%y -e vi %f +%l +\"normal %c|\"");
#elif defined (Q_OS_WIN)
return QLatin1String("notepad %f");
#else
return QString();
#endif
}
EditorSplitter *EditorManager::editorSplitter() const EditorSplitter *EditorManager::editorSplitter() const
{ {
return m_d->m_splitter; return m_d->m_splitter;
@@ -1003,29 +1003,32 @@ bool EditorManager::saveFile(IEditor *editor)
return success; return success;
} }
namespace { EditorManager::ReadOnlyAction
enum ReadOnlyAction { RO_Cancel, RO_OpenSCC, RO_MakeWriteable, RO_SaveAs }; EditorManager::promptReadOnlyFile(const QString &fileName,
} const IVersionControl *versionControl,
QWidget *parent,
static ReadOnlyAction promptReadOnly(const QString &fileName, bool hasSCC, QWidget *parent) bool displaySaveAsButton)
{ {
QMessageBox msgBox(QMessageBox::Question, QObject::tr("File is Read Only"), QMessageBox msgBox(QMessageBox::Question, QObject::tr("File is Read Only"),
QObject::tr("The file %1 is read only.").arg(fileName), QObject::tr("The file %1 is read only.").arg(fileName),
QMessageBox::Cancel, parent); QMessageBox::Cancel, parent);
QPushButton *sccButton = 0; QPushButton *sccButton = 0;
if (hasSCC) if (versionControl && versionControl->supportsOperation(IVersionControl::OpenOperation))
sccButton = msgBox.addButton(QObject::tr("Open with SCC"), QMessageBox::AcceptRole); sccButton = msgBox.addButton(QObject::tr("Open with VCS (%1)").arg(versionControl->name()), QMessageBox::AcceptRole);
QPushButton *makeWritableButton = msgBox.addButton(QObject::tr("Make writable"), QMessageBox::AcceptRole); QPushButton *makeWritableButton = msgBox.addButton(QObject::tr("Make writable"), QMessageBox::AcceptRole);
QPushButton *saveAsButton = msgBox.addButton(QObject::tr("Save as ..."), QMessageBox::ActionRole);
if (hasSCC) QPushButton *saveAsButton = 0;
msgBox.setDefaultButton(sccButton); if (displaySaveAsButton)
else msgBox.addButton(QObject::tr("Save as ..."), QMessageBox::ActionRole);
msgBox.setDefaultButton(makeWritableButton);
msgBox.setDefaultButton(sccButton ? sccButton : makeWritableButton);
msgBox.exec(); msgBox.exec();
QAbstractButton *clickedButton = msgBox.clickedButton(); QAbstractButton *clickedButton = msgBox.clickedButton();
if (clickedButton == sccButton) if (clickedButton == sccButton)
return RO_OpenSCC; return RO_OpenVCS;
if (clickedButton == makeWritableButton) if (clickedButton == makeWritableButton)
return RO_MakeWriteable; return RO_MakeWriteable;
if (clickedButton == saveAsButton) if (clickedButton == saveAsButton)
@@ -1042,8 +1045,8 @@ EditorManager::makeEditorWritable(IEditor *editor)
IFile *file = editor->file(); IFile *file = editor->file();
const QString &fileName = file->fileName(); const QString &fileName = file->fileName();
switch (promptReadOnly(fileName, versionControl, m_d->m_core->mainWindow())) { switch (promptReadOnlyFile(fileName, versionControl, m_d->m_core->mainWindow(), true)) {
case RO_OpenSCC: case RO_OpenVCS:
if (!versionControl->vcsOpen(fileName)) { if (!versionControl->vcsOpen(fileName)) {
QMessageBox::warning(m_d->m_core->mainWindow(), tr("Failed!"), tr("Could not open the file for edit with SCC.")); QMessageBox::warning(m_d->m_core->mainWindow(), tr("Failed!"), tr("Could not open the file for edit with SCC."));
return Failed; return Failed;

View File

@@ -55,6 +55,7 @@ class IEditorFactory;
class MimeType; class MimeType;
class IFile; class IFile;
class IMode; class IMode;
class IVersionControl;
enum MakeWritableResult { enum MakeWritableResult {
OpenedWithVersionControl, OpenedWithVersionControl,
@@ -159,6 +160,16 @@ public:
QString defaultExternalEditor() const; QString defaultExternalEditor() const;
QString externalEditorHelpText() const; QString externalEditorHelpText() const;
// Helper to display a message dialog when encountering a read-only
// file, prompting the user about how to make it writeable.
enum ReadOnlyAction { RO_Cancel, RO_OpenVCS, RO_MakeWriteable, RO_SaveAs };
static ReadOnlyAction promptReadOnlyFile(const QString &fileName,
const IVersionControl *versionControl,
QWidget *parent,
bool displaySaveAsButton = false);
signals: signals:
void currentEditorChanged(Core::IEditor *editor); void currentEditorChanged(Core::IEditor *editor);
void editorCreated(Core::IEditor *editor, const QString &fileName); void editorCreated(Core::IEditor *editor, const QString &fileName);

View File

@@ -45,51 +45,53 @@ class CORE_EXPORT IVersionControl : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
enum Operation { AddOperation, DeleteOperation, OpenOperation };
IVersionControl(QObject *parent = 0) : QObject(parent) {} IVersionControl(QObject *parent = 0) : QObject(parent) {}
virtual ~IVersionControl() {} virtual ~IVersionControl() {}
// Returns wheter files in this directory should be managed with this virtual QString name() const = 0;
// Enable the VCS, that is, make its menu actions visible.
virtual bool isEnabled() const = 0;
virtual void setEnabled(bool enabled) = 0;
// Returns whether files in this directory should be managed with this
// version control. // version control.
virtual bool managesDirectory(const QString &filename) const = 0; virtual bool managesDirectory(const QString &filename) const = 0;
// This function should return the topmost directory, for // This function should return the topmost directory, for which this
// which this IVersionControl should be used. // IVersionControl should be used. The VCSManager assumes that all files
// The VCSManager assumes that all files in the returned directory // in the returned directory are managed by the same IVersionControl
// are managed by the same IVersionControl
// Note that this is used as an optimization, so that the VCSManager // Note that this is used as an optimization, so that the VCSManager
// doesn't need to call managesDirectory(..) for each directory // doesn't need to call managesDirectory(..) for each directory
// This function is called after finding out that the directory is managed by // This function is called after finding out that the directory is managed
// a specific version control // by a specific version control.
virtual QString findTopLevelForDirectory(const QString &directory) const = 0; virtual QString findTopLevelForDirectory(const QString &directory) const = 0;
// Called prior to save, if the file is read only. // Called to query whether a VCS supports the respective operations.
// Should be implemented if the scc requires a operation before editing the file virtual bool supportsOperation(Operation operation) const = 0;
// E.g. p4 edit
// Note: The EditorManager calls this for the editors // Called prior to save, if the file is read only. Should be implemented
// if the scc requires a operation before editing the file, e.g. 'p4 edit'
// Note: The EditorManager calls this for the editors.
virtual bool vcsOpen(const QString &fileName) = 0; virtual bool vcsOpen(const QString &fileName) = 0;
// Called after a file has been added to a project // Called after a file has been added to a project If the version control
// If the version control needs to know which files it needs to track // needs to know which files it needs to track you should reimplement this
// you should reimplement this function // function, e.g. 'p4 add', 'cvs add', 'svn add'.
// E.g. p4 add, cvs add, svn add // Note: This function should be called from IProject subclasses after
// Note: This function should be called from IProject subclasses after files // files are added to the project
// are added to the project
virtual bool vcsAdd(const QString &filename) = 0; virtual bool vcsAdd(const QString &filename) = 0;
// Called after a file has been removed from the project (if the user wants) // Called after a file has been removed from the project (if the user
// E.g. p4 delete, svn delete // wants), e.g. 'p4 delete', 'svn delete'.
// You probably want to call SccManager::showDeleteDialog, which asks the user to // You probably want to call VcsManager::showDeleteDialog, which asks the
// confirm the deletion // user to confirm the deletion
virtual bool vcsDelete(const QString &filename) = 0; virtual bool vcsDelete(const QString &filename) = 0;
// TODO: ADD A WAY TO DETECT WHETHER A FILE IS MANAGED, e.g // TODO: ADD A WAY TO DETECT WHETHER A FILE IS MANAGED, e.g
// virtual bool sccManaged(const QStryng &filename) = 0; // virtual bool sccManaged(const QStryng &filename) = 0;
// TODO
// we probably want to have a function supports( enum Operation ) or
// something which describes which "kind" of revision control system it is.
// That is to check wheter a given operation is needed.
// But well I don't know yet how all different version control systems work
}; };
} // namespace Core } // namespace Core

View File

@@ -127,6 +127,7 @@ MainWindow::MainWindow() :
m_mimeDatabase(new MimeDatabase), m_mimeDatabase(new MimeDatabase),
m_navigationWidget(0), m_navigationWidget(0),
m_rightPaneWidget(0), m_rightPaneWidget(0),
m_versionDialog(0),
m_activeContext(0), m_activeContext(0),
m_pluginManager(0), m_pluginManager(0),
m_outputPane(new OutputPane(m_globalContext)), m_outputPane(new OutputPane(m_globalContext)),
@@ -1085,8 +1086,20 @@ void MainWindow::openRecentFile()
void MainWindow::aboutQtCreator() void MainWindow::aboutQtCreator()
{ {
VersionDialog versionDialog(this); if (!m_versionDialog) {
versionDialog.exec(); m_versionDialog = new VersionDialog(this);
connect(m_versionDialog, SIGNAL(finished(int)),
this, SLOT(destroyVersionDialog()));
}
m_versionDialog->show();
}
void MainWindow::destroyVersionDialog()
{
if (m_versionDialog) {
m_versionDialog->deleteLater();
m_versionDialog = 0;
}
} }
void MainWindow::aboutPlugins() void MainWindow::aboutPlugins()

View File

@@ -83,6 +83,7 @@ class OutputPane;
class ProgressManager; class ProgressManager;
class ShortcutSettings; class ShortcutSettings;
class ViewManager; class ViewManager;
class VersionDialog;
class CORE_EXPORT MainWindow : public QMainWindow class CORE_EXPORT MainWindow : public QMainWindow
{ {
@@ -160,6 +161,7 @@ private slots:
void aboutPlugins(); void aboutPlugins();
void updateFocusWidget(QWidget *old, QWidget *now); void updateFocusWidget(QWidget *old, QWidget *now);
void toggleNavigation(); void toggleNavigation();
void destroyVersionDialog();
private: private:
void updateContextObject(IContext *context); void updateContextObject(IContext *context);
@@ -190,6 +192,7 @@ private:
NavigationWidget *m_navigationWidget; NavigationWidget *m_navigationWidget;
RightPaneWidget *m_rightPaneWidget; RightPaneWidget *m_rightPaneWidget;
Core::BaseView *m_outputView; Core::BaseView *m_outputView;
VersionDialog *m_versionDialog;
IContext * m_activeContext; IContext * m_activeContext;

View File

@@ -45,8 +45,18 @@
#include <QtCore/QFileInfo> #include <QtCore/QFileInfo>
#include <QtGui/QMessageBox> #include <QtGui/QMessageBox>
enum { debug = 0 };
namespace Core { namespace Core {
typedef QList<IVersionControl *> VersionControlList;
static inline VersionControlList allVersionControls()
{
return ExtensionSystem::PluginManager::instance()->getObjects<IVersionControl>();
}
// ---- VCSManagerPrivate
struct VCSManagerPrivate { struct VCSManagerPrivate {
QMap<QString, IVersionControl *> m_cachedMatches; QMap<QString, IVersionControl *> m_cachedMatches;
}; };
@@ -61,31 +71,54 @@ VCSManager::~VCSManager()
delete m_d; delete m_d;
} }
void VCSManager::setVCSEnabled(const QString &directory)
{
if (debug)
qDebug() << Q_FUNC_INFO << directory;
IVersionControl* managingVCS = findVersionControlForDirectory(directory);
const VersionControlList versionControls = allVersionControls();
foreach(IVersionControl *versionControl, versionControls) {
const bool newEnabled = versionControl == managingVCS;
if (newEnabled != versionControl->isEnabled())
versionControl->setEnabled(newEnabled);
}
}
void VCSManager::setAllVCSEnabled()
{
if (debug)
qDebug() << Q_FUNC_INFO;
const VersionControlList versionControls = allVersionControls();
foreach(IVersionControl *versionControl, versionControls)
if (!versionControl->isEnabled())
versionControl->setEnabled(true);
}
IVersionControl* VCSManager::findVersionControlForDirectory(const QString &directory) IVersionControl* VCSManager::findVersionControlForDirectory(const QString &directory)
{ {
// first look into the cache // first look into the cache, check the whole name
int pos = 0;
{ // First try the whole name {
QMap<QString, IVersionControl *>::const_iterator it = m_d->m_cachedMatches.constFind(directory); const QMap<QString, IVersionControl *>::const_iterator it = m_d->m_cachedMatches.constFind(directory);
if (it != m_d->m_cachedMatches.constEnd()) { if (it != m_d->m_cachedMatches.constEnd())
return it.value(); return it.value();
}
} }
int pos = 0;
const QChar slash = QLatin1Char('/');
while(true) { while(true) {
int index = directory.indexOf('/', pos); int index = directory.indexOf(slash, pos);
if (index == -1) if (index == -1)
break; break;
QString directoryPart = directory.left(index); const QString directoryPart = directory.left(index);
QMap<QString, IVersionControl *>::const_iterator it = m_d->m_cachedMatches.constFind(directoryPart); QMap<QString, IVersionControl *>::const_iterator it = m_d->m_cachedMatches.constFind(directoryPart);
if (it != m_d->m_cachedMatches.constEnd()) { if (it != m_d->m_cachedMatches.constEnd())
return it.value(); return it.value();
}
pos = index+1; pos = index+1;
} }
// ah nothing so ask the IVersionControls directly // ah nothing so ask the IVersionControls directly
QList<IVersionControl *> versionControls = ExtensionSystem::PluginManager::instance()->getObjects<IVersionControl>(); const VersionControlList versionControls = allVersionControls();
foreach(IVersionControl * versionControl, versionControls) { foreach(IVersionControl * versionControl, versionControls) {
if (versionControl->managesDirectory(directory)) { if (versionControl->managesDirectory(directory)) {
m_d->m_cachedMatches.insert(versionControl->findTopLevelForDirectory(directory), versionControl); m_d->m_cachedMatches.insert(versionControl->findTopLevelForDirectory(directory), versionControl);
@@ -95,20 +128,20 @@ IVersionControl* VCSManager::findVersionControlForDirectory(const QString &direc
return 0; return 0;
} }
void VCSManager::showDeleteDialog(const QString &fileName) bool VCSManager::showDeleteDialog(const QString &fileName)
{ {
IVersionControl *vc = findVersionControlForDirectory(QFileInfo(fileName).absolutePath()); IVersionControl *vc = findVersionControlForDirectory(QFileInfo(fileName).absolutePath());
if (!vc) if (!vc || !vc->supportsOperation(IVersionControl::DeleteOperation))
return; return true;
const QString title = QCoreApplication::translate("VCSManager", "Version Control"); const QString title = QCoreApplication::translate("VCSManager", "Version Control");
const QString msg = QCoreApplication::translate("VCSManager", const QString msg = QCoreApplication::translate("VCSManager",
"Would you like to remove this file from the version control system?\n" "Would you like to remove this file from the version control system (%1)?\n"
"Note: This might remove the local file."); "Note: This might remove the local file.").arg(vc->name());
const QMessageBox::StandardButton button = const QMessageBox::StandardButton button =
QMessageBox::question(0, title, msg, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); QMessageBox::question(0, title, msg, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
if (button == QMessageBox::Yes) { if (button != QMessageBox::Yes)
vc->vcsDelete(fileName); return true;
} return vc->vcsDelete(fileName);
} }
} // namespace Core } // namespace Core

View File

@@ -62,10 +62,16 @@ public:
IVersionControl *findVersionControlForDirectory(const QString &directory); IVersionControl *findVersionControlForDirectory(const QString &directory);
// Shows a confirmation dialog, // Enable the VCS managing a certain directory only. This should
// wheter the file should also be deleted from revision control // be used by project manager classes.
// Calls sccDelete on the file void setVCSEnabled(const QString &directory);
void showDeleteDialog(const QString &fileName); // Enable all VCS.
void setAllVCSEnabled();
// Shows a confirmation dialog, whether the file should also be deleted
// from revision control Calls sccDelete on the file. Returns false
// if a failure occurs
bool showDeleteDialog(const QString &fileName);
private: private:
VCSManagerPrivate *m_d; VCSManagerPrivate *m_d;

View File

@@ -206,6 +206,7 @@ void CPPEditor::createToolBar(CPPEditorEditable *editable)
connect(m_methodCombo, SIGNAL(activated(int)), this, SLOT(jumpToMethod(int))); connect(m_methodCombo, SIGNAL(activated(int)), this, SLOT(jumpToMethod(int)));
connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(updateMethodBoxIndex())); connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(updateMethodBoxIndex()));
connect(m_methodCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(updateMethodBoxToolTip()));
connect(file(), SIGNAL(changed()), this, SLOT(updateFileName())); connect(file(), SIGNAL(changed()), this, SLOT(updateFileName()));
@@ -355,10 +356,16 @@ void CPPEditor::updateMethodBoxIndex()
if (lastIndex.isValid()) { if (lastIndex.isValid()) {
bool blocked = m_methodCombo->blockSignals(true); bool blocked = m_methodCombo->blockSignals(true);
m_methodCombo->setCurrentIndex(lastIndex.row()); m_methodCombo->setCurrentIndex(lastIndex.row());
updateMethodBoxToolTip();
(void) m_methodCombo->blockSignals(blocked); (void) m_methodCombo->blockSignals(blocked);
} }
} }
void CPPEditor::updateMethodBoxToolTip()
{
m_methodCombo->setToolTip(m_methodCombo->currentText());
}
static bool isCompatible(Name *name, Name *otherName) static bool isCompatible(Name *name, Name *otherName)
{ {
if (NameId *nameId = name->asNameId()) { if (NameId *nameId = name->asNameId()) {

View File

@@ -115,7 +115,7 @@ private slots:
void updateFileName(); void updateFileName();
void jumpToMethod(int index); void jumpToMethod(int index);
void updateMethodBoxIndex(); void updateMethodBoxIndex();
void updateMethodBoxToolTip();
void onDocumentUpdated(CPlusPlus::Document::Ptr doc); void onDocumentUpdated(CPlusPlus::Document::Ptr doc);
private: private:

View File

@@ -0,0 +1,49 @@
/***************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Qt Software Information (qt-info@nokia.com)
**
**
** Non-Open Source Usage
**
** Licensees may use this file in accordance with the Qt Beta Version
** License Agreement, Agreement version 2.2 provided with the Software or,
** alternatively, in accordance with the terms contained in a written
** agreement between you and Nokia.
**
** GNU General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU General
** Public License versions 2.0 or 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the packaging
** of this file. Please review the following information to ensure GNU
** General Public Licensing requirements will be met:
**
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
** http://www.gnu.org/copyleft/gpl.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt GPL Exception
** version 1.2, included in the file GPL_EXCEPTION.txt in this package.
**
***************************************************************************/
#include "cppclassesfilter.h"
using namespace CppTools::Internal;
CppClassesFilter::CppClassesFilter(CppModelManager *manager, Core::EditorManager *editorManager)
: CppQuickOpenFilter(manager, editorManager)
{
setShortcutString("c");
setIncludedByDefault(false);
search.setSymbolsToSearchFor(SearchSymbols::Classes);
}
CppClassesFilter::~CppClassesFilter()
{
}

View File

@@ -0,0 +1,58 @@
/***************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Qt Software Information (qt-info@nokia.com)
**
**
** Non-Open Source Usage
**
** Licensees may use this file in accordance with the Qt Beta Version
** License Agreement, Agreement version 2.2 provided with the Software or,
** alternatively, in accordance with the terms contained in a written
** agreement between you and Nokia.
**
** GNU General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU General
** Public License versions 2.0 or 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the packaging
** of this file. Please review the following information to ensure GNU
** General Public Licensing requirements will be met:
**
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
** http://www.gnu.org/copyleft/gpl.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt GPL Exception
** version 1.2, included in the file GPL_EXCEPTION.txt in this package.
**
***************************************************************************/
#ifndef CPPCLASSESFILTER_H
#define CPPCLASSESFILTER_H
#include <cppquickopenfilter.h>
namespace CppTools {
namespace Internal {
class CppClassesFilter : public CppQuickOpenFilter
{
Q_OBJECT
public:
CppClassesFilter(CppModelManager *manager, Core::EditorManager *editorManager);
~CppClassesFilter();
QString trName() const { return tr("Classes"); }
QString name() const { return QLatin1String("Classes"); }
Priority priority() const { return Medium; }
};
} // namespace Internal
} // namespace CppTools
#endif // CPPCLASSESFILTER_H

View File

@@ -60,7 +60,7 @@
using namespace CppTools::Internal; using namespace CppTools::Internal;
CppHoverHandler::CppHoverHandler(CppModelManager *manager, QObject *parent) CppHoverHandler::CppHoverHandler(CppModelManager *manager, QObject *parent)
: QObject(parent), m_manager(manager) : QObject(parent), m_manager(manager), m_helpEngineNeedsSetup(false)
{ {
QFileInfo fi(ExtensionSystem::PluginManager::instance()->getObject<Core::ICore>()->settings()->fileName()); QFileInfo fi(ExtensionSystem::PluginManager::instance()->getObject<Core::ICore>()->settings()->fileName());
m_helpEngine = new QHelpEngineCore(fi.absolutePath() m_helpEngine = new QHelpEngineCore(fi.absolutePath()
@@ -68,6 +68,7 @@ CppHoverHandler::CppHoverHandler(CppModelManager *manager, QObject *parent)
//m_helpEngine->setAutoSaveFilter(false); //m_helpEngine->setAutoSaveFilter(false);
m_helpEngine->setupData(); m_helpEngine->setupData();
m_helpEngine->setCurrentFilter(tr("Unfiltered")); m_helpEngine->setCurrentFilter(tr("Unfiltered"));
m_helpEngineNeedsSetup = m_helpEngine->registeredDocumentations().count() == 0;
} }
void CppHoverHandler::updateContextHelpId(TextEditor::ITextEditor *editor, int pos) void CppHoverHandler::updateContextHelpId(TextEditor::ITextEditor *editor, int pos)
@@ -234,6 +235,12 @@ void CppHoverHandler::updateHelpIdAndTooltip(TextEditor::ITextEditor *editor, in
} }
} }
if (m_helpEngineNeedsSetup
&& m_helpEngine->registeredDocumentations().count() > 0) {
m_helpEngine->setupData();
m_helpEngineNeedsSetup = false;
}
if (!m_helpId.isEmpty() && !m_helpEngine->linksForIdentifier(m_helpId).isEmpty()) { if (!m_helpId.isEmpty() && !m_helpEngine->linksForIdentifier(m_helpId).isEmpty()) {
m_toolTip = QString(QLatin1String("<table><tr><td valign=middle><nobr>%1</td>" m_toolTip = QString(QLatin1String("<table><tr><td valign=middle><nobr>%1</td>"
"<td><img src=\":/cpptools/images/f1.svg\"></td></tr></table>")).arg(Qt::escape(m_toolTip)); "<td><img src=\":/cpptools/images/f1.svg\"></td></tr></table>")).arg(Qt::escape(m_toolTip));

View File

@@ -68,6 +68,7 @@ private:
QHelpEngineCore *m_helpEngine; QHelpEngineCore *m_helpEngine;
QString m_helpId; QString m_helpId;
QString m_toolTip; QString m_toolTip;
bool m_helpEngineNeedsSetup;
}; };
} // namespace Internal } // namespace Internal

View File

@@ -129,9 +129,12 @@ public:
void setProjectFiles(const QStringList &files) void setProjectFiles(const QStringList &files)
{ m_projectFiles = files; } { m_projectFiles = files; }
void operator()(QString &fileName) void run(QString &fileName)
{ sourceNeeded(fileName, IncludeGlobal); } { sourceNeeded(fileName, IncludeGlobal); }
void operator()(QString &fileName)
{ run(fileName); }
protected: protected:
bool includeFile(const QString &absoluteFilePath, QByteArray *result) bool includeFile(const QString &absoluteFilePath, QByteArray *result)
{ {
@@ -253,6 +256,25 @@ protected:
m_currentDoc->appendMacro(macroName, macroText); m_currentDoc->appendMacro(macroName, macroText);
} }
virtual void startExpandingMacro(unsigned offset,
const rpp::Macro &,
const QByteArray &originalText)
{
if (! m_currentDoc)
return;
//qDebug() << "start expanding:" << macro.name << "text:" << originalText;
m_currentDoc->addMacroUse(offset, originalText.length());
}
virtual void stopExpandingMacro(unsigned, const rpp::Macro &)
{
if (! m_currentDoc)
return;
//qDebug() << "stop expanding:" << macro.name;
}
void mergeEnvironment(Document::Ptr doc) void mergeEnvironment(Document::Ptr doc)
{ {
QSet<QString> processed; QSet<QString> processed;
@@ -390,6 +412,8 @@ CppModelManager::CppModelManager(QObject *parent) :
CppModelManagerInterface(parent), CppModelManagerInterface(parent),
m_core(ExtensionSystem::PluginManager::instance()->getObject<Core::ICore>()) m_core(ExtensionSystem::PluginManager::instance()->getObject<Core::ICore>())
{ {
m_dirty = true;
m_projectExplorer = ExtensionSystem::PluginManager::instance() m_projectExplorer = ExtensionSystem::PluginManager::instance()
->getObject<ProjectExplorer::ProjectExplorerPlugin>(); ->getObject<ProjectExplorer::ProjectExplorerPlugin>();
@@ -398,6 +422,9 @@ CppModelManager::CppModelManager(QObject *parent) :
ProjectExplorer::SessionManager *session = m_projectExplorer->session(); ProjectExplorer::SessionManager *session = m_projectExplorer->session();
Q_ASSERT(session != 0); Q_ASSERT(session != 0);
connect(session, SIGNAL(projectAdded(ProjectExplorer::Project*)),
this, SLOT(onProjectAdded(ProjectExplorer::Project*)));
connect(session, SIGNAL(aboutToRemoveProject(ProjectExplorer::Project *)), connect(session, SIGNAL(aboutToRemoveProject(ProjectExplorer::Project *)),
this, SLOT(onAboutToRemoveProject(ProjectExplorer::Project *))); this, SLOT(onAboutToRemoveProject(ProjectExplorer::Project *)));
@@ -429,7 +456,7 @@ Document::Ptr CppModelManager::document(const QString &fileName)
CppModelManager::DocumentTable CppModelManager::documents() CppModelManager::DocumentTable CppModelManager::documents()
{ return m_documents; } { return m_documents; }
QStringList CppModelManager::projectFiles() const QStringList CppModelManager::updateProjectFiles() const
{ {
QStringList files; QStringList files;
QMapIterator<ProjectExplorer::Project *, ProjectInfo> it(m_projects); QMapIterator<ProjectExplorer::Project *, ProjectInfo> it(m_projects);
@@ -441,7 +468,7 @@ QStringList CppModelManager::projectFiles() const
return files; return files;
} }
QStringList CppModelManager::includePaths() const QStringList CppModelManager::updateIncludePaths() const
{ {
QStringList includePaths; QStringList includePaths;
QMapIterator<ProjectExplorer::Project *, ProjectInfo> it(m_projects); QMapIterator<ProjectExplorer::Project *, ProjectInfo> it(m_projects);
@@ -453,7 +480,7 @@ QStringList CppModelManager::includePaths() const
return includePaths; return includePaths;
} }
QStringList CppModelManager::frameworkPaths() const QStringList CppModelManager::updateFrameworkPaths() const
{ {
QStringList frameworkPaths; QStringList frameworkPaths;
QMapIterator<ProjectExplorer::Project *, ProjectInfo> it(m_projects); QMapIterator<ProjectExplorer::Project *, ProjectInfo> it(m_projects);
@@ -465,7 +492,7 @@ QStringList CppModelManager::frameworkPaths() const
return frameworkPaths; return frameworkPaths;
} }
QByteArray CppModelManager::definedMacros() const QByteArray CppModelManager::updateDefinedMacros() const
{ {
QByteArray macros; QByteArray macros;
QMapIterator<ProjectExplorer::Project *, ProjectInfo> it(m_projects); QMapIterator<ProjectExplorer::Project *, ProjectInfo> it(m_projects);
@@ -477,7 +504,7 @@ QByteArray CppModelManager::definedMacros() const
return macros; return macros;
} }
QMap<QString, QByteArray> CppModelManager::buildWorkingCopyList() const QMap<QString, QByteArray> CppModelManager::buildWorkingCopyList()
{ {
QMap<QString, QByteArray> workingCopy; QMap<QString, QByteArray> workingCopy;
QMapIterator<TextEditor::ITextEditor *, CppEditorSupport *> it(m_editorSupport); QMapIterator<TextEditor::ITextEditor *, CppEditorSupport *> it(m_editorSupport);
@@ -505,11 +532,17 @@ CppModelManager::ProjectInfo *CppModelManager::projectInfo(ProjectExplorer::Proj
QFuture<void> CppModelManager::refreshSourceFiles(const QStringList &sourceFiles) QFuture<void> CppModelManager::refreshSourceFiles(const QStringList &sourceFiles)
{ {
if (qgetenv("QTCREATOR_NO_CODE_INDEXER").isNull()) { if (! sourceFiles.isEmpty() && qgetenv("QTCREATOR_NO_CODE_INDEXER").isNull()) {
const QMap<QString, QByteArray> workingCopy = buildWorkingCopyList(); const QMap<QString, QByteArray> workingCopy = buildWorkingCopyList();
QFuture<void> result = QtConcurrent::run(&CppModelManager::parse, this, CppPreprocessor *preproc = new CppPreprocessor(this);
sourceFiles, workingCopy); preproc->setProjectFiles(projectFiles());
preproc->setIncludePaths(includePaths());
preproc->setFrameworkPaths(frameworkPaths());
preproc->setWorkingCopy(workingCopy);
QFuture<void> result = QtConcurrent::run(&CppModelManager::parse,
preproc, sourceFiles);
if (sourceFiles.count() > 1) { if (sourceFiles.count() > 1) {
m_core->progressManager()->addTask(result, tr("Indexing"), m_core->progressManager()->addTask(result, tr("Indexing"),
@@ -595,6 +628,22 @@ void CppModelManager::onDocumentUpdated(Document::Ptr doc)
QList<QTextEdit::ExtraSelection> selections; QList<QTextEdit::ExtraSelection> selections;
#ifdef QTCREATOR_WITH_MACRO_HIGHLIGHTING
// set up the format for the macros
QTextCharFormat macroFormat;
macroFormat.setUnderlineStyle(QTextCharFormat::SingleUnderline);
QTextCursor c = ed->textCursor();
foreach (const Document::Block block, doc->macroUses()) {
QTextEdit::ExtraSelection sel;
sel.cursor = c;
sel.cursor.setPosition(block.begin());
sel.cursor.setPosition(block.end(), QTextCursor::KeepAnchor);
sel.format = macroFormat;
selections.append(sel);
}
#endif // QTCREATOR_WITH_MACRO_HIGHLIGHTING
// set up the format for the errors // set up the format for the errors
QTextCharFormat errorFormat; QTextCharFormat errorFormat;
errorFormat.setUnderlineStyle(QTextCharFormat::WaveUnderline); errorFormat.setUnderlineStyle(QTextCharFormat::WaveUnderline);
@@ -640,36 +689,39 @@ void CppModelManager::onDocumentUpdated(Document::Ptr doc)
} }
} }
void CppModelManager::onProjectAdded(ProjectExplorer::Project *)
{
m_dirty = true;
}
void CppModelManager::onAboutToRemoveProject(ProjectExplorer::Project *project) void CppModelManager::onAboutToRemoveProject(ProjectExplorer::Project *project)
{ {
m_dirty = true;
m_projects.remove(project); m_projects.remove(project);
GC(); GC();
} }
void CppModelManager::onSessionUnloaded() void CppModelManager::onSessionUnloaded()
{ {
if (m_core->progressManager()) if (m_core->progressManager()) {
m_core->progressManager()->cancelTasks(CppTools::Constants::TASK_INDEX); m_core->progressManager()->cancelTasks(CppTools::Constants::TASK_INDEX);
m_dirty = true;
}
} }
void CppModelManager::parse(QFutureInterface<void> &future, void CppModelManager::parse(QFutureInterface<void> &future,
CppModelManager *model, CppPreprocessor *preproc,
QStringList files, QStringList files)
QMap<QString, QByteArray> workingCopy)
{ {
Q_ASSERT(! files.isEmpty());
// Change the priority of the background parser thread to idle. // Change the priority of the background parser thread to idle.
QThread::currentThread()->setPriority(QThread::IdlePriority); QThread::currentThread()->setPriority(QThread::IdlePriority);
future.setProgressRange(0, files.size()); future.setProgressRange(0, files.size());
CppPreprocessor preproc(model);
preproc.setWorkingCopy(workingCopy);
preproc.setProjectFiles(model->projectFiles());
preproc.setIncludePaths(model->includePaths());
preproc.setFrameworkPaths(model->frameworkPaths());
QString conf = QLatin1String(pp_configuration_file); QString conf = QLatin1String(pp_configuration_file);
(void) preproc(conf); (void) preproc->run(conf);
const int STEP = 10; const int STEP = 10;
@@ -688,7 +740,7 @@ void CppModelManager::parse(QFutureInterface<void> &future,
#endif #endif
QString fileName = files.at(i); QString fileName = files.at(i);
preproc(fileName); preproc->run(fileName);
if (! (i % STEP)) // Yields execution of the current thread. if (! (i % STEP)) // Yields execution of the current thread.
QThread::yieldCurrentThread(); QThread::yieldCurrentThread();
@@ -698,8 +750,12 @@ void CppModelManager::parse(QFutureInterface<void> &future,
#endif #endif
} }
future.setProgressValue(files.size());
// Restore the previous thread priority. // Restore the previous thread priority.
QThread::currentThread()->setPriority(QThread::NormalPriority); QThread::currentThread()->setPriority(QThread::NormalPriority);
delete preproc;
} }
void CppModelManager::GC() void CppModelManager::GC()
@@ -707,7 +763,7 @@ void CppModelManager::GC()
DocumentTable documents = m_documents; DocumentTable documents = m_documents;
QSet<QString> processed; QSet<QString> processed;
QStringList todo = m_projectFiles; QStringList todo = projectFiles();
while (! todo.isEmpty()) { while (! todo.isEmpty()) {
QString fn = todo.last(); QString fn = todo.last();

View File

@@ -58,6 +58,7 @@ namespace CppTools {
namespace Internal { namespace Internal {
class CppEditorSupport; class CppEditorSupport;
class CppPreprocessor;
class CppHoverHandler; class CppHoverHandler;
class CppModelManager : public CppModelManagerInterface class CppModelManager : public CppModelManagerInterface
@@ -97,18 +98,54 @@ private Q_SLOTS:
void onDocumentUpdated(CPlusPlus::Document::Ptr doc); void onDocumentUpdated(CPlusPlus::Document::Ptr doc);
void onAboutToRemoveProject(ProjectExplorer::Project *project); void onAboutToRemoveProject(ProjectExplorer::Project *project);
void onSessionUnloaded(); void onSessionUnloaded();
void onProjectAdded(ProjectExplorer::Project *project);
private: private:
QMap<QString, QByteArray> buildWorkingCopyList() const; QMap<QString, QByteArray> buildWorkingCopyList();
QStringList projectFiles() const;
QStringList includePaths() const; QStringList projectFiles()
QStringList frameworkPaths() const; {
QByteArray definedMacros() const; ensureUpdated();
return m_projectFiles;
}
QStringList includePaths()
{
ensureUpdated();
return m_includePaths;
}
QStringList frameworkPaths()
{
ensureUpdated();
return m_frameworkPaths;
}
QByteArray definedMacros()
{
ensureUpdated();
return m_definedMacros;
}
QStringList updateProjectFiles() const;
QStringList updateIncludePaths() const;
QStringList updateFrameworkPaths() const;
QByteArray updateDefinedMacros() const;
void ensureUpdated() {
if (! m_dirty)
return;
m_projectFiles = updateProjectFiles();
m_includePaths = updateIncludePaths();
m_frameworkPaths = updateFrameworkPaths();
m_definedMacros = updateDefinedMacros();
m_dirty = false;
}
static void parse(QFutureInterface<void> &future, static void parse(QFutureInterface<void> &future,
CppModelManager *model, CppPreprocessor *preproc,
QStringList files, QStringList files);
QMap<QString, QByteArray> workingCopy);
private: private:
Core::ICore *m_core; Core::ICore *m_core;
@@ -116,8 +153,12 @@ private:
CppHoverHandler *m_hoverHandler; CppHoverHandler *m_hoverHandler;
DocumentTable m_documents; DocumentTable m_documents;
// List of available source files // cache
bool m_dirty;
QStringList m_projectFiles; QStringList m_projectFiles;
QStringList m_includePaths;
QStringList m_frameworkPaths;
QByteArray m_definedMacros;
// editor integration // editor integration
QMap<TextEditor::ITextEditor *, CppEditorSupport *> m_editorSupport; QMap<TextEditor::ITextEditor *, CppEditorSupport *> m_editorSupport;

View File

@@ -32,172 +32,13 @@
***************************************************************************/ ***************************************************************************/
#include "cppquickopenfilter.h" #include "cppquickopenfilter.h"
#include "cppmodelmanager.h"
#include <Literals.h> #include <coreplugin/editormanager/editormanager.h>
#include <Symbols.h>
#include <SymbolVisitor.h>
#include <Scope.h>
#include <cplusplus/Overview.h>
#include <cplusplus/Icons.h>
#include <coreplugin/editormanager/ieditor.h> #include <coreplugin/editormanager/ieditor.h>
#include <texteditor/itexteditor.h> #include <texteditor/itexteditor.h>
#include <texteditor/basetexteditor.h> #include <texteditor/basetexteditor.h>
#include <QtCore/QMultiMap>
#include <functional>
using namespace CPlusPlus;
namespace CppTools {
namespace Internal {
class SearchSymbols: public std::unary_function<Document::Ptr, QList<ModelItemInfo> >,
protected SymbolVisitor
{
Overview overview;
Icons icons;
QList<ModelItemInfo> items;
public:
QList<ModelItemInfo> operator()(Document::Ptr doc)
{ return operator()(doc, QString()); }
QList<ModelItemInfo> operator()(Document::Ptr doc, const QString &scope)
{
QString previousScope = switchScope(scope);
items.clear();
for (unsigned i = 0; i < doc->globalSymbolCount(); ++i) {
accept(doc->globalSymbolAt(i));
}
(void) switchScope(previousScope);
return items;
}
protected:
using SymbolVisitor::visit;
void accept(Symbol *symbol)
{ Symbol::visitSymbol(symbol, this); }
QString switchScope(const QString &scope)
{
QString previousScope = _scope;
_scope = scope;
return previousScope;
}
virtual bool visit(Enum *symbol)
{
QString name = symbolName(symbol);
QString previousScope = switchScope(name);
QIcon icon = icons.iconForSymbol(symbol);
Scope *members = symbol->members();
items.append(ModelItemInfo(name, QString(), ModelItemInfo::Enum,
QString::fromUtf8(symbol->fileName(), symbol->fileNameLength()),
symbol->line(),
icon));
for (unsigned i = 0; i < members->symbolCount(); ++i) {
accept(members->symbolAt(i));
}
(void) switchScope(previousScope);
return false;
}
virtual bool visit(Function *symbol)
{
QString name = symbolName(symbol);
QString type = overview.prettyType(symbol->type());
QIcon icon = icons.iconForSymbol(symbol);
items.append(ModelItemInfo(name, type, ModelItemInfo::Method,
QString::fromUtf8(symbol->fileName(), symbol->fileNameLength()),
symbol->line(),
icon));
return false;
}
virtual bool visit(Namespace *symbol)
{
QString name = symbolName(symbol);
QString previousScope = switchScope(name);
Scope *members = symbol->members();
for (unsigned i = 0; i < members->symbolCount(); ++i) {
accept(members->symbolAt(i));
}
(void) switchScope(previousScope);
return false;
}
#if 0
// This visit method would make function declaration be included in QuickOpen
virtual bool visit(Declaration *symbol)
{
if (symbol->type()->isFunction()) {
QString name = symbolName(symbol);
QString type = overview.prettyType(symbol->type());
//QIcon icon = ...;
items.append(ModelItemInfo(name, type, ModelItemInfo::Method,
QString::fromUtf8(symbol->fileName(), symbol->line()),
symbol->line()));
}
return false;
}
#endif
virtual bool visit(Class *symbol)
{
QString name = symbolName(symbol);
QString previousScope = switchScope(name);
QIcon icon = icons.iconForSymbol(symbol);
items.append(ModelItemInfo(name, QString(), ModelItemInfo::Class,
QString::fromUtf8(symbol->fileName(), symbol->fileNameLength()),
symbol->line(),
icon));
Scope *members = symbol->members();
for (unsigned i = 0; i < members->symbolCount(); ++i) {
accept(members->symbolAt(i));
}
(void) switchScope(previousScope);
return false;
}
QString symbolName(Symbol *symbol) const
{
QString name = _scope;
if (! name.isEmpty())
name += QLatin1String("::");
QString symbolName = overview.prettyName(symbol->name());
if (symbolName.isEmpty()) {
QString type;
if (symbol->isNamespace()) {
type = QLatin1String("namespace");
} else if (symbol->isEnum()) {
type = QLatin1String("enum");
} else if (Class *c = symbol->asClass()) {
if (c->isUnion()) {
type = QLatin1String("union");
} else if (c->isStruct()) {
type = QLatin1String("struct");
} else {
type = QLatin1String("class");
}
} else {
type = QLatin1String("symbol");
}
symbolName = QLatin1String("<anonymous ");
symbolName += type;
symbolName += QLatin1String(">");
}
name += symbolName;
return name;
}
private:
QString _scope;
};
} // namespace Internal
} // namespace CppTools
using namespace CppTools::Internal; using namespace CppTools::Internal;
CppQuickOpenFilter::CppQuickOpenFilter(CppModelManager *manager, Core::EditorManager *editorManager) CppQuickOpenFilter::CppQuickOpenFilter(CppModelManager *manager, Core::EditorManager *editorManager)
@@ -225,9 +66,8 @@ void CppQuickOpenFilter::onDocumentUpdated(CPlusPlus::Document::Ptr doc)
void CppQuickOpenFilter::onAboutToRemoveFiles(const QStringList &files) void CppQuickOpenFilter::onAboutToRemoveFiles(const QStringList &files)
{ {
foreach (QString file, files) { foreach (const QString &file, files)
m_searchList.remove(file); m_searchList.remove(file);
}
} }
void CppQuickOpenFilter::refresh(QFutureInterface<void> &future) void CppQuickOpenFilter::refresh(QFutureInterface<void> &future)
@@ -245,7 +85,6 @@ QList<QuickOpen::FilterEntry> CppQuickOpenFilter::matchesFor(const QString &orig
return entries; return entries;
bool hasWildcard = (entry.contains('*') || entry.contains('?')); bool hasWildcard = (entry.contains('*') || entry.contains('?'));
SearchSymbols search;
QMutableMapIterator<QString, Info> it(m_searchList); QMutableMapIterator<QString, Info> it(m_searchList);
while (it.hasNext()) { while (it.hasNext()) {
it.next(); it.next();
@@ -276,6 +115,5 @@ QList<QuickOpen::FilterEntry> CppQuickOpenFilter::matchesFor(const QString &orig
void CppQuickOpenFilter::accept(QuickOpen::FilterEntry selection) const void CppQuickOpenFilter::accept(QuickOpen::FilterEntry selection) const
{ {
ModelItemInfo info = qvariant_cast<CppTools::Internal::ModelItemInfo>(selection.internalData); ModelItemInfo info = qvariant_cast<CppTools::Internal::ModelItemInfo>(selection.internalData);
TextEditor::BaseTextEditor::openEditorAt(info.fileName, info.line); TextEditor::BaseTextEditor::openEditorAt(info.fileName, info.line);
} }

View File

@@ -34,45 +34,18 @@
#ifndef CPPQUICKOPENFILTER_H #ifndef CPPQUICKOPENFILTER_H
#define CPPQUICKOPENFILTER_H #define CPPQUICKOPENFILTER_H
#include "cppmodelmanager.h" #include "searchsymbols.h"
#include <cplusplus/CppDocument.h>
#include <coreplugin/editormanager/editormanager.h>
#include <quickopen/iquickopenfilter.h> #include <quickopen/iquickopenfilter.h>
#include <QtGui/QIcon>
#include <QFile> namespace Core {
#include <QMetaType> class EditorManager;
}
namespace CppTools { namespace CppTools {
namespace Internal { namespace Internal {
struct ModelItemInfo class CppModelManager;
{
enum ItemType { Enum, Class, Method };
ModelItemInfo()
{ }
ModelItemInfo(const QString &symbolName,
const QString &symbolType,
ItemType type,
const QString &fileName,
int line,
const QIcon &icon)
: symbolName(symbolName),
symbolType(symbolType),
type(type),
fileName(fileName),
line(line),
icon(icon)
{ }
QString symbolName;
QString symbolType;
ItemType type;
QString fileName;
int line;
QIcon icon;
};
class CppQuickOpenFilter : public QuickOpen::IQuickOpenFilter class CppQuickOpenFilter : public QuickOpen::IQuickOpenFilter
{ {
@@ -82,12 +55,15 @@ public:
~CppQuickOpenFilter(); ~CppQuickOpenFilter();
QString trName() const { return tr("Classes and Methods"); } QString trName() const { return tr("Classes and Methods"); }
QString name() const { return "Classes and Methods"; } QString name() const { return QLatin1String("Classes and Methods"); }
Priority priority() const { return Medium; } Priority priority() const { return Medium; }
QList<QuickOpen::FilterEntry> matchesFor(const QString &entry); QList<QuickOpen::FilterEntry> matchesFor(const QString &entry);
void accept(QuickOpen::FilterEntry selection) const; void accept(QuickOpen::FilterEntry selection) const;
void refresh(QFutureInterface<void> &future); void refresh(QFutureInterface<void> &future);
protected:
SearchSymbols search;
private slots: private slots:
void onDocumentUpdated(CPlusPlus::Document::Ptr doc); void onDocumentUpdated(CPlusPlus::Document::Ptr doc);
void onAboutToRemoveFiles(const QStringList &files); void onAboutToRemoveFiles(const QStringList &files);
@@ -114,6 +90,4 @@ private:
} // namespace Internal } // namespace Internal
} // namespace CppTools } // namespace CppTools
Q_DECLARE_METATYPE(CppTools::Internal::ModelItemInfo)
#endif // CPPQUICKOPENFILTER_H #endif // CPPQUICKOPENFILTER_H

View File

@@ -32,6 +32,7 @@
***************************************************************************/ ***************************************************************************/
#include "cpptools.h" #include "cpptools.h"
#include "cppclassesfilter.h"
#include "cppcodecompletion.h" #include "cppcodecompletion.h"
#include "cpphoverhandler.h" #include "cpphoverhandler.h"
#include "cppmodelmanager.h" #include "cppmodelmanager.h"
@@ -87,6 +88,7 @@ bool CppToolsPlugin::initialize(const QStringList & /*arguments*/, QString *)
CppQuickOpenFilter *quickOpenFilter = new CppQuickOpenFilter(m_modelManager, CppQuickOpenFilter *quickOpenFilter = new CppQuickOpenFilter(m_modelManager,
m_core->editorManager()); m_core->editorManager());
addAutoReleasedObject(quickOpenFilter); addAutoReleasedObject(quickOpenFilter);
addAutoReleasedObject(new CppClassesFilter(m_modelManager, m_core->editorManager()));
// Menus // Menus
Core::IActionContainer *mtools = am->actionContainer(Core::Constants::M_TOOLS); Core::IActionContainer *mtools = am->actionContainer(Core::Constants::M_TOOLS);

View File

@@ -4,31 +4,27 @@ include(../../qworkbenchplugin.pri)
include(../../plugins/quickopen/quickopen.pri) include(../../plugins/quickopen/quickopen.pri)
include(cpptools_dependencies.pri) include(cpptools_dependencies.pri)
#DEFINES += QT_NO_CAST_FROM_ASCII # DEFINES += QT_NO_CAST_FROM_ASCII
DEFINES += QT_NO_CAST_TO_ASCII DEFINES += QT_NO_CAST_TO_ASCII
unix:QMAKE_CXXFLAGS_DEBUG+=-O3 unix:QMAKE_CXXFLAGS_DEBUG += -O3
INCLUDEPATH += . INCLUDEPATH += .
DEFINES += CPPTOOLS_LIBRARY DEFINES += CPPTOOLS_LIBRARY
CONFIG += help CONFIG += help
include(rpp/rpp.pri)|error("Can't find RPP") include(rpp/rpp.pri)|error("Can't find RPP")
HEADERS += cpptools_global.h \
HEADERS += \ cppquickopenfilter.h \
cpptools_global.h \ cppclassesfilter.h \
cppquickopenfilter.h searchsymbols.h
SOURCES += cppquickopenfilter.cpp \
SOURCES += \ cpptoolseditorsupport.cpp \
cppquickopenfilter.cpp \ cppclassesfilter.cpp \
cpptoolseditorsupport.cpp searchsymbols.cpp
# Input # Input
SOURCES += cpptools.cpp \ SOURCES += cpptools.cpp \
cppmodelmanager.cpp \ cppmodelmanager.cpp \
cppcodecompletion.cpp \ cppcodecompletion.cpp \
cpphoverhandler.cpp cpphoverhandler.cpp
HEADERS += cpptools.h \ HEADERS += cpptools.h \
cppmodelmanager.h \ cppmodelmanager.h \
cppcodecompletion.h \ cppcodecompletion.h \
@@ -36,5 +32,4 @@ HEADERS += cpptools.h \
cppmodelmanagerinterface.h \ cppmodelmanagerinterface.h \
cpptoolseditorsupport.h \ cpptoolseditorsupport.h \
cpptoolsconstants.h cpptoolsconstants.h
RESOURCES += cpptools.qrc RESOURCES += cpptools.qrc

View File

@@ -40,6 +40,8 @@
namespace rpp { namespace rpp {
class Macro;
class Client class Client
{ {
Client(const Client &other); Client(const Client &other);
@@ -61,6 +63,13 @@ public:
virtual void macroAdded(const QByteArray &macroId, const QByteArray &text) = 0; virtual void macroAdded(const QByteArray &macroId, const QByteArray &text) = 0;
virtual void sourceNeeded(QString &fileName, IncludeType mode) = 0; // ### FIX the signature. virtual void sourceNeeded(QString &fileName, IncludeType mode) = 0; // ### FIX the signature.
virtual void startExpandingMacro(unsigned offset,
const Macro &macro,
const QByteArray &originalTextt) = 0;
virtual void stopExpandingMacro(unsigned offset,
const Macro &macro) = 0;
virtual void startSkippingBlocks(unsigned offset) = 0; virtual void startSkippingBlocks(unsigned offset) = 0;
virtual void stopSkippingBlocks(unsigned offset) = 0; virtual void stopSkippingBlocks(unsigned offset) = 0;
}; };

View File

@@ -575,7 +575,17 @@ void pp::operator()(const QByteArray &source, QByteArray *result)
const QByteArray spell = tokenSpell(*identifierToken); const QByteArray spell = tokenSpell(*identifierToken);
if (env.isBuiltinMacro(spell)) { if (env.isBuiltinMacro(spell)) {
const Macro trivial;
if (client)
client->startExpandingMacro(identifierToken->offset,
trivial, spell);
expand(spell.constBegin(), spell.constEnd(), result); expand(spell.constBegin(), spell.constEnd(), result);
if (client)
client->stopExpandingMacro(_dot->offset, trivial);
continue; continue;
} }
@@ -585,18 +595,36 @@ void pp::operator()(const QByteArray &source, QByteArray *result)
} else { } else {
if (! m->function_like) { if (! m->function_like) {
if (_dot->isNot(T_LPAREN)) { if (_dot->isNot(T_LPAREN)) {
if (client)
client->startExpandingMacro(identifierToken->offset,
*m, spell);
m->hidden = true; m->hidden = true;
expand(m->definition.constBegin(), expand(m->definition.constBegin(),
m->definition.constEnd(), m->definition.constEnd(),
result); result);
if (client)
client->stopExpandingMacro(_dot->offset, *m);
m->hidden = false; m->hidden = false;
continue; continue;
} else { } else {
QByteArray tmp; QByteArray tmp;
m->hidden = true; m->hidden = true;
if (client)
client->startExpandingMacro(identifierToken->offset,
*m, spell);
expand(m->definition.constBegin(), expand(m->definition.constBegin(),
m->definition.constEnd(), m->definition.constEnd(),
&tmp); &tmp);
if (client)
client->stopExpandingMacro(_dot->offset, *m);
m->hidden = false; m->hidden = false;
m = 0; // reset the active the macro m = 0; // reset the active the macro
@@ -640,9 +668,20 @@ void pp::operator()(const QByteArray &source, QByteArray *result)
const char *beginOfText = startOfToken(*identifierToken); const char *beginOfText = startOfToken(*identifierToken);
const char *endOfText = endOfToken(*_dot); const char *endOfText = endOfToken(*_dot);
++_dot; // skip T_RPAREN ++_dot; // skip T_RPAREN
//m->hidden = true;
if (client) {
const QByteArray text =
QByteArray::fromRawData(beginOfText,
endOfText - beginOfText);
client->startExpandingMacro(identifierToken->offset,
*m, text);
}
expand(beginOfText, endOfText, result); expand(beginOfText, endOfText, result);
//m->hidden = false;
if (client)
client->stopExpandingMacro(_dot->offset, *m);
} }
} }
} }

View File

@@ -0,0 +1,178 @@
/***************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Qt Software Information (qt-info@nokia.com)
**
**
** Non-Open Source Usage
**
** Licensees may use this file in accordance with the Qt Beta Version
** License Agreement, Agreement version 2.2 provided with the Software or,
** alternatively, in accordance with the terms contained in a written
** agreement between you and Nokia.
**
** GNU General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU General
** Public License versions 2.0 or 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the packaging
** of this file. Please review the following information to ensure GNU
** General Public Licensing requirements will be met:
**
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
** http://www.gnu.org/copyleft/gpl.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt GPL Exception
** version 1.2, included in the file GPL_EXCEPTION.txt in this package.
**
***************************************************************************/
#include "searchsymbols.h"
#include <Literals.h>
#include <Scope.h>
using namespace CPlusPlus;
using namespace CppTools::Internal;
SearchSymbols::SearchSymbols():
symbolsToSearchFor(ClassesMethodsFunctionsAndEnums)
{
}
void SearchSymbols::setSymbolsToSearchFor(SymbolType type)
{
symbolsToSearchFor = type;
}
QList<ModelItemInfo> SearchSymbols::operator()(Document::Ptr doc, const QString &scope)
{
QString previousScope = switchScope(scope);
items.clear();
for (unsigned i = 0; i < doc->globalSymbolCount(); ++i) {
accept(doc->globalSymbolAt(i));
}
(void) switchScope(previousScope);
return items;
}
QString SearchSymbols::switchScope(const QString &scope)
{
QString previousScope = _scope;
_scope = scope;
return previousScope;
}
bool SearchSymbols::visit(Enum *symbol)
{
if (symbolsToSearchFor != ClassesMethodsFunctionsAndEnums)
return false;
QString name = symbolName(symbol);
QString previousScope = switchScope(name);
QIcon icon = icons.iconForSymbol(symbol);
Scope *members = symbol->members();
items.append(ModelItemInfo(name, QString(), ModelItemInfo::Enum,
QString::fromUtf8(symbol->fileName(), symbol->fileNameLength()),
symbol->line(),
icon));
for (unsigned i = 0; i < members->symbolCount(); ++i) {
accept(members->symbolAt(i));
}
(void) switchScope(previousScope);
return false;
}
bool SearchSymbols::visit(Function *symbol)
{
if (symbolsToSearchFor != ClassesMethodsFunctionsAndEnums)
return false;
QString name = symbolName(symbol);
QString type = overview.prettyType(symbol->type());
QIcon icon = icons.iconForSymbol(symbol);
items.append(ModelItemInfo(name, type, ModelItemInfo::Method,
QString::fromUtf8(symbol->fileName(), symbol->fileNameLength()),
symbol->line(),
icon));
return false;
}
bool SearchSymbols::visit(Namespace *symbol)
{
QString name = symbolName(symbol);
QString previousScope = switchScope(name);
Scope *members = symbol->members();
for (unsigned i = 0; i < members->symbolCount(); ++i) {
accept(members->symbolAt(i));
}
(void) switchScope(previousScope);
return false;
}
#if 0
bool SearchSymbols::visit(Declaration *symbol)
{
if (symbol->type()->isFunction()) {
QString name = symbolName(symbol);
QString type = overview.prettyType(symbol->type());
//QIcon icon = ...;
items.append(ModelItemInfo(name, type, ModelItemInfo::Method,
QString::fromUtf8(symbol->fileName(), symbol->line()),
symbol->line()));
}
return false;
}
#endif
bool SearchSymbols::visit(Class *symbol)
{
QString name = symbolName(symbol);
QString previousScope = switchScope(name);
QIcon icon = icons.iconForSymbol(symbol);
items.append(ModelItemInfo(name, QString(), ModelItemInfo::Class,
QString::fromUtf8(symbol->fileName(), symbol->fileNameLength()),
symbol->line(),
icon));
Scope *members = symbol->members();
for (unsigned i = 0; i < members->symbolCount(); ++i) {
accept(members->symbolAt(i));
}
(void) switchScope(previousScope);
return false;
}
QString SearchSymbols::symbolName(const Symbol *symbol) const
{
QString name = _scope;
if (! name.isEmpty())
name += QLatin1String("::");
QString symbolName = overview.prettyName(symbol->name());
if (symbolName.isEmpty()) {
QString type;
if (symbol->isNamespace()) {
type = QLatin1String("namespace");
} else if (symbol->isEnum()) {
type = QLatin1String("enum");
} else if (const Class *c = symbol->asClass()) {
if (c->isUnion()) {
type = QLatin1String("union");
} else if (c->isStruct()) {
type = QLatin1String("struct");
} else {
type = QLatin1String("class");
}
} else {
type = QLatin1String("symbol");
}
symbolName = QLatin1String("<anonymous ");
symbolName += type;
symbolName += QLatin1String(">");
}
name += symbolName;
return name;
}

View File

@@ -0,0 +1,128 @@
/***************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Qt Software Information (qt-info@nokia.com)
**
**
** Non-Open Source Usage
**
** Licensees may use this file in accordance with the Qt Beta Version
** License Agreement, Agreement version 2.2 provided with the Software or,
** alternatively, in accordance with the terms contained in a written
** agreement between you and Nokia.
**
** GNU General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU General
** Public License versions 2.0 or 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the packaging
** of this file. Please review the following information to ensure GNU
** General Public Licensing requirements will be met:
**
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
** http://www.gnu.org/copyleft/gpl.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt GPL Exception
** version 1.2, included in the file GPL_EXCEPTION.txt in this package.
**
***************************************************************************/
#ifndef SEARCHSYMBOLS_H
#define SEARCHSYMBOLS_H
#include <cplusplus/CppDocument.h>
#include <cplusplus/Icons.h>
#include <cplusplus/Overview.h>
#include <Symbols.h>
#include <SymbolVisitor.h>
#include <QIcon>
#include <QMetaType>
#include <QString>
namespace CppTools {
namespace Internal {
struct ModelItemInfo
{
enum ItemType { Enum, Class, Method };
ModelItemInfo()
{ }
ModelItemInfo(const QString &symbolName,
const QString &symbolType,
ItemType type,
const QString &fileName,
int line,
const QIcon &icon)
: symbolName(symbolName),
symbolType(symbolType),
type(type),
fileName(fileName),
line(line),
icon(icon)
{ }
QString symbolName;
QString symbolType;
ItemType type;
QString fileName;
int line;
QIcon icon;
};
class SearchSymbols: public std::unary_function<CPlusPlus::Document::Ptr, QList<ModelItemInfo> >,
protected CPlusPlus::SymbolVisitor
{
public:
// TODO: Probably should use QFlags
enum SymbolType {
Classes,
ClassesMethodsFunctionsAndEnums
};
SearchSymbols();
void setSymbolsToSearchFor(SymbolType type);
QList<ModelItemInfo> operator()(CPlusPlus::Document::Ptr doc)
{ return operator()(doc, QString()); }
QList<ModelItemInfo> operator()(CPlusPlus::Document::Ptr doc, const QString &scope);
protected:
using SymbolVisitor::visit;
void accept(CPlusPlus::Symbol *symbol)
{ CPlusPlus::Symbol::visitSymbol(symbol, this); }
QString switchScope(const QString &scope);
virtual bool visit(CPlusPlus::Enum *symbol);
virtual bool visit(CPlusPlus::Function *symbol);
virtual bool visit(CPlusPlus::Namespace *symbol);
#if 0
// This visit method would make function declaration be included in QuickOpen
virtual bool visit(CPlusPlus::Declaration *symbol);
#endif
virtual bool visit(CPlusPlus::Class *symbol);
QString symbolName(const CPlusPlus::Symbol *symbol) const;
private:
QString _scope;
CPlusPlus::Overview overview;
CPlusPlus::Icons icons;
QList<ModelItemInfo> items;
SymbolType symbolsToSearchFor;
};
} // namespace Internal
} // namespace CppTools
Q_DECLARE_METATYPE(CppTools::Internal::ModelItemInfo)
#endif // SEARCHSYMBOLS_H

View File

@@ -231,6 +231,11 @@ BreakHandler::BreakHandler(QObject *parent)
{ {
} }
BreakHandler::~BreakHandler()
{
clear();
}
int BreakHandler::columnCount(const QModelIndex &parent) const int BreakHandler::columnCount(const QModelIndex &parent) const
{ {
return parent.isValid() ? 0 : 6; return parent.isValid() ? 0 : 6;

View File

@@ -113,6 +113,7 @@ class BreakHandler : public QAbstractItemModel
public: public:
explicit BreakHandler(QObject *parent = 0); explicit BreakHandler(QObject *parent = 0);
~BreakHandler();
void removeAllBreakpoints(); void removeAllBreakpoints();
void setAllPending(); void setAllPending();

View File

@@ -317,10 +317,20 @@ void DebuggerManager::init()
m_debugDumpersAction = new QAction(this); m_debugDumpersAction = new QAction(this);
m_debugDumpersAction->setText(tr("Debug Custom Dumpers")); m_debugDumpersAction->setText(tr("Debug Custom Dumpers"));
m_debugDumpersAction->setToolTip(tr("This is an internal tool to "
"make debugging the Custom Data Dumper code easier. "
"Using this action is in general not needed unless you "
"want do debug Qt Creator itself."));
m_debugDumpersAction->setCheckable(true); m_debugDumpersAction->setCheckable(true);
m_skipKnownFramesAction = new QAction(this); m_skipKnownFramesAction = new QAction(this);
m_skipKnownFramesAction->setText(tr("Skip Known Frames When Stepping")); m_skipKnownFramesAction->setText(tr("Skip Known Frames When Stepping"));
m_skipKnownFramesAction->setToolTip(tr("After checking this option"
"'Step Into' combines in certain situations several steps, "
"leading to 'less noisy' debugging. So will, e.g., the atomic "
"reference counting code be skipped, and a single 'Step Into' "
"for a signal emission will end up directly in the slot connected "
"to it"));
m_skipKnownFramesAction->setCheckable(true); m_skipKnownFramesAction->setCheckable(true);
m_useCustomDumpersAction = new QAction(this); m_useCustomDumpersAction = new QAction(this);
@@ -330,13 +340,6 @@ void DebuggerManager::init()
m_useCustomDumpersAction->setCheckable(true); m_useCustomDumpersAction->setCheckable(true);
m_useCustomDumpersAction->setChecked(true); m_useCustomDumpersAction->setChecked(true);
m_useCustomDumpersAction = new QAction(this);
m_useCustomDumpersAction->setText(tr("Use Custom Display for Qt Objects"));
m_useCustomDumpersAction->setToolTip(tr("Checking this will make the debugger "
"try to use code to format certain data (QObject, QString, ...) nicely. "));
m_useCustomDumpersAction->setCheckable(true);
m_useCustomDumpersAction->setChecked(true);
m_useFastStartAction = new QAction(this); m_useFastStartAction = new QAction(this);
m_useFastStartAction->setText(tr("Fast Debugger Start")); m_useFastStartAction->setText(tr("Fast Debugger Start"));
m_useFastStartAction->setToolTip(tr("Checking this will make the debugger " m_useFastStartAction->setToolTip(tr("Checking this will make the debugger "
@@ -622,7 +625,7 @@ void DebuggerManager::notifyInferiorPidChanged(int pid)
void DebuggerManager::showApplicationOutput(const QString &prefix, const QString &str) void DebuggerManager::showApplicationOutput(const QString &prefix, const QString &str)
{ {
applicationOutputAvailable(prefix, str); emit applicationOutputAvailable(prefix, str);
} }
void DebuggerManager::shutdown() void DebuggerManager::shutdown()

View File

@@ -44,6 +44,7 @@
#include <QtCore/QDebug> #include <QtCore/QDebug>
#include <QtCore/QDir> #include <QtCore/QDir>
#include <QtCore/QFileInfo> #include <QtCore/QFileInfo>
#include <QtGui/QTextDocument>
using namespace Debugger::Internal; using namespace Debugger::Internal;
@@ -140,8 +141,8 @@ void DebuggerRunControl::slotAddToOutputWindow(const QString &prefix, const QStr
{ {
Q_UNUSED(prefix); Q_UNUSED(prefix);
foreach (const QString &l, line.split('\n')) foreach (const QString &l, line.split('\n'))
emit addToOutputWindow(this, prefix + l); emit addToOutputWindow(this, prefix + Qt::escape(l));
//emit addToOutputWindow(this, prefix + line); //emit addToOutputWindow(this, prefix + Qt::escape(line));
} }
void DebuggerRunControl::stop() void DebuggerRunControl::stop()

View File

@@ -110,7 +110,6 @@ enum GdbCommandType
GdbFileExecAndSymbols, GdbFileExecAndSymbols,
GdbQueryPwd, GdbQueryPwd,
GdbQuerySources, GdbQuerySources,
GdbQuerySources2,
GdbAsyncOutput2, GdbAsyncOutput2,
GdbExecRun, GdbExecRun,
GdbExecRunToFunction, GdbExecRunToFunction,
@@ -126,7 +125,6 @@ enum GdbCommandType
GdbInfoProc, GdbInfoProc,
GdbQueryDataDumper1, GdbQueryDataDumper1,
GdbQueryDataDumper2, GdbQueryDataDumper2,
GdbInitializeSocket1,
BreakCondition = 200, BreakCondition = 200,
BreakEnablePending, BreakEnablePending,
@@ -444,7 +442,7 @@ void GdbEngine::handleResponse()
break; break;
} }
if (token == -1 && *from != '&' && *from != '~') { if (token == -1 && *from != '&' && *from != '~' && *from != '*') {
// FIXME: On Linux the application's std::out is merged in here. // FIXME: On Linux the application's std::out is merged in here.
// High risk of falsely interpreting this as MI output. // High risk of falsely interpreting this as MI output.
// We assume that we _always_ use tokens, so not finding a token // We assume that we _always_ use tokens, so not finding a token
@@ -493,8 +491,10 @@ void GdbEngine::handleResponse()
m_inbuffer = QByteArray(from, to - from); m_inbuffer = QByteArray(from, to - from);
if (asyncClass == "stopped") { if (asyncClass == "stopped") {
handleAsyncOutput(record); handleAsyncOutput(record);
} else if (asyncClass == "running") {
// Archer has 'thread-id="all"' here
} else { } else {
qDebug() << "INGNORED ASYNC OUTPUT " << record.toString(); qDebug() << "IGNORED ASYNC OUTPUT " << record.toString();
} }
break; break;
} }
@@ -633,18 +633,10 @@ void GdbEngine::readGdbStandardOutput()
{ {
// This is the function called whenever the Gdb process created // This is the function called whenever the Gdb process created
// output. As a rule of thumb, stdout contains _real_ Gdb output // output. As a rule of thumb, stdout contains _real_ Gdb output
// as responses to our command (with exception of the data dumpers) // as responses to our command
// and "spontaneous" events like messages on loaded shared libraries. // and "spontaneous" events like messages on loaded shared libraries.
// Otoh, stderr contains application output produced by qDebug etc. // OTOH, stderr contains application output produced by qDebug etc.
// There is no organized way to pass application stdout output // There is no organized way to pass application stdout output.
// The result of custom data dumpers arrives over the socket _before_
// the corresponding Gdb "^done" message arrives here over stdout
// and is merged into the response via m_pendingCustomValueContents.
// Note that this code here runs syncronized to the arriving
// output. The completed response will be signalled by a queued
// connection to the handlers.
QByteArray out = m_gdbProc.readAllStandardOutput(); QByteArray out = m_gdbProc.readAllStandardOutput();
@@ -765,19 +757,12 @@ void GdbEngine::handleResultRecord(const GdbResultRecord &record)
//qDebug() << "TOKEN: " << record.token //qDebug() << "TOKEN: " << record.token
// << " ACCEPTABLE: " << m_oldestAcceptableToken; // << " ACCEPTABLE: " << m_oldestAcceptableToken;
//qDebug() << ""; //qDebug() << "";
//qDebug() << qPrintable(currentTime()) << "Reading response: "
// << record.toString() << "\n";
//qDebug() << "\nRESULT" << record.token << record.toString(); //qDebug() << "\nRESULT" << record.token << record.toString();
int token = record.token; int token = record.token;
if (token == -1) if (token == -1)
return; return;
if (!m_cookieForToken.contains(token)) {
qDebug() << "NO SUCH TOKEN (ANYMORE): " << token;
return;
}
GdbCookie cmd = m_cookieForToken.take(token); GdbCookie cmd = m_cookieForToken.take(token);
// FIXME: this falsely rejects results from the custom dumper recognition // FIXME: this falsely rejects results from the custom dumper recognition
@@ -788,12 +773,6 @@ void GdbEngine::handleResultRecord(const GdbResultRecord &record)
return; return;
} }
// We get _two_ results for a '-exec-foo' command: First a
// 'running' notification, then a 'stopped' or similar.
// So put it back.
if (record.resultClass == GdbResultRunning)
m_cookieForToken[token] = cmd;
#if 0 #if 0
qDebug() << "# handleOutput, " qDebug() << "# handleOutput, "
<< "cmd type: " << cmd.type << "cmd type: " << cmd.type
@@ -858,18 +837,12 @@ void GdbEngine::handleResult(const GdbResultRecord & record, int type,
case GdbQuerySources: case GdbQuerySources:
handleQuerySources(record); handleQuerySources(record);
break; break;
case GdbQuerySources2:
handleQuerySources2(record, cookie);
break;
case GdbAsyncOutput2: case GdbAsyncOutput2:
handleAsyncOutput2(cookie.value<GdbMi>()); handleAsyncOutput2(cookie.value<GdbMi>());
break; break;
case GdbInfoShared: case GdbInfoShared:
handleInfoShared(record); handleInfoShared(record);
break; break;
case GdbInitializeSocket1:
//qDebug() << " INIT SOCKET" << record.toString();
break;
case GdbQueryDataDumper1: case GdbQueryDataDumper1:
handleQueryDataDumper1(record); handleQueryDataDumper1(record);
break; break;
@@ -1072,13 +1045,6 @@ void GdbEngine::handleInfoShared(const GdbResultRecord &record)
} }
} }
void GdbEngine::handleQuerySources2(const GdbResultRecord &record,
const QVariant &cookie)
{
if (record.resultClass == GdbResultDone)
handleAsyncOutput2(cookie.value<GdbMi>());
}
void GdbEngine::handleExecJumpToLine(const GdbResultRecord &record) void GdbEngine::handleExecJumpToLine(const GdbResultRecord &record)
{ {
// FIXME: remove this special case as soon as 'jump' // FIXME: remove this special case as soon as 'jump'
@@ -3681,11 +3647,16 @@ void GdbEngine::handleStackListLocals(const GdbResultRecord &record)
// stage 2/2 // stage 2/2
// There could be shadowed variables // There could be shadowed variables
QHash<QString, int> seen;
QList<GdbMi> locals = record.data.findChild("locals").children(); QList<GdbMi> locals = record.data.findChild("locals").children();
locals += m_currentFunctionArgs; locals += m_currentFunctionArgs;
setLocals(locals);
}
void GdbEngine::setLocals(const QList<GdbMi> &locals)
{
//qDebug() << m_varToType; //qDebug() << m_varToType;
QHash<QString, int> seen;
foreach (const GdbMi &item, locals) { foreach (const GdbMi &item, locals) {
#ifdef Q_OS_MAC #ifdef Q_OS_MAC

View File

@@ -206,8 +206,6 @@ private:
void handleShowVersion(const GdbResultRecord &response); void handleShowVersion(const GdbResultRecord &response);
void handleQueryPwd(const GdbResultRecord &response); void handleQueryPwd(const GdbResultRecord &response);
void handleQuerySources(const GdbResultRecord &response); void handleQuerySources(const GdbResultRecord &response);
void handleQuerySources2(const GdbResultRecord &response,
const QVariant &);
QByteArray m_inbuffer; QByteArray m_inbuffer;
@@ -219,7 +217,6 @@ private:
QByteArray m_pendingConsoleStreamOutput; QByteArray m_pendingConsoleStreamOutput;
QByteArray m_pendingTargetStreamOutput; QByteArray m_pendingTargetStreamOutput;
QByteArray m_pendingLogStreamOutput; QByteArray m_pendingLogStreamOutput;
//QByteArray m_pendingCustomValueContents;
QString m_pwd; QString m_pwd;
// contains the first token number for the current round // contains the first token number for the current round
@@ -329,6 +326,7 @@ private:
void handleVarListChildrenHelper(const GdbMi &child, void handleVarListChildrenHelper(const GdbMi &child,
const WatchData &parent); const WatchData &parent);
void setWatchDataType(WatchData &data, const GdbMi &mi); void setWatchDataType(WatchData &data, const GdbMi &mi);
void setLocals(const QList<GdbMi> &locals);
QString m_editedData; QString m_editedData;
int m_pendingRequests; int m_pendingRequests;

View File

@@ -1,7 +1,8 @@
<ui version="4.0" > <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Find::Internal::FindDialog</class> <class>Find::Internal::FindDialog</class>
<widget class="QDialog" name="Find::Internal::FindDialog" > <widget class="QDialog" name="Find::Internal::FindDialog">
<property name="geometry" > <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
@@ -9,109 +10,109 @@
<height>168</height> <height>168</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy" > <property name="sizePolicy">
<sizepolicy vsizetype="Minimum" hsizetype="Minimum" > <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="windowTitle" > <property name="windowTitle">
<string>Search for...</string> <string>Search for...</string>
</property> </property>
<property name="sizeGripEnabled" > <property name="sizeGripEnabled">
<bool>false</bool> <bool>false</bool>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout" > <layout class="QVBoxLayout" name="verticalLayout">
<item> <item>
<layout class="QGridLayout" name="gridLayout" > <layout class="QGridLayout" name="gridLayout">
<item row="0" column="0" > <item row="0" column="0">
<widget class="QLabel" name="label" > <widget class="QLabel" name="label">
<property name="sizePolicy" > <property name="sizePolicy">
<sizepolicy vsizetype="Preferred" hsizetype="Fixed" > <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="minimumSize" > <property name="minimumSize">
<size> <size>
<width>80</width> <width>80</width>
<height>0</height> <height>0</height>
</size> </size>
</property> </property>
<property name="text" > <property name="text">
<string>Sc&amp;ope:</string> <string>Sc&amp;ope:</string>
</property> </property>
<property name="alignment" > <property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property> </property>
<property name="buddy" > <property name="buddy">
<cstring>filterList</cstring> <cstring>filterList</cstring>
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="1" > <item row="0" column="1">
<widget class="QComboBox" name="filterList" > <widget class="QComboBox" name="filterList">
<property name="sizePolicy" > <property name="sizePolicy">
<sizepolicy vsizetype="Fixed" hsizetype="Expanding" > <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="2" > <item row="0" column="2">
<widget class="QPushButton" name="searchButton" > <widget class="QPushButton" name="searchButton">
<property name="text" > <property name="text">
<string>&amp;Search</string> <string>&amp;Search</string>
</property> </property>
<property name="default" > <property name="default">
<bool>true</bool> <bool>true</bool>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="0" > <item row="1" column="0">
<widget class="QLabel" name="label_2" > <widget class="QLabel" name="label_2">
<property name="text" > <property name="text">
<string>Search &amp;for:</string> <string>Search &amp;for:</string>
</property> </property>
<property name="alignment" > <property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property> </property>
<property name="buddy" > <property name="buddy">
<cstring>searchTerm</cstring> <cstring>searchTerm</cstring>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="1" > <item row="1" column="1">
<widget class="QLineEdit" name="searchTerm" /> <widget class="QLineEdit" name="searchTerm"/>
</item> </item>
<item row="1" column="2" > <item row="1" column="2">
<widget class="QPushButton" name="closeButton" > <widget class="QPushButton" name="closeButton">
<property name="text" > <property name="text">
<string>&amp;Close</string> <string>Close</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="0" colspan="2" > <item row="4" column="0" colspan="2">
<widget class="QWidget" native="1" name="configWidget" > <widget class="QWidget" name="configWidget" native="true">
<property name="sizePolicy" > <property name="sizePolicy">
<sizepolicy vsizetype="Fixed" hsizetype="Preferred" > <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>10</verstretch> <verstretch>10</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="1" > <item row="2" column="1">
<widget class="QCheckBox" name="matchCase" > <widget class="QCheckBox" name="matchCase">
<property name="text" > <property name="text">
<string>Match &amp;case</string> <string>&amp;Case sensitive</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="1" > <item row="3" column="1">
<widget class="QCheckBox" name="wholeWords" > <widget class="QCheckBox" name="wholeWords">
<property name="text" > <property name="text">
<string>&amp;Whole words only</string> <string>&amp;Whole words only</string>
</property> </property>
</widget> </widget>
@@ -119,11 +120,11 @@
</layout> </layout>
</item> </item>
<item> <item>
<spacer name="verticalSpacer_2" > <spacer name="verticalSpacer_2">
<property name="orientation" > <property name="orientation">
<enum>Qt::Vertical</enum> <enum>Qt::Vertical</enum>
</property> </property>
<property name="sizeHint" stdset="0" > <property name="sizeHint" stdset="0">
<size> <size>
<width>0</width> <width>0</width>
<height>0</height> <height>0</height>

View File

@@ -80,16 +80,16 @@ void CommitData::clear()
panelInfo.clear(); panelInfo.clear();
panelData.clear(); panelData.clear();
commitFiles.clear(); stagedFiles.clear();
notUpdatedFiles.clear(); unstagedFiles.clear();
untrackedFiles.clear(); untrackedFiles.clear();
} }
QDebug operator<<(QDebug d, const CommitData &data) QDebug operator<<(QDebug d, const CommitData &data)
{ {
d << data.panelInfo << data.panelData; d << data.panelInfo << data.panelData;
d.nospace() << "Commit: " << data.commitFiles << " Not updated: " d.nospace() << "Commit: " << data.stagedFiles << " Not updated: "
<< data.notUpdatedFiles << " Untracked: " << data.untrackedFiles; << data.unstagedFiles << " Untracked: " << data.untrackedFiles;
return d; return d;
} }

View File

@@ -71,8 +71,8 @@ struct CommitData
void clear(); void clear();
GitSubmitEditorPanelInfo panelInfo; GitSubmitEditorPanelInfo panelInfo;
GitSubmitEditorPanelData panelData; GitSubmitEditorPanelData panelData;
QStringList commitFiles; QStringList stagedFiles;
QStringList notUpdatedFiles; QStringList unstagedFiles;
QStringList untrackedFiles; QStringList untrackedFiles;
}; };

View File

@@ -17,7 +17,9 @@ HEADERS += gitplugin.h \
giteditor.h \ giteditor.h \
annotationhighlighter.h \ annotationhighlighter.h \
gitsubmiteditorwidget.h \ gitsubmiteditorwidget.h \
gitsubmiteditor.h gitsubmiteditor.h \
gitversioncontrol.h \
gitsettings.h
SOURCES += gitplugin.cpp \ SOURCES += gitplugin.cpp \
gitoutputwindow.cpp \ gitoutputwindow.cpp \
@@ -28,7 +30,9 @@ SOURCES += gitplugin.cpp \
giteditor.cpp \ giteditor.cpp \
annotationhighlighter.cpp \ annotationhighlighter.cpp \
gitsubmiteditorwidget.cpp \ gitsubmiteditorwidget.cpp \
gitsubmiteditor.cpp gitsubmiteditor.cpp \
gitversioncontrol.cpp \
gitsettings.cpp
FORMS += changeselectiondialog.ui \ FORMS += changeselectiondialog.ui \
settingspage.ui \ settingspage.ui \

View File

@@ -35,6 +35,7 @@
#include "gitplugin.h" #include "gitplugin.h"
#include "gitconstants.h" #include "gitconstants.h"
#include "commitdata.h" #include "commitdata.h"
#include "gitsubmiteditor.h"
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
#include <coreplugin/coreconstants.h> #include <coreplugin/coreconstants.h>
@@ -49,8 +50,11 @@
#include <QtCore/QRegExp> #include <QtCore/QRegExp>
#include <QtCore/QTemporaryFile> #include <QtCore/QTemporaryFile>
#include <QtCore/QFuture> #include <QtCore/QFuture>
#include <QtCore/QTime>
#include <QtGui/QErrorMessage> #include <QtGui/QMessageBox>
#include <QtGui/QMainWindow> // for msg box parent
#include <QtGui/QPushButton>
using namespace Git; using namespace Git;
using namespace Git::Internal; using namespace Git::Internal;
@@ -76,22 +80,37 @@ inline Core::IEditor* locateEditor(const Core::ICore *core, const char *property
return 0; return 0;
} }
static inline QString msgRepositoryNotFound(const QString &dir)
{
return GitClient::tr("Unable to determine the repository for %1.").arg(dir);
}
static inline QString msgParseFilesFailed()
{
return GitClient::tr("Unable to parse the file output.");
}
// 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"));
return GitClient::tr("%1 Executing: %2 %3\n").arg(timeStamp, binary, args.join(QString(QLatin1Char(' '))));
}
// ---------------- GitClient
GitClient::GitClient(GitPlugin* plugin, Core::ICore *core) : GitClient::GitClient(GitPlugin* plugin, Core::ICore *core) :
m_msgWait(tr("Waiting for data...")), m_msgWait(tr("Waiting for data...")),
m_plugin(plugin), m_plugin(plugin),
m_core(core) m_core(core)
{ {
if (QSettings *s = m_core->settings())
m_settings.fromSettings(s);
} }
GitClient::~GitClient() GitClient::~GitClient()
{ {
} }
bool GitClient::vcsOpen(const QString &fileName)
{
return m_plugin->vcsOpen(fileName);
}
QString GitClient::findRepositoryForFile(const QString &fileName) QString GitClient::findRepositoryForFile(const QString &fileName)
{ {
const QString gitDirectory = QLatin1String(kGitDirectoryC); const QString gitDirectory = QLatin1String(kGitDirectoryC);
@@ -176,7 +195,7 @@ void GitClient::diff(const QString &workingDirectory, const QStringList &fileNam
const QString title = tr("Git Diff"); const QString title = tr("Git Diff");
VCSBase::VCSBaseEditor *editor = createVCSEditor(kind, title, workingDirectory, true, "originalFileName", workingDirectory); VCSBase::VCSBaseEditor *editor = createVCSEditor(kind, title, workingDirectory, true, "originalFileName", workingDirectory);
executeGit(workingDirectory, arguments, m_plugin->m_outputWindow, editor); executeGit(workingDirectory, arguments, m_plugin->outputWindow(), editor);
} }
@@ -194,27 +213,26 @@ void GitClient::diff(const QString &workingDirectory, const QString &fileName)
const QString sourceFile = source(workingDirectory, fileName); const QString sourceFile = source(workingDirectory, fileName);
VCSBase::VCSBaseEditor *editor = createVCSEditor(kind, title, sourceFile, true, "originalFileName", sourceFile); VCSBase::VCSBaseEditor *editor = createVCSEditor(kind, title, sourceFile, true, "originalFileName", sourceFile);
executeGit(workingDirectory, arguments, m_plugin->m_outputWindow, editor); executeGit(workingDirectory, arguments, m_plugin->outputWindow(), editor);
} }
void GitClient::status(const QString &workingDirectory) void GitClient::status(const QString &workingDirectory)
{ {
QStringList statusArgs(QLatin1String("status")); QStringList statusArgs(QLatin1String("status"));
statusArgs << QLatin1String("-u"); statusArgs << QLatin1String("-u");
executeGit(workingDirectory, statusArgs, m_plugin->m_outputWindow, 0,true); executeGit(workingDirectory, statusArgs, m_plugin->outputWindow(), 0,true);
} }
void GitClient::log(const QString &workingDirectory, const QString &fileName) void GitClient::log(const QString &workingDirectory, const QString &fileName)
{ {
if (Git::Constants::debug) if (Git::Constants::debug)
qDebug() << "log" << workingDirectory << fileName; qDebug() << "log" << workingDirectory << fileName;
QStringList arguments;
int logCount = 10;
if (m_plugin->m_settingsPage && m_plugin->m_settingsPage->logCount() > 0)
logCount = m_plugin->m_settingsPage->logCount();
arguments << QLatin1String("log") << QLatin1String("-n") QStringList arguments(QLatin1String("log"));
<< QString::number(logCount);
if (m_settings.logCount > 0)
arguments << QLatin1String("-n") << QString::number(m_settings.logCount);
if (!fileName.isEmpty()) if (!fileName.isEmpty())
arguments << fileName; arguments << fileName;
@@ -222,7 +240,7 @@ void GitClient::log(const QString &workingDirectory, const QString &fileName)
const QString kind = QLatin1String(Git::Constants::GIT_LOG_EDITOR_KIND); const QString kind = QLatin1String(Git::Constants::GIT_LOG_EDITOR_KIND);
const QString sourceFile = source(workingDirectory, fileName); const QString sourceFile = source(workingDirectory, fileName);
VCSBase::VCSBaseEditor *editor = createVCSEditor(kind, title, sourceFile, false, "logFileName", sourceFile); VCSBase::VCSBaseEditor *editor = createVCSEditor(kind, title, sourceFile, false, "logFileName", sourceFile);
executeGit(workingDirectory, arguments, m_plugin->m_outputWindow, editor); executeGit(workingDirectory, arguments, m_plugin->outputWindow(), editor);
} }
void GitClient::show(const QString &source, const QString &id) void GitClient::show(const QString &source, const QString &id)
@@ -238,7 +256,7 @@ void GitClient::show(const QString &source, const QString &id)
const QFileInfo sourceFi(source); const QFileInfo sourceFi(source);
const QString workDir = sourceFi.isDir() ? sourceFi.absoluteFilePath() : sourceFi.absolutePath(); const QString workDir = sourceFi.isDir() ? sourceFi.absoluteFilePath() : sourceFi.absolutePath();
executeGit(workDir, arguments, m_plugin->m_outputWindow, editor); executeGit(workDir, arguments, m_plugin->outputWindow(), editor);
} }
void GitClient::blame(const QString &workingDirectory, const QString &fileName) void GitClient::blame(const QString &workingDirectory, const QString &fileName)
@@ -253,7 +271,7 @@ void GitClient::blame(const QString &workingDirectory, const QString &fileName)
const QString sourceFile = source(workingDirectory, fileName); const QString sourceFile = source(workingDirectory, fileName);
VCSBase::VCSBaseEditor *editor = createVCSEditor(kind, title, sourceFile, true, "blameFileName", sourceFile); VCSBase::VCSBaseEditor *editor = createVCSEditor(kind, title, sourceFile, true, "blameFileName", sourceFile);
executeGit(workingDirectory, arguments, m_plugin->m_outputWindow, editor); executeGit(workingDirectory, arguments, m_plugin->outputWindow(), editor);
} }
void GitClient::checkout(const QString &workingDirectory, const QString &fileName) void GitClient::checkout(const QString &workingDirectory, const QString &fileName)
@@ -267,7 +285,7 @@ void GitClient::checkout(const QString &workingDirectory, const QString &fileNam
arguments << QLatin1String("checkout") << QLatin1String("HEAD") << QLatin1String("--") arguments << QLatin1String("checkout") << QLatin1String("HEAD") << QLatin1String("--")
<< fileName; << fileName;
executeGit(workingDirectory, arguments, m_plugin->m_outputWindow, 0,true); executeGit(workingDirectory, arguments, m_plugin->outputWindow(), 0,true);
} }
void GitClient::hardReset(const QString &workingDirectory, const QString &commit) void GitClient::hardReset(const QString &workingDirectory, const QString &commit)
@@ -277,7 +295,7 @@ void GitClient::hardReset(const QString &workingDirectory, const QString &commit
if (!commit.isEmpty()) if (!commit.isEmpty())
arguments << commit; arguments << commit;
executeGit(workingDirectory, arguments, m_plugin->m_outputWindow, 0,true); executeGit(workingDirectory, arguments, m_plugin->outputWindow(), 0,true);
} }
void GitClient::addFile(const QString &workingDirectory, const QString &fileName) void GitClient::addFile(const QString &workingDirectory, const QString &fileName)
@@ -285,7 +303,7 @@ void GitClient::addFile(const QString &workingDirectory, const QString &fileName
QStringList arguments; QStringList arguments;
arguments << QLatin1String("add") << fileName; arguments << QLatin1String("add") << fileName;
executeGit(workingDirectory, arguments, m_plugin->m_outputWindow, 0,true); executeGit(workingDirectory, arguments, m_plugin->outputWindow(), 0,true);
} }
bool GitClient::synchronousAdd(const QString &workingDirectory, const QStringList &files) bool GitClient::synchronousAdd(const QString &workingDirectory, const QStringList &files)
@@ -300,14 +318,27 @@ bool GitClient::synchronousAdd(const QString &workingDirectory, const QStringLis
if (!rc) { if (!rc) {
const QString errorMessage = tr("Unable to add %n file(s) to %1: %2", 0, files.size()). const QString errorMessage = tr("Unable to add %n file(s) to %1: %2", 0, files.size()).
arg(workingDirectory, QString::fromLocal8Bit(errorText)); arg(workingDirectory, QString::fromLocal8Bit(errorText));
m_plugin->m_outputWindow->append(errorMessage); m_plugin->outputWindow()->append(errorMessage);
m_plugin->m_outputWindow->popup(false); m_plugin->outputWindow()->popup(false);
} }
return rc; return rc;
} }
bool GitClient::synchronousReset(const QString &workingDirectory, bool GitClient::synchronousReset(const QString &workingDirectory,
const QStringList &files) const QStringList &files)
{
QString errorMessage;
const bool rc = synchronousReset(workingDirectory, files, &errorMessage);
if (!rc) {
m_plugin->outputWindow()->append(errorMessage);
m_plugin->outputWindow()->popup(false);
}
return rc;
}
bool GitClient::synchronousReset(const QString &workingDirectory,
const QStringList &files,
QString *errorMessage)
{ {
if (Git::Constants::debug) if (Git::Constants::debug)
qDebug() << Q_FUNC_INFO << workingDirectory << files; qDebug() << Q_FUNC_INFO << workingDirectory << files;
@@ -317,14 +348,30 @@ bool GitClient::synchronousReset(const QString &workingDirectory,
arguments << QLatin1String("reset") << QLatin1String("HEAD") << QLatin1String("--") << files; arguments << QLatin1String("reset") << QLatin1String("HEAD") << QLatin1String("--") << files;
const bool rc = synchronousGit(workingDirectory, arguments, &outputText, &errorText); const bool rc = synchronousGit(workingDirectory, arguments, &outputText, &errorText);
const QString output = QString::fromLocal8Bit(outputText); const QString output = QString::fromLocal8Bit(outputText);
m_plugin->m_outputWindow->popup(false); m_plugin->outputWindow()->popup(false);
m_plugin->m_outputWindow->append(output); m_plugin->outputWindow()->append(output);
// Note that git exits with 1 even if the operation is successful // Note that git exits with 1 even if the operation is successful
// Assume real failure if the output does not contain "foo.cpp modified" // Assume real failure if the output does not contain "foo.cpp modified"
if (!rc && !output.contains(QLatin1String("modified"))) { if (!rc && !output.contains(QLatin1String("modified"))) {
const QString errorMessage = tr("Unable to reset %n file(s) in %1: %2", 0, files.size()). *errorMessage = tr("Unable to reset %n file(s) in %1: %2", 0, files.size()).arg(workingDirectory, QString::fromLocal8Bit(errorText));
arg(workingDirectory, QString::fromLocal8Bit(errorText)); return false;
m_plugin->m_outputWindow->append(errorMessage); }
return true;
}
bool GitClient::synchronousCheckout(const QString &workingDirectory,
const QStringList &files,
QString *errorMessage)
{
if (Git::Constants::debug)
qDebug() << Q_FUNC_INFO << workingDirectory << files;
QByteArray outputText;
QByteArray errorText;
QStringList arguments;
arguments << QLatin1String("checkout") << QLatin1String("--") << files;
const bool rc = synchronousGit(workingDirectory, arguments, &outputText, &errorText);
if (!rc) {
*errorMessage = tr("Unable to checkout %n file(s) in %1: %2", 0, files.size()).arg(workingDirectory, QString::fromLocal8Bit(errorText));
return false; return false;
} }
return true; return true;
@@ -336,13 +383,14 @@ void GitClient::executeGit(const QString &workingDirectory, const QStringList &a
{ {
if (Git::Constants::debug) if (Git::Constants::debug)
qDebug() << "executeGit" << workingDirectory << arguments << editor; qDebug() << "executeGit" << workingDirectory << arguments << editor;
outputWindow->clearContents();
m_plugin->outputWindow()->append(formatCommand(QLatin1String(kGitCommand), arguments));
QProcess process; QProcess process;
ProjectExplorer::Environment environment = ProjectExplorer::Environment::systemEnvironment(); ProjectExplorer::Environment environment = ProjectExplorer::Environment::systemEnvironment();
if (m_plugin->m_settingsPage && !m_plugin->m_settingsPage->adoptEnvironment()) if (m_settings.adoptPath)
environment.set(QLatin1String("PATH"), m_plugin->m_settingsPage->path()); environment.set(QLatin1String("PATH"), m_settings.path);
GitCommand* command = new GitCommand(); GitCommand* command = new GitCommand();
if (outputToWindow) { if (outputToWindow) {
@@ -361,23 +409,28 @@ void GitClient::executeGit(const QString &workingDirectory, const QStringList &a
command->execute(arguments, workingDirectory, environment); command->execute(arguments, workingDirectory, environment);
} }
bool GitClient::synchronousGit(const QString &workingDirectory bool GitClient::synchronousGit(const QString &workingDirectory,
, const QStringList &arguments const QStringList &arguments,
, QByteArray* outputText QByteArray* outputText,
, QByteArray* errorText) QByteArray* errorText,
bool logCommandToWindow)
{ {
if (Git::Constants::debug) if (Git::Constants::debug)
qDebug() << "synchronousGit" << workingDirectory << arguments; qDebug() << "synchronousGit" << workingDirectory << arguments;
QProcess process; const QString binary = QLatin1String(kGitCommand);
if (logCommandToWindow)
m_plugin->outputWindow()->append(formatCommand(binary, arguments));
QProcess process;
process.setWorkingDirectory(workingDirectory); process.setWorkingDirectory(workingDirectory);
ProjectExplorer::Environment environment = ProjectExplorer::Environment::systemEnvironment(); ProjectExplorer::Environment environment = ProjectExplorer::Environment::systemEnvironment();
if (m_plugin->m_settingsPage && !m_plugin->m_settingsPage->adoptEnvironment()) if (m_settings.adoptPath)
environment.set(QLatin1String("PATH"), m_plugin->m_settingsPage->path()); environment.set(QLatin1String("PATH"), m_settings.path);
process.setEnvironment(environment.toStringList()); process.setEnvironment(environment.toStringList());
process.start(QLatin1String(kGitCommand), arguments); process.start(binary, arguments);
if (!process.waitForFinished()) { if (!process.waitForFinished()) {
if (errorText) if (errorText)
*errorText = "Error: Git timed out"; *errorText = "Error: Git timed out";
@@ -411,6 +464,34 @@ static inline QString trimFileSpecification(QString fileSpec)
return fileSpec; return fileSpec;
} }
GitClient::StatusResult GitClient::gitStatus(const QString &workingDirectory,
bool untracked,
QString *output,
QString *errorMessage)
{
// Run 'status'. Note that git returns exitcode 1 if there are no added files.
QByteArray outputText;
QByteArray errorText;
QStringList statusArgs(QLatin1String("status"));
if (untracked)
statusArgs << QLatin1String("-u");
const bool statusRc = synchronousGit(workingDirectory, statusArgs, &outputText, &errorText);
if (output)
*output = QString::fromLocal8Bit(outputText).remove(QLatin1Char('\r'));
// Is it something really fatal?
if (!statusRc && !outputText.contains(kBranchIndicatorC)) {
if (errorMessage) {
const QString error = QString::fromLocal8Bit(errorText).remove(QLatin1Char('\r'));
*errorMessage = tr("Unable to obtain the status: %1").arg(error);
}
return StatusFailed;
}
// Unchanged?
if (outputText.contains("nothing to commit"))
return StatusUnchanged;
return StatusChanged;
}
/* Parse a git status file list: /* Parse a git status file list:
* \code * \code
# Changes to be committed: # Changes to be committed:
@@ -421,10 +502,11 @@ static inline QString trimFileSpecification(QString fileSpec)
#<tab>modified:<blanks>git.pro #<tab>modified:<blanks>git.pro
\endcode \endcode
*/ */
static bool parseFiles(const QStringList &lines, CommitData *d) static bool parseFiles(const QString &output, CommitData *d)
{ {
enum State { None, CommitFiles, NotUpdatedFiles, UntrackedFiles }; enum State { None, CommitFiles, NotUpdatedFiles, UntrackedFiles };
const QStringList lines = output.split(QLatin1Char('\n'));
const QString branchIndicator = QLatin1String(kBranchIndicatorC); const QString branchIndicator = QLatin1String(kBranchIndicatorC);
const QString commitIndicator = QLatin1String("# Changes to be committed:"); const QString commitIndicator = QLatin1String("# Changes to be committed:");
const QString notUpdatedIndicator = QLatin1String("# Changed but not updated:"); const QString notUpdatedIndicator = QLatin1String("# Changed but not updated:");
@@ -457,10 +539,10 @@ static bool parseFiles(const QStringList &lines, CommitData *d)
const QString fileSpec = line.mid(2).trimmed(); const QString fileSpec = line.mid(2).trimmed();
switch (s) { switch (s) {
case CommitFiles: case CommitFiles:
d->commitFiles.push_back(trimFileSpecification(fileSpec)); d->stagedFiles.push_back(trimFileSpecification(fileSpec));
break; break;
case NotUpdatedFiles: case NotUpdatedFiles:
d->notUpdatedFiles.push_back(trimFileSpecification(fileSpec)); d->unstagedFiles.push_back(trimFileSpecification(fileSpec));
break; break;
case UntrackedFiles: case UntrackedFiles:
d->untrackedFiles.push_back(QLatin1String("untracked: ") + fileSpec); d->untrackedFiles.push_back(QLatin1String("untracked: ") + fileSpec);
@@ -474,7 +556,7 @@ static bool parseFiles(const QStringList &lines, CommitData *d)
} }
} }
} }
return !d->commitFiles.empty() || !d->notUpdatedFiles.empty() || !d->untrackedFiles.empty(); return !d->stagedFiles.empty() || !d->unstagedFiles.empty() || !d->untrackedFiles.empty();
} }
bool GitClient::getCommitData(const QString &workingDirectory, bool GitClient::getCommitData(const QString &workingDirectory,
@@ -482,12 +564,15 @@ bool GitClient::getCommitData(const QString &workingDirectory,
CommitData *d, CommitData *d,
QString *errorMessage) QString *errorMessage)
{ {
if (Git::Constants::debug)
qDebug() << Q_FUNC_INFO << workingDirectory;
d->clear(); d->clear();
// Find repo // Find repo
const QString repoDirectory = GitClient::findRepositoryForDirectory(workingDirectory); const QString repoDirectory = GitClient::findRepositoryForDirectory(workingDirectory);
if (repoDirectory.isEmpty()) { if (repoDirectory.isEmpty()) {
*errorMessage = tr("Unable to determine the repository for %1.").arg(workingDirectory); *errorMessage = msgRepositoryNotFound(workingDirectory);
return false; return false;
} }
@@ -508,23 +593,15 @@ bool GitClient::getCommitData(const QString &workingDirectory,
} }
// Run status. Note that it has exitcode 1 if there are no added files. // Run status. Note that it has exitcode 1 if there are no added files.
QByteArray outputText; QString output;
QByteArray errorText; switch (gitStatus(repoDirectory, untrackedFilesInCommit, &output, errorMessage)) {
QStringList statusArgs(QLatin1String("status")); case StatusChanged:
if (untrackedFilesInCommit) break;
statusArgs << QLatin1String("-u"); case StatusUnchanged:
const bool statusRc = synchronousGit(workingDirectory, statusArgs, &outputText, &errorText); *errorMessage = msgNoChangedFiles();
if (!statusRc) { return false;
// Something fatal case StatusFailed:
if (!outputText.contains(kBranchIndicatorC)) { return false;
*errorMessage = tr("Unable to obtain the project status: %1").arg(QString::fromLocal8Bit(errorText));
return false;
}
// All unchanged
if (outputText.contains("nothing to commit")) {
*errorMessage = tr("There are no modified files.");
return false;
}
} }
// Output looks like: // Output looks like:
@@ -545,9 +622,8 @@ bool GitClient::getCommitData(const QString &workingDirectory,
// # // #
// # list of files... // # list of files...
const QStringList lines = QString::fromLocal8Bit(outputText).remove(QLatin1Char('\r')).split(QLatin1Char('\n')); if (!parseFiles(output, d)) {
if (!parseFiles(lines, d)) { *errorMessage = msgParseFilesFailed();
*errorMessage = tr("Unable to parse the file output.");
return false; return false;
} }
@@ -570,24 +646,24 @@ bool GitClient::getCommitData(const QString &workingDirectory,
} }
// addAndCommit: // addAndCommit:
bool GitClient::addAndCommit(const QString &workingDirectory, bool GitClient::addAndCommit(const QString &repositoryDirectory,
const GitSubmitEditorPanelData &data, const GitSubmitEditorPanelData &data,
const QString &messageFile, const QString &messageFile,
const QStringList &checkedFiles, const QStringList &checkedFiles,
const QStringList &origCommitFiles) const QStringList &origCommitFiles)
{ {
if (Git::Constants::debug) if (Git::Constants::debug)
qDebug() << "GitClient::addAndCommit:" << workingDirectory << checkedFiles << origCommitFiles; qDebug() << "GitClient::addAndCommit:" << repositoryDirectory << checkedFiles << origCommitFiles;
// Do we need to reset any files that had been added before // Do we need to reset any files that had been added before
// (did the user uncheck any previously added files) // (did the user uncheck any previously added files)
const QSet<QString> resetFiles = origCommitFiles.toSet().subtract(checkedFiles.toSet()); const QSet<QString> resetFiles = origCommitFiles.toSet().subtract(checkedFiles.toSet());
if (!resetFiles.empty()) if (!resetFiles.empty())
if (!synchronousReset(workingDirectory, resetFiles.toList())) if (!synchronousReset(repositoryDirectory, resetFiles.toList()))
return false; return false;
// Re-add all to make sure we have the latest changes // Re-add all to make sure we have the latest changes
if (!synchronousAdd(workingDirectory, checkedFiles)) if (!synchronousAdd(repositoryDirectory, checkedFiles))
return false; return false;
// Do the final commit // Do the final commit
@@ -598,24 +674,192 @@ bool GitClient::addAndCommit(const QString &workingDirectory,
QByteArray outputText; QByteArray outputText;
QByteArray errorText; QByteArray errorText;
const bool rc = synchronousGit(workingDirectory, args, &outputText, &errorText); const bool rc = synchronousGit(repositoryDirectory, args, &outputText, &errorText);
const QString message = rc ? const QString message = rc ?
tr("Committed %n file(s).", 0, checkedFiles.size()) : tr("Committed %n file(s).\n", 0, checkedFiles.size()) :
tr("Unable to commit %n file(s): %1", 0, checkedFiles.size()).arg(QString::fromLocal8Bit(errorText)); tr("Unable to commit %n file(s): %1\n", 0, checkedFiles.size()).arg(QString::fromLocal8Bit(errorText));
m_plugin->m_outputWindow->append(message); m_plugin->outputWindow()->append(message);
m_plugin->m_outputWindow->popup(false); m_plugin->outputWindow()->popup(false);
return rc; return rc;
} }
static inline bool askWithInformativeText(QWidget *parent,
const QString &title,
const QString &msg,
const QString &inf,
bool defaultValue)
{
QMessageBox msgBox(QMessageBox::Question, title, msg, QMessageBox::Yes|QMessageBox::No, parent);
msgBox.setInformativeText(inf);
msgBox.setDefaultButton(defaultValue ? QMessageBox::Yes : QMessageBox::No);
return msgBox.exec() == QMessageBox::Yes;
}
/* Revert: This function can be called with a file list (to revert single
* files) or a single directory (revert all). Qt Creator currently has only
* 'revert single' in its VCS menus, but the code is prepared to deal with
* reverting a directory pending a sophisticated selection dialog in the
* VCSBase plugin. */
GitClient::RevertResult GitClient::revertI(QStringList files, bool *ptrToIsDirectory, QString *errorMessage)
{
if (Git::Constants::debug)
qDebug() << Q_FUNC_INFO << files;
if (files.empty())
return RevertCanceled;
// Figure out the working directory
const QFileInfo firstFile(files.front());
const bool isDirectory = firstFile.isDir();
if (ptrToIsDirectory)
*ptrToIsDirectory = isDirectory;
const QString workingDirectory = isDirectory ? firstFile.absoluteFilePath() : firstFile.absolutePath();
const QString repoDirectory = GitClient::findRepositoryForDirectory(workingDirectory);
if (repoDirectory.isEmpty()) {
*errorMessage = msgRepositoryNotFound(workingDirectory);
return RevertFailed;
}
// Check for changes
QString output;
switch (gitStatus(repoDirectory, false, &output, errorMessage)) {
case StatusChanged:
break;
case StatusUnchanged:
return RevertUnchanged;
case StatusFailed:
return RevertFailed;
}
CommitData d;
if (!parseFiles(output, &d)) {
*errorMessage = msgParseFilesFailed();
return RevertFailed;
}
// If we are looking at files, make them relative to the repository
// directory to match them in the status output list.
if (!isDirectory) {
const QDir repoDir(repoDirectory);
const QStringList::iterator cend = files.end();
for (QStringList::iterator it = files.begin(); it != cend; ++it)
*it = repoDir.relativeFilePath(*it);
}
// From the status output, determine all modified [un]staged files.
const QString modifiedPattern = QLatin1String("modified: ");
const QStringList allStagedFiles = GitSubmitEditor::statusListToFileList(d.stagedFiles.filter(modifiedPattern));
const QStringList allUnstagedFiles = GitSubmitEditor::statusListToFileList(d.unstagedFiles.filter(modifiedPattern));
// Unless a directory was passed, filter all modified files for the
// argument file list.
QStringList stagedFiles = allStagedFiles;
QStringList unstagedFiles = allUnstagedFiles;
if (!isDirectory) {
const QSet<QString> filesSet = files.toSet();
stagedFiles = allStagedFiles.toSet().intersect(filesSet).toList();
unstagedFiles = allUnstagedFiles.toSet().intersect(filesSet).toList();
}
if (Git::Constants::debug)
qDebug() << Q_FUNC_INFO << d.stagedFiles << d.unstagedFiles << allStagedFiles << allUnstagedFiles << stagedFiles << unstagedFiles;
if (stagedFiles.empty() && unstagedFiles.empty())
return RevertUnchanged;
// Ask to revert (to do: Handle lists with a selection dialog)
const QMessageBox::StandardButton answer
= QMessageBox::question(m_core->mainWindow(),
tr("Revert"),
tr("The file has been changed. Do you want to revert it?"),
QMessageBox::Yes|QMessageBox::No,
QMessageBox::No);
if (answer == QMessageBox::No)
return RevertCanceled;
// Unstage the staged files
if (!stagedFiles.empty() && !synchronousReset(repoDirectory, stagedFiles, errorMessage))
return RevertFailed;
// Finally revert!
if (!synchronousCheckout(repoDirectory, stagedFiles + unstagedFiles, errorMessage))
return RevertFailed;
return RevertOk;
}
void GitClient::revert(const QStringList &files)
{
bool isDirectory;
QString errorMessage;
switch (revertI(files, &isDirectory, &errorMessage)) {
case RevertOk:
case RevertCanceled:
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();
}
break;
case RevertFailed:
m_plugin->outputWindow()->append(errorMessage);
m_plugin->outputWindow()->popup();
break;
}
}
void GitClient::pull(const QString &workingDirectory) void GitClient::pull(const QString &workingDirectory)
{ {
executeGit(workingDirectory, QStringList(QLatin1String("pull")), m_plugin->m_outputWindow, 0,true); executeGit(workingDirectory, QStringList(QLatin1String("pull")), m_plugin->outputWindow(), 0, true);
} }
void GitClient::push(const QString &workingDirectory) void GitClient::push(const QString &workingDirectory)
{ {
executeGit(workingDirectory, QStringList(QLatin1String("push")), m_plugin->m_outputWindow, 0,true); executeGit(workingDirectory, QStringList(QLatin1String("push")), m_plugin->outputWindow(), 0, true);
}
QString GitClient::msgNoChangedFiles()
{
return tr("There are no modified files.");
}
void GitClient::stash(const QString &workingDirectory)
{
// Check for changes and stash
QString errorMessage;
switch (gitStatus(workingDirectory, false, 0, &errorMessage)) {
case StatusChanged:
executeGit(workingDirectory, QStringList(QLatin1String("stash")), m_plugin->outputWindow(), 0, true);
break;
case StatusUnchanged:
m_plugin->outputWindow()->append(msgNoChangedFiles());
m_plugin->outputWindow()->popup();
break;
case StatusFailed:
m_plugin->outputWindow()->append(errorMessage);
m_plugin->outputWindow()->popup();
break;
}
}
void GitClient::stashPop(const QString &workingDirectory)
{
QStringList arguments(QLatin1String("stash"));
arguments << QLatin1String("pop");
executeGit(workingDirectory, arguments, m_plugin->outputWindow(), 0, true);
}
void GitClient::branchList(const QString &workingDirectory)
{
QStringList arguments(QLatin1String("branch"));
arguments << QLatin1String("-r");
executeGit(workingDirectory, arguments, m_plugin->outputWindow(), 0, true);
}
void GitClient::stashList(const QString &workingDirectory)
{
QStringList arguments(QLatin1String("stash"));
arguments << QLatin1String("list");
executeGit(workingDirectory, arguments, m_plugin->outputWindow(), 0, true);
} }
QString GitClient::readConfig(const QString &workingDirectory, const QStringList &configVar) QString GitClient::readConfig(const QString &workingDirectory, const QStringList &configVar)
@@ -624,8 +868,8 @@ QString GitClient::readConfig(const QString &workingDirectory, const QStringList
arguments << QLatin1String("config") << configVar; arguments << QLatin1String("config") << configVar;
QByteArray outputText; QByteArray outputText;
if (synchronousGit(workingDirectory, arguments, &outputText)) if (synchronousGit(workingDirectory, arguments, &outputText, 0, false))
return QString::fromLocal8Bit(outputText); return QString::fromLocal8Bit(outputText).remove(QLatin1Char('\r'));
return QString(); return QString();
} }
@@ -635,6 +879,21 @@ QString GitClient::readConfigValue(const QString &workingDirectory, const QStrin
return readConfig(workingDirectory, QStringList(configVar)).remove(QLatin1Char('\n')); return readConfig(workingDirectory, QStringList(configVar)).remove(QLatin1Char('\n'));
} }
GitSettings GitClient::settings() const
{
return m_settings;
}
void GitClient::setSettings(const GitSettings &s)
{
if (s != m_settings) {
m_settings = s;
if (QSettings *s = m_core->settings())
m_settings.toSettings(s);
}
}
// ------------------------ GitCommand
GitCommand::GitCommand() GitCommand::GitCommand()
{ {
} }

View File

@@ -34,6 +34,8 @@
#ifndef GITCLIENT_H #ifndef GITCLIENT_H
#define GITCLIENT_H #define GITCLIENT_H
#include "gitsettings.h"
#include <coreplugin/iversioncontrol.h> #include <coreplugin/iversioncontrol.h>
#include <coreplugin/editormanager/ieditor.h> #include <coreplugin/editormanager/ieditor.h>
#include <projectexplorer/environment.h> #include <projectexplorer/environment.h>
@@ -62,17 +64,14 @@ class GitCommand;
struct CommitData; struct CommitData;
struct GitSubmitEditorPanelData; struct GitSubmitEditorPanelData;
class GitClient : public Core::IVersionControl class GitClient : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
GitClient(GitPlugin *plugin, Core::ICore *core); explicit GitClient(GitPlugin *plugin, Core::ICore *core);
~GitClient(); ~GitClient();
bool vcsOpen(const QString &fileName);
bool vcsAdd(const QString &) { return false; }
bool vcsDelete(const QString &) { return false; }
bool managesDirectory(const QString &) const { return false; } bool managesDirectory(const QString &) const { return false; }
QString findTopLevelForDirectory(const QString &) const { return QString(); } QString findTopLevelForDirectory(const QString &) const { return QString(); }
@@ -91,9 +90,17 @@ public:
void addFile(const QString &workingDirectory, const QString &fileName); void addFile(const QString &workingDirectory, const QString &fileName);
bool synchronousAdd(const QString &workingDirectory, const QStringList &files); bool synchronousAdd(const QString &workingDirectory, const QStringList &files);
bool synchronousReset(const QString &workingDirectory, const QStringList &files); bool synchronousReset(const QString &workingDirectory, const QStringList &files);
bool synchronousReset(const QString &workingDirectory, const QStringList &files, QString *errorMessage);
bool synchronousCheckout(const QString &workingDirectory, const QStringList &files, QString *errorMessage);
void pull(const QString &workingDirectory); void pull(const QString &workingDirectory);
void push(const QString &workingDirectory); void push(const QString &workingDirectory);
void stash(const QString &workingDirectory);
void stashPop(const QString &workingDirectory);
void revert(const QStringList &files);
void branchList(const QString &workingDirectory);
void stashList(const QString &workingDirectory);
QString readConfig(const QString &workingDirectory, const QStringList &configVar); QString readConfig(const QString &workingDirectory, const QStringList &configVar);
QString readConfigValue(const QString &workingDirectory, const QString &configVar); QString readConfigValue(const QString &workingDirectory, const QString &configVar);
@@ -109,6 +116,17 @@ public:
const QStringList &checkedFiles, const QStringList &checkedFiles,
const QStringList &origCommitFiles); const QStringList &origCommitFiles);
enum StatusResult { StatusChanged, StatusUnchanged, StatusFailed };
StatusResult gitStatus(const QString &workingDirectory,
bool untracked,
QString *output = 0,
QString *errorMessage = 0);
GitSettings settings() const;
void setSettings(const GitSettings &s);
static QString msgNoChangedFiles();
public slots: public slots:
void show(const QString &source, const QString &id); void show(const QString &source, const QString &id);
@@ -128,13 +146,18 @@ private:
bool outputToWindow = false); bool outputToWindow = false);
bool synchronousGit(const QString &workingDirectory, bool synchronousGit(const QString &workingDirectory,
const QStringList &arguments, const QStringList &arguments,
QByteArray* outputText = 0, QByteArray* outputText = 0,
QByteArray* errorText = 0); QByteArray* errorText = 0,
bool logCommandToWindow = true);
enum RevertResult { RevertOk, RevertUnchanged, RevertCanceled, RevertFailed };
RevertResult revertI(QStringList files, bool *isDirectory, QString *errorMessage);
const QString m_msgWait; const QString m_msgWait;
GitPlugin *m_plugin; GitPlugin *m_plugin;
Core::ICore *m_core; Core::ICore *m_core;
GitSettings m_settings;
}; };
class GitCommand : public QObject class GitCommand : public QObject

View File

@@ -104,6 +104,7 @@ void GitOutputWindow::append(const QString &text)
const QStringList lines = text.split(QLatin1Char('\n')); const QStringList lines = text.split(QLatin1Char('\n'));
foreach (const QString &s, lines) foreach (const QString &s, lines)
m_outputListWidget->addItem(s); m_outputListWidget->addItem(s);
m_outputListWidget->scrollToBottom();
popup(); popup();
} }

View File

@@ -33,6 +33,7 @@
#include "gitplugin.h" #include "gitplugin.h"
#include "gitclient.h" #include "gitclient.h"
#include "gitversioncontrol.h"
#include "giteditor.h" #include "giteditor.h"
#include "gitconstants.h" #include "gitconstants.h"
#include "changeselectiondialog.h" #include "changeselectiondialog.h"
@@ -117,7 +118,9 @@ GitPlugin::GitPlugin() :
m_undoFileAction(0), m_undoFileAction(0),
m_undoProjectAction(0), m_undoProjectAction(0),
m_showAction(0), m_showAction(0),
m_addAction(0), m_stageAction(0),
m_unstageAction(0),
m_revertAction(0),
m_commitAction(0), m_commitAction(0),
m_pullAction(0), m_pullAction(0),
m_pushAction(0), m_pushAction(0),
@@ -125,6 +128,10 @@ GitPlugin::GitPlugin() :
m_diffSelectedFilesAction(0), m_diffSelectedFilesAction(0),
m_undoAction(0), m_undoAction(0),
m_redoAction(0), m_redoAction(0),
m_stashAction(0),
m_stashPopAction(0),
m_stashListAction(0),
m_branchListAction(0),
m_projectExplorer(0), m_projectExplorer(0),
m_gitClient(0), m_gitClient(0),
m_outputWindow(0), m_outputWindow(0),
@@ -132,6 +139,7 @@ GitPlugin::GitPlugin() :
m_settingsPage(0), m_settingsPage(0),
m_coreListener(0), m_coreListener(0),
m_submitEditorFactory(0), m_submitEditorFactory(0),
m_versionControl(0),
m_changeTmpFile(0) m_changeTmpFile(0)
{ {
Q_ASSERT(m_instance == 0); Q_ASSERT(m_instance == 0);
@@ -170,6 +178,12 @@ GitPlugin::~GitPlugin()
m_submitEditorFactory = 0; m_submitEditorFactory = 0;
} }
if (m_versionControl) {
removeObject(m_versionControl);
delete m_versionControl;
m_versionControl = 0;
}
cleanChangeTmpFile(); cleanChangeTmpFile();
delete m_gitClient; delete m_gitClient;
m_instance = 0; m_instance = 0;
@@ -198,6 +212,15 @@ static const VCSBase::VCSBaseSubmitEditorParameters submitParameters = {
Git::Constants::DIFF_SELECTED Git::Constants::DIFF_SELECTED
}; };
static inline Core::ICommand *createSeparator(Core::ActionManagerInterface *am,
const QList<int> &context,
const QString &id,
QObject *parent)
{
QAction *a = new QAction(parent);
a->setSeparator(true);
return am->registerAction(a, id, context);
}
bool GitPlugin::initialize(const QStringList &arguments, QString *error_message) bool GitPlugin::initialize(const QStringList &arguments, QString *error_message)
{ {
@@ -235,6 +258,9 @@ bool GitPlugin::initialize(const QStringList &arguments, QString *error_message)
m_submitEditorFactory = new GitSubmitEditorFactory(&submitParameters); m_submitEditorFactory = new GitSubmitEditorFactory(&submitParameters);
addObject(m_submitEditorFactory); addObject(m_submitEditorFactory);
m_versionControl = new GitVersionControl(m_gitClient);
addObject(m_versionControl);
//register actions //register actions
Core::ActionManagerInterface *actionManager = m_core->actionManager(); Core::ActionManagerInterface *actionManager = m_core->actionManager();
@@ -245,9 +271,12 @@ bool GitPlugin::initialize(const QStringList &arguments, QString *error_message)
actionManager->createMenu(QLatin1String("Git")); actionManager->createMenu(QLatin1String("Git"));
gitContainer->menu()->setTitle(tr("&Git")); gitContainer->menu()->setTitle(tr("&Git"));
toolsContainer->addMenu(gitContainer); toolsContainer->addMenu(gitContainer);
if (QAction *ma = gitContainer->menu()->menuAction()) {
ma->setEnabled(m_versionControl->isEnabled());
connect(m_versionControl, SIGNAL(enabledChanged(bool)), ma, SLOT(setVisible(bool)));
}
Core::ICommand *command; Core::ICommand *command;
QAction *tmpaction;
m_diffAction = new QAction(tr("Diff current file"), this); m_diffAction = new QAction(tr("Diff current file"), this);
command = actionManager->registerAction(m_diffAction, "Git.Diff", globalcontext); command = actionManager->registerAction(m_diffAction, "Git.Diff", globalcontext);
@@ -284,18 +313,27 @@ bool GitPlugin::initialize(const QStringList &arguments, QString *error_message)
connect(m_undoFileAction, SIGNAL(triggered()), this, SLOT(undoFileChanges())); connect(m_undoFileAction, SIGNAL(triggered()), this, SLOT(undoFileChanges()));
gitContainer->addAction(command); gitContainer->addAction(command);
m_addAction = new QAction(tr("Add File"), this); m_stageAction = new QAction(tr("Stage file for commit"), this);
command = actionManager->registerAction(m_addAction, "Git.Add", globalcontext); command = actionManager->registerAction(m_stageAction, "Git.Stage", globalcontext);
command->setDefaultKeySequence(QKeySequence(tr("Alt+G,Alt+A"))); command->setDefaultKeySequence(QKeySequence(tr("Alt+G,Alt+A")));
command->setAttribute(Core::ICommand::CA_UpdateText); command->setAttribute(Core::ICommand::CA_UpdateText);
connect(m_addAction, SIGNAL(triggered()), this, SLOT(addFile())); connect(m_stageAction, SIGNAL(triggered()), this, SLOT(stageFile()));
gitContainer->addAction(command); gitContainer->addAction(command);
tmpaction = new QAction(this); m_unstageAction = new QAction(tr("Unstage file from commit"), this);
tmpaction->setSeparator(true); command = actionManager->registerAction(m_unstageAction, "Git.Unstage", globalcontext);
command = actionManager->registerAction(tmpaction, QLatin1String("Git.Sep.Project"), globalcontext); command->setAttribute(Core::ICommand::CA_UpdateText);
connect(m_unstageAction, SIGNAL(triggered()), this, SLOT(unstageFile()));
gitContainer->addAction(command); gitContainer->addAction(command);
m_revertAction = new QAction(tr("Revert..."), this);
command = actionManager->registerAction(m_revertAction, "Git.Revert", globalcontext);
command->setAttribute(Core::ICommand::CA_UpdateText);
connect(m_revertAction, SIGNAL(triggered()), this, SLOT(revertFile()));
gitContainer->addAction(command);
gitContainer->addAction(createSeparator(actionManager, globalcontext, QLatin1String("Git.Sep.Project"), this));
m_diffProjectAction = new QAction(tr("Diff current project"), this); m_diffProjectAction = new QAction(tr("Diff current project"), this);
command = actionManager->registerAction(m_diffProjectAction, "Git.DiffProject", globalcontext); command = actionManager->registerAction(m_diffProjectAction, "Git.DiffProject", globalcontext);
command->setDefaultKeySequence(QKeySequence("Alt+G,Alt+Shift+D")); command->setDefaultKeySequence(QKeySequence("Alt+G,Alt+Shift+D"));
@@ -322,15 +360,26 @@ bool GitPlugin::initialize(const QStringList &arguments, QString *error_message)
connect(m_undoProjectAction, SIGNAL(triggered()), this, SLOT(undoProjectChanges())); connect(m_undoProjectAction, SIGNAL(triggered()), this, SLOT(undoProjectChanges()));
gitContainer->addAction(command); gitContainer->addAction(command);
tmpaction = new QAction(this); gitContainer->addAction(createSeparator(actionManager, globalcontext, QLatin1String("Git.Sep.Global"), this));
tmpaction->setSeparator(true);
command = actionManager->registerAction(tmpaction, QLatin1String("Git.Sep.Global"), globalcontext); m_stashAction = new QAction(tr("Stash"), this);
m_stashAction->setToolTip("Saves the current state of your work.");
command = actionManager->registerAction(m_stashAction, "Git.Stash", globalcontext);
command->setAttribute(Core::ICommand::CA_UpdateText);
connect(m_stashAction, SIGNAL(triggered()), this, SLOT(stash()));
gitContainer->addAction(command); gitContainer->addAction(command);
m_showAction = new QAction(tr("Show commit..."), this); m_pullAction = new QAction(tr("Pull"), this);
command = actionManager->registerAction(m_showAction, "Git.ShowCommit", globalcontext); command = actionManager->registerAction(m_pullAction, "Git.Pull", globalcontext);
command->setAttribute(Core::ICommand::CA_UpdateText); command->setAttribute(Core::ICommand::CA_UpdateText);
connect(m_showAction, SIGNAL(triggered()), this, SLOT(showCommit())); connect(m_pullAction, SIGNAL(triggered()), this, SLOT(pull()));
gitContainer->addAction(command);
m_stashPopAction = new QAction(tr("Stash pop"), this);
m_stashAction->setToolTip("Restores changes saved to the stash list using \"Stash\".");
command = actionManager->registerAction(m_stashPopAction, "Git.StashPop", globalcontext);
command->setAttribute(Core::ICommand::CA_UpdateText);
connect(m_stashPopAction, SIGNAL(triggered()), this, SLOT(stashPop()));
gitContainer->addAction(command); gitContainer->addAction(command);
m_commitAction = new QAction(tr("Commit..."), this); m_commitAction = new QAction(tr("Commit..."), this);
@@ -340,24 +389,37 @@ bool GitPlugin::initialize(const QStringList &arguments, QString *error_message)
connect(m_commitAction, SIGNAL(triggered()), this, SLOT(startCommit())); connect(m_commitAction, SIGNAL(triggered()), this, SLOT(startCommit()));
gitContainer->addAction(command); gitContainer->addAction(command);
m_pullAction = new QAction(tr("Pull"), this);
command = actionManager->registerAction(m_pullAction, "Git.Pull", globalcontext);
command->setAttribute(Core::ICommand::CA_UpdateText);
connect(m_pullAction, SIGNAL(triggered()), this, SLOT(pull()));
gitContainer->addAction(command);
m_pushAction = new QAction(tr("Push"), this); m_pushAction = new QAction(tr("Push"), this);
command = actionManager->registerAction(m_pushAction, "Git.Push", globalcontext); command = actionManager->registerAction(m_pushAction, "Git.Push", globalcontext);
command->setAttribute(Core::ICommand::CA_UpdateText); command->setAttribute(Core::ICommand::CA_UpdateText);
connect(m_pushAction, SIGNAL(triggered()), this, SLOT(push())); connect(m_pushAction, SIGNAL(triggered()), this, SLOT(push()));
gitContainer->addAction(command); gitContainer->addAction(command);
gitContainer->addAction(createSeparator(actionManager, globalcontext, QLatin1String("Git.Sep.Branch"), this));
m_branchListAction = new QAction(tr("List branches"), this);
command = actionManager->registerAction(m_branchListAction, "Git.BranchList", globalcontext);
command->setAttribute(Core::ICommand::CA_UpdateText);
connect(m_branchListAction, SIGNAL(triggered()), this, SLOT(branchList()));
gitContainer->addAction(command);
m_stashListAction = new QAction(tr("List stashes"), this);
command = actionManager->registerAction(m_stashListAction, "Git.StashList", globalcontext);
command->setAttribute(Core::ICommand::CA_UpdateText);
connect(m_stashListAction, SIGNAL(triggered()), this, SLOT(stashList()));
gitContainer->addAction(command);
m_showAction = new QAction(tr("Show commit..."), this);
command = actionManager->registerAction(m_showAction, "Git.ShowCommit", globalcontext);
command->setAttribute(Core::ICommand::CA_UpdateText);
connect(m_showAction, SIGNAL(triggered()), this, SLOT(showCommit()));
gitContainer->addAction(command);
// Submit editor // Submit editor
QList<int> submitContext; QList<int> submitContext;
submitContext.push_back(m_core->uniqueIDManager()->uniqueIdentifier(QLatin1String(Constants::C_GITSUBMITEDITOR))); submitContext.push_back(m_core->uniqueIDManager()->uniqueIdentifier(QLatin1String(Constants::C_GITSUBMITEDITOR)));
m_submitCurrentAction = new QAction(VCSBase::VCSBaseSubmitEditor::submitIcon(), tr("Commit"), this); m_submitCurrentAction = new QAction(VCSBase::VCSBaseSubmitEditor::submitIcon(), tr("Commit"), this);
command = actionManager->registerAction(m_submitCurrentAction, Constants::SUBMIT_CURRENT, submitContext); command = actionManager->registerAction(m_submitCurrentAction, Constants::SUBMIT_CURRENT, submitContext);
// TODO
connect(m_submitCurrentAction, SIGNAL(triggered()), this, SLOT(submitCurrentLog())); connect(m_submitCurrentAction, SIGNAL(triggered()), this, SLOT(submitCurrentLog()));
m_diffSelectedFilesAction = new QAction(VCSBase::VCSBaseSubmitEditor::diffIcon(), tr("Diff Selected Files"), this); m_diffSelectedFilesAction = new QAction(VCSBase::VCSBaseSubmitEditor::diffIcon(), tr("Diff Selected Files"), this);
@@ -383,12 +445,6 @@ void GitPlugin::extensionsInitialized()
m_projectExplorer = ExtensionSystem::PluginManager::instance()->getObject<ProjectExplorer::ProjectExplorerPlugin>(); m_projectExplorer = ExtensionSystem::PluginManager::instance()->getObject<ProjectExplorer::ProjectExplorerPlugin>();
} }
bool GitPlugin::vcsOpen(const QString &fileName)
{
Q_UNUSED(fileName);
return false;
}
void GitPlugin::submitEditorDiff(const QStringList &files) void GitPlugin::submitEditorDiff(const QStringList &files)
{ {
if (files.empty()) if (files.empty())
@@ -412,7 +468,7 @@ void GitPlugin::diffCurrentProject()
m_gitClient->diff(workingDirectory, QString()); m_gitClient->diff(workingDirectory, QString());
} }
QFileInfo GitPlugin::currentFile() QFileInfo GitPlugin::currentFile() const
{ {
QString fileName = m_core->fileManager()->currentFile(); QString fileName = m_core->fileManager()->currentFile();
QFileInfo fileInfo(fileName); QFileInfo fileInfo(fileName);
@@ -495,14 +551,28 @@ void GitPlugin::undoProjectChanges()
m_gitClient->hardReset(workingDirectory, QString()); m_gitClient->hardReset(workingDirectory, QString());
} }
void GitPlugin::addFile() void GitPlugin::stageFile()
{ {
QFileInfo fileInfo = currentFile(); const QFileInfo fileInfo = currentFile();
QString fileName = fileInfo.fileName(); const QString fileName = fileInfo.fileName();
QString workingDirectory = fileInfo.absolutePath(); const QString workingDirectory = fileInfo.absolutePath();
m_gitClient->addFile(workingDirectory, fileName); m_gitClient->addFile(workingDirectory, fileName);
} }
void GitPlugin::unstageFile()
{
const QFileInfo fileInfo = currentFile();
const QString fileName = fileInfo.fileName();
const QString workingDirectory = fileInfo.absolutePath();
m_gitClient->synchronousReset(workingDirectory, QStringList(fileName));
}
void GitPlugin::revertFile()
{
const QFileInfo fileInfo = currentFile();
m_gitClient->revert(QStringList(fileInfo.absoluteFilePath()));
}
void GitPlugin::startCommit() void GitPlugin::startCommit()
{ {
if (m_changeTmpFile) { if (m_changeTmpFile) {
@@ -528,7 +598,7 @@ void GitPlugin::startCommit()
// Store repository for diff and the original list of // Store repository for diff and the original list of
// files to be able to unstage files the user unchecks // files to be able to unstage files the user unchecks
m_submitRepository = data.panelInfo.repository; m_submitRepository = data.panelInfo.repository;
m_submitOrigCommitFiles = GitSubmitEditor::statusListToFileList(data.commitFiles); m_submitOrigCommitFiles = GitSubmitEditor::statusListToFileList(data.stagedFiles);
if (Git::Constants::debug) if (Git::Constants::debug)
qDebug() << Q_FUNC_INFO << data << commitTemplate; qDebug() << Q_FUNC_INFO << data << commitTemplate;
@@ -560,7 +630,7 @@ Core::IEditor *GitPlugin::openSubmitEditor(const QString &fileName, const Commit
Q_ASSERT(submitEditor); Q_ASSERT(submitEditor);
// The actions are for some reason enabled by the context switching // The actions are for some reason enabled by the context switching
// mechanism. Disable them correctly. // mechanism. Disable them correctly.
m_submitCurrentAction->setEnabled(!cd.commitFiles.empty()); m_submitCurrentAction->setEnabled(!cd.stagedFiles.empty());
m_diffSelectedFilesAction->setEnabled(false); m_diffSelectedFilesAction->setEnabled(false);
m_undoAction->setEnabled(false); m_undoAction->setEnabled(false);
m_redoAction->setEnabled(false); m_redoAction->setEnabled(false);
@@ -627,26 +697,52 @@ bool GitPlugin::editorAboutToClose(Core::IEditor *iEditor)
void GitPlugin::pull() void GitPlugin::pull()
{ {
QString workingDirectory = getWorkingDirectory(); const QString workingDirectory = getWorkingDirectory();
if (workingDirectory.isEmpty()) if (!workingDirectory.isEmpty())
return; m_gitClient->pull(workingDirectory);
m_gitClient->pull(workingDirectory);
} }
void GitPlugin::push() void GitPlugin::push()
{ {
QString workingDirectory = getWorkingDirectory(); const QString workingDirectory = getWorkingDirectory();
if (workingDirectory.isEmpty()) if (!workingDirectory.isEmpty())
return; m_gitClient->push(workingDirectory);
m_gitClient->push(workingDirectory); }
void GitPlugin::stash()
{
const QString workingDirectory = getWorkingDirectory();
if (!workingDirectory.isEmpty())
m_gitClient->stash(workingDirectory);
}
void GitPlugin::stashPop()
{
const QString workingDirectory = getWorkingDirectory();
if (!workingDirectory.isEmpty())
m_gitClient->stashPop(workingDirectory);
}
void GitPlugin::branchList()
{
const QString workingDirectory = getWorkingDirectory();
if (!workingDirectory.isEmpty())
m_gitClient->branchList(workingDirectory);
}
void GitPlugin::stashList()
{
const QString workingDirectory = getWorkingDirectory();
if (!workingDirectory.isEmpty())
m_gitClient->stashList(workingDirectory);
} }
void GitPlugin::updateActions() void GitPlugin::updateActions()
{ {
QFileInfo current = currentFile(); const QFileInfo current = currentFile();
const QString fileName = current.fileName(); const QString fileName = current.fileName();
const QString currentDirectory = getWorkingDirectory(); const QString currentDirectory = getWorkingDirectory();
QString repository = m_gitClient->findRepositoryForFile(current.absoluteFilePath()); const QString repository = m_gitClient->findRepositoryForFile(current.absoluteFilePath());
// First check for file commands and if the current file is inside // First check for file commands and if the current file is inside
// a Git-repository // a Git-repository
m_diffAction->setText(tr("Diff %1").arg(fileName)); m_diffAction->setText(tr("Diff %1").arg(fileName));
@@ -654,7 +750,9 @@ void GitPlugin::updateActions()
m_logAction->setText(tr("Log %1").arg(fileName)); m_logAction->setText(tr("Log %1").arg(fileName));
m_blameAction->setText(tr("Blame %1").arg(fileName)); m_blameAction->setText(tr("Blame %1").arg(fileName));
m_undoFileAction->setText(tr("Undo changes for %1").arg(fileName)); m_undoFileAction->setText(tr("Undo changes for %1").arg(fileName));
m_addAction->setText(tr("Add %1").arg(fileName)); m_stageAction->setText(tr("Stage %1 for commit").arg(fileName));
m_unstageAction->setText(tr("Unstage %1 from commit").arg(fileName));
m_revertAction->setText(tr("Revert %1...").arg(fileName));
if (repository.isEmpty()) { if (repository.isEmpty()) {
// If the file is not in a repository, the corresponding project will // If the file is not in a repository, the corresponding project will
// be neither and we can disable everything and return // be neither and we can disable everything and return
@@ -663,7 +761,9 @@ void GitPlugin::updateActions()
m_logAction->setEnabled(false); m_logAction->setEnabled(false);
m_blameAction->setEnabled(false); m_blameAction->setEnabled(false);
m_undoFileAction->setEnabled(false); m_undoFileAction->setEnabled(false);
m_addAction->setEnabled(false); m_stageAction->setEnabled(false);
m_unstageAction->setEnabled(false);
m_revertAction->setEnabled(false);
m_diffProjectAction->setEnabled(false); m_diffProjectAction->setEnabled(false);
m_diffProjectAction->setText(tr("Diff Project")); m_diffProjectAction->setText(tr("Diff Project"));
m_statusProjectAction->setText(tr("Status Project")); m_statusProjectAction->setText(tr("Status Project"));
@@ -679,12 +779,14 @@ void GitPlugin::updateActions()
m_logAction->setEnabled(true); m_logAction->setEnabled(true);
m_blameAction->setEnabled(true); m_blameAction->setEnabled(true);
m_undoFileAction->setEnabled(true); m_undoFileAction->setEnabled(true);
m_addAction->setEnabled(true); m_stageAction->setEnabled(true);
m_unstageAction->setEnabled(true);
m_revertAction->setEnabled(true);
} }
if (m_projectExplorer && m_projectExplorer->currentNode() if (m_projectExplorer && m_projectExplorer->currentNode()
&& m_projectExplorer->currentNode()->projectNode()) { && m_projectExplorer->currentNode()->projectNode()) {
QString name = QFileInfo(m_projectExplorer->currentNode()->projectNode()->path()).baseName(); const QString name = QFileInfo(m_projectExplorer->currentNode()->projectNode()->path()).baseName();
m_diffProjectAction->setEnabled(true); m_diffProjectAction->setEnabled(true);
m_diffProjectAction->setText(tr("Diff Project %1").arg(name)); m_diffProjectAction->setText(tr("Diff Project %1").arg(name));
m_statusProjectAction->setEnabled(true); m_statusProjectAction->setEnabled(true);
@@ -720,4 +822,19 @@ void GitPlugin::showCommit()
m_gitClient->show(m_changeSelectionDialog->m_ui.repositoryEdit->text(), change); m_gitClient->show(m_changeSelectionDialog->m_ui.repositoryEdit->text(), change);
} }
GitOutputWindow *GitPlugin::outputWindow() const
{
return m_outputWindow;
}
GitSettings GitPlugin::settings() const
{
return m_gitClient->settings();
}
void GitPlugin::setSettings(const GitSettings &s)
{
m_gitClient->setSettings(s);
}
Q_EXPORT_PLUGIN(GitPlugin) Q_EXPORT_PLUGIN(GitPlugin)

View File

@@ -55,6 +55,7 @@ QT_END_NAMESPACE
namespace Core { namespace Core {
class IEditorFactory; class IEditorFactory;
class ICore; class ICore;
class IVersionControl;
} }
namespace Git { namespace Git {
@@ -65,6 +66,7 @@ namespace Internal {
class ChangeSelectionDialog; class ChangeSelectionDialog;
class GitSubmitEditor; class GitSubmitEditor;
struct CommitData; struct CommitData;
struct GitSettings;
// Just a proxy for GitPlugin // Just a proxy for GitPlugin
class CoreListener : public Core::ICoreListener class CoreListener : public Core::ICoreListener
@@ -87,14 +89,17 @@ public:
~GitPlugin(); ~GitPlugin();
static GitPlugin *instance(); static GitPlugin *instance();
bool vcsOpen(const QString &fileName);
bool initialize(const QStringList &arguments bool initialize(const QStringList &arguments
, QString *error_message); , QString *error_message);
void extensionsInitialized(); void extensionsInitialized();
QString getWorkingDirectory(); QString getWorkingDirectory();
GitOutputWindow *outputWindow() const;
GitSettings settings() const;
void setSettings(const GitSettings &s);
public slots: public slots:
void updateActions(); void updateActions();
bool editorAboutToClose(Core::IEditor *editor); bool editorAboutToClose(Core::IEditor *editor);
@@ -111,16 +116,21 @@ private slots:
void logProject(); void logProject();
void undoFileChanges(); void undoFileChanges();
void undoProjectChanges(); void undoProjectChanges();
void addFile(); void stageFile();
void unstageFile();
void revertFile();
void showCommit(); void showCommit();
void startCommit(); void startCommit();
void stash();
void stashPop();
void branchList();
void stashList();
void pull(); void pull();
void push(); void push();
private: private:
friend class GitClient; QFileInfo currentFile() const;
QFileInfo currentFile();
Core::IEditor *openSubmitEditor(const QString &fileName, const CommitData &cd); Core::IEditor *openSubmitEditor(const QString &fileName, const CommitData &cd);
void cleanChangeTmpFile(); void cleanChangeTmpFile();
@@ -136,7 +146,9 @@ private:
QAction *m_undoFileAction; QAction *m_undoFileAction;
QAction *m_undoProjectAction; QAction *m_undoProjectAction;
QAction *m_showAction; QAction *m_showAction;
QAction *m_addAction; QAction *m_stageAction;
QAction *m_unstageAction;
QAction *m_revertAction;
QAction *m_commitAction; QAction *m_commitAction;
QAction *m_pullAction; QAction *m_pullAction;
QAction *m_pushAction; QAction *m_pushAction;
@@ -145,6 +157,10 @@ private:
QAction *m_diffSelectedFilesAction; QAction *m_diffSelectedFilesAction;
QAction *m_undoAction; QAction *m_undoAction;
QAction *m_redoAction; QAction *m_redoAction;
QAction *m_stashAction;
QAction *m_stashPopAction;
QAction *m_stashListAction;
QAction *m_branchListAction;
ProjectExplorer::ProjectExplorerPlugin *m_projectExplorer; ProjectExplorer::ProjectExplorerPlugin *m_projectExplorer;
GitClient *m_gitClient; GitClient *m_gitClient;
@@ -154,6 +170,7 @@ private:
QList<Core::IEditorFactory*> m_editorFactories; QList<Core::IEditorFactory*> m_editorFactories;
CoreListener *m_coreListener; CoreListener *m_coreListener;
Core::IEditorFactory *m_submitEditorFactory; Core::IEditorFactory *m_submitEditorFactory;
Core::IVersionControl *m_versionControl;
QString m_submitRepository; QString m_submitRepository;
QStringList m_submitOrigCommitFiles; QStringList m_submitOrigCommitFiles;
QTemporaryFile *m_changeTmpFile; QTemporaryFile *m_changeTmpFile;

View File

@@ -0,0 +1,79 @@
/***************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Qt Software Information (qt-info@nokia.com)
**
**
** Non-Open Source Usage
**
** Licensees may use this file in accordance with the Qt Beta Version
** License Agreement, Agreement version 2.2 provided with the Software or,
** alternatively, in accordance with the terms contained in a written
** agreement between you and Nokia.
**
** GNU General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU General
** Public License versions 2.0 or 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the packaging
** of this file. Please review the following information to ensure GNU
** General Public Licensing requirements will be met:
**
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
** http://www.gnu.org/copyleft/gpl.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt GPL Exception
** version 1.2, included in the file GPL_EXCEPTION.txt in this package.
**
***************************************************************************/
#include "gitsettings.h"
#include <QtCore/QSettings>
#include <QtCore/QTextStream>
static const char *groupC = "Git";
static const char *sysEnvKeyC = "SysEnv";
static const char *pathKeyC = "Path";
static const char *logCountKeyC = "LogCount";
enum { defaultLogCount = 10 };
namespace Git {
namespace Internal {
GitSettings::GitSettings() :
adoptPath(false),
logCount(defaultLogCount)
{
}
void GitSettings::fromSettings(QSettings *settings)
{
settings->beginGroup(QLatin1String(groupC));
adoptPath = settings->value(QLatin1String(sysEnvKeyC), false).toBool();
path = settings->value(QLatin1String(pathKeyC), QString()).toString();
logCount = settings->value(QLatin1String(logCountKeyC), defaultLogCount).toInt();
settings->endGroup();
}
void GitSettings::toSettings(QSettings *settings) const
{
settings->beginGroup(QLatin1String(groupC));
settings->setValue(QLatin1String(sysEnvKeyC), adoptPath);
settings->setValue(QLatin1String(pathKeyC), path);
settings->setValue(QLatin1String(logCountKeyC), logCount);
settings->endGroup();
}
bool GitSettings::equals(const GitSettings &s) const
{
return adoptPath == s.adoptPath && path == s.path && logCount == s.logCount;
}
}
}

View File

@@ -0,0 +1,69 @@
/***************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Qt Software Information (qt-info@nokia.com)
**
**
** Non-Open Source Usage
**
** Licensees may use this file in accordance with the Qt Beta Version
** License Agreement, Agreement version 2.2 provided with the Software or,
** alternatively, in accordance with the terms contained in a written
** agreement between you and Nokia.
**
** GNU General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU General
** Public License versions 2.0 or 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the packaging
** of this file. Please review the following information to ensure GNU
** General Public Licensing requirements will be met:
**
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
** http://www.gnu.org/copyleft/gpl.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt GPL Exception
** version 1.2, included in the file GPL_EXCEPTION.txt in this package.
**
***************************************************************************/
#ifndef GITSETTINGS_H
#define GITSETTINGS_H
#include <QtCore/QStringList>
QT_BEGIN_NAMESPACE
class QSettings;
QT_END_NAMESPACE
namespace Git {
namespace Internal {
// Todo: Add user name and password?
struct GitSettings
{
GitSettings();
void fromSettings(QSettings *);
void toSettings(QSettings *) const;
bool equals(const GitSettings &s) const;
bool adoptPath;
QString path;
int logCount;
};
inline bool operator==(const GitSettings &p1, const GitSettings &p2)
{ return p1.equals(p2); }
inline bool operator!=(const GitSettings &p1, const GitSettings &p2)
{ return !p1.equals(p2); }
} // namespace Internal
} // namespace Git
#endif // GITSETTINGS_H

View File

@@ -67,9 +67,9 @@ void GitSubmitEditor::setCommitData(const CommitData &d)
submitEditorWidget()->setPanelData(d.panelData); submitEditorWidget()->setPanelData(d.panelData);
submitEditorWidget()->setPanelInfo(d.panelInfo); submitEditorWidget()->setPanelInfo(d.panelInfo);
addFiles(d.commitFiles, true, true); addFiles(d.stagedFiles, true, true);
// Not Updated: Initially unchecked // Not Updated: Initially unchecked
addFiles(d.notUpdatedFiles, false, true); addFiles(d.unstagedFiles, false, true);
addFiles(d.untrackedFiles, false, true); addFiles(d.untrackedFiles, false, true);
} }

View File

@@ -0,0 +1,104 @@
/***************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Qt Software Information (qt-info@nokia.com)
**
**
** Non-Open Source Usage
**
** Licensees may use this file in accordance with the Qt Beta Version
** License Agreement, Agreement version 2.2 provided with the Software or,
** alternatively, in accordance with the terms contained in a written
** agreement between you and Nokia.
**
** GNU General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU General
** Public License versions 2.0 or 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the packaging
** of this file. Please review the following information to ensure GNU
** General Public Licensing requirements will be met:
**
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
** http://www.gnu.org/copyleft/gpl.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt GPL Exception
** version 1.2, included in the file GPL_EXCEPTION.txt in this package.
**
***************************************************************************/
#include "gitversioncontrol.h"
#include "gitclient.h"
namespace Git {
namespace Internal {
GitVersionControl::GitVersionControl(GitClient *client) :
m_enabled(true),
m_client(client)
{
}
QString GitVersionControl::name() const
{
return QLatin1String("git");
}
bool GitVersionControl::isEnabled() const
{
return m_enabled;
}
void GitVersionControl::setEnabled(bool enabled)
{
if (m_enabled != enabled) {
m_enabled = enabled;
emit enabledChanged(m_enabled);
}
}
bool GitVersionControl::supportsOperation(Operation operation) const
{
bool rc = false;
switch (operation) {
case AddOperation:
case DeleteOperation:
case OpenOperation:
break;
}
return rc;
}
bool GitVersionControl::vcsOpen(const QString & /*fileName*/)
{
return false;
}
bool GitVersionControl::vcsAdd(const QString & /*fileName*/)
{
return false;
}
bool GitVersionControl::vcsDelete(const QString & /*fileName*/)
{
// TODO: implement using 'git rm'.
return false;
}
bool GitVersionControl::managesDirectory(const QString &directory) const
{
return !GitClient::findRepositoryForDirectory(directory).isEmpty();
}
QString GitVersionControl::findTopLevelForDirectory(const QString &directory) const
{
return GitClient::findRepositoryForDirectory(directory);
}
} // Internal
} // Git

View File

@@ -31,52 +31,45 @@
** **
***************************************************************************/ ***************************************************************************/
#ifndef INDEXWINDOW_H #ifndef GITVERSIONCONTROL_H
#define INDEXWINDOW_H #define GITVERSIONCONTROL_H
#include <QtCore/QUrl> #include <coreplugin/iversioncontrol.h>
#include <QtGui/QWidget>
#include <QtGui/QLineEdit>
QT_BEGIN_NAMESPACE namespace Git {
namespace Internal {
class QHelpIndexWidget; class GitClient;
class QHelpEngine;
class IndexWindow : public QWidget // Just a proxy for GitPlugin
class GitVersionControl : public Core::IVersionControl
{ {
Q_OBJECT Q_OBJECT
public: public:
IndexWindow(QHelpEngine *helpEngine, QWidget *parent = 0); explicit GitVersionControl(GitClient *plugin);
~IndexWindow();
void setSearchLineEditText(const QString &text); virtual QString name() const;
QString searchLineEditText() const
{ virtual bool isEnabled() const;
return m_searchLineEdit->text(); virtual void setEnabled(bool enabled);
}
bool managesDirectory(const QString &directory) const;
virtual QString findTopLevelForDirectory(const QString &directory) const;
virtual bool supportsOperation(Operation operation) const;
virtual bool vcsOpen(const QString &fileName);
virtual bool vcsAdd(const QString &fileName);
virtual bool vcsDelete(const QString &filename);
signals: signals:
void linkActivated(const QUrl &link); void enabledChanged(bool);
void linksActivated(const QMap<QString, QUrl> &links,
const QString &keyword);
void escapePressed();
private slots:
void filterIndices(const QString &filter);
void enableSearchLineEdit();
void disableSearchLineEdit();
private: private:
bool eventFilter(QObject *obj, QEvent *e); bool m_enabled;
void focusInEvent(QFocusEvent *e); GitClient *m_client;
QLineEdit *m_searchLineEdit;
QHelpIndexWidget *m_indexWidget;
QHelpEngine *m_helpEngine;
}; };
QT_END_NAMESPACE } // Internal
} // Git
#endif // INDEXWINDOW_H #endif // GITVERSIONCONTROL_H

View File

@@ -32,35 +32,44 @@
***************************************************************************/ ***************************************************************************/
#include "settingspage.h" #include "settingspage.h"
#include "gitsettings.h"
#include "gitplugin.h"
#include <coreplugin/icore.h>
#include <extensionsystem/pluginmanager.h>
#include <QtCore/QSettings>
#include <QtGui/QLineEdit>
#include <QtGui/QFileDialog>
#include <QtCore/QDebug> #include <QtCore/QDebug>
using namespace Git::Internal; using namespace Git::Internal;
static const char *groupC = "Git"; SettingsPageWidget::SettingsPageWidget(QWidget *parent) :
static const char *sysEnvKeyC = "SysEnv"; QWidget(parent)
static const char *pathKeyC = "Path"; {
static const char *logCountKeyC = "LogCount"; m_ui.setupUi(this);
connect(m_ui.adoptButton, SIGNAL(clicked()), this, SLOT(setSystemPath()));
}
GitSettings SettingsPageWidget::settings() const
{
GitSettings rc;
rc.path = m_ui.pathLineEdit->text();
rc.adoptPath = m_ui.environmentGroupBox->isChecked() && !rc.path.isEmpty();
rc.logCount = m_ui.logCountSpinBox->value();
return rc;
}
void SettingsPageWidget::setSettings(const GitSettings &s)
{
m_ui.environmentGroupBox->setChecked(s.adoptPath);
m_ui.pathLineEdit->setText(s.path);
m_ui.logCountSpinBox->setValue(s.logCount);
}
void SettingsPageWidget::setSystemPath()
{
m_ui.pathLineEdit->setText(QLatin1String(qgetenv("PATH")));
}
// -------- SettingsPage
SettingsPage::SettingsPage() SettingsPage::SettingsPage()
{ {
Core::ICore *coreIFace = ExtensionSystem::PluginManager::instance()->getObject<Core::ICore>();
if (coreIFace)
m_settings = coreIFace->settings();
if (m_settings) {
m_settings->beginGroup(QLatin1String(groupC));
m_adopt = m_settings->value(QLatin1String(sysEnvKeyC), true).toBool();
m_path = m_settings->value(QLatin1String(pathKeyC), QString()).toString();
m_logCount = m_settings->value(QLatin1String(logCountKeyC), 10).toInt();
m_settings->endGroup();
}
} }
QString SettingsPage::name() const QString SettingsPage::name() const
@@ -68,7 +77,7 @@ QString SettingsPage::name() const
return tr("General"); return tr("General");
} }
QString SettingsPage::category() const QString SettingsPage::category() const
{ {
return QLatin1String("Git"); return QLatin1String("Git");
} }
@@ -80,37 +89,17 @@ QString SettingsPage::trCategory() const
QWidget *SettingsPage::createPage(QWidget *parent) QWidget *SettingsPage::createPage(QWidget *parent)
{ {
QWidget *w = new QWidget(parent); if (!m_widget)
m_ui.setupUi(w); m_widget = new SettingsPageWidget(parent);
m_ui.adoptCheckBox->setChecked(m_adopt); m_widget->setSettings(GitPlugin::instance()->settings());
m_ui.pathLineEdit->setText(m_path); return m_widget;
m_ui.logLineEdit->setText(QString::number(m_logCount));
connect(m_ui.adoptButton, SIGNAL(clicked()), this, SLOT(setSystemPath()));
return w;
} }
void SettingsPage::finished(bool accepted) void SettingsPage::finished(bool accepted)
{ {
if (!accepted) if (!accepted || !m_widget)
return; return;
m_adopt = m_ui.adoptCheckBox->isChecked(); GitPlugin::instance()->setSettings(m_widget->settings());
m_path = m_ui.pathLineEdit->text();
m_logCount = m_ui.logLineEdit->text().toInt();
if (!m_settings)
return;
m_settings->beginGroup(QLatin1String(groupC));
m_settings->setValue(QLatin1String(sysEnvKeyC), m_adopt);
m_settings->setValue(QLatin1String(pathKeyC), m_path);
m_settings->setValue(QLatin1String(logCountKeyC), m_logCount);
m_settings->endGroup();
} }
void SettingsPage::setSystemPath()
{
m_path = qgetenv("PATH");
m_ui.pathLineEdit->setText(m_path);
}

View File

@@ -35,6 +35,7 @@
#define SETTINGSPAGE_H #define SETTINGSPAGE_H
#include <QtGui/QWidget> #include <QtGui/QWidget>
#include <QtCore/QPointer>
#include <coreplugin/dialogs/ioptionspage.h> #include <coreplugin/dialogs/ioptionspage.h>
@@ -47,6 +48,23 @@ QT_END_NAMESPACE
namespace Git { namespace Git {
namespace Internal { namespace Internal {
struct GitSettings;
class SettingsPageWidget : public QWidget {
Q_OBJECT
public:
explicit SettingsPageWidget(QWidget *parent = 0);
GitSettings settings() const;
void setSettings(const GitSettings &);
private slots:
void setSystemPath();
private:
Ui::SettingsPage m_ui;
};
class SettingsPage : public Core::IOptionsPage class SettingsPage : public Core::IOptionsPage
{ {
Q_OBJECT Q_OBJECT
@@ -61,20 +79,8 @@ public:
QWidget *createPage(QWidget *parent); QWidget *createPage(QWidget *parent);
void finished(bool accepted); void finished(bool accepted);
bool adoptEnvironment() const { return m_adopt; }
int logCount() const { return m_logCount; }
QString path() const { return m_path; }
private slots:
void setSystemPath();
private: private:
Ui_SettingsPage m_ui; QPointer<SettingsPageWidget> m_widget;
QSettings *m_settings;
bool m_adopt;
QString m_path;
int m_logCount;
}; };
} // namespace Internal } // namespace Internal

View File

@@ -6,103 +6,113 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>345</width> <width>436</width>
<height>177</height> <height>186</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string>Form</string> <string>Form</string>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QHBoxLayout" name="horizontalLayout">
<item> <item>
<widget class="QCheckBox" name="adoptCheckBox"> <layout class="QVBoxLayout" name="verticalLayout">
<property name="text">
<string>Use System Environment</string>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="enabled">
<bool>true</bool>
</property>
<property name="title">
<string>Environment variables</string>
</property>
<property name="checkable">
<bool>false</bool>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>PATH:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="pathLineEdit"/>
</item>
<item row="0" column="2">
<widget class="QPushButton" name="adoptButton">
<property name="text">
<string>Adopt</string>
</property>
</widget>
</item>
<item row="1" column="0">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>52</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="1" colspan="2">
<widget class="QLabel" name="label_2">
<property name="text">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt; font-weight:600;&quot;&gt;Note&lt;/span&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; that Git needs Perl in the environment as well&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item> <item>
<widget class="QLabel" name="label_3"> <widget class="QGroupBox" name="environmentGroupBox">
<property name="text"> <property name="enabled">
<string>Commit display count:</string> <bool>true</bool>
</property> </property>
<property name="title">
<string>Environment variables</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="pathlabel">
<property name="text">
<string>PATH:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLineEdit" name="pathLineEdit"/>
</item>
<item>
<widget class="QPushButton" name="adoptButton">
<property name="text">
<string>From system</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QLabel" name="noteLabel">
<property name="text">
<string>&lt;b&gt;Note:&lt;/b&gt;</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="noteFieldlabel">
<property name="text">
<string>Git needs to find Perl in the environment as well.</string>
</property>
</widget>
</item>
</layout>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QLineEdit" name="logLineEdit"> <layout class="QFormLayout" name="logFormLayout">
<property name="toolTip"> <property name="fieldGrowthPolicy">
<string>Note that huge amount of commits might take some time.</string> <enum>QFormLayout::ExpandingFieldsGrow</enum>
</property> </property>
</widget> <item row="0" column="1">
<widget class="QSpinBox" name="logCountSpinBox">
<property name="toolTip">
<string>Note that huge amount of commits might take some time.</string>
</property>
<property name="maximum">
<number>1000</number>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="logCountLabel">
<property name="text">
<string>Log commit display count:</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item> </item>
</layout> </layout>
</item> </item>
<item> <item>
<spacer> <spacer name="horizontalSpacer">
<property name="orientation"> <property name="orientation">
<enum>Qt::Vertical</enum> <enum>Qt::Horizontal</enum>
</property> </property>
<property name="sizeHint" stdset="0"> <property name="sizeHint" stdset="0">
<size> <size>
<width>141</width> <width>40</width>
<height>20</height> <height>20</height>
</size> </size>
</property> </property>
@@ -114,22 +124,5 @@ p, li { white-space: pre-wrap; }
<tabstop>pathLineEdit</tabstop> <tabstop>pathLineEdit</tabstop>
</tabstops> </tabstops>
<resources/> <resources/>
<connections> <connections/>
<connection>
<sender>adoptCheckBox</sender>
<signal>toggled(bool)</signal>
<receiver>groupBox</receiver>
<slot>setDisabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>144</x>
<y>33</y>
</hint>
<hint type="destinationlabel">
<x>139</x>
<y>65</y>
</hint>
</hints>
</connection>
</connections>
</ui> </ui>

View File

@@ -16,8 +16,8 @@ HEADERS += helpplugin.h \
searchwidget.h \ searchwidget.h \
helpfindsupport.h \ helpfindsupport.h \
help_global.h \ help_global.h \
helpindexfilter.h \ helpindexfilter.h
indexwindow.h
SOURCES += helpplugin.cpp \ SOURCES += helpplugin.cpp \
docsettingspage.cpp \ docsettingspage.cpp \
filtersettingspage.cpp \ filtersettingspage.cpp \
@@ -26,6 +26,7 @@ SOURCES += helpplugin.cpp \
searchwidget.cpp \ searchwidget.cpp \
helpfindsupport.cpp \ helpfindsupport.cpp \
helpindexfilter.cpp helpindexfilter.cpp
FORMS += docsettingspage.ui \ FORMS += docsettingspage.ui \
filtersettingspage.ui filtersettingspage.ui
RESOURCES += help.qrc RESOURCES += help.qrc

View File

@@ -235,6 +235,10 @@ bool PerforcePlugin::initialize(const QStringList & /*arguments*/, QString *erro
am->createMenu(QLatin1String(PERFORCE_MENU)); am->createMenu(QLatin1String(PERFORCE_MENU));
mperforce->menu()->setTitle(tr("&Perforce")); mperforce->menu()->setTitle(tr("&Perforce"));
mtools->addMenu(mperforce); mtools->addMenu(mperforce);
if (QAction *ma = mperforce->menu()->menuAction()) {
ma->setEnabled(m_versionControl->isEnabled());
connect(m_versionControl, SIGNAL(enabledChanged(bool)), ma, SLOT(setVisible(bool)));
}
QList<int> globalcontext; QList<int> globalcontext;
globalcontext << Core::Constants::C_GLOBAL_ID; globalcontext << Core::Constants::C_GLOBAL_ID;
@@ -401,17 +405,17 @@ void PerforcePlugin::extensionsInitialized()
void PerforcePlugin::openCurrentFile() void PerforcePlugin::openCurrentFile()
{ {
runP4Cmd(QStringList() << QLatin1String("edit") << currentFileName(), QStringList(), true); vcsOpen(currentFileName());
} }
void PerforcePlugin::addCurrentFile() void PerforcePlugin::addCurrentFile()
{ {
runP4Cmd(QStringList() << QLatin1String("add") << currentFileName(), QStringList(), true); vcsAdd(currentFileName());
} }
void PerforcePlugin::deleteCurrentFile() void PerforcePlugin::deleteCurrentFile()
{ {
runP4Cmd(QStringList() << QLatin1String("delete") << currentFileName(), QStringList(), true); vcsDelete(currentFileName());
} }
void PerforcePlugin::revertCurrentFile() void PerforcePlugin::revertCurrentFile()
@@ -422,7 +426,7 @@ void PerforcePlugin::revertCurrentFile()
QTextCodec *codec = VCSBase::VCSBaseEditor::getCodec(m_coreInstance, fileName); QTextCodec *codec = VCSBase::VCSBaseEditor::getCodec(m_coreInstance, fileName);
QStringList args; QStringList args;
args << QLatin1String("diff") << QLatin1String("-sa"); args << QLatin1String("diff") << QLatin1String("-sa");
PerforceResponse result = runP4Cmd(args, QStringList(), false, true, codec); PerforceResponse result = runP4Cmd(args, QStringList(), CommandToWindow|StdErrToWindow|ErrorToWindow, codec);
if (result.error) if (result.error)
return; return;
@@ -440,7 +444,7 @@ void PerforcePlugin::revertCurrentFile()
foreach (Core::IFile *file, files) { foreach (Core::IFile *file, files) {
fm->blockFileChange(file); fm->blockFileChange(file);
} }
PerforceResponse result2 = runP4Cmd(QStringList() << QLatin1String("revert") << fileName, QStringList(), true); PerforceResponse result2 = runP4Cmd(QStringList() << QLatin1String("revert") << fileName, QStringList(), CommandToWindow|StdOutToWindow|StdErrToWindow|ErrorToWindow);
Core::IFile::ReloadBehavior tempBehavior = Core::IFile::ReloadBehavior tempBehavior =
Core::IFile::ReloadAll; Core::IFile::ReloadAll;
foreach (Core::IFile *file, files) { foreach (Core::IFile *file, files) {
@@ -485,7 +489,7 @@ void PerforcePlugin::printOpenedFileList()
Core::IEditor *e = m_coreInstance->editorManager()->currentEditor(); Core::IEditor *e = m_coreInstance->editorManager()->currentEditor();
if (e) if (e)
e->widget()->setFocus(); e->widget()->setFocus();
PerforceResponse result = runP4Cmd(QStringList() << QLatin1String("opened"), QStringList(), true); PerforceResponse result = runP4Cmd(QStringList() << QLatin1String("opened"), QStringList(), CommandToWindow|StdOutToWindow|StdErrToWindow|ErrorToWindow);
} }
#ifdef USE_P4_API #ifdef USE_P4_API
@@ -518,7 +522,8 @@ void PerforcePlugin::submit()
return; return;
} }
PerforceResponse result = runP4Cmd(QStringList()<< QLatin1String("change") << QLatin1String("-o"), QStringList(), false); PerforceResponse result = runP4Cmd(QStringList()<< QLatin1String("change") << QLatin1String("-o"), QStringList(),
CommandToWindow|StdErrToWindow|ErrorToWindow);
if (result.error) { if (result.error) {
delete m_changeTmpFile; delete m_changeTmpFile;
m_changeTmpFile = 0; m_changeTmpFile = 0;
@@ -546,7 +551,8 @@ void PerforcePlugin::submit()
foreach (const QString &f, files) foreach (const QString &f, files)
nativeFiles << QDir::toNativeSeparators(f); nativeFiles << QDir::toNativeSeparators(f);
PerforceResponse result2 = runP4Cmd(QStringList(QLatin1String("fstat")), nativeFiles, false); PerforceResponse result2 = runP4Cmd(QStringList(QLatin1String("fstat")), nativeFiles,
CommandToWindow|StdErrToWindow|ErrorToWindow);
if (result2.error) { if (result2.error) {
delete m_changeTmpFile; delete m_changeTmpFile;
m_changeTmpFile = 0; m_changeTmpFile = 0;
@@ -593,8 +599,10 @@ void PerforcePlugin::printPendingChanges()
PendingChangesDialog dia(pendingChangesData(), m_coreInstance->mainWindow()); PendingChangesDialog dia(pendingChangesData(), m_coreInstance->mainWindow());
qApp->restoreOverrideCursor(); qApp->restoreOverrideCursor();
if (dia.exec() == QDialog::Accepted) { if (dia.exec() == QDialog::Accepted) {
int i = dia.changeNumber(); const int i = dia.changeNumber();
PerforceResponse result = runP4Cmd(QStringList()<<"submit"<<"-c"<<QString::number(i), QStringList(), true); QStringList args(QLatin1String("submit"));
args << QLatin1String("-c") << QString::number(i);
runP4Cmd(args, QStringList(), CommandToWindow|StdOutToWindow|StdErrToWindow|ErrorToWindow);
} }
} }
@@ -624,7 +632,8 @@ void PerforcePlugin::annotate(const QString &fileName)
QTextCodec *codec = VCSBase::VCSBaseEditor::getCodec(m_coreInstance, fileName); QTextCodec *codec = VCSBase::VCSBaseEditor::getCodec(m_coreInstance, fileName);
QStringList args; QStringList args;
args << QLatin1String("annotate") << QLatin1String("-cqi") << fileName; args << QLatin1String("annotate") << QLatin1String("-cqi") << fileName;
const PerforceResponse result = runP4Cmd(args, QStringList(), false, true, codec); const PerforceResponse result = runP4Cmd(args, QStringList(),
CommandToWindow|StdErrToWindow|ErrorToWindow, codec);
if (!result.error) { if (!result.error) {
const QFileInfo fi(fileName); const QFileInfo fi(fileName);
showOutputInEditor(tr("p4 annotate %1").arg(fi.fileName()), result.stdOut, VCSBase::AnnotateOutput, codec); showOutputInEditor(tr("p4 annotate %1").arg(fi.fileName()), result.stdOut, VCSBase::AnnotateOutput, codec);
@@ -650,7 +659,8 @@ void PerforcePlugin::filelog(const QString &fileName)
QTextCodec *codec = VCSBase::VCSBaseEditor::getCodec(m_coreInstance, fileName); QTextCodec *codec = VCSBase::VCSBaseEditor::getCodec(m_coreInstance, fileName);
QStringList args; QStringList args;
args << QLatin1String("filelog") << QLatin1String("-li") << fileName; args << QLatin1String("filelog") << QLatin1String("-li") << fileName;
const PerforceResponse result = runP4Cmd(args, QStringList(), false, true, codec); const PerforceResponse result = runP4Cmd(args, QStringList(),
CommandToWindow|StdErrToWindow|ErrorToWindow, codec);
if (!result.error) { if (!result.error) {
const QFileInfo fi(fileName); const QFileInfo fi(fileName);
showOutputInEditor(tr("p4 filelog %1").arg(fi.fileName()), result.stdOut, VCSBase::LogOutput, codec); showOutputInEditor(tr("p4 filelog %1").arg(fi.fileName()), result.stdOut, VCSBase::LogOutput, codec);
@@ -714,18 +724,19 @@ bool PerforcePlugin::managesDirectory(const QString &directory) const
QStringList args; QStringList args;
args << QLatin1String("fstat") << QLatin1String("-m1") << p4Path; args << QLatin1String("fstat") << QLatin1String("-m1") << p4Path;
const PerforceResponse result = runP4Cmd(args, QStringList(), false, false); const PerforceResponse result = runP4Cmd(args, QStringList(), 0u);
return result.stdOut.contains("depotFile") || result.stdErr.contains("... - no such file(s)"); return result.stdOut.contains("depotFile") || result.stdErr.contains("... - no such file(s)");
} }
QString PerforcePlugin::findTopLevelForDirectory(const QString & /* dir */) const QString PerforcePlugin::findTopLevelForDirectory(const QString & /* dir */) const
{ {
// First check with p4 client -o // First check with p4 client -o
PerforceResponse result = runP4Cmd(QStringList() << QLatin1String("client") << QLatin1String("-o"), QStringList(), false, false); PerforceResponse result = runP4Cmd(QStringList() << QLatin1String("client") << QLatin1String("-o"), QStringList(), 0u);
if (result.error) if (result.error)
return QString::null; return QString::null;
QRegExp regExp(QLatin1String("(\\n|\\r\\n|\\r)Root:\\s*(.*)(\\n|\\r\\n|\\r)")); QRegExp regExp(QLatin1String("(\\n|\\r\\n|\\r)Root:\\s*(.*)(\\n|\\r\\n|\\r)"));
Q_ASSERT(regExp.isValid());
regExp.setMinimal(true); regExp.setMinimal(true);
if (regExp.indexIn(result.stdOut) != -1) { if (regExp.indexIn(result.stdOut) != -1) {
QString file = regExp.cap(2).trimmed(); QString file = regExp.cap(2).trimmed();
@@ -737,20 +748,24 @@ QString PerforcePlugin::findTopLevelForDirectory(const QString & /* dir */) cons
bool PerforcePlugin::vcsOpen(const QString &fileName) bool PerforcePlugin::vcsOpen(const QString &fileName)
{ {
PerforceResponse result = runP4Cmd(QStringList() << QLatin1String("edit") << QDir::toNativeSeparators(fileName), QStringList(), true); PerforceResponse result = runP4Cmd(QStringList() << QLatin1String("edit") << QDir::toNativeSeparators(fileName), QStringList(),
CommandToWindow|StdOutToWindow|StdErrToWindow|ErrorToWindow);
return !result.error; return !result.error;
} }
bool PerforcePlugin::vcsAdd(const QString &fileName) bool PerforcePlugin::vcsAdd(const QString &fileName)
{ {
PerforceResponse result = runP4Cmd(QStringList() << QLatin1String("add") << fileName, QStringList(), true); PerforceResponse result = runP4Cmd(QStringList() << QLatin1String("add") << fileName, QStringList(),
CommandToWindow|StdOutToWindow|StdErrToWindow|ErrorToWindow);
return !result.error; return !result.error;
} }
bool PerforcePlugin::vcsDelete(const QString &fileName) bool PerforcePlugin::vcsDelete(const QString &fileName)
{ {
PerforceResponse result = runP4Cmd(QStringList() << QLatin1String("revert") << fileName, QStringList(), true); PerforceResponse result = runP4Cmd(QStringList() << QLatin1String("revert") << fileName, QStringList(),
PerforceResponse result2 = runP4Cmd(QStringList() << QLatin1String("delete") << fileName, QStringList(), true); CommandToWindow|StdOutToWindow|StdErrToWindow|ErrorToWindow);
PerforceResponse result2 = runP4Cmd(QStringList() << QLatin1String("delete") << fileName, QStringList(),
CommandToWindow|StdOutToWindow|StdErrToWindow|ErrorToWindow);
// TODO need to carefully parse the actual messages from perforce // TODO need to carefully parse the actual messages from perforce
// or do a fstat before to decide what to do // or do a fstat before to decide what to do
@@ -763,8 +778,7 @@ bool PerforcePlugin::vcsDelete(const QString &fileName)
PerforceResponse PerforcePlugin::runP4Cmd(const QStringList &args, PerforceResponse PerforcePlugin::runP4Cmd(const QStringList &args,
const QStringList &extraArgs, const QStringList &extraArgs,
bool showStdOutInOutputWindow, unsigned logFlags,
bool showStdErrInOutputWindow,
QTextCodec *outputCodec) const QTextCodec *outputCodec) const
{ {
if (Perforce::Constants::debug) if (Perforce::Constants::debug)
@@ -797,12 +811,14 @@ PerforceResponse PerforcePlugin::runP4Cmd(const QStringList &args,
} }
actualArgs << args; actualArgs << args;
response.command = m_settings.p4Command; if (logFlags & CommandToWindow) {
response.command += blank; QString command = m_settings.p4Command;
response.command += actualArgs.join(QString(blank)); command += blank;
const QString timeStamp = QTime::currentTime().toString(QLatin1String("HH:mm")); command += actualArgs.join(QString(blank));
const QString outputText = tr("%1 Executing: %2\n").arg(timeStamp, response.command); const QString timeStamp = QTime::currentTime().toString(QLatin1String("HH:mm"));
showOutput(outputText, false); const QString outputText = tr("%1 Executing: %2\n").arg(timeStamp, command);
showOutput(outputText, false);
}
// Run, connect stderr to the output window // Run, connect stderr to the output window
Core::Utils::SynchronousProcess process; Core::Utils::SynchronousProcess process;
@@ -811,13 +827,13 @@ PerforceResponse PerforcePlugin::runP4Cmd(const QStringList &args,
process.setEnvironment(environment()); process.setEnvironment(environment());
// connect stderr to the output window if desired // connect stderr to the output window if desired
if (showStdErrInOutputWindow) { if (logFlags & StdErrToWindow) {
process.setStdErrBufferedSignalsEnabled(true); process.setStdErrBufferedSignalsEnabled(true);
connect(&process, SIGNAL(stdErrBuffered(QString,bool)), m_perforceOutputWindow, SLOT(append(QString,bool))); connect(&process, SIGNAL(stdErrBuffered(QString,bool)), m_perforceOutputWindow, SLOT(append(QString,bool)));
} }
// connect stdout to the output window if desired // connect stdout to the output window if desired
if (showStdOutInOutputWindow) { if (logFlags & StdOutToWindow) {
process.setStdOutBufferedSignalsEnabled(true); process.setStdOutBufferedSignalsEnabled(true);
connect(&process, SIGNAL(stdOutBuffered(QString,bool)), m_perforceOutputWindow, SLOT(append(QString,bool))); connect(&process, SIGNAL(stdOutBuffered(QString,bool)), m_perforceOutputWindow, SLOT(append(QString,bool)));
} }
@@ -843,13 +859,15 @@ PerforceResponse PerforcePlugin::runP4Cmd(const QStringList &args,
response.message = tr("Could not start perforce '%1'. Please check your settings in the preferences.").arg(m_settings.p4Command); response.message = tr("Could not start perforce '%1'. Please check your settings in the preferences.").arg(m_settings.p4Command);
break; break;
case Core::Utils::SynchronousProcessResponse::Hang: case Core::Utils::SynchronousProcessResponse::Hang:
response.message = tr("Subversion did not respond within timeout limit (%1 ms).").arg(p4Timeout ); response.message = tr("Perforce did not respond within timeout limit (%1 ms).").arg(p4Timeout );
break; break;
} }
if (response.error) if (response.error) {
m_perforceOutputWindow->append(response.message, true); if (Perforce::Constants::debug)
qDebug() << response.message;
if (logFlags & ErrorToWindow)
m_perforceOutputWindow->append(response.message, true);
}
return response; return response;
} }
@@ -919,7 +937,7 @@ void PerforcePlugin::p4Diff(const QStringList &files, QString diffname)
} }
} }
const PerforceResponse result = runP4Cmd(QStringList() << QLatin1String("diff") << QLatin1String("-du"), files, false, codec); const PerforceResponse result = runP4Cmd(QStringList() << QLatin1String("diff") << QLatin1String("-du"), files, CommandToWindow|StdErrToWindow|ErrorToWindow, codec);
if (result.error) if (result.error)
return; return;
@@ -944,7 +962,7 @@ void PerforcePlugin::describe(const QString & source, const QString &n)
QTextCodec *codec = source.isEmpty() ? static_cast<QTextCodec *>(0) : VCSBase::VCSBaseEditor::getCodec(m_coreInstance, source); QTextCodec *codec = source.isEmpty() ? static_cast<QTextCodec *>(0) : VCSBase::VCSBaseEditor::getCodec(m_coreInstance, source);
QStringList args; QStringList args;
args << QLatin1String("describe") << QLatin1String("-du") << n; args << QLatin1String("describe") << QLatin1String("-du") << n;
const PerforceResponse result = runP4Cmd(args, QStringList(), codec); const PerforceResponse result = runP4Cmd(args, QStringList(), CommandToWindow|StdErrToWindow|ErrorToWindow, codec);
if (!result.error) if (!result.error)
showOutputInEditor(tr("p4 describe %1").arg(n), result.stdOut, VCSBase::DiffOutput, codec); showOutputInEditor(tr("p4 describe %1").arg(n), result.stdOut, VCSBase::DiffOutput, codec);
} }

View File

@@ -86,7 +86,6 @@ private:
struct PerforceResponse struct PerforceResponse
{ {
bool error; bool error;
QString command;
QString stdOut; QString stdOut;
QString stdErr; QString stdErr;
QString message; QString message;
@@ -161,12 +160,15 @@ private:
Core::IEditor *showOutputInEditor(const QString& title, const QString output, Core::IEditor *showOutputInEditor(const QString& title, const QString output,
int editorType, int editorType,
QTextCodec *codec = 0); QTextCodec *codec = 0);
// Verbosity flags for runP4Cmd.
enum RunLogFlags { CommandToWindow = 0x1, StdOutToWindow = 0x2, StdErrToWindow = 0x4, ErrorToWindow = 0x8 };
// args are passed as command line arguments // args are passed as command line arguments
// extra args via a tempfile and the option -x "temp-filename" // extra args via a tempfile and the option -x "temp-filename"
PerforceResponse runP4Cmd(const QStringList &args, PerforceResponse runP4Cmd(const QStringList &args,
const QStringList &extraArgs = QStringList(), const QStringList &extraArgs = QStringList(),
bool showStdOutInOutputWindow = false, unsigned logFlags = CommandToWindow|StdErrToWindow|ErrorToWindow,
bool showStdErrInOutputWindow = true,
QTextCodec *outputCodec = 0) const; QTextCodec *outputCodec = 0) const;
void openFiles(const QStringList &files); void openFiles(const QStringList &files);

View File

@@ -38,10 +38,41 @@ namespace Perforce {
namespace Internal { namespace Internal {
PerforceVersionControl::PerforceVersionControl(PerforcePlugin *plugin) : PerforceVersionControl::PerforceVersionControl(PerforcePlugin *plugin) :
m_enabled(true),
m_plugin(plugin) m_plugin(plugin)
{ {
} }
QString PerforceVersionControl::name() const
{
return QLatin1String("perforce");
}
bool PerforceVersionControl::isEnabled() const
{
return m_enabled;
}
void PerforceVersionControl::setEnabled(bool enabled)
{
if (m_enabled != enabled) {
m_enabled = enabled;
emit enabledChanged(m_enabled);
}
}
bool PerforceVersionControl::supportsOperation(Operation operation) const
{
bool rc = true;
switch (operation) {
case AddOperation:
case DeleteOperation:
case OpenOperation:
break;
}
return rc;
}
bool PerforceVersionControl::vcsOpen(const QString &fileName) bool PerforceVersionControl::vcsOpen(const QString &fileName)
{ {
return m_plugin->vcsOpen(fileName); return m_plugin->vcsOpen(fileName);

View File

@@ -46,13 +46,25 @@ class PerforceVersionControl : public Core::IVersionControl
Q_OBJECT Q_OBJECT
public: public:
explicit PerforceVersionControl(PerforcePlugin *plugin); explicit PerforceVersionControl(PerforcePlugin *plugin);
virtual QString name() const;
virtual bool isEnabled() const;
virtual void setEnabled(bool enabled);
bool managesDirectory(const QString &directory) const; bool managesDirectory(const QString &directory) const;
virtual QString findTopLevelForDirectory(const QString &directory) const; virtual QString findTopLevelForDirectory(const QString &directory) const;
virtual bool supportsOperation(Operation operation) const;
virtual bool vcsOpen(const QString &fileName); virtual bool vcsOpen(const QString &fileName);
virtual bool vcsAdd(const QString &fileName); virtual bool vcsAdd(const QString &fileName);
virtual bool vcsDelete(const QString &filename); virtual bool vcsDelete(const QString &filename);
signals:
void enabledChanged(bool);
private: private:
bool m_enabled;
PerforcePlugin *m_plugin; PerforcePlugin *m_plugin;
}; };

View File

@@ -39,6 +39,7 @@
#include <QtCore/QEventLoop> #include <QtCore/QEventLoop>
#include <QtCore/QDebug> #include <QtCore/QDebug>
#include <QtCore/QTimer> #include <QtCore/QTimer>
#include <QtGui/QTextDocument>
using namespace ProjectExplorer; using namespace ProjectExplorer;
@@ -165,7 +166,7 @@ void AbstractProcessStep::run(QFutureInterface<bool> & fi)
void AbstractProcessStep::processStarted() void AbstractProcessStep::processStarted()
{ {
emit addToOutputWindow(tr("<font color=\"#0000ff\">Starting: %1 %2</font>\n").arg(m_command, m_arguments.join(" "))); emit addToOutputWindow(tr("<font color=\"#0000ff\">Starting: %1 %2</font>\n").arg(m_command, Qt::escape(m_arguments.join(" "))));
} }
bool AbstractProcessStep::processFinished(int exitCode, QProcess::ExitStatus status) bool AbstractProcessStep::processFinished(int exitCode, QProcess::ExitStatus status)
@@ -196,7 +197,7 @@ void AbstractProcessStep::processReadyReadStdOutput()
void AbstractProcessStep::stdOut(const QString &line) void AbstractProcessStep::stdOut(const QString &line)
{ {
emit addToOutputWindow(line); emit addToOutputWindow(Qt::escape(line));
} }
void AbstractProcessStep::processReadyReadStdError() void AbstractProcessStep::processReadyReadStdError()
@@ -211,7 +212,7 @@ void AbstractProcessStep::processReadyReadStdError()
void AbstractProcessStep::stdError(const QString &line) void AbstractProcessStep::stdError(const QString &line)
{ {
emit addToOutputWindow(QLatin1String("<font color=\"#ff0000\">") + line + QLatin1String("</font>")); emit addToOutputWindow(QLatin1String("<font color=\"#ff0000\">") + Qt::escape(line) + QLatin1String("</font>"));
} }
void AbstractProcessStep::checkForCancel() void AbstractProcessStep::checkForCancel()

View File

@@ -108,12 +108,14 @@ QWidget *AllProjectsFind::createConfigWidget()
gridLayout->setMargin(0); gridLayout->setMargin(0);
m_configWidget->setLayout(gridLayout); m_configWidget->setLayout(gridLayout);
gridLayout->addWidget(createRegExpWidget(), 0, 1); gridLayout->addWidget(createRegExpWidget(), 0, 1);
QLabel * const filePatternLabel = new QLabel(tr("File pattern:")); QLabel * const filePatternLabel = new QLabel(tr("File &pattern:"));
filePatternLabel->setMinimumWidth(80); filePatternLabel->setMinimumWidth(80);
filePatternLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); filePatternLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
filePatternLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter); filePatternLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
QWidget *patternWidget = createPatternWidget();
filePatternLabel->setBuddy(patternWidget);
gridLayout->addWidget(filePatternLabel, 1, 0, Qt::AlignRight); gridLayout->addWidget(filePatternLabel, 1, 0, Qt::AlignRight);
gridLayout->addWidget(createPatternWidget(), 1, 1); gridLayout->addWidget(patternWidget, 1, 1);
m_configWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); m_configWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
} }
return m_configWidget; return m_configWidget;

View File

@@ -38,6 +38,7 @@
#include <projectexplorer/projectexplorerconstants.h> #include <projectexplorer/projectexplorerconstants.h>
#include <QtGui/QLabel> #include <QtGui/QLabel>
#include <QtGui/QTextDocument>
#include <QDebug> #include <QDebug>
using namespace ProjectExplorer; using namespace ProjectExplorer;
@@ -160,7 +161,7 @@ void ApplicationRunControl::slotError(const QString & err)
void ApplicationRunControl::slotAddToOutputWindow(const QString &line) void ApplicationRunControl::slotAddToOutputWindow(const QString &line)
{ {
emit addToOutputWindow(this, line); emit addToOutputWindow(this, Qt::escape(line));
} }
void ApplicationRunControl::processExited(int exitCode) void ApplicationRunControl::processExited(int exitCode)

View File

@@ -104,12 +104,14 @@ QWidget *CurrentProjectFind::createConfigWidget()
layout->setMargin(0); layout->setMargin(0);
m_configWidget->setLayout(layout); m_configWidget->setLayout(layout);
layout->addWidget(createRegExpWidget(), 0, 1); layout->addWidget(createRegExpWidget(), 0, 1);
QLabel * const filePatternLabel = new QLabel(tr("File pattern:")); QLabel * const filePatternLabel = new QLabel(tr("File &pattern:"));
filePatternLabel->setMinimumWidth(80); filePatternLabel->setMinimumWidth(80);
filePatternLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); filePatternLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
filePatternLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter); filePatternLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
QWidget *patternWidget = createPatternWidget();
filePatternLabel->setBuddy(patternWidget);
layout->addWidget(filePatternLabel, 1, 0, Qt::AlignRight); layout->addWidget(filePatternLabel, 1, 0, Qt::AlignRight);
layout->addWidget(createPatternWidget(), 1, 1); layout->addWidget(patternWidget, 1, 1);
m_configWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); m_configWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
} }
return m_configWidget; return m_configWidget;

View File

@@ -76,6 +76,7 @@
#include <coreplugin/welcomemode.h> #include <coreplugin/welcomemode.h>
#include <coreplugin/vcsmanager.h> #include <coreplugin/vcsmanager.h>
#include <coreplugin/iversioncontrol.h> #include <coreplugin/iversioncontrol.h>
#include <coreplugin/vcsmanager.h>
#include <utils/listutils.h> #include <utils/listutils.h>
#include <QtCore/qplugin.h> #include <QtCore/qplugin.h>
@@ -685,28 +686,19 @@ void ProjectExplorerPlugin::loadAction()
updateActions(); updateActions();
} }
bool ProjectExplorerPlugin::saveAction(Project *pro) void ProjectExplorerPlugin::unloadProject()
{ {
if (debug) if (debug)
qDebug() << "ProjectExplorerPlugin::saveAction"; qDebug() << "ProjectExplorerPlugin::unloadProject";
if (!pro) Core::IFile *fi = m_currentProject->file();
pro = m_currentProject;
Q_ASSERT(pro);
Core::IFile *fi = pro->file();
if (!fi) // TODO Why saving the session here????
fi = m_session->file();
if (!fi || fi->fileName().isEmpty()) //nothing to save? if (!fi || fi->fileName().isEmpty()) //nothing to save?
return false; return;
QList<Core::IFile*> filesToSave; QList<Core::IFile*> filesToSave;
filesToSave << fi; filesToSave << fi;
if (pro) filesToSave << m_currentProject->dependencies();
filesToSave << pro->dependencies();
// check the number of modified files // check the number of modified files
int readonlycount = 0; int readonlycount = 0;
@@ -721,20 +713,10 @@ bool ProjectExplorerPlugin::saveAction(Project *pro)
else else
success = m_core->fileManager()->saveModifiedFilesSilently(filesToSave).isEmpty(); success = m_core->fileManager()->saveModifiedFilesSilently(filesToSave).isEmpty();
if (success) if (!success)
addToRecentProjects(fi->fileName());
updateActions();
return success;
}
void ProjectExplorerPlugin::unloadProject()
{
if (debug)
qDebug() << "ProjectExplorerPlugin::unloadProject";
if (!saveAction(m_currentProject))
return; return;
addToRecentProjects(fi->fileName());
m_session->removeProject(m_currentProject); m_session->removeProject(m_currentProject);
updateActions(); updateActions();
} }
@@ -1172,6 +1154,13 @@ void ProjectExplorerPlugin::setCurrent(Project *project, QString filePath, Node
if (projectChanged) { if (projectChanged) {
if (debug) if (debug)
qDebug() << "ProjectExplorer - currentProjectChanged(" << (project ? project->name() : "0") << ")"; qDebug() << "ProjectExplorer - currentProjectChanged(" << (project ? project->name() : "0") << ")";
// Enable the right VCS
if (const Core::IFile *projectFile = project ? project->file() : static_cast<const Core::IFile *>(0)) {
m_core->vcsManager()->setVCSEnabled(QFileInfo(projectFile->fileName()).absolutePath());
} else {
m_core->vcsManager()->setAllVCSEnabled();
}
emit currentProjectChanged(project); emit currentProjectChanged(project);
updateActions(); updateActions();
} }
@@ -1584,27 +1573,28 @@ void ProjectExplorerPlugin::addExistingFiles()
fileNames.removeOne(file); fileNames.removeOne(file);
} }
if (Core::IVersionControl *vcManager = m_core->vcsManager()->findVersionControlForDirectory(dir)) { if (Core::IVersionControl *vcManager = m_core->vcsManager()->findVersionControlForDirectory(dir))
const QString files = fileNames.join("\n"); if (vcManager->supportsOperation(Core::IVersionControl::AddOperation)) {
QMessageBox::StandardButton button = const QString files = fileNames.join(QString(QLatin1Char('\n')));
QMessageBox::StandardButton button =
QMessageBox::question(m_core->mainWindow(), tr("Add to Version Control"), QMessageBox::question(m_core->mainWindow(), tr("Add to Version Control"),
tr("Add files\n%1\nto version control?").arg(files), tr("Add files\n%1\nto version control (%2)?").arg(files, vcManager->name()),
QMessageBox::Yes | QMessageBox::No); QMessageBox::Yes | QMessageBox::No);
if (button == QMessageBox::Yes) { if (button == QMessageBox::Yes) {
QStringList notAddedToVc; QStringList notAddedToVc;
foreach (const QString file, fileNames) { foreach (const QString &file, fileNames) {
if (!vcManager->vcsAdd(file)) if (!vcManager->vcsAdd(file))
notAddedToVc << file; notAddedToVc << file;
} }
if (!notAddedToVc.isEmpty()) { if (!notAddedToVc.isEmpty()) {
const QString message = tr("Could not add following files to version control\n"); const QString message = tr("Could not add following files to version control (%1)\n").arg(vcManager->name());
const QString filesNotAdded = notAddedToVc.join("\n"); const QString filesNotAdded = notAddedToVc.join(QString(QLatin1Char('\n')));
QMessageBox::warning(m_core->mainWindow(), tr("Add files to version control failed"), QMessageBox::warning(m_core->mainWindow(), tr("Add files to version control failed"),
message + filesNotAdded); message + filesNotAdded);
}
} }
} }
}
} }
void ProjectExplorerPlugin::openFile() void ProjectExplorerPlugin::openFile()

View File

@@ -139,7 +139,6 @@ private slots:
void cancelBuild(); void cancelBuild();
void debugProject(); void debugProject();
void editDependencies(); void editDependencies();
bool saveAction(ProjectExplorer::Project *pro = 0);
void loadAction(); void loadAction();
void unloadProject(); void unloadProject();
void clearSession(); void clearSession();

View File

@@ -118,7 +118,11 @@ void ProjectFileWizardExtension::firstExtensionPageShown(const QList<Core::Gener
m_context->versionControl = m_core->vcsManager()->findVersionControlForDirectory(directory); m_context->versionControl = m_core->vcsManager()->findVersionControlForDirectory(directory);
m_context->page->setFilesDisplay(fileNames); m_context->page->setFilesDisplay(fileNames);
m_context->page->setAddToVersionControlEnabled(m_context->versionControl != 0);
const bool canAddToVCS = m_context->versionControl && m_context->versionControl->supportsOperation(Core::IVersionControl::AddOperation);
if (m_context->versionControl)
m_context->page->setVCSDisplay(m_context->versionControl->name());
m_context->page->setAddToVersionControlEnabled(canAddToVCS);
} }
static ProjectNode *currentProject() static ProjectNode *currentProject()

View File

@@ -108,6 +108,11 @@ void ProjectWizardPage::changeEvent(QEvent *e)
} }
} }
void ProjectWizardPage::setVCSDisplay(const QString &vcsName)
{
m_ui->addToVersionControlLabel->setText(tr("Add to &VCS (%1)").arg(vcsName));
}
void ProjectWizardPage::setFilesDisplay(const QStringList &files) void ProjectWizardPage::setFilesDisplay(const QStringList &files)
{ {
QString fileMessage; { QString fileMessage; {

View File

@@ -69,6 +69,7 @@ public:
bool addToVersionControl() const; bool addToVersionControl() const;
void setAddToVersionControlEnabled(bool b); void setAddToVersionControlEnabled(bool b);
void setVCSDisplay(const QString &vcsName);
void setFilesDisplay(const QStringList &files); void setFilesDisplay(const QStringList &files);
protected: protected:

View File

@@ -939,6 +939,7 @@ void SessionManager::removeProjects(QList<Project *> remove)
// Delete projects // Delete projects
foreach (Project *pro, remove) { foreach (Project *pro, remove) {
pro->saveSettings();
m_file->m_projects.removeOne(pro); m_file->m_projects.removeOne(pro);
if (pro == m_file->m_startupProject) if (pro == m_file->m_startupProject)

View File

@@ -37,6 +37,7 @@
#include <coreplugin/actionmanager/actionmanager.h> #include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/editormanager/editormanager.h> #include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/coreconstants.h> #include <coreplugin/coreconstants.h>
#include <coreplugin/uniqueidmanager.h>
#include <texteditor/itexteditor.h> #include <texteditor/itexteditor.h>
#include <texteditor/basetexteditor.h> #include <texteditor/basetexteditor.h>
#include <projectexplorerconstants.h> #include <projectexplorerconstants.h>
@@ -47,6 +48,8 @@
#include <QtGui/QListView> #include <QtGui/QListView>
#include <QtGui/QPainter> #include <QtGui/QPainter>
#include <QtCore/QAbstractItemModel> #include <QtCore/QAbstractItemModel>
#include <QtGui/QApplication>
#include <QtGui/QClipboard>
#include <QtGui/QFont> #include <QtGui/QFont>
#include <QtGui/QFontMetrics> #include <QtGui/QFontMetrics>
#include <QtGui/QTextLayout> #include <QtGui/QTextLayout>
@@ -81,7 +84,7 @@ public:
QModelIndex firstError() const; QModelIndex firstError() const;
void setFileNotFound(const QModelIndex &index, bool b); void setFileNotFound(const QModelIndex &index, bool b);
enum Roles { File = Qt::UserRole, Line, Description, FileNotFound }; enum Roles { File = Qt::UserRole, Line, Description, FileNotFound, Type };
private: private:
QList<TaskItem> m_items; QList<TaskItem> m_items;
int m_maxSizeOfFileName; int m_maxSizeOfFileName;
@@ -196,6 +199,8 @@ QVariant TaskModel::data(const QModelIndex &index, int role) const
return m_items.at(index.row()).description; return m_items.at(index.row()).description;
else if (role == TaskModel::FileNotFound) else if (role == TaskModel::FileNotFound)
return m_items.at(index.row()).fileNotFound; return m_items.at(index.row()).fileNotFound;
else if (role == TaskModel::Type)
return (int)m_items.at(index.row()).type;
else if (role == Qt::DecorationRole) { else if (role == Qt::DecorationRole) {
if (m_items.at(index.row()).type == ProjectExplorer::BuildParserInterface::Error) { if (m_items.at(index.row()).type == ProjectExplorer::BuildParserInterface::Error) {
return QIcon(":/projectexplorer/images/compile_error.png"); return QIcon(":/projectexplorer/images/compile_error.png");
@@ -257,6 +262,15 @@ TaskWindow::TaskWindow()
TaskDelegate *tld = new TaskDelegate(this); TaskDelegate *tld = new TaskDelegate(this);
m_listview->setItemDelegate(tld); m_listview->setItemDelegate(tld);
m_listview->setWindowIcon(QIcon(":/qt4projectmanager/images/window.png")); m_listview->setWindowIcon(QIcon(":/qt4projectmanager/images/window.png"));
m_listview->setContextMenuPolicy(Qt::ActionsContextMenu);
m_taskWindowContext = new TaskWindowContext(m_listview);
m_coreIFace->addContextObject(m_taskWindowContext);
m_copyAction = new QAction(QIcon(Core::Constants::ICON_COPY), tr("&Copy"), this);
m_coreIFace->actionManager()->
registerAction(m_copyAction, Core::Constants::COPY, m_taskWindowContext->context());
m_listview->addAction(m_copyAction);
connect(m_listview->selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), connect(m_listview->selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)),
tld, SLOT(currentChanged(const QModelIndex &, const QModelIndex &))); tld, SLOT(currentChanged(const QModelIndex &, const QModelIndex &)));
@@ -266,12 +280,15 @@ TaskWindow::TaskWindow()
connect(m_listview, SIGNAL(clicked(const QModelIndex &)), connect(m_listview, SIGNAL(clicked(const QModelIndex &)),
this, SLOT(showTaskInFile(const QModelIndex &))); this, SLOT(showTaskInFile(const QModelIndex &)));
connect(m_copyAction, SIGNAL(triggered()), SLOT(copy()));
m_errorCount = 0; m_errorCount = 0;
m_currentTask = -1; m_currentTask = -1;
} }
TaskWindow::~TaskWindow() TaskWindow::~TaskWindow()
{ {
m_coreIFace->removeContextObject(m_taskWindowContext);
delete m_listview; delete m_listview;
delete m_model; delete m_model;
} }
@@ -291,6 +308,7 @@ void TaskWindow::clearContents()
m_errorCount = 0; m_errorCount = 0;
m_currentTask = -1; m_currentTask = -1;
m_model->clear(); m_model->clear();
m_copyAction->setEnabled(false);
emit tasksChanged(); emit tasksChanged();
} }
@@ -305,6 +323,7 @@ void TaskWindow::addItem(ProjectExplorer::BuildParserInterface::PatternType type
m_model->addTask(type, description, file, line); m_model->addTask(type, description, file, line);
if (type == ProjectExplorer::BuildParserInterface::Error) if (type == ProjectExplorer::BuildParserInterface::Error)
++m_errorCount; ++m_errorCount;
m_copyAction->setEnabled(true);
emit tasksChanged(); emit tasksChanged();
} }
@@ -327,6 +346,25 @@ void TaskWindow::showTaskInFile(const QModelIndex &index)
m_listview->selectionModel()->select(index, QItemSelectionModel::ClearAndSelect); m_listview->selectionModel()->select(index, QItemSelectionModel::ClearAndSelect);
} }
void TaskWindow::copy()
{
QModelIndex index = m_listview->selectionModel()->currentIndex();
QString file = index.data(TaskModel::File).toString();
QString line = index.data(TaskModel::Line).toString();
QString description = index.data(TaskModel::Description).toString();
QString type;
switch (index.data(TaskModel::Type).toInt()) {
case ProjectExplorer::BuildParserInterface::Error:
type = "error: ";
break;
case ProjectExplorer::BuildParserInterface::Warning:
type = "warning: ";
break;
}
QApplication::clipboard()->setText(file + ':' + line + ": " + type + description);
}
int TaskWindow::numberOfTasks() const int TaskWindow::numberOfTasks() const
{ {
return m_model->rowCount(QModelIndex()); return m_model->rowCount(QModelIndex());
@@ -483,7 +521,7 @@ void TaskDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
painter->fillRect(width, 2 + opt.rect.top(), gwidth, fm.height() + 1, lg); painter->fillRect(width, 2 + opt.rect.top(), gwidth, fm.height() + 1, lg);
} }
} else { } else {
// Descritption // Description
QString description = index.data(TaskModel::Description).toString(); QString description = index.data(TaskModel::Description).toString();
// Layout the description // Layout the description
int leading = fm.leading(); int leading = fm.leading();
@@ -536,3 +574,21 @@ void TaskDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
painter->drawLine(0, opt.rect.bottom(), opt.rect.right(), opt.rect.bottom()); painter->drawLine(0, opt.rect.bottom(), opt.rect.right(), opt.rect.bottom());
painter->restore(); painter->restore();
} }
TaskWindowContext::TaskWindowContext(QWidget *widget)
: m_taskList(widget)
{
Core::ICore *core = ExtensionSystem::PluginManager::instance()->getObject<Core::ICore>();
m_context << core->uniqueIDManager()->uniqueIdentifier(Core::Constants::C_PROBLEM_PANE);
}
QList<int> TaskWindowContext::context() const
{
return m_context;
}
QWidget *TaskWindowContext::widget()
{
return m_taskList;
}

View File

@@ -37,6 +37,7 @@
#include "buildparserinterface.h" #include "buildparserinterface.h"
#include <coreplugin/ioutputpane.h> #include <coreplugin/ioutputpane.h>
#include <coreplugin/icontext.h>
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
#include <QtGui/QTreeWidget> #include <QtGui/QTreeWidget>
@@ -49,6 +50,7 @@ namespace Internal {
class TaskModel; class TaskModel;
class TaskView; class TaskView;
class TaskWindowContext;
class TaskWindow : public Core::IOutputPane class TaskWindow : public Core::IOutputPane
{ {
@@ -82,6 +84,7 @@ signals:
private slots: private slots:
void showTaskInFile(const QModelIndex &index); void showTaskInFile(const QModelIndex &index);
void copy();
private: private:
int sizeHintForColumn(int column) const; int sizeHintForColumn(int column) const;
@@ -92,6 +95,8 @@ private:
TaskModel *m_model; TaskModel *m_model;
TaskView *m_listview; TaskView *m_listview;
TaskWindowContext *m_taskWindowContext;
QAction *m_copyAction;
}; };
class TaskView : public QListView class TaskView : public QListView
@@ -122,6 +127,17 @@ private:
void generateGradientPixmap(int width, int height, QColor color, bool selected) const; void generateGradientPixmap(int width, int height, QColor color, bool selected) const;
}; };
class TaskWindowContext : public Core::IContext
{
public:
TaskWindowContext(QWidget *widget);
virtual QList<int> context() const;
virtual QWidget *widget();
private:
QWidget *m_taskList;
QList<int> m_context;
};
} //namespace Internal } //namespace Internal
} //namespace ProjectExplorer } //namespace ProjectExplorer

View File

@@ -40,13 +40,13 @@ using namespace Qt4ProjectManager;
GccParser::GccParser() GccParser::GccParser()
{ {
m_regExp.setPattern("^([^\\(\\)]+[^\\d]):(\\d+):(\\d+:)*(\\s(warning|error):)?(.+)$"); m_regExp.setPattern("^([^\\(\\)]+[^\\d]):(\\d+):(\\d+:)*(\\s(warning|error):)?\\s(.+)$");
m_regExp.setMinimal(true); m_regExp.setMinimal(true);
m_regExpIncluded.setPattern("^.*from\\s([^:]+):(\\d+)(,|:)$"); m_regExpIncluded.setPattern("^.*from\\s([^:]+):(\\d+)(,|:)$");
m_regExpIncluded.setMinimal(true); m_regExpIncluded.setMinimal(true);
m_regExpLinker.setPattern("^(\\S+)\\(\\S+\\):(.+)$"); m_regExpLinker.setPattern("^(\\S+)\\(\\S+\\):\\s(.+)$");
m_regExpLinker.setMinimal(true); m_regExpLinker.setMinimal(true);
//make[4]: Entering directory `/home/kkoehne/dev/ide-explorer/src/plugins/qtscripteditor' //make[4]: Entering directory `/home/kkoehne/dev/ide-explorer/src/plugins/qtscripteditor'

View File

@@ -159,7 +159,6 @@ bool QMakeStep::init(const QString &name)
setCommand(name, program); setCommand(name, program);
setArguments(name, args); setArguments(name, args);
setEnvironment(name, environment); setEnvironment(name, environment);
setWorkingDirectory(name, workingDirectory);
return AbstractProcessStep::init(name); return AbstractProcessStep::init(name);
} }

View File

@@ -84,7 +84,7 @@ Qt4PriFileNode::Qt4PriFileNode(Qt4Project *project,
: ProjectNode(filePath), : ProjectNode(filePath),
m_core(project->qt4ProjectManager()->core()), m_core(project->qt4ProjectManager()->core()),
m_project(project), m_project(project),
m_projectFilePath(filePath), m_projectFilePath(QDir::fromNativeSeparators(filePath)),
m_projectDir(QFileInfo(filePath).absolutePath()), m_projectDir(QFileInfo(filePath).absolutePath()),
m_includeFile(0), m_includeFile(0),
m_saveTimer(new QTimer(this)), m_saveTimer(new QTimer(this)),
@@ -265,46 +265,18 @@ bool Qt4PriFileNode::changeIncludes(ProFile *includeFile, const QStringList &pro
return false; return false;
} }
namespace {
enum ReadOnlyAction { RO_Cancel, RO_OpenSCC, RO_MakeWriteable };
}
static ReadOnlyAction promptReadOnly(const QString &fileName, bool hasSCC, QWidget *parent)
{
QMessageBox msgBox(QMessageBox::Question, QObject::tr("File is Read Only"),
QObject::tr("The file %1 is read only.").arg(fileName),
QMessageBox::Cancel, parent);
QPushButton *sccButton = 0;
if (hasSCC)
sccButton = msgBox.addButton(QObject::tr("Open with SCC"), QMessageBox::AcceptRole);
QPushButton *makeWritableButton = msgBox.addButton(QObject::tr("Make writable"), QMessageBox::AcceptRole);
if (hasSCC)
msgBox.setDefaultButton(sccButton);
else
msgBox.setDefaultButton(makeWritableButton);
msgBox.exec();
QAbstractButton *clickedButton = msgBox.clickedButton();
if (clickedButton == sccButton)
return RO_OpenSCC;
if (clickedButton == makeWritableButton)
return RO_MakeWriteable;
return RO_Cancel;
}
bool Qt4PriFileNode::priFileWritable(const QString &path) bool Qt4PriFileNode::priFileWritable(const QString &path)
{ {
const QString dir = QFileInfo(path).dir().path(); const QString dir = QFileInfo(path).dir().path();
Core::IVersionControl *versionControl = m_core->vcsManager()->findVersionControlForDirectory(dir); Core::IVersionControl *versionControl = m_core->vcsManager()->findVersionControlForDirectory(dir);
switch (promptReadOnly(path, versionControl != 0, m_core->mainWindow())) { switch (Core::EditorManager::promptReadOnlyFile(path, versionControl, m_core->mainWindow(), false)) {
case RO_OpenSCC: case Core::EditorManager::RO_OpenVCS:
if (!versionControl->vcsOpen(path)) { if (!versionControl->vcsOpen(path)) {
QMessageBox::warning(m_core->mainWindow(), tr("Failed!"), tr("Could not open the file for edit with SCC.")); QMessageBox::warning(m_core->mainWindow(), tr("Failed!"), tr("Could not open the file for edit with SCC."));
return false; return false;
} }
break; break;
case RO_MakeWriteable: { case Core::EditorManager::RO_MakeWriteable: {
const bool permsOk = QFile::setPermissions(path, QFile::permissions(path) | QFile::WriteUser); const bool permsOk = QFile::setPermissions(path, QFile::permissions(path) | QFile::WriteUser);
if (!permsOk) { if (!permsOk) {
QMessageBox::warning(m_core->mainWindow(), tr("Failed!"), tr("Could not set permissions to writable.")); QMessageBox::warning(m_core->mainWindow(), tr("Failed!"), tr("Could not set permissions to writable."));
@@ -312,10 +284,10 @@ bool Qt4PriFileNode::priFileWritable(const QString &path)
} }
break; break;
} }
case RO_Cancel: { case Core::EditorManager::RO_SaveAs:
case Core::EditorManager::RO_Cancel:
return false; return false;
} }
}
return true; return true;
} }
@@ -457,7 +429,8 @@ void Qt4PriFileNode::save()
if (modifiedFileHandle) if (modifiedFileHandle)
fileManager->blockFileChange(modifiedFileHandle); fileManager->blockFileChange(modifiedFileHandle);
ProWriter pw; ProWriter pw;
bool ok = pw.write(m_includeFile, m_includeFile->fileName()); const bool ok = pw.write(m_includeFile, m_includeFile->fileName());
Q_UNUSED(ok)
m_includeFile->setModified(false); m_includeFile->setModified(false);
m_project->qt4ProjectManager()->notifyChanged(m_includeFile->fileName()); m_project->qt4ProjectManager()->notifyChanged(m_includeFile->fileName());
if (modifiedFileHandle) if (modifiedFileHandle)

View File

@@ -35,6 +35,7 @@
#include "consoleappwizard.h" #include "consoleappwizard.h"
#include "modulespage.h" #include "modulespage.h"
#include <QtCore/QDebug>
#include <utils/projectintropage.h> #include <utils/projectintropage.h>
namespace Qt4ProjectManager { namespace Qt4ProjectManager {
@@ -51,13 +52,11 @@ ConsoleAppWizardDialog::ConsoleAppWizardDialog(const QString &templateName,
setWindowIcon(icon); setWindowIcon(icon);
setWindowTitle(templateName); setWindowTitle(templateName);
Core::BaseFileWizard::setupWizard(this); Core::BaseFileWizard::setupWizard(this);
setOptions(QWizard::IndependentPages | QWizard::HaveNextButtonOnLastPage);
m_introPage->setDescription(tr("This wizard generates a Qt4 console application " m_introPage->setDescription(tr("This wizard generates a Qt4 console application "
"project. The application derives from QCoreApplication and does not " "project. The application derives from QCoreApplication and does not "
"present a GUI. You can press 'Finish' at any point in time.")); "present a GUI. You can press 'Finish' at any point in time."));
m_introPage->setFinalPage(true);
addPage(m_introPage); addPage(m_introPage);
m_modulesPage->setModuleSelected(QLatin1String("core")); m_modulesPage->setModuleSelected(QLatin1String("core"));

View File

@@ -63,7 +63,6 @@ GuiAppWizardDialog::GuiAppWizardDialog(const QString &templateName,
setWindowIcon(icon); setWindowIcon(icon);
setWindowTitle(templateName); setWindowTitle(templateName);
Core::BaseFileWizard::setupWizard(this); Core::BaseFileWizard::setupWizard(this);
setOptions(QWizard::IndependentPages);
m_introPage->setDescription(tr("This wizard generates a Qt4 GUI application " m_introPage->setDescription(tr("This wizard generates a Qt4 GUI application "
"project. The application derives by default from QApplication " "project. The application derives by default from QApplication "

View File

@@ -38,10 +38,43 @@ using namespace Subversion;
using namespace Subversion::Internal; using namespace Subversion::Internal;
SubversionControl::SubversionControl(SubversionPlugin *plugin) : SubversionControl::SubversionControl(SubversionPlugin *plugin) :
m_enabled(true),
m_plugin(plugin) m_plugin(plugin)
{ {
} }
QString SubversionControl::name() const
{
return QLatin1String("subversion");
}
bool SubversionControl::isEnabled() const
{
return m_enabled;
}
void SubversionControl::setEnabled(bool enabled)
{
if (m_enabled != enabled) {
m_enabled = enabled;
emit enabledChanged(m_enabled);
}
}
bool SubversionControl::supportsOperation(Operation operation) const
{
bool rc = true;
switch (operation) {
case AddOperation:
case DeleteOperation:
break;
case OpenOperation:
rc = false;
break;
}
return rc;
}
bool SubversionControl::vcsOpen(const QString & /* fileName */) bool SubversionControl::vcsOpen(const QString & /* fileName */)
{ {
// Open for edit: N/A // Open for edit: N/A

View File

@@ -47,13 +47,24 @@ class SubversionControl : public Core::IVersionControl
Q_OBJECT Q_OBJECT
public: public:
explicit SubversionControl(SubversionPlugin *plugin); explicit SubversionControl(SubversionPlugin *plugin);
virtual QString name() const;
virtual bool isEnabled() const;
virtual void setEnabled(bool enabled);
virtual bool managesDirectory(const QString &directory) const; virtual bool managesDirectory(const QString &directory) const;
virtual QString findTopLevelForDirectory(const QString &directory) const; virtual QString findTopLevelForDirectory(const QString &directory) const;
virtual bool supportsOperation(Operation operation) const;
virtual bool vcsOpen(const QString &fileName); virtual bool vcsOpen(const QString &fileName);
virtual bool vcsAdd(const QString &fileName); virtual bool vcsAdd(const QString &fileName);
virtual bool vcsDelete(const QString &filename); virtual bool vcsDelete(const QString &filename);
signals:
void enabledChanged(bool);
private: private:
bool m_enabled;
SubversionPlugin *m_plugin; SubversionPlugin *m_plugin;
}; };

View File

@@ -276,6 +276,10 @@ bool SubversionPlugin::initialize(const QStringList & /*arguments*/, QString *er
ami->createMenu(QLatin1String(SUBVERSION_MENU)); ami->createMenu(QLatin1String(SUBVERSION_MENU));
subversionMenu->menu()->setTitle(tr("&Subversion")); subversionMenu->menu()->setTitle(tr("&Subversion"));
toolsContainer->addMenu(subversionMenu); toolsContainer->addMenu(subversionMenu);
if (QAction *ma = subversionMenu->menu()->menuAction()) {
ma->setEnabled(m_versionControl->isEnabled());
connect(m_versionControl, SIGNAL(enabledChanged(bool)), ma, SLOT(setVisible(bool)));
}
QList<int> globalcontext; QList<int> globalcontext;
globalcontext << m_coreInstance->uniqueIDManager()->uniqueIdentifier(C_GLOBAL); globalcontext << m_coreInstance->uniqueIDManager()->uniqueIdentifier(C_GLOBAL);

View File

@@ -146,7 +146,7 @@ QWidget *BaseFileFind::createPatternWidget()
*/ */
QString filterToolTip = tr("List of comma separated wildcard filters"); QString filterToolTip = tr("List of comma separated wildcard filters");
/* /*
QLabel *label = new QLabel(tr("File pattern:")); QLabel *label = new QLabel(tr("File &pattern:"));
label->setToolTip(filterToolTip); label->setToolTip(filterToolTip);
*/ */
/* /*
@@ -163,6 +163,7 @@ QWidget *BaseFileFind::createPatternWidget()
m_filterCombo->setToolTip(filterToolTip); m_filterCombo->setToolTip(filterToolTip);
syncComboWithSettings(m_filterCombo, m_filterSetting); syncComboWithSettings(m_filterCombo, m_filterSetting);
/* /*
label->setBuddy(m_filterCombo);
hlayout->addWidget(m_filterCombo); hlayout->addWidget(m_filterCombo);
*/ */
return m_filterCombo; return m_filterCombo;
@@ -170,7 +171,7 @@ QWidget *BaseFileFind::createPatternWidget()
QWidget *BaseFileFind::createRegExpWidget() QWidget *BaseFileFind::createRegExpWidget()
{ {
m_useRegExpCheckBox = new QCheckBox(tr("Use Regular Expressions")); m_useRegExpCheckBox = new QCheckBox(tr("Use Regular E&xpressions"));
m_useRegExpCheckBox->setChecked(m_useRegExp); m_useRegExpCheckBox->setChecked(m_useRegExp);
connect(m_useRegExpCheckBox, SIGNAL(toggled(bool)), this, SLOT(syncRegExpSetting(bool))); connect(m_useRegExpCheckBox, SIGNAL(toggled(bool)), this, SLOT(syncRegExpSetting(bool)));
return m_useRegExpCheckBox; return m_useRegExpCheckBox;

View File

@@ -502,7 +502,8 @@ void BaseTextEditor::currentEditorChanged(Core::IEditor *editor)
if (editor == d->m_editable) { if (editor == d->m_editable) {
if (d->m_document->hasDecodingError()) { if (d->m_document->hasDecodingError()) {
Core::EditorManager::instance()->showEditorInfoBar(QLatin1String(Constants::SELECT_ENCODING), Core::EditorManager::instance()->showEditorInfoBar(QLatin1String(Constants::SELECT_ENCODING),
tr("<b>Error:</b> Could not decode \"%1\" with \"%2\"-encoding. Editing not possible.").arg(displayName()).arg(QString::fromLatin1(d->m_document->codec()->name())), tr("<b>Error:</b> Could not decode \"%1\" with \"%2\"-encoding. Editing not possible.")
.arg(displayName()).arg(QString::fromLatin1(d->m_document->codec()->name())),
tr("Select Encoding"), tr("Select Encoding"),
this, SLOT(selectEncoding())); this, SLOT(selectEncoding()));
} }

View File

@@ -88,7 +88,8 @@ QWidget *FindInFiles::createConfigWidget()
m_configWidget->setLayout(gridLayout); m_configWidget->setLayout(gridLayout);
gridLayout->addWidget(createRegExpWidget(), 0, 1, 1, 2); gridLayout->addWidget(createRegExpWidget(), 0, 1, 1, 2);
gridLayout->addWidget(new QLabel(tr("Directory:")), 1, 0, Qt::AlignRight); QLabel *dirLabel = new QLabel(tr("&Directory:"));
gridLayout->addWidget(dirLabel, 1, 0, Qt::AlignRight);
m_directory = new QComboBox; m_directory = new QComboBox;
m_directory->setEditable(true); m_directory->setEditable(true);
m_directory->setMaxCount(30); m_directory->setMaxCount(30);
@@ -98,17 +99,20 @@ QWidget *FindInFiles::createConfigWidget()
m_directory->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); m_directory->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
m_directory->setModel(&m_directoryStrings); m_directory->setModel(&m_directoryStrings);
syncComboWithSettings(m_directory, m_directorySetting); syncComboWithSettings(m_directory, m_directorySetting);
dirLabel->setBuddy(m_directory);
gridLayout->addWidget(m_directory, 1, 1); gridLayout->addWidget(m_directory, 1, 1);
QPushButton *browseButton = new QPushButton(tr("Browse")); QPushButton *browseButton = new QPushButton(tr("&Browse"));
gridLayout->addWidget(browseButton, 1, 2); gridLayout->addWidget(browseButton, 1, 2);
connect(browseButton, SIGNAL(clicked()), this, SLOT(openFileBrowser())); connect(browseButton, SIGNAL(clicked()), this, SLOT(openFileBrowser()));
QLabel * const filePatternLabel = new QLabel(tr("File pattern:")); QLabel * const filePatternLabel = new QLabel(tr("File &pattern:"));
filePatternLabel->setMinimumWidth(80); filePatternLabel->setMinimumWidth(80);
filePatternLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); filePatternLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
filePatternLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter); filePatternLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
QWidget *patternWidget = createPatternWidget();
filePatternLabel->setBuddy(patternWidget);
gridLayout->addWidget(filePatternLabel, 2, 0); gridLayout->addWidget(filePatternLabel, 2, 0);
gridLayout->addWidget(createPatternWidget(), 2, 1, 1, 2); gridLayout->addWidget(patternWidget, 2, 1, 1, 2);
m_configWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); m_configWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
} }
return m_configWidget; return m_configWidget;