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

0001 /*
0002     SPDX-FileCopyrightText: 2022 Waqar Ahmed <waqar.17a@gmail.com>
0003     SPDX-License-Identifier: LGPL-2.0-or-later
0004 */
0005 
0006 #pragma once
0007 
0008 #include "diffeditor.h"
0009 #include <QWidget>
0010 
0011 #include "kateprivate_export.h"
0012 
0013 #include <KTextEditor/Document>
0014 
0015 namespace KSyntaxHighlighting
0016 {
0017 class SyntaxHighlighter;
0018 }
0019 
0020 /**
0021  * - Small wrapper over DiffWidget. It tries to reuse an existing diff widget instead of opening a new one
0022  * - Two DiffWidgets are considered equal if their DiffParams.arguments match
0023  * - The diff is always recalculated
0024  */
0025 class DiffWidgetManager
0026 {
0027 public:
0028     static void openDiff(const QByteArray &diff, DiffParams p, class KTextEditor::MainWindow *mw);
0029     static void diffDocs(KTextEditor::Document *l, KTextEditor::Document *r, class KTextEditor::MainWindow *mw);
0030 
0031 private:
0032     static DiffWidget *existingDiffWidgetForParams(KTextEditor::MainWindow *mw, const DiffParams &p);
0033 };
0034 
0035 class KATE_PRIVATE_EXPORT DiffWidget : public QWidget
0036 {
0037     Q_OBJECT
0038     friend DiffWidgetManager;
0039     friend class DiffWidgetTests;
0040 
0041 public:
0042     explicit DiffWidget(DiffParams p, QWidget *parent = nullptr);
0043     ~DiffWidget();
0044 
0045     void diffDocs(KTextEditor::Document *l, KTextEditor::Document *r);
0046 
0047     void openDiff(const QByteArray &diff);
0048 
0049     Q_INVOKABLE bool shouldClose()
0050     {
0051         return true;
0052     }
0053 
0054     bool isHunk(int line) const;
0055     bool isFileNameLine(int line) const
0056     {
0057         return std::find(m_linesWithFileName.begin(), m_linesWithFileName.end(), line) != m_linesWithFileName.end();
0058     }
0059     int hunkLineCount(int hunkLine);
0060 
0061 protected:
0062     void showEvent(QShowEvent *e) override;
0063 
0064 private:
0065     void clearData();
0066     void handleStyleChange(int);
0067     void handleStageUnstage(DiffEditor *e, int startLine, int endLine, int actionType, DiffParams::Flag);
0068     void handleStageUnstage_unified(int startLine, int endLine, int actionType, DiffParams::Flag);
0069     void handleStageUnstage_sideBySide(DiffEditor *e, int startLine, int endLine, int actionType, DiffParams::Flag);
0070     void handleStageUnstage_raw(int startLine, int endLine, int actionType, DiffParams::Flag flags);
0071     void doStageUnStage(int startLine, int endLine, int actionType, DiffParams::Flag);
0072     void onError(const QByteArray &error, int code);
0073     void parseAndShowDiff(const QByteArray &raw);
0074     void parseAndShowDiffUnified(const QByteArray &raw);
0075     enum ApplyFlags { None = 0, Staged = 1, Discard = 2 };
0076     void applyDiff(const QString &diff, ApplyFlags flags);
0077     void runGitDiff();
0078     static QStringList diffDocsGitArgs(KTextEditor::Document *l, KTextEditor::Document *r);
0079     void showWithFullContext();
0080 
0081     void jumpToNextFile();
0082     void jumpToPrevFile();
0083     void jumpToNextHunk();
0084     void jumpToPrevHunk();
0085 
0086     // Struct representing a view line to diff line in the original diff
0087     // Lines which are added or removed are stored, context lines and
0088     // other metaData is ignored
0089     struct ViewLineToDiffLine {
0090         int line;
0091         int diffLine;
0092         // Only used in side-by-side mode
0093         bool added;
0094     };
0095 
0096     class DiffEditor *m_left;
0097     class DiffEditor *m_right;
0098     class QPlainTextEdit *const m_commitInfo;
0099     class Toolbar *const m_toolbar;
0100     KSyntaxHighlighting::AbstractHighlighter *leftHl;
0101     KSyntaxHighlighting::AbstractHighlighter *rightHl;
0102     DiffStyle m_style = SideBySide;
0103     DiffParams m_params;
0104     QByteArray m_rawDiff; // Raw diff saved as is
0105     std::vector<ViewLineToDiffLine> m_lineToRawDiffLine;
0106     std::vector<ViewLineToDiffLine> m_lineToDiffHunkLine;
0107     std::vector<int> m_linesWithFileName;
0108     bool m_stopScrollSync = false;
0109     bool m_blockShowEvent = true;
0110 };