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