Commit dfb0d98a authored by Waqar Ahmed's avatar Waqar Ahmed Committed by Christoph Cullmann
Browse files

Add jump to hunk/file

Also, allow to hide the commit info
parent bb551a06
......@@ -91,6 +91,19 @@ DiffEditor::DiffEditor(DiffParams::Flags f, QWidget *parent)
connect(this, &QPlainTextEdit::updateRequest, this, &DiffEditor::updateLineNumberArea);
setReadOnly(true);
m_timeLine.setDuration(1000);
m_timeLine.setFrameRange(0, 250);
connect(&m_timeLine, &QTimeLine::frameChanged, this, [this](int) {
if (!m_animateTextRect.isNull()) {
viewport()->update(m_animateTextRect);
}
});
connect(&m_timeLine, &QTimeLine::finished, this, [this] {
auto r = m_animateTextRect;
m_animateTextRect = QRect();
viewport()->update(r);
});
}
void DiffEditor::updateDiffColors(bool darkMode)
......@@ -106,6 +119,25 @@ void DiffEditor::updateDiffColors(bool darkMode)
green2.setAlphaF(0.20);
}
void DiffEditor::scrollToBlock(int block)
{
if (m_timeLine.state() == QTimeLine::Running) {
m_timeLine.stop();
auto r = m_animateTextRect;
m_animateTextRect = QRect();
viewport()->update(r);
}
int lineNo = 0;
for (int i = 0; i < block; ++i) {
lineNo += document()->findBlockByNumber(i).lineCount();
}
verticalScrollBar()->setValue(lineNo);
QTextBlock b = document()->findBlockByNumber(block);
m_animateTextRect = blockBoundingGeometry(b).translated(contentOffset()).toRect();
m_timeLine.start();
}
void DiffEditor::resizeEvent(QResizeEvent *event)
{
QPlainTextEdit::resizeEvent(event);
......@@ -333,6 +365,12 @@ void DiffEditor::paintEvent(QPaintEvent *e)
p.restore();
}
if (m_animateTextRect.contains(offset.toPoint())) {
QColor c(Qt::red);
c.setAlpha(m_timeLine.currentFrame());
p.fillRect(m_animateTextRect, c);
}
offset.ry() += r.height();
if (offset.y() > viewportRect.height()) {
break;
......
......@@ -12,6 +12,8 @@
#include <KSyntaxHighlighting/FoldingRegion>
#include <KSyntaxHighlighting/SyntaxHighlighter>
#include <QTimeLine>
class DiffSyntaxHighlighter final : public KSyntaxHighlighting::SyntaxHighlighter
{
public:
......@@ -93,6 +95,13 @@ public:
return green1;
}
int firstVisibleBlockNumber() const
{
return QPlainTextEdit::firstVisibleBlock().blockNumber();
}
void scrollToBlock(int block);
protected:
void resizeEvent(QResizeEvent *event) override;
void paintEvent(QPaintEvent *e) override;
......@@ -116,6 +125,9 @@ private:
class DiffWidget *const m_diffWidget;
DiffParams::Flags m_flags;
QTimeLine m_timeLine;
QRect m_animateTextRect;
Q_SIGNALS:
void switchStyle(int);
void actionTriggered(DiffEditor *e, int startLine, int endLine, int actionType, DiffParams::Flag);
......
......@@ -14,27 +14,101 @@
#include <QPainterPath>
#include <QPointer>
#include <QRegularExpression>
#include <QScopedValueRollback>
#include <QScrollBar>
#include <QSyntaxHighlighter>
#include <QTemporaryFile>
#include <QToolBar>
#include <QToolButton>
#include <KConfigGroup>
#include <KLocalizedString>
#include <KSharedConfig>
#include <KSyntaxHighlighting/Definition>
#include <KSyntaxHighlighting/Format>
#include <KSyntaxHighlighting/Repository>
#include <KTextEditor/Editor>
class Toolbar : public QToolBar
{
Q_OBJECT
public:
Toolbar(QWidget *parent)
: QToolBar(parent)
{
setContentsMargins({});
if (layout()) {
layout()->setContentsMargins({});
}
setToolButtonStyle(Qt::ToolButtonIconOnly);
KConfigGroup cgGeneral = KConfigGroup(KSharedConfig::openConfig(), "General");
bool show = cgGeneral.readEntry("DiffWidget Show Commit Info", true);
m_showCommitInfoAction = addAction(QIcon::fromTheme(QStringLiteral("view-visible")), QString());
m_showCommitInfoAction->setCheckable(true);
m_showCommitInfoAction->setToolTip(i18n("Show/Hide Commit Info"));
m_showCommitInfoAction->setChecked(show);
connect(m_showCommitInfoAction, &QAction::toggled, this, &Toolbar::showCommitInfoChanged);
m_showNextFile = addAction(QIcon::fromTheme(QStringLiteral("arrow-down-double")), QString());
m_showNextFile->setToolTip(i18n("Jump to Next File"));
connect(m_showNextFile, &QAction::triggered, this, &Toolbar::jumpToNextFile);
m_showPrevFile = addAction(QIcon::fromTheme(QStringLiteral("arrow-up-double")), QString());
m_showPrevFile->setToolTip(i18n("Jump to Previous File"));
connect(m_showPrevFile, &QAction::triggered, this, &Toolbar::jumpToPrevFile);
m_showNextHunk = addAction(QIcon::fromTheme(QStringLiteral("arrow-down")), QString());
m_showNextHunk->setToolTip(i18n("Jump to Next Hunk"));
connect(m_showNextHunk, &QAction::triggered, this, &Toolbar::jumpToNextHunk);
m_showPrevHunk = addAction(QIcon::fromTheme(QStringLiteral("arrow-up")), QString());
m_showPrevHunk->setToolTip(i18n("Jump to Previous Hunk"));
connect(m_showPrevHunk, &QAction::triggered, this, &Toolbar::jumpToPrevHunk);
}
void setShowCommitActionVisible(bool vis)
{
if (m_showCommitInfoAction->isVisible() != vis) {
m_showCommitInfoAction->setVisible(vis);
}
}
bool showCommitInfo()
{
return m_showCommitInfoAction->isChecked();
}
private:
QAction *m_showCommitInfoAction;
QAction *m_showNextFile;
QAction *m_showPrevFile;
QAction *m_showNextHunk;
QAction *m_showPrevHunk;
Q_SIGNALS:
void showCommitInfoChanged(bool);
void jumpToNextFile();
void jumpToPrevFile();
void jumpToNextHunk();
void jumpToPrevHunk();
};
DiffWidget::DiffWidget(DiffParams p, QWidget *parent)
: QWidget(parent)
, m_left(new DiffEditor(p.flags, this))
, m_right(new DiffEditor(p.flags, this))
, m_commitInfo(new QPlainTextEdit(this))
, m_toolbar(new Toolbar(this))
, m_params(p)
{
auto layout = new QVBoxLayout(this);
layout->setSpacing(2);
layout->setContentsMargins({});
layout->addWidget(m_commitInfo);
layout->addWidget(m_toolbar);
auto diffLayout = new QHBoxLayout;
diffLayout->setContentsMargins({});
diffLayout->addWidget(m_left);
......@@ -47,9 +121,15 @@ DiffWidget::DiffWidget(DiffParams p, QWidget *parent)
rightHl->setTheme(KTextEditor::Editor::instance()->theme());
connect(m_left->verticalScrollBar(), &QScrollBar::valueChanged, this, [this](int v) {
if (m_stopScrollSync) {
return;
}
m_right->verticalScrollBar()->setValue(v);
});
connect(m_right->verticalScrollBar(), &QScrollBar::valueChanged, this, [this](int v) {
if (m_stopScrollSync) {
return;
}
m_left->verticalScrollBar()->setValue(v);
});
......@@ -66,6 +146,16 @@ DiffWidget::DiffWidget(DiffParams p, QWidget *parent)
m_commitInfo->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
m_commitInfo->setMaximumHeight(250);
connect(m_toolbar, &Toolbar::showCommitInfoChanged, this, [this](bool v) {
m_commitInfo->setVisible(v);
KConfigGroup cgGeneral = KConfigGroup(KSharedConfig::openConfig(), "General");
cgGeneral.writeEntry("DiffWidget Show Commit Info", v);
});
connect(m_toolbar, &Toolbar::jumpToNextFile, this, &DiffWidget::jumpToNextFile);
connect(m_toolbar, &Toolbar::jumpToPrevFile, this, &DiffWidget::jumpToPrevFile);
connect(m_toolbar, &Toolbar::jumpToNextHunk, this, &DiffWidget::jumpToNextHunk);
connect(m_toolbar, &Toolbar::jumpToPrevHunk, this, &DiffWidget::jumpToPrevHunk);
KSharedConfig::Ptr config = KSharedConfig::openConfig();
KConfigGroup cgGeneral = KConfigGroup(config, "General");
handleStyleChange(cgGeneral.readEntry("Diff Show Style", (int)SideBySide));
......@@ -800,10 +890,14 @@ static QString commitInfoFromDiff(const QByteArray &raw)
void DiffWidget::openDiff(const QByteArray &raw)
{
if ((m_params.flags & DiffParams::ShowCommitInfo) && m_style != DiffStyle::Raw) {
m_toolbar->setShowCommitActionVisible(true);
m_commitInfo->setPlainText(commitInfoFromDiff(raw));
m_commitInfo->show();
if (m_toolbar->showCommitInfo()) {
m_commitInfo->show();
}
} else {
m_commitInfo->hide();
m_toolbar->setShowCommitActionVisible(false);
}
if (m_style == SideBySide) {
......@@ -861,3 +955,77 @@ int DiffWidget::hunkLineCount(int hunkLine)
return 0;
}
void DiffWidget::jumpToNextFile()
{
const int block = m_left->firstVisibleBlockNumber();
int nextFileLineNo = 0;
for (const auto &i : m_linesWithFileName) {
if (i > block) {
nextFileLineNo = i;
break;
}
}
QScopedValueRollback r(m_stopScrollSync, true);
m_left->scrollToBlock(nextFileLineNo);
if (m_style == SideBySide) {
m_right->scrollToBlock(nextFileLineNo);
}
}
void DiffWidget::jumpToPrevFile()
{
const int block = m_left->firstVisibleBlockNumber();
int prevFileLineNo = 0;
for (auto i = m_linesWithFileName.crbegin(); i != m_linesWithFileName.crend(); ++i) {
if (*i < block) {
prevFileLineNo = *i;
break;
}
}
QScopedValueRollback r(m_stopScrollSync, true);
m_left->scrollToBlock(prevFileLineNo);
if (m_style == SideBySide) {
m_right->scrollToBlock(prevFileLineNo);
}
}
void DiffWidget::jumpToNextHunk()
{
const int block = m_left->firstVisibleBlockNumber();
int nextHunkLineNo = 0;
for (const auto &i : m_lineToDiffHunkLine) {
if (i.line > block) {
nextHunkLineNo = i.line;
break;
}
}
QScopedValueRollback r(m_stopScrollSync, true);
m_left->scrollToBlock(nextHunkLineNo);
if (m_style == SideBySide) {
m_right->scrollToBlock(nextHunkLineNo);
}
}
void DiffWidget::jumpToPrevHunk()
{
const int block = m_left->firstVisibleBlockNumber();
int prevHunkLineNo = 0;
for (auto i = m_lineToDiffHunkLine.crbegin(); i != m_lineToDiffHunkLine.crend(); ++i) {
if (i->line < block) {
prevHunkLineNo = i->line;
break;
}
}
QScopedValueRollback r(m_stopScrollSync, true);
m_left->scrollToBlock(prevHunkLineNo);
if (m_style == SideBySide) {
m_right->scrollToBlock(prevHunkLineNo);
}
}
#include "diffwidget.moc"
......@@ -51,6 +51,11 @@ private:
void applyDiff(const QString &diff, ApplyFlags flags);
void runGitDiff();
void jumpToNextFile();
void jumpToPrevFile();
void jumpToNextHunk();
void jumpToPrevHunk();
// Struct representing a view line to diff line in the original diff
// Lines which are added or removed are stored, context lines and
// other metaData is ignored
......@@ -64,6 +69,7 @@ private:
class DiffEditor *m_left;
class DiffEditor *m_right;
class QPlainTextEdit *const m_commitInfo;
class Toolbar *const m_toolbar;
KSyntaxHighlighting::AbstractHighlighter *leftHl;
KSyntaxHighlighting::AbstractHighlighter *rightHl;
DiffStyle m_style = SideBySide;
......@@ -72,4 +78,5 @@ private:
QVector<ViewLineToDiffLine> m_lineToRawDiffLine;
QVector<ViewLineToDiffLine> m_lineToDiffHunkLine;
QVector<int> m_linesWithFileName;
bool m_stopScrollSync = false;
};
Supports Markdown
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