diff options
Diffstat (limited to 'src/mergeresultwindow.h')
-rw-r--r-- | src/mergeresultwindow.h | 454 |
1 files changed, 454 insertions, 0 deletions
diff --git a/src/mergeresultwindow.h b/src/mergeresultwindow.h new file mode 100644 index 0000000..fdc4b5c --- /dev/null +++ b/src/mergeresultwindow.h @@ -0,0 +1,454 @@ +/*************************************************************************** + mergeresultwindow.h - description + ------------------- + begin : Mon Mar 18 2002 + copyright : (C) 2002-2007 by Joachim Eibl + email : joachim.eibl at gmx.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef MERGERESULTWINDOW_H +#define MERGERESULTWINDOW_H + +#include "diff.h" + +#include <qwidget.h> +#include <qpixmap.h> +#include <qtimer.h> + +class QPainter; + +class Overview : public QWidget +{ + Q_OBJECT +public: + Overview( QWidget* pParent, OptionDialog* pOptions ); + + void init( Diff3LineList* pDiff3LineList, bool bTripleDiff ); + void reset(); + void setRange( int firstLine, int pageHeight ); + void setPaintingAllowed( bool bAllowPainting ); + + enum e_OverviewMode { eOMNormal, eOMAvsB, eOMAvsC, eOMBvsC }; + void setOverviewMode( e_OverviewMode eOverviewMode ); + e_OverviewMode getOverviewMode(); + +public slots: + void setFirstLine(int firstLine); + void slotRedraw(); +signals: + void setLine(int); +private: + const Diff3LineList* m_pDiff3LineList; + OptionDialog* m_pOptions; + bool m_bTripleDiff; + int m_firstLine; + int m_pageHeight; + QPixmap m_pixmap; + bool m_bPaintingAllowed; + e_OverviewMode m_eOverviewMode; + int m_nofLines; + + virtual void paintEvent( QPaintEvent* e ); + virtual void mousePressEvent( QMouseEvent* e ); + virtual void mouseMoveEvent( QMouseEvent* e ); + void drawColumn( QPainter& p, e_OverviewMode eOverviewMode, int x, int w, int h, int nofLines ); +}; + + +enum e_MergeDetails +{ + eDefault, + eNoChange, + eBChanged, + eCChanged, + eBCChanged, // conflict + eBCChangedAndEqual, // possible conflict + eBDeleted, + eCDeleted, + eBCDeleted, // possible conflict + + eBChanged_CDeleted, // conflict + eCChanged_BDeleted, // conflict + eBAdded, + eCAdded, + eBCAdded, // conflict + eBCAddedAndEqual // possible conflict +}; + +void mergeOneLine( const Diff3Line& d, e_MergeDetails& mergeDetails, bool& bConflict, bool& bLineRemoved, int& src, bool bTwoInputs ); + +enum e_MergeSrcSelector +{ + A=1, + B=2, + C=3 +}; + +class MergeResultWindow : public QWidget +{ + Q_OBJECT +public: + MergeResultWindow( + QWidget* pParent, + OptionDialog* pOptionDialog, + QStatusBar* pStatusBar + ); + + void init( + const LineData* pLineDataA, int sizeA, + const LineData* pLineDataB, int sizeB, + const LineData* pLineDataC, int sizeC, + const Diff3LineList* pDiff3LineList, + TotalDiffStatus* pTotalDiffStatus + ); + + void reset(); + + bool saveDocument( const QString& fileName, QTextCodec* pEncoding ); + int getNrOfUnsolvedConflicts(int* pNrOfWhiteSpaceConflicts=0); + void choose(int selector); + void chooseGlobal(int selector, bool bConflictsOnly, bool bWhiteSpaceOnly ); + + int getNofColumns(); + int getNofLines(); + int getNofVisibleColumns(); + int getNofVisibleLines(); + QString getSelection(); + void resetSelection(); + void showNrOfConflicts(); + bool isDeltaAboveCurrent(); + bool isDeltaBelowCurrent(); + bool isConflictAboveCurrent(); + bool isConflictBelowCurrent(); + bool isUnsolvedConflictAtCurrent(); + bool isUnsolvedConflictAboveCurrent(); + bool isUnsolvedConflictBelowCurrent(); + bool findString( const QString& s, int& d3vLine, int& posInLine, bool bDirDown, bool bCaseSensitive ); + void setSelection( int firstLine, int startPos, int lastLine, int endPos ); + void setOverviewMode( Overview::e_OverviewMode eOverviewMode ); + Overview::e_OverviewMode getOverviewMode(); +public slots: + void setFirstLine(int firstLine); + void setFirstColumn(int firstCol); + + void slotGoCurrent(); + void slotGoTop(); + void slotGoBottom(); + void slotGoPrevDelta(); + void slotGoNextDelta(); + void slotGoPrevUnsolvedConflict(); + void slotGoNextUnsolvedConflict(); + void slotGoPrevConflict(); + void slotGoNextConflict(); + void slotAutoSolve(); + void slotUnsolve(); + void slotMergeHistory(); + void slotRegExpAutoMerge(); + void slotSplitDiff( int firstD3lLineIdx, int lastD3lLineIdx ); + void slotJoinDiffs( int firstD3lLineIdx, int lastD3lLineIdx ); + void slotSetFastSelectorLine(int); + void setPaintingAllowed(bool); + void updateSourceMask(); + +signals: + void scroll( int deltaX, int deltaY ); + void modifiedChanged(bool bModified); + void setFastSelectorRange( int line1, int nofLines ); + void sourceMask( int srcMask, int enabledMask ); + void resizeSignal(); + void selectionEnd(); + void newSelection(); + void updateAvailabilities(); + void showPopupMenu( const QPoint& point ); + void noRelevantChangesDetected(); + +private: + void merge(bool bAutoSolve, int defaultSelector, bool bConflictsOnly=false, bool bWhiteSpaceOnly=false ); + QString getString( int lineIdx ); + + OptionDialog* m_pOptionDialog; + + const LineData* m_pldA; + const LineData* m_pldB; + const LineData* m_pldC; + int m_sizeA; + int m_sizeB; + int m_sizeC; + + const Diff3LineList* m_pDiff3LineList; + TotalDiffStatus* m_pTotalDiffStatus; + + bool m_bPaintingAllowed; + int m_delayedDrawTimer; + Overview::e_OverviewMode m_eOverviewMode; + +private: + class MergeEditLine + { + public: + MergeEditLine(Diff3LineList::const_iterator i, int src=0){m_id3l=i; m_src=src; m_bLineRemoved=false; } + void setConflict() { m_src=0; m_bLineRemoved=false; m_str=QString(); } + bool isConflict() { return m_src==0 && !m_bLineRemoved && m_str.isNull(); } + void setRemoved(int src=0) { m_src=src; m_bLineRemoved=true; m_str=QString(); } + bool isRemoved() { return m_bLineRemoved; } + bool isEditableText() { return !isConflict() && !isRemoved(); } + void setString( const QString& s ){ m_str=s; m_bLineRemoved=false; m_src=0; } + QString getString( const MergeResultWindow* ); + bool isModified() { return ! m_str.isNull() || (m_bLineRemoved && m_src==0); } + + void setSource( int src, bool bLineRemoved ) { m_src=src; m_bLineRemoved =bLineRemoved; } + int src() { return m_src; } + Diff3LineList::const_iterator id3l(){return m_id3l;} + // getString() is implemented as MergeResultWindow::getString() + private: + Diff3LineList::const_iterator m_id3l; + int m_src; // 1, 2 or 3 for A, B or C respectively, or 0 when line is from neither source. + QString m_str; // String when modified by user or null-string when orig data is used. + bool m_bLineRemoved; + }; + + class MergeEditLineList : private std::list<MergeEditLine> + { // I want to know the size immediately! + private: + typedef std::list<MergeEditLine> BASE; + int m_size; + int* m_pTotalSize; + public: + typedef std::list<MergeEditLine>::iterator iterator; + typedef std::list<MergeEditLine>::reverse_iterator reverse_iterator; + typedef std::list<MergeEditLine>::const_iterator const_iterator; + MergeEditLineList(){m_size=0; m_pTotalSize=0; } + void clear() { ds(-m_size); BASE::clear(); } + void push_back( const MergeEditLine& m) { ds(+1); BASE::push_back(m); } + void push_front( const MergeEditLine& m) { ds(+1); BASE::push_front(m); } + iterator erase( iterator i ) { ds(-1); return BASE::erase(i); } + iterator insert( iterator i, const MergeEditLine& m ) { ds(+1); return BASE::insert(i,m); } + int size(){ if (!m_pTotalSize) m_size = BASE::size(); return m_size; } + iterator begin(){return BASE::begin();} + iterator end(){return BASE::end();} + reverse_iterator rbegin(){return BASE::rbegin();} + reverse_iterator rend(){return BASE::rend();} + MergeEditLine& front(){return BASE::front();} + MergeEditLine& back(){return BASE::back();} + bool empty() { return m_size==0; } + void splice(iterator destPos, MergeEditLineList& srcList, iterator srcFirst, iterator srcLast) + { + int* pTotalSize = getTotalSizePtr() ? getTotalSizePtr() : srcList.getTotalSizePtr(); + srcList.setTotalSizePtr(0); // Force size-recalc after splice, because splice doesn't handle size-tracking + setTotalSizePtr(0); + BASE::splice( destPos, srcList, srcFirst, srcLast ); + srcList.setTotalSizePtr( pTotalSize ); + setTotalSizePtr( pTotalSize ); + } + + void setTotalSizePtr(int* pTotalSize) + { + if ( pTotalSize==0 && m_pTotalSize!=0 ) { *m_pTotalSize -= size(); } + else if ( pTotalSize!=0 && m_pTotalSize==0 ) { *pTotalSize += size(); } + m_pTotalSize = pTotalSize; + } + int* getTotalSizePtr() + { + return m_pTotalSize; + } + + private: + void ds(int deltaSize) + { + m_size+=deltaSize; + if (m_pTotalSize!=0) *m_pTotalSize+=deltaSize; + } + }; + + friend class MergeEditLine; + + struct MergeLine + { + MergeLine() + { + srcSelect=0; mergeDetails=eDefault; d3lLineIdx = -1; srcRangeLength=0; + bConflict=false; bDelta=false; bWhiteSpaceConflict=false; + } + Diff3LineList::const_iterator id3l; + int d3lLineIdx; // Needed to show the correct window pos. + int srcRangeLength; // how many src-lines have this properties + e_MergeDetails mergeDetails; + bool bConflict; + bool bWhiteSpaceConflict; + bool bDelta; + int srcSelect; + MergeEditLineList mergeEditLineList; + void split( MergeLine& ml2, int d3lLineIdx2 ) // The caller must insert the ml2 after this ml in the m_mergeLineList + { + if ( d3lLineIdx2<d3lLineIdx || d3lLineIdx2 >= d3lLineIdx + srcRangeLength ) + return; //Error + ml2.mergeDetails = mergeDetails; + ml2.bConflict = bConflict; + ml2.bWhiteSpaceConflict = bWhiteSpaceConflict; + ml2.bDelta = bDelta; + ml2.srcSelect = srcSelect; + + ml2.d3lLineIdx = d3lLineIdx2; + ml2.srcRangeLength = srcRangeLength - (d3lLineIdx2-d3lLineIdx); + srcRangeLength = d3lLineIdx2-d3lLineIdx; // current MergeLine controls fewer lines + ml2.id3l = id3l; + for(int i=0; i<srcRangeLength; ++i) + ++ml2.id3l; + + ml2.mergeEditLineList.clear(); + // Search for best place to splice + for(MergeEditLineList::iterator i=mergeEditLineList.begin(); i!=mergeEditLineList.end();++i) + { + if (i->id3l()==ml2.id3l) + { + ml2.mergeEditLineList.splice( ml2.mergeEditLineList.begin(), mergeEditLineList, i, mergeEditLineList.end() ); + return; + } + } + ml2.mergeEditLineList.setTotalSizePtr( mergeEditLineList.getTotalSizePtr() ); + ml2.mergeEditLineList.push_back(MergeEditLine(ml2.id3l)); + } + void join( MergeLine& ml2 ) // The caller must remove the ml2 from the m_mergeLineList after this call + { + srcRangeLength += ml2.srcRangeLength; + ml2.mergeEditLineList.clear(); + mergeEditLineList.clear(); + mergeEditLineList.push_back(MergeEditLine(id3l)); // Create a simple conflict + if ( ml2.bConflict ) bConflict = true; + if ( !ml2.bWhiteSpaceConflict ) bWhiteSpaceConflict = false; + if ( ml2.bDelta ) bDelta = true; + } + }; + +private: + static bool sameKindCheck( const MergeLine& ml1, const MergeLine& ml2 ); + struct HistoryMapEntry + { + MergeEditLineList mellA; + MergeEditLineList mellB; + MergeEditLineList mellC; + MergeEditLineList& choice( bool bThreeInputs ); + bool staysInPlace( bool bThreeInputs, Diff3LineList::const_iterator& iHistoryEnd ); + }; + typedef std::map<QString,HistoryMapEntry> HistoryMap; + void collectHistoryInformation( int src, Diff3LineList::const_iterator iHistoryBegin, Diff3LineList::const_iterator iHistoryEnd, HistoryMap& historyMap, std::list< HistoryMap::iterator >& hitList ); + + typedef std::list<MergeLine> MergeLineList; + MergeLineList m_mergeLineList; + MergeLineList::iterator m_currentMergeLineIt; + bool isItAtEnd( bool bIncrement, MergeLineList::iterator i ) + { + if ( bIncrement ) return i!=m_mergeLineList.end(); + else return i!=m_mergeLineList.begin(); + } + + int m_currentPos; + bool checkOverviewIgnore(MergeLineList::iterator &i); + + enum e_Direction { eUp, eDown }; + enum e_EndPoint { eDelta, eConflict, eUnsolvedConflict, eLine, eEnd }; + void go( e_Direction eDir, e_EndPoint eEndPoint ); + void calcIteratorFromLineNr( + int line, + MergeLineList::iterator& mlIt, + MergeEditLineList::iterator& melIt + ); + MergeLineList::iterator splitAtDiff3LineIdx( int d3lLineIdx ); + + virtual void paintEvent( QPaintEvent* e ); + + + void myUpdate(int afterMilliSecs); + virtual void timerEvent(QTimerEvent*); + void writeLine( + MyPainter& p, int line, const QString& str, + int srcSelect, e_MergeDetails mergeDetails, int rangeMark, bool bUserModified, bool bLineRemoved, bool bWhiteSpaceConflict + ); + void setFastSelector(MergeLineList::iterator i); + void convertToLinePos( int x, int y, int& line, int& pos ); + virtual void mousePressEvent ( QMouseEvent* e ); + virtual void mouseDoubleClickEvent ( QMouseEvent* e ); + virtual void mouseReleaseEvent ( QMouseEvent * ); + virtual void mouseMoveEvent ( QMouseEvent * ); + virtual void resizeEvent( QResizeEvent* e ); + virtual void keyPressEvent( QKeyEvent* e ); + virtual void wheelEvent( QWheelEvent* e ); + virtual void focusInEvent( QFocusEvent* e ); + virtual bool focusNextPrevChild(bool){return false;} + + QPixmap m_pixmap; + int m_firstLine; + int m_firstColumn; + int m_nofColumns; + int m_nofLines; + int m_totalSize; //Same as m_nofLines, but calculated differently + bool m_bMyUpdate; + bool m_bInsertMode; + bool m_bModified; + void setModified(bool bModified=true); + + int m_scrollDeltaX; + int m_scrollDeltaY; + int m_cursorXPos; + int m_cursorYPos; + int m_cursorOldXPos; + bool m_bCursorOn; // blinking on and off each second + QTimer m_cursorTimer; + bool m_bCursorUpdate; + QStatusBar* m_pStatusBar; + + Selection m_selection; + + bool deleteSelection2( QString& str, int& x, int& y, + MergeLineList::iterator& mlIt, MergeEditLineList::iterator& melIt ); + bool doRelevantChangesExist(); +public slots: + void deleteSelection(); + void pasteClipboard(bool bFromSelection); +private slots: + void slotCursorUpdate(); +}; + +class QLineEdit; +class QTextCodec; +class QComboBox; +class QLabel; +class WindowTitleWidget : public QWidget +{ + Q_OBJECT +private: + QLabel* m_pLabel; + QLineEdit* m_pFileNameLineEdit; + //QPushButton* m_pBrowseButton; + QLabel* m_pModifiedLabel; + QLabel* m_pEncodingLabel; + QComboBox* m_pEncodingSelector; + OptionDialog* m_pOptionDialog; + std::map<int, QTextCodec*> m_codecMap; +public: + WindowTitleWidget(OptionDialog* pOptionDialog, QWidget* pParent ); + QTextCodec* getEncoding(); + void setFileName(const QString& fileName ); + QString getFileName(); + void setEncodings( QTextCodec* pCodecForA, QTextCodec* pCodecForB, QTextCodec* pCodecForC ); + void setEncoding( QTextCodec* pCodec ); + + bool eventFilter( QObject* o, QEvent* e ); +public slots: + void slotSetModified( bool bModified ); +//private slots: +// void slotBrowseButtonClicked(); + +}; + +#endif + |