File indexing completed on 2024-05-12 05:52:05

0001 /*
0002     SPDX-FileCopyrightText: 2022 Waqar Ahmed <waqar.17a@gmail.com>
0003     SPDX-License-Identifier: LGPL-2.0-or-later
0004 */
0005 #pragma once
0006 
0007 #include "diffparams.h"
0008 #include <KTextEditor/Range>
0009 #include <QPlainTextEdit>
0010 
0011 #include <KSyntaxHighlighting/FoldingRegion>
0012 #include <KSyntaxHighlighting/SyntaxHighlighter>
0013 
0014 #include <QTimeLine>
0015 
0016 class DiffSyntaxHighlighter final : public KSyntaxHighlighting::SyntaxHighlighter
0017 {
0018 public:
0019     DiffSyntaxHighlighter(QTextDocument *parent, class DiffWidget *diffWidget);
0020 
0021     void highlightBlock(const QString &text) override;
0022     void applyFormat(int offset, int length, const KSyntaxHighlighting::Format &format) override;
0023     void applyFolding(int, int, KSyntaxHighlighting::FoldingRegion) override
0024     {
0025         // no folding
0026     }
0027 
0028 private:
0029     class DiffWidget *const m_diffWidget;
0030 };
0031 
0032 using IntT = qsizetype;
0033 
0034 struct Change {
0035     IntT pos;
0036     IntT len;
0037     enum { FullBlock = -2 };
0038 };
0039 
0040 struct LineHighlight {
0041     std::vector<Change> changes;
0042     IntT line;
0043     bool added;
0044 };
0045 
0046 enum DiffStyle { SideBySide = 0, Unified, Raw };
0047 
0048 class DiffEditor : public QPlainTextEdit
0049 {
0050     Q_OBJECT
0051     friend class LineNumArea;
0052 
0053 public:
0054     enum { Line = 0, Hunk = 1 };
0055     DiffEditor(DiffParams::Flags, QWidget *parent = nullptr);
0056 
0057     void clearData()
0058     {
0059         clear();
0060         m_data.clear();
0061         setLineNumberData({}, {}, 0);
0062     }
0063     void appendData(const std::vector<LineHighlight> &newData)
0064     {
0065         m_data.insert(m_data.end(), newData.begin(), newData.end());
0066     }
0067 
0068     void setLineNumberData(std::vector<int> lineNosA, std::vector<int> lineNosB, int maxLineNum);
0069 
0070     KTextEditor::Range selectionRange() const;
0071 
0072     bool isHunkLine(int line) const;
0073     void toggleFoldHunk(int block);
0074     bool isHunkFolded(int blockNumber);
0075     const LineHighlight *highlightingForLine(int line);
0076 
0077     QColor removedColor() const
0078     {
0079         return red1;
0080     }
0081     QColor addedColor() const
0082     {
0083         return green1;
0084     }
0085 
0086     int firstVisibleBlockNumber() const
0087     {
0088         return QPlainTextEdit::firstVisibleBlock().blockNumber();
0089     }
0090 
0091     void scrollToBlock(int block, bool flashBlock = false);
0092 
0093     // Returns the line number that user sees
0094     int firstVisibleLineNumber() const;
0095     void scrollToLineNumber(int lineNo);
0096 
0097 protected:
0098     void resizeEvent(QResizeEvent *event) override;
0099     void paintEvent(QPaintEvent *e) override;
0100     void contextMenuEvent(QContextMenuEvent *e) override;
0101 
0102 private:
0103     void updateLineNumberArea(const QRect &rect, int dy);
0104     void updateLineNumAreaGeometry();
0105     void updateLineNumberAreaWidth(int);
0106     void updateDiffColors(bool darkMode);
0107     void onContextMenuRequest();
0108     void addStageUnstageDiscardActions(QMenu *menu);
0109 
0110     std::vector<LineHighlight> m_data;
0111     QColor red1;
0112     QColor red2;
0113     QColor green1;
0114     QColor green2;
0115     QColor hunkSeparatorColor;
0116     class LineNumArea *const m_lineNumArea;
0117     class DiffWidget *const m_diffWidget;
0118     DiffParams::Flags m_flags;
0119 
0120     QTimeLine m_timeLine;
0121     QRect m_animateTextRect;
0122 
0123 Q_SIGNALS:
0124     void switchStyle(int);
0125     void actionTriggered(DiffEditor *e, int startLine, int endLine, int actionType, DiffParams::Flag);
0126 };