File indexing completed on 2024-10-13 05:04:12
0001 // clang-format off 0002 /* 0003 * KDiff3 - Text Diff And Merge Tool 0004 * 0005 * SPDX-FileCopyrightText: 2002-2011 Joachim Eibl, joachim.eibl at gmx.de 0006 * SPDX-FileCopyrightText: 2018-2020 Michael Reeves reeves.87@gmail.com 0007 * SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 // clang-format on 0010 0011 #ifndef MERGERESULTWINDOW_H 0012 #define MERGERESULTWINDOW_H 0013 0014 #include "diff.h" 0015 #include "FileNameLineEdit.h" 0016 #include "MergeEditLine.h" 0017 #include "options.h" 0018 #include "Overview.h" 0019 #include "selection.h" 0020 #include "LineRef.h" 0021 #include "TypeUtils.h" 0022 0023 #include <boost/signals2.hpp> 0024 #include <memory> 0025 0026 #include <QLineEdit> 0027 #include <QPointer> 0028 #include <QSharedPointer> 0029 #include <QStatusBar> 0030 #include <QTextLayout> 0031 #include <QTimer> 0032 #include <QWidget> 0033 0034 class QPainter; 0035 class RLPainter; 0036 class QScrollBar; 0037 class KActionCollection; 0038 class KToggleAction; 0039 0040 class KDiff3App; 0041 class UndoRecord; 0042 0043 class MergeResultWindow: public QWidget 0044 { 0045 Q_OBJECT 0046 public: 0047 static QPointer<QScrollBar> mVScrollBar; 0048 0049 MergeResultWindow(QWidget* pParent, QStatusBar* pStatusBar); 0050 0051 void init( 0052 const std::shared_ptr<LineDataVector> &pLineDataA, LineRef sizeA, 0053 const std::shared_ptr<LineDataVector> &pLineDataB, LineRef sizeB, 0054 const std::shared_ptr<LineDataVector> &pLineDataC, LineRef sizeC, 0055 const Diff3LineList* pDiff3LineList, 0056 TotalDiffStatus* pTotalDiffStatus, 0057 bool bAutoSolve 0058 ); 0059 0060 void setupConnections(const KDiff3App* app); 0061 0062 static void initActions(KActionCollection* ac); 0063 0064 void connectActions() const; 0065 void reset(); 0066 0067 bool saveDocument(const QString& fileName, const char* encoding, e_LineEndStyle eLineEndStyle); 0068 [[nodiscard]] qint32 getNumberOfUnsolvedConflicts(qint32* pNrOfWhiteSpaceConflicts = nullptr) const; 0069 void choose(const e_SrcSelector selector); 0070 void chooseGlobal(e_SrcSelector selector, bool bConflictsOnly, bool bWhiteSpaceOnly); 0071 0072 [[nodiscard]] qint32 getMaxTextWidth(); // width of longest text line 0073 [[nodiscard]] LineType getNofLines() const; 0074 [[nodiscard]] qint32 getVisibleTextAreaWidth() const; // text area width without the border 0075 [[nodiscard]] qint32 getNofVisibleLines() const; 0076 [[nodiscard]] QString getSelection() const; 0077 void resetSelection(); 0078 void showNumberOfConflicts(bool showIfNone = false); 0079 [[nodiscard]] bool isDeltaAboveCurrent() const; 0080 [[nodiscard]] bool isDeltaBelowCurrent() const; 0081 [[nodiscard]] bool isConflictAboveCurrent() const; 0082 [[nodiscard]] bool isConflictBelowCurrent() const; 0083 [[nodiscard]] bool isUnsolvedConflictAtCurrent() const; 0084 [[nodiscard]] bool isUnsolvedConflictAboveCurrent() const; 0085 [[nodiscard]] bool isUnsolvedConflictBelowCurrent() const; 0086 bool findString(const QString& s, LineRef& d3vLine, QtSizeType& posInLine, bool bDirDown, bool bCaseSensitive); 0087 void setSelection(LineType firstLine, QtSizeType startPos, LineType lastLine, QtSizeType endPos); 0088 [[nodiscard]] e_OverviewMode getOverviewMode() const; 0089 0090 void slotUpdateAvailabilities(); 0091 0092 private: 0093 static QPointer<QAction> chooseAEverywhere; 0094 static QPointer<QAction> chooseBEverywhere; 0095 static QPointer<QAction> chooseCEverywhere; 0096 static QPointer<QAction> chooseAForUnsolvedConflicts; 0097 static QPointer<QAction> chooseBForUnsolvedConflicts; 0098 static QPointer<QAction> chooseCForUnsolvedConflicts; 0099 static QPointer<QAction> chooseAForUnsolvedWhiteSpaceConflicts; 0100 static QPointer<QAction> chooseBForUnsolvedWhiteSpaceConflicts; 0101 static QPointer<QAction> chooseCForUnsolvedWhiteSpaceConflicts; 0102 0103 struct HistoryMapEntry { 0104 MergeEditLineList mellA; 0105 MergeEditLineList mellB; 0106 MergeEditLineList mellC; 0107 MergeEditLineList& choice(bool bThreeInputs); 0108 bool staysInPlace(bool bThreeInputs, Diff3LineList::const_iterator& iHistoryEnd); 0109 }; 0110 typedef std::map<QString, HistoryMapEntry> HistoryMap; 0111 0112 enum class Direction 0113 { 0114 eUp, 0115 eDown 0116 }; 0117 0118 enum class EndPoint 0119 { 0120 eDelta, 0121 eConflict, 0122 eUnsolvedConflict, 0123 eLine, 0124 eEnd 0125 }; 0126 0127 enum class RangeMark 0128 { 0129 none = 0, 0130 begin = 1, 0131 end = 2, 0132 current = 4 0133 }; 0134 Q_DECLARE_FLAGS(RangeFlags, RangeMark); 0135 0136 std::shared_ptr<UndoRecord> mUndoRec; 0137 0138 std::shared_ptr<LineDataVector> m_pldA = nullptr; 0139 std::shared_ptr<LineDataVector> m_pldB = nullptr; 0140 std::shared_ptr<LineDataVector> m_pldC = nullptr; 0141 LineRef m_sizeA = 0; 0142 LineRef m_sizeB = 0; 0143 LineRef m_sizeC = 0; 0144 0145 const Diff3LineList* m_pDiff3LineList = nullptr; 0146 TotalDiffStatus* m_pTotalDiffStatus = nullptr; 0147 0148 qint32 m_delayedDrawTimer = 0; 0149 e_OverviewMode mOverviewMode = e_OverviewMode::eOMNormal; 0150 QString m_persistentStatusMessage; 0151 0152 MergeBlockList m_mergeBlockList; 0153 MergeBlockList::iterator m_currentMergeBlockIt; 0154 0155 qint32 m_currentPos; 0156 0157 QPixmap m_pixmap; 0158 LineRef m_firstLine = 0; 0159 qint32 m_horizScrollOffset = 0; 0160 LineType m_nofLines = 0; 0161 qint32 m_maxTextWidth = -1; 0162 bool m_bMyUpdate = false; 0163 bool m_bInsertMode = true; 0164 bool m_bModified = false; 0165 void setModified(bool bModified = true); 0166 0167 qint32 m_scrollDeltaX = 0; 0168 qint32 m_scrollDeltaY = 0; 0169 SafeInt<qint32> m_cursorXPos = 0; 0170 SafeInt<qint32> m_cursorXPixelPos = 0; 0171 LineRef m_cursorYPos = 0; 0172 qint32 m_cursorOldXPixelPos = 0; 0173 bool m_bCursorOn = true; // blinking on and off each second 0174 QTimer m_cursorTimer; 0175 bool m_bCursorUpdate = false; 0176 QStatusBar* m_pStatusBar; 0177 0178 Selection m_selection; 0179 /* 0180 This list exists solely to auto disconnect boost signals. 0181 */ 0182 std::list<boost::signals2::scoped_connection> connections; 0183 // Overrides 0184 void paintEvent(QPaintEvent* e) override; 0185 void timerEvent(QTimerEvent*) override; 0186 bool event(QEvent*) override; 0187 void mousePressEvent(QMouseEvent* e) override; 0188 void mouseDoubleClickEvent(QMouseEvent* e) override; 0189 void mouseReleaseEvent(QMouseEvent*) override; 0190 void mouseMoveEvent(QMouseEvent*) override; 0191 void resizeEvent(QResizeEvent* e) override; 0192 void keyPressEvent(QKeyEvent* e) override; 0193 void wheelEvent(QWheelEvent* pWheelEvent) override; 0194 void focusInEvent(QFocusEvent* e) override; 0195 //Costum functions 0196 void merge(bool bAutoSolve, e_SrcSelector defaultSelector, bool bConflictsOnly = false, bool bWhiteSpaceOnly = false); 0197 QString getString(qint32 lineIdx); 0198 void showUnsolvedConflictsStatusMessage(); 0199 0200 void collectHistoryInformation(e_SrcSelector src, const HistoryRange& historyRange, HistoryMap& historyMap, std::list<HistoryMap::iterator>& hitList); 0201 0202 bool isItAtEnd(bool bIncrement, const MergeBlockList::const_iterator i) const 0203 { 0204 if(bIncrement) 0205 return i != m_mergeBlockList.end(); 0206 else 0207 return i != m_mergeBlockList.begin(); 0208 } 0209 0210 bool checkOverviewIgnore(const MergeBlockList::const_iterator i) const; 0211 0212 void go(Direction eDir, EndPoint eEndPoint); 0213 bool calcIteratorFromLineNr( 0214 LineType line, 0215 MergeBlockList::iterator& mbIt, 0216 MergeEditLineList::iterator& melIt); 0217 0218 qint32 getTextXOffset() const; 0219 QVector<QTextLayout::FormatRange> getTextLayoutForLine(LineRef line, const QString& s, QTextLayout& textLayout); 0220 void myUpdate(qint32 afterMilliSecs); 0221 void writeLine( 0222 RLPainter& p, LineRef line, const QString& str, 0223 enum e_SrcSelector srcSelect, e_MergeDetails mergeDetails, RangeFlags rangeMark, bool bUserModified, bool bLineRemoved, bool bWhiteSpaceConflict); 0224 void setFastSelector(MergeBlockList::iterator i); 0225 LineRef convertToLine(qint32 y); 0226 0227 bool canCut() { return hasFocus() && !getSelection().isEmpty(); } 0228 bool canCopy() { return hasFocus() && !getSelection().isEmpty(); } 0229 0230 bool deleteSelection2(QString& str, SafeInt<qint32>& x, qint32& y, 0231 MergeBlockList::iterator& mbIt, MergeEditLineList::iterator& melIt); 0232 bool doRelevantChangesExist(); 0233 0234 public Q_SLOTS: 0235 void setOverviewMode(e_OverviewMode eOverviewMode); 0236 void setFirstLine(LineRef firstLine); 0237 void setHorizScrollOffset(const qint32 horizScrollOffset); 0238 0239 void slotGoCurrent(); 0240 void slotGoTop(); 0241 void slotGoBottom(); 0242 void slotGoPrevDelta(); 0243 void slotGoNextDelta(); 0244 void slotGoPrevUnsolvedConflict(); 0245 void slotGoNextUnsolvedConflict(); 0246 void slotGoPrevConflict(); 0247 void slotGoNextConflict(); 0248 void slotAutoSolve(); 0249 void slotUnsolve(); 0250 void slotMergeHistory(); 0251 void slotRegExpAutoMerge(); 0252 void slotSplitDiff(LineType firstD3lLineIdx, LineType lastD3lLineIdx); 0253 void slotJoinDiffs(LineType firstD3lLineIdx, LineType lastD3lLineIdx); 0254 void slotSetFastSelectorLine(LineType); 0255 void setPaintingAllowed(bool); 0256 void updateSourceMask(); 0257 void slotStatusMessageChanged(const QString&); 0258 0259 void slotChooseAEverywhere() { chooseGlobal(e_SrcSelector::A, false, false); } 0260 void slotChooseBEverywhere() { chooseGlobal(e_SrcSelector::B, false, false); } 0261 void slotChooseCEverywhere() { chooseGlobal(e_SrcSelector::C, false, false); } 0262 0263 void slotChooseAForUnsolvedConflicts() { chooseGlobal(e_SrcSelector::A, true, false); } 0264 void slotChooseBForUnsolvedConflicts() { chooseGlobal(e_SrcSelector::B, true, false); } 0265 void slotChooseCForUnsolvedConflicts() { chooseGlobal(e_SrcSelector::C, true, false); } 0266 0267 void slotChooseAForUnsolvedWhiteSpaceConflicts() { chooseGlobal(e_SrcSelector::A, true, true); } 0268 void slotChooseBForUnsolvedWhiteSpaceConflicts() { chooseGlobal(e_SrcSelector::B, true, true); } 0269 void slotChooseCForUnsolvedWhiteSpaceConflicts() { chooseGlobal(e_SrcSelector::C, true, true); } 0270 0271 void slotRefresh(); 0272 0273 void slotResize(); 0274 0275 void slotCut(); 0276 void slotCopy(); 0277 void slotSelectAll(); 0278 0279 void scrollVertically(qint32 deltaY); 0280 0281 void deleteSelection(); 0282 void pasteClipboard(bool bFromSelection); 0283 private Q_SLOTS: 0284 void slotCursorUpdate(); 0285 0286 Q_SIGNALS: 0287 void statusBarMessage(const QString& message); 0288 void scrollMergeResultWindow(qint32 deltaX, qint32 deltaY); 0289 void modifiedChanged(bool bModified); 0290 void setFastSelectorRange(LineRef line1, LineType nofLines); 0291 void sourceMask(qint32 srcMask, qint32 enabledMask); 0292 void resizeSignal(); 0293 void selectionEnd(); 0294 void newSelection(); 0295 void updateAvailabilities(); 0296 void showPopupMenu(const QPoint& point); 0297 void noRelevantChangesDetected(); 0298 }; 0299 0300 class QLineEdit; 0301 class QComboBox; 0302 class QLabel; 0303 0304 class WindowTitleWidget: public QWidget 0305 { 0306 Q_OBJECT 0307 private: 0308 struct { 0309 QByteArray name; 0310 bool hasBOM = false; 0311 } EcodingItemData; 0312 0313 QLabel* m_pLabel; 0314 FileNameLineEdit* m_pFileNameLineEdit; 0315 //QPushButton* m_pBrowseButton; 0316 QLabel* m_pModifiedLabel; 0317 QLabel* m_pLineEndStyleLabel; 0318 QComboBox* m_pLineEndStyleSelector; 0319 QLabel* m_pEncodingLabel; 0320 QComboBox* m_pEncodingSelector; 0321 0322 public: 0323 WindowTitleWidget(); 0324 const char* getEncoding(); 0325 void setFileName(const QString& fileName); 0326 QString getFileName(); 0327 void setEncodings(const char* pCodecForA, const char* pCodecForB, const char* pCodecForC); 0328 void setEncoding(const char* encoding); 0329 void setLineEndStyles(e_LineEndStyle eLineEndStyleA, e_LineEndStyle eLineEndStyleB, e_LineEndStyle eLineEndStyleC); 0330 e_LineEndStyle getLineEndStyle(); 0331 0332 bool eventFilter(QObject* o, QEvent* e) override; 0333 public Q_SLOTS: 0334 void slotSetModified(bool bModified); 0335 //private Q_SLOTS: 0336 // void slotBrowseButtonClicked(); 0337 }; 0338 0339 #endif