Commit 8808f0fa authored by Tobias Hunger's avatar Tobias Hunger
Browse files

VCS: Handle code folding in diff view

Allow to do codefolding on files and hunks in the diff editor
parent f84c2285
......@@ -114,7 +114,7 @@ QString GitEditor::changeUnderCursor(const QTextCursor &c) const
VCSBase::DiffHighlighter *GitEditor::createDiffHighlighter() const
{
const QRegExp filePattern(QLatin1String("^[-+][-+][-+] [ab].*"));
const QRegExp filePattern(QLatin1String("^(diff --git a/|index |[+-][+-][+-] [ab]).*$"));
return new VCSBase::DiffHighlighter(filePattern);
}
......
......@@ -29,6 +29,8 @@
#include "diffhighlighter.h"
#include <texteditor/basetextdocumentlayout.h>
#include <utils/qtcassert.h>
#include <QtCore/QDebug>
......@@ -36,7 +38,12 @@
#include <QtCore/QRegExp>
#include <QtGui/QBrush>
static const int BASE_LEVEL = 0;
static const int FILE_LEVEL = 1;
static const int LOCATION_LEVEL = 2;
namespace VCSBase {
namespace Internal {
// Formats used by DiffHighlighter
enum DiffFormats {
......@@ -48,8 +55,16 @@ enum DiffFormats {
NumDiffFormats
};
enum FoldingState {
StartOfFile,
Header,
File,
Location
};
// --- DiffHighlighterPrivate
struct DiffHighlighterPrivate {
class DiffHighlighterPrivate {
public:
DiffHighlighterPrivate(const QRegExp &filePattern);
inline DiffFormats analyzeLine(const QString &block) const;
......@@ -59,13 +74,16 @@ struct DiffHighlighterPrivate {
const QChar m_diffOutIndicator;
QTextCharFormat m_formats[NumDiffFormats];
QTextCharFormat m_addedTrailingWhiteSpaceFormat;
FoldingState m_foldingState;
};
DiffHighlighterPrivate::DiffHighlighterPrivate(const QRegExp &filePattern) :
m_filePattern(filePattern),
m_locationIndicator(QLatin1String("@@")),
m_diffInIndicator(QLatin1Char('+')),
m_diffOutIndicator(QLatin1Char('-'))
m_diffOutIndicator(QLatin1Char('-')),
m_foldingState(StartOfFile)
{
QTC_ASSERT(filePattern.isValid(), /**/);
}
......@@ -85,11 +103,13 @@ DiffFormats DiffHighlighterPrivate::analyzeLine(const QString &text) const
return DiffTextFormat;
}
} // namespace Internal
// --- DiffHighlighter
DiffHighlighter::DiffHighlighter(const QRegExp &filePattern,
QTextDocument *document) :
TextEditor::SyntaxHighlighter(document),
m_d(new DiffHighlighterPrivate(filePattern))
m_d(new Internal::DiffHighlighterPrivate(filePattern))
{
}
......@@ -113,11 +133,11 @@ void DiffHighlighter::highlightBlock(const QString &text)
return;
const int length = text.length();
const DiffFormats format = m_d->analyzeLine(text);
const Internal::DiffFormats format = m_d->analyzeLine(text);
switch (format) {
case DiffTextFormat:
case Internal::DiffTextFormat:
break;
case DiffInFormat: {
case Internal::DiffInFormat: {
// Mark trailing whitespace.
const int trimmedLen = trimmedLength(text);
setFormat(0, trimmedLen, m_d->m_formats[format]);
......@@ -129,6 +149,61 @@ void DiffHighlighter::highlightBlock(const QString &text)
setFormat(0, length, m_d->m_formats[format]);
break;
}
// codefolding:
TextEditor::TextBlockUserData *data =
TextEditor::BaseTextDocumentLayout::userData(currentBlock());
Q_ASSERT(data);
if (!TextEditor::BaseTextDocumentLayout::testUserData(currentBlock().previous()))
m_d->m_foldingState = Internal::StartOfFile;
switch (m_d->m_foldingState) {
case Internal::StartOfFile:
case Internal::Header:
switch (format) {
case Internal::DiffFileFormat:
m_d->m_foldingState = Internal::File;
TextEditor::BaseTextDocumentLayout::setFoldingIndent(currentBlock(), BASE_LEVEL);
break;
case Internal::DiffLocationFormat:
m_d->m_foldingState = Internal::Location;
TextEditor::BaseTextDocumentLayout::setFoldingIndent(currentBlock(), FILE_LEVEL);
break;
default:
m_d->m_foldingState = Internal::Header;
TextEditor::BaseTextDocumentLayout::setFoldingIndent(currentBlock(), BASE_LEVEL);
break;
}
break;
case Internal::File:
switch (format) {
case Internal::DiffFileFormat:
TextEditor::BaseTextDocumentLayout::setFoldingIndent(currentBlock(), FILE_LEVEL);
break;
case Internal::DiffLocationFormat:
m_d->m_foldingState = Internal::Location;
TextEditor::BaseTextDocumentLayout::setFoldingIndent(currentBlock(), FILE_LEVEL);
break;
default:
TextEditor::BaseTextDocumentLayout::setFoldingIndent(currentBlock(), FILE_LEVEL);
break;
}
break;
case Internal::Location:
switch (format) {
case Internal::DiffFileFormat:
m_d->m_foldingState = Internal::File;
TextEditor::BaseTextDocumentLayout::setFoldingIndent(currentBlock(), BASE_LEVEL);
break;
case Internal::DiffLocationFormat:
TextEditor::BaseTextDocumentLayout::setFoldingIndent(currentBlock(), FILE_LEVEL);
break;
default:
TextEditor::BaseTextDocumentLayout::setFoldingIndent(currentBlock(), LOCATION_LEVEL);
break;
}
break;
}
}
static inline QTextCharFormat invertedColorFormat(const QTextCharFormat &in)
......@@ -141,10 +216,11 @@ static inline QTextCharFormat invertedColorFormat(const QTextCharFormat &in)
void DiffHighlighter::setFormats(const QVector<QTextCharFormat> &s)
{
if (s.size() == NumDiffFormats) {
if (s.size() == Internal::NumDiffFormats) {
qCopy(s.constBegin(), s.constEnd(), m_d->m_formats);
// Display trailing blanks with colors swapped
m_d->m_addedTrailingWhiteSpaceFormat = invertedColorFormat(m_d->m_formats[DiffInFormat]);
m_d->m_addedTrailingWhiteSpaceFormat =
invertedColorFormat(m_d->m_formats[Internal::DiffInFormat]);
} else {
qWarning("%s: insufficient setting size: %d", Q_FUNC_INFO, s.size());
}
......
......@@ -48,7 +48,9 @@ namespace TextEditor {
namespace VCSBase {
struct DiffHighlighterPrivate;
namespace Internal {
class DiffHighlighterPrivate;
} // namespace Internal
/* A highlighter for diffs. Parametrizable by the file indicator,
* which is for example '^====' in case of p4:
......@@ -81,7 +83,7 @@ public:
QRegExp filePattern() const;
private:
DiffHighlighterPrivate *m_d;
Internal::DiffHighlighterPrivate *m_d;
};
} // namespace VCSBase
......
......@@ -201,6 +201,7 @@ void VCSBaseEditor::init()
break;
case DiffOutput: {
DiffHighlighter *dh = createDiffHighlighter();
setCodeFoldingSupported(true);
baseTextDocument()->setSyntaxHighlighter(dh);
d->m_diffFilePattern = dh->filePattern();
connect(this, SIGNAL(textChanged()), this, SLOT(slotPopulateDiffBrowser()));
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment