joachim99@8: /*************************************************************************** joachim99@8: difftextwindow.cpp - description joachim99@8: ------------------- joachim99@8: begin : Mon Apr 8 2002 joachim99@77: copyright : (C) 2002-2007 by Joachim Eibl joachim99@69: email : joachim.eibl at gmx.de joachim99@8: ***************************************************************************/ joachim99@8: joachim99@8: /*************************************************************************** joachim99@8: * * joachim99@8: * This program is free software; you can redistribute it and/or modify * joachim99@8: * it under the terms of the GNU General Public License as published by * joachim99@8: * the Free Software Foundation; either version 2 of the License, or * joachim99@8: * (at your option) any later version. * joachim99@8: * * joachim99@8: ***************************************************************************/ joachim99@8: joachim99@69: #include "difftextwindow.h" joachim99@8: #include "merger.h" joachim99@75: #include "optiondialog.h" joachim99@75: joachim99@75: #include joachim99@70: #include joachim99@75: #include joachim99@75: #include joachim99@75: #include joachim99@75: #include joachim99@75: #include joachim99@75: #include joachim99@75: #include joachim99@75: #include joachim99@75: #include joachim99@75: #include Chris@113: #include joachim99@75: joachim99@51: #include joachim99@69: #include joachim99@8: joachim99@77: #include joachim99@77: #include joachim99@75: #include joachim99@75: joachim99@75: joachim99@69: class DiffTextWindowData joachim99@69: { joachim99@69: public: joachim99@69: DiffTextWindowData( DiffTextWindow* p ) joachim99@69: { joachim99@69: m_pDiffTextWindow = p; joachim99@69: m_bPaintingAllowed = false; joachim99@69: m_pLineData = 0; joachim99@69: m_size = 0; joachim99@69: m_bWordWrap = false; joachim99@69: m_delayedDrawTimer = 0; joachim99@69: m_pDiff3LineVector = 0; joachim99@69: m_pManualDiffHelpList = 0; joachim99@69: m_pOptionDialog = 0; joachim99@69: m_fastSelectorLine1 = 0; joachim99@69: m_fastSelectorNofLines = 0; joachim99@69: m_bTriple = 0; joachim99@69: m_winIdx = 0; joachim99@69: m_firstLine = 0; joachim99@69: m_oldFirstLine = 0; joachim99@69: m_oldFirstColumn = 0; joachim99@69: m_firstColumn = 0; joachim99@69: m_lineNumberWidth = 0; joachim99@69: m_pStatusBar = 0; joachim99@69: m_scrollDeltaX = 0; joachim99@69: m_scrollDeltaY = 0; joachim99@69: m_bMyUpdate = false; joachim99@69: m_bSelectionInProgress = false; joachim99@92: m_pTextCodec = 0; joachim99@95: #if defined(_WIN32) || defined(Q_OS_OS2) joachim99@92: m_eLineEndStyle = eLineEndStyleDos; joachim99@92: #else joachim99@92: m_eLineEndStyle = eLineEndStyleUnix; joachim99@92: #endif joachim99@69: } joachim99@69: DiffTextWindow* m_pDiffTextWindow; joachim99@69: DiffTextWindowFrame* m_pDiffTextWindowFrame; joachim99@92: QTextCodec* m_pTextCodec; joachim99@92: e_LineEndStyle m_eLineEndStyle; joachim99@8: joachim99@69: bool m_bPaintingAllowed; joachim99@69: const LineData* m_pLineData; joachim99@69: int m_size; joachim99@69: QString m_filename; joachim99@69: bool m_bWordWrap; joachim99@69: int m_delayedDrawTimer; joachim99@69: joachim99@69: const Diff3LineVector* m_pDiff3LineVector; joachim99@69: Diff3WrapLineVector m_diff3WrapLineVector; joachim99@69: const ManualDiffHelpList* m_pManualDiffHelpList; joachim99@69: joachim99@69: OptionDialog* m_pOptionDialog; joachim99@69: QColor m_cThis; joachim99@69: QColor m_cDiff1; joachim99@69: QColor m_cDiff2; joachim99@69: QColor m_cDiffBoth; joachim99@69: joachim99@69: int m_fastSelectorLine1; joachim99@69: int m_fastSelectorNofLines; joachim99@69: joachim99@69: bool m_bTriple; joachim99@69: int m_winIdx; joachim99@69: int m_firstLine; joachim99@69: int m_oldFirstLine; joachim99@69: int m_oldFirstColumn; joachim99@69: int m_firstColumn; joachim99@69: int m_lineNumberWidth; joachim99@69: joachim99@69: void getLineInfo( joachim99@69: const Diff3Line& d, joachim99@69: int& lineIdx, joachim99@69: DiffList*& pFineDiff1, DiffList*& pFineDiff2, // return values joachim99@69: int& changed, int& changed2 ); joachim99@69: joachim99@69: QString getString( int d3lIdx ); joachim99@69: QString getLineString( int line ); joachim99@69: joachim99@69: void writeLine( joachim99@69: MyPainter& p, const LineData* pld, joachim99@69: const DiffList* pLineDiff1, const DiffList* pLineDiff2, int line, joachim99@69: int whatChanged, int whatChanged2, int srcLineIdx, joachim99@69: int wrapLineOffset, int wrapLineLength, bool bWrapLine, const QRect& invalidRect, int deviceWidth joachim99@69: ); joachim99@69: joachim99@69: void draw( MyPainter& p, const QRect& invalidRect, int deviceWidth, int beginLine, int endLine ); joachim99@69: joachim99@69: QStatusBar* m_pStatusBar; joachim99@69: joachim99@69: Selection m_selection; joachim99@69: joachim99@69: int m_scrollDeltaX; joachim99@69: int m_scrollDeltaY; joachim99@69: joachim99@69: bool m_bMyUpdate; joachim99@69: void myUpdate(int afterMilliSecs ); joachim99@69: joachim99@69: int leftInfoWidth() { return 4+m_lineNumberWidth; } // Nr of information columns on left side joachim99@69: int convertLineOnScreenToLineInSource( int lineOnScreen, e_CoordType coordType, bool bFirstLine ); joachim99@69: joachim99@69: bool m_bSelectionInProgress; joachim99@69: QPoint m_lastKnownMousePos; joachim99@69: }; joachim99@8: joachim99@8: DiffTextWindow::DiffTextWindow( joachim99@69: DiffTextWindowFrame* pParent, joachim99@8: QStatusBar* pStatusBar, joachim99@69: OptionDialog* pOptionDialog, joachim99@69: int winIdx joachim99@8: ) joachim99@75: : QWidget(pParent) joachim99@8: { joachim99@75: setObjectName(QString("DiffTextWindow%1").arg(winIdx)); joachim99@75: setAttribute( Qt::WA_OpaquePaintEvent ); joachim99@80: //setAttribute( Qt::WA_PaintOnScreen ); joachim99@75: joachim99@69: d = new DiffTextWindowData(this); joachim99@69: d->m_pDiffTextWindowFrame = pParent; joachim99@70: setFocusPolicy( Qt::ClickFocus ); joachim99@8: setAcceptDrops( true ); joachim99@8: joachim99@69: d->m_pOptionDialog = pOptionDialog; joachim99@92: init( 0, 0, d->m_eLineEndStyle, 0, 0, 0, 0, false ); joachim99@8: joachim99@8: setMinimumSize(QSize(20,20)); joachim99@8: joachim99@69: d->m_pStatusBar = pStatusBar; joachim99@69: d->m_bPaintingAllowed = true; joachim99@69: d->m_bWordWrap = false; joachim99@69: d->m_winIdx = winIdx; joachim99@27: joachim99@69: setFont(d->m_pOptionDialog->m_font); joachim99@8: } joachim99@8: joachim99@69: DiffTextWindow::~DiffTextWindow() joachim99@69: { joachim99@69: delete d; joachim99@69: } joachim99@8: joachim99@8: void DiffTextWindow::init( joachim99@8: const QString& filename, joachim99@92: QTextCodec* pTextCodec, joachim99@92: e_LineEndStyle eLineEndStyle, joachim99@58: const LineData* pLineData, joachim99@8: int size, joachim99@8: const Diff3LineVector* pDiff3LineVector, joachim99@69: const ManualDiffHelpList* pManualDiffHelpList, joachim99@8: bool bTriple joachim99@8: ) joachim99@8: { joachim99@69: d->m_filename = filename; joachim99@69: d->m_pLineData = pLineData; joachim99@69: d->m_size = size; joachim99@69: d->m_pDiff3LineVector = pDiff3LineVector; joachim99@69: d->m_diff3WrapLineVector.clear(); joachim99@69: d->m_pManualDiffHelpList = pManualDiffHelpList; joachim99@8: joachim99@69: d->m_firstLine = 0; joachim99@69: d->m_oldFirstLine = -1; joachim99@69: d->m_firstColumn = 0; joachim99@69: d->m_oldFirstColumn = -1; joachim99@69: d->m_bTriple = bTriple; joachim99@69: d->m_scrollDeltaX=0; joachim99@69: d->m_scrollDeltaY=0; joachim99@69: d->m_bMyUpdate = false; joachim99@69: d->m_fastSelectorLine1 = 0; joachim99@69: d->m_fastSelectorNofLines = 0; joachim99@69: d->m_lineNumberWidth = 0; joachim99@69: d->m_selection.reset(); joachim99@69: d->m_selection.oldFirstLine = -1; // reset is not enough here. joachim99@69: d->m_selection.oldLastLine = -1; joachim99@69: d->m_selection.lastLine = -1; joachim99@8: joachim99@92: d->m_pTextCodec = pTextCodec; joachim99@92: d->m_eLineEndStyle = eLineEndStyle; joachim99@92: joachim99@8: update(); joachim99@69: d->m_pDiffTextWindowFrame->init(); joachim99@69: } joachim99@69: joachim99@69: void DiffTextWindow::reset() joachim99@69: { joachim99@69: d->m_pLineData=0; joachim99@69: d->m_size=0; joachim99@69: d->m_pDiff3LineVector=0; joachim99@69: d->m_filename=""; joachim99@69: d->m_diff3WrapLineVector.clear(); joachim99@8: } joachim99@8: joachim99@8: void DiffTextWindow::setPaintingAllowed( bool bAllowPainting ) joachim99@8: { joachim99@69: if (d->m_bPaintingAllowed != bAllowPainting) joachim99@8: { joachim99@69: d->m_bPaintingAllowed = bAllowPainting; joachim99@69: if ( d->m_bPaintingAllowed ) update(); joachim99@69: else reset(); joachim99@8: } joachim99@8: } joachim99@8: joachim99@8: void DiffTextWindow::dragEnterEvent( QDragEnterEvent* e ) joachim99@8: { joachim99@75: e->setAccepted( e->mimeData()->hasUrls() || e->mimeData()->hasText() ); joachim99@8: // Note that the corresponding drop is handled in KDiff3App::eventFilter(). joachim99@8: } joachim99@8: joachim99@69: joachim99@8: void DiffTextWindow::setFirstLine(int firstLine) joachim99@8: { joachim99@66: int fontHeight = fontMetrics().height(); joachim99@69: joachim99@66: int newFirstLine = max2(0,firstLine); joachim99@66: joachim99@69: int deltaY = fontHeight * ( d->m_firstLine - newFirstLine ); joachim99@69: joachim99@69: d->m_firstLine = newFirstLine; joachim99@69: joachim99@69: if ( d->m_bSelectionInProgress && d->m_selection.firstLine != -1 ) joachim99@66: { joachim99@69: int line, pos; joachim99@69: convertToLinePos( d->m_lastKnownMousePos.x(), d->m_lastKnownMousePos.y(), line, pos ); joachim99@69: d->m_selection.end( line, pos ); joachim99@69: update(); joachim99@66: } joachim99@66: else joachim99@66: { joachim99@69: QWidget::scroll( 0, deltaY ); joachim99@66: } joachim99@69: d->m_pDiffTextWindowFrame->setFirstLine( d->m_firstLine ); joachim99@69: } joachim99@69: joachim99@69: int DiffTextWindow::getFirstLine() joachim99@69: { joachim99@69: return d->m_firstLine; joachim99@8: } joachim99@8: joachim99@8: void DiffTextWindow::setFirstColumn(int firstCol) joachim99@8: { joachim99@66: int fontWidth = fontMetrics().width('W'); joachim99@69: int xOffset = d->leftInfoWidth() * fontWidth; joachim99@69: joachim99@66: int newFirstColumn = max2(0,firstCol); joachim99@66: joachim99@69: int deltaX = fontWidth * ( d->m_firstColumn - newFirstColumn ); joachim99@66: joachim99@69: d->m_firstColumn = newFirstColumn; joachim99@68: joachim99@69: QRect r( xOffset, 0, width()-xOffset, height() ); joachim99@69: joachim99@69: if ( d->m_pOptionDialog->m_bRightToLeftLanguage ) joachim99@68: { joachim99@68: deltaX = -deltaX; joachim99@75: r = QRect( width()-1-xOffset, 0, -(width()-xOffset), height() ).normalized(); joachim99@68: } joachim99@68: joachim99@69: if ( d->m_bSelectionInProgress && d->m_selection.firstLine != -1 ) joachim99@69: { joachim99@69: int line, pos; joachim99@69: convertToLinePos( d->m_lastKnownMousePos.x(), d->m_lastKnownMousePos.y(), line, pos ); joachim99@69: d->m_selection.end( line, pos ); joachim99@69: update(); joachim99@69: } joachim99@69: else joachim99@69: { joachim99@69: QWidget::scroll( deltaX, 0, r ); joachim99@69: } joachim99@8: } joachim99@8: joachim99@8: int DiffTextWindow::getNofColumns() joachim99@8: { joachim99@69: if (d->m_bWordWrap) joachim99@8: { joachim99@66: return getNofVisibleColumns(); joachim99@8: } joachim99@66: else joachim99@66: { joachim99@66: int nofColumns = 0; joachim99@69: for( int i = 0; i< d->m_size; ++i ) joachim99@66: { joachim99@69: if ( d->m_pLineData[i].width( d->m_pOptionDialog->m_tabSize ) > nofColumns ) joachim99@69: nofColumns = d->m_pLineData[i].width( d->m_pOptionDialog->m_tabSize ); joachim99@66: } joachim99@66: return nofColumns; joachim99@66: } joachim99@8: } joachim99@8: joachim99@8: int DiffTextWindow::getNofLines() joachim99@8: { joachim99@69: return d->m_bWordWrap ? d->m_diff3WrapLineVector.size() : joachim99@69: d->m_pDiff3LineVector->size(); joachim99@66: } joachim99@66: joachim99@66: joachim99@66: int DiffTextWindow::convertLineToDiff3LineIdx( int line ) joachim99@66: { joachim99@69: if ( d->m_bWordWrap && d->m_diff3WrapLineVector.size()>0 ) joachim99@69: return d->m_diff3WrapLineVector[ min2( line, (int)d->m_diff3WrapLineVector.size()-1 ) ].diff3LineIndex; joachim99@66: else joachim99@66: return line; joachim99@66: } joachim99@66: joachim99@66: int DiffTextWindow::convertDiff3LineIdxToLine( int d3lIdx ) joachim99@66: { joachim99@69: if ( d->m_bWordWrap && d->m_pDiff3LineVector!=0 && d->m_pDiff3LineVector->size()>0 ) joachim99@69: return (*d->m_pDiff3LineVector)[ min2( d3lIdx, (int)d->m_pDiff3LineVector->size()-1 ) ]->sumLinesNeededForDisplay; joachim99@66: else joachim99@66: return d3lIdx; joachim99@8: } joachim99@8: joachim99@8: /** Returns a line number where the linerange [line, line+nofLines] can joachim99@8: be displayed best. If it fits into the currently visible range then joachim99@8: the returned value is the current firstLine. joachim99@8: */ joachim99@8: int getBestFirstLine( int line, int nofLines, int firstLine, int visibleLines ) joachim99@8: { joachim99@8: int newFirstLine = firstLine; joachim99@8: if ( line < firstLine || line + nofLines + 2 > firstLine + visibleLines ) joachim99@8: { joachim99@8: if ( nofLines > visibleLines || nofLines <= ( 2*visibleLines / 3 - 1) ) joachim99@8: newFirstLine = line - visibleLines/3; joachim99@8: else joachim99@8: newFirstLine = line - (visibleLines - nofLines); joachim99@8: } joachim99@8: joachim99@8: return newFirstLine; joachim99@8: } joachim99@8: joachim99@8: joachim99@8: void DiffTextWindow::setFastSelectorRange( int line1, int nofLines ) joachim99@69: { joachim99@69: d->m_fastSelectorLine1 = line1; joachim99@69: d->m_fastSelectorNofLines = nofLines; joachim99@8: if ( isVisible() ) joachim99@8: { joachim99@66: int newFirstLine = getBestFirstLine( joachim99@69: convertDiff3LineIdxToLine(d->m_fastSelectorLine1), joachim99@69: convertDiff3LineIdxToLine(d->m_fastSelectorLine1+d->m_fastSelectorNofLines)-convertDiff3LineIdxToLine(d->m_fastSelectorLine1), joachim99@69: d->m_firstLine, joachim99@66: getNofVisibleLines() joachim99@66: ); joachim99@69: if ( newFirstLine != d->m_firstLine ) joachim99@8: { joachim99@69: scroll( 0, newFirstLine - d->m_firstLine ); joachim99@8: } joachim99@8: joachim99@8: update(); joachim99@8: } joachim99@8: } joachim99@8: joachim99@8: joachim99@66: void DiffTextWindow::showStatusLine(int line ) joachim99@8: { joachim99@66: int d3lIdx = convertLineToDiff3LineIdx( line ); joachim99@98: if( d->m_pDiff3LineVector!=0 && d3lIdx >= 0 && d3lIdx<(int)d->m_pDiff3LineVector->size() ) joachim99@8: { joachim99@69: const Diff3Line* pD3l = (*d->m_pDiff3LineVector)[d3lIdx]; joachim99@69: if ( pD3l != 0 ) joachim99@69: { joachim99@69: int l = pD3l->getLineInFile( d->m_winIdx ); joachim99@8: joachim99@75: QString s = i18n("File") + " " + d->m_filename; joachim99@69: if ( l!=-1 ) joachim99@75: s += ": " + i18n("Line") + " " + QString::number( l+1 ); joachim99@69: else joachim99@75: s += ": " + i18n("Line not available"); joachim99@75: if (d->m_pStatusBar!=0) d->m_pStatusBar->showMessage(s); joachim99@69: joachim99@69: emit lineClicked( d->m_winIdx, l ); joachim99@69: } joachim99@8: } joachim99@8: } joachim99@8: joachim99@66: void DiffTextWindow::focusInEvent(QFocusEvent* e) joachim99@66: { joachim99@66: emit gotFocus(); joachim99@66: QWidget::focusInEvent(e); joachim99@66: } joachim99@8: joachim99@8: void DiffTextWindow::mousePressEvent ( QMouseEvent* e ) joachim99@8: { joachim99@69: if ( e->button() == Qt::LeftButton ) joachim99@8: { joachim99@8: int line; joachim99@8: int pos; joachim99@8: convertToLinePos( e->x(), e->y(), line, pos ); joachim99@69: if ( pos < d->m_firstColumn ) joachim99@8: { joachim99@66: emit setFastSelectorLine( convertLineToDiff3LineIdx(line) ); joachim99@69: d->m_selection.firstLine = -1; // Disable current d->m_selection joachim99@8: } joachim99@8: else joachim99@8: { // Selection joachim99@8: resetSelection(); joachim99@69: d->m_selection.start( line, pos ); joachim99@69: d->m_selection.end( line, pos ); joachim99@69: d->m_bSelectionInProgress = true; joachim99@69: d->m_lastKnownMousePos = e->pos(); joachim99@8: joachim99@66: showStatusLine( line ); joachim99@8: } joachim99@8: } joachim99@8: } joachim99@8: joachim99@68: bool isCTokenChar( QChar c ) joachim99@8: { joachim99@8: return (c=='_') || joachim99@8: ( c>='A' && c<='Z' ) || ( c>='a' && c<='z' ) || joachim99@8: (c>='0' && c<='9'); joachim99@8: } joachim99@8: joachim99@8: /// Calculate where a token starts and ends, given the x-position on screen. joachim99@69: void calcTokenPos( const QString& s, int posOnScreen, int& pos1, int& pos2, int tabSize ) joachim99@8: { joachim99@8: // Cursor conversions that consider g_tabSize joachim99@69: int pos = convertToPosInText( s, max2( 0, posOnScreen ), tabSize ); joachim99@68: if ( pos>=(int)s.length() ) joachim99@8: { joachim99@68: pos1=s.length(); joachim99@68: pos2=s.length(); joachim99@8: return; joachim99@8: } joachim99@8: joachim99@8: pos1 = pos; joachim99@8: pos2 = pos+1; joachim99@8: joachim99@68: if( isCTokenChar( s[pos1] ) ) joachim99@8: { joachim99@68: while( pos1>=0 && isCTokenChar( s[pos1] ) ) joachim99@8: --pos1; joachim99@8: ++pos1; joachim99@8: joachim99@68: while( pos2<(int)s.length() && isCTokenChar( s[pos2] ) ) joachim99@8: ++pos2; joachim99@8: } joachim99@8: } joachim99@8: joachim99@8: void DiffTextWindow::mouseDoubleClickEvent( QMouseEvent* e ) joachim99@8: { joachim99@69: d->m_bSelectionInProgress = false; joachim99@69: d->m_lastKnownMousePos = e->pos(); joachim99@69: if ( e->button() == Qt::LeftButton ) joachim99@8: { joachim99@8: int line; joachim99@8: int pos; joachim99@8: convertToLinePos( e->x(), e->y(), line, pos ); joachim99@8: joachim99@8: // Get the string data of the current line joachim99@68: QString s; joachim99@69: if ( d->m_bWordWrap ) joachim99@66: { joachim99@75: if ( line<0 || line >= (int)d->m_diff3WrapLineVector.size() ) joachim99@75: return; joachim99@69: const Diff3WrapLine& d3wl = d->m_diff3WrapLineVector[line]; joachim99@69: s = d->getString( d3wl.diff3LineIndex ).mid( d3wl.wrapLineOffset, d3wl.wrapLineLength ); joachim99@66: } joachim99@66: else joachim99@66: { joachim99@75: if ( line<0 || line >= (int)d->m_pDiff3LineVector->size() ) joachim99@75: return; joachim99@69: s = d->getString( line ); joachim99@66: } joachim99@69: joachim99@8: if ( ! s.isEmpty() ) joachim99@8: { joachim99@8: int pos1, pos2; joachim99@69: calcTokenPos( s, pos, pos1, pos2, d->m_pOptionDialog->m_tabSize ); joachim99@8: joachim99@8: resetSelection(); joachim99@69: d->m_selection.start( line, convertToPosOnScreen( s, pos1, d->m_pOptionDialog->m_tabSize ) ); joachim99@69: d->m_selection.end( line, convertToPosOnScreen( s, pos2, d->m_pOptionDialog->m_tabSize ) ); joachim99@8: update(); joachim99@69: // emit d->m_selectionEnd() happens in the mouseReleaseEvent. joachim99@66: showStatusLine( line ); joachim99@8: } joachim99@8: } joachim99@8: } joachim99@8: joachim99@69: void DiffTextWindow::mouseReleaseEvent ( QMouseEvent* e ) joachim99@8: { joachim99@69: d->m_bSelectionInProgress = false; joachim99@69: d->m_lastKnownMousePos = e->pos(); joachim99@8: //if ( e->button() == LeftButton ) joachim99@8: { joachim99@75: if (d->m_delayedDrawTimer) joachim99@75: killTimer(d->m_delayedDrawTimer); joachim99@69: d->m_delayedDrawTimer = 0; joachim99@69: if (d->m_selection.firstLine != -1 ) joachim99@8: { joachim99@8: emit selectionEnd(); joachim99@8: } joachim99@8: } joachim99@69: d->m_scrollDeltaX=0; joachim99@69: d->m_scrollDeltaY=0; joachim99@8: } joachim99@8: joachim99@69: inline int sqr(int x){return x*x;} joachim99@69: joachim99@8: void DiffTextWindow::mouseMoveEvent ( QMouseEvent * e ) joachim99@8: { joachim99@8: int line; joachim99@8: int pos; joachim99@8: convertToLinePos( e->x(), e->y(), line, pos ); joachim99@69: d->m_lastKnownMousePos = e->pos(); joachim99@69: joachim99@69: if (d->m_selection.firstLine != -1 ) joachim99@8: { joachim99@69: d->m_selection.end( line, pos ); joachim99@8: joachim99@66: showStatusLine( line ); joachim99@8: joachim99@8: // Scroll because mouse moved out of the window joachim99@8: const QFontMetrics& fm = fontMetrics(); joachim99@8: int fontWidth = fm.width('W'); joachim99@8: int deltaX=0; joachim99@8: int deltaY=0; joachim99@69: if ( ! d->m_pOptionDialog->m_bRightToLeftLanguage ) joachim99@68: { joachim99@69: if ( e->x() < d->leftInfoWidth()*fontWidth ) deltaX = -1 - abs(e->x()-d->leftInfoWidth()*fontWidth)/fontWidth; joachim99@69: if ( e->x() > width() ) deltaX = +1 + abs(e->x()-width())/fontWidth; joachim99@68: } joachim99@68: else joachim99@68: { joachim99@69: if ( e->x() > width()-1-d->leftInfoWidth()*fontWidth ) deltaX=+1+ abs(e->x() - (width()-1-d->leftInfoWidth()*fontWidth)) / fontWidth; joachim99@69: if ( e->x() < fontWidth ) deltaX=-1- abs(e->x()-fontWidth)/fontWidth; joachim99@68: } joachim99@69: if ( e->y() < 0 ) deltaY = -1 - sqr( e->y() ) / sqr(fm.height()); joachim99@69: if ( e->y() > height() ) deltaY = +1 + sqr( e->y() - height() ) / sqr(fm.height()); joachim99@80: if ( (deltaX != 0 && d->m_scrollDeltaX!=deltaX) || (deltaY!= 0 && d->m_scrollDeltaY!=deltaY) ) joachim99@8: { joachim99@69: d->m_scrollDeltaX = deltaX; joachim99@69: d->m_scrollDeltaY = deltaY; joachim99@8: emit scroll( deltaX, deltaY ); joachim99@80: if (d->m_delayedDrawTimer) joachim99@80: killTimer( d->m_delayedDrawTimer ); joachim99@69: d->m_delayedDrawTimer = startTimer(50); joachim99@66: } joachim99@66: else joachim99@66: { joachim99@69: d->m_scrollDeltaX = deltaX; joachim99@69: d->m_scrollDeltaY = deltaY; joachim99@69: d->myUpdate(0); joachim99@8: } joachim99@8: } joachim99@8: } joachim99@8: joachim99@8: joachim99@69: void DiffTextWindowData::myUpdate(int afterMilliSecs) joachim99@8: { joachim99@75: if (m_delayedDrawTimer) joachim99@75: m_pDiffTextWindow->killTimer( m_delayedDrawTimer ); joachim99@8: m_bMyUpdate = true; joachim99@69: m_delayedDrawTimer = m_pDiffTextWindow->startTimer( afterMilliSecs ); joachim99@8: } joachim99@8: joachim99@8: void DiffTextWindow::timerEvent(QTimerEvent*) joachim99@8: { joachim99@69: killTimer(d->m_delayedDrawTimer); joachim99@69: d->m_delayedDrawTimer = 0; joachim99@8: joachim99@69: if ( d->m_bMyUpdate ) joachim99@8: { joachim99@69: int fontHeight = fontMetrics().height(); joachim99@69: joachim99@69: if ( d->m_selection.oldLastLine != -1 ) joachim99@69: { joachim99@69: int lastLine; joachim99@69: int firstLine; joachim99@69: if ( d->m_selection.oldFirstLine != -1 ) joachim99@69: { joachim99@69: firstLine = min3( d->m_selection.oldFirstLine, d->m_selection.lastLine, d->m_selection.oldLastLine ); joachim99@69: lastLine = max3( d->m_selection.oldFirstLine, d->m_selection.lastLine, d->m_selection.oldLastLine ); joachim99@69: } joachim99@69: else joachim99@69: { joachim99@69: firstLine = min2( d->m_selection.lastLine, d->m_selection.oldLastLine ); joachim99@69: lastLine = max2( d->m_selection.lastLine, d->m_selection.oldLastLine ); joachim99@69: } joachim99@69: int y1 = ( firstLine - d->m_firstLine ) * fontHeight; joachim99@69: int y2 = min2( height(), ( lastLine - d->m_firstLine + 1 ) * fontHeight ); joachim99@69: joachim99@69: if ( y10 ) joachim99@69: { joachim99@69: QRect invalidRect = QRect( 0, y1, width(), y2-y1 ); joachim99@69: update( invalidRect ); joachim99@69: } joachim99@69: } joachim99@69: joachim99@69: d->m_bMyUpdate = false; joachim99@8: } joachim99@8: joachim99@69: if ( d->m_scrollDeltaX != 0 || d->m_scrollDeltaY != 0 ) joachim99@8: { joachim99@69: d->m_selection.end( d->m_selection.lastLine + d->m_scrollDeltaY, d->m_selection.lastPos + d->m_scrollDeltaX ); joachim99@69: emit scroll( d->m_scrollDeltaX, d->m_scrollDeltaY ); joachim99@69: killTimer(d->m_delayedDrawTimer); joachim99@69: d->m_delayedDrawTimer = startTimer(50); joachim99@8: } joachim99@8: } joachim99@8: joachim99@8: void DiffTextWindow::resetSelection() joachim99@8: { joachim99@69: d->m_selection.reset(); joachim99@8: update(); joachim99@8: } joachim99@8: joachim99@8: void DiffTextWindow::convertToLinePos( int x, int y, int& line, int& pos ) joachim99@8: { joachim99@8: const QFontMetrics& fm = fontMetrics(); joachim99@8: int fontHeight = fm.height(); joachim99@8: int fontWidth = fm.width('W'); joachim99@69: int xOffset = ( d->leftInfoWidth() - d->m_firstColumn ) * fontWidth; joachim99@8: joachim99@69: int yOffset = - d->m_firstLine * fontHeight; joachim99@8: joachim99@8: line = ( y - yOffset ) / fontHeight; joachim99@69: if ( ! d->m_pOptionDialog->m_bRightToLeftLanguage ) joachim99@68: pos = ( x - xOffset ) / fontWidth; joachim99@68: else joachim99@68: pos = ( (width() - 1 - x) - xOffset ) / fontWidth; joachim99@8: } joachim99@8: joachim99@8: int Selection::firstPosInLine(int l) joachim99@8: { joachim99@8: assert( firstLine != -1 ); joachim99@8: joachim99@8: int l1 = firstLine; joachim99@8: int l2 = lastLine; joachim99@8: int p1 = firstPos; joachim99@8: int p2 = lastPos; joachim99@8: if ( l1>l2 ){ std::swap(l1,l2); std::swap(p1,p2); } joachim99@8: if ( l1==l2 && p1>p2 ){ std::swap(p1,p2); } joachim99@8: joachim99@8: if ( l==l1 ) joachim99@8: return p1; joachim99@8: return 0; joachim99@8: } joachim99@8: joachim99@8: int Selection::lastPosInLine(int l) joachim99@8: { joachim99@8: assert( firstLine != -1 ); joachim99@8: joachim99@8: int l1 = firstLine; joachim99@8: int l2 = lastLine; joachim99@8: int p1 = firstPos; joachim99@8: int p2 = lastPos; joachim99@8: joachim99@8: if ( l1>l2 ){ std::swap(l1,l2); std::swap(p1,p2); } joachim99@8: if ( l1==l2 && p1>p2 ){ std::swap(p1,p2); } joachim99@8: joachim99@8: if ( l==l2 ) joachim99@8: return p2; joachim99@8: return INT_MAX; joachim99@8: } joachim99@8: joachim99@8: bool Selection::within( int l, int p ) joachim99@8: { joachim99@8: if ( firstLine == -1 ) return false; joachim99@8: int l1 = firstLine; joachim99@8: int l2 = lastLine; joachim99@8: int p1 = firstPos; joachim99@8: int p2 = lastPos; joachim99@8: if ( l1>l2 ){ std::swap(l1,l2); std::swap(p1,p2); } joachim99@8: if ( l1==l2 && p1>p2 ){ std::swap(p1,p2); } joachim99@8: if( l1 <= l && l <= l2 ) joachim99@8: { joachim99@8: if ( l1==l2 ) joachim99@8: return p>=p1 && p=p1; joachim99@8: if ( l==l2 ) joachim99@8: return pl2 ){ std::swap(l1,l2); } joachim99@8: joachim99@8: return ( l1 <= l && l <= l2 ); joachim99@8: } joachim99@8: joachim99@80: class DrawTextOptimizer joachim99@80: // Drawing continuous text is much faster than drawing one char after another. joachim99@80: { joachim99@80: private: joachim99@80: QFont m_font; joachim99@80: QPen m_pen; joachim99@80: QString m_text; joachim99@80: QPoint m_pos; joachim99@80: MyPainter* m_pPainter; joachim99@80: QFontMetrics m_fm; joachim99@80: void draw() joachim99@80: { joachim99@80: if ( m_pPainter && !m_text.isEmpty() ) joachim99@80: { joachim99@80: m_pPainter->setFont( m_font ); joachim99@80: m_pPainter->setPen( m_pen ); joachim99@80: m_pPainter->drawText( m_pos.x(), m_pos.y(), m_text, true ); joachim99@80: m_text = QString(); joachim99@80: } joachim99@80: } joachim99@80: public: joachim99@80: DrawTextOptimizer( MyPainter* pPainter ) joachim99@80: : m_fm(pPainter->fontMetrics()) joachim99@80: { joachim99@80: m_pPainter = pPainter; joachim99@80: m_font = m_pPainter->font(); joachim99@80: m_pen = m_pPainter->pen(); joachim99@80: } joachim99@80: ~DrawTextOptimizer() { end(); } joachim99@80: void setFont( const QFont& f ) joachim99@80: { joachim99@80: if ( f!=m_font ) joachim99@80: { joachim99@80: draw(); joachim99@80: m_font = f; joachim99@80: m_fm = m_pPainter->fontMetrics(); joachim99@80: } joachim99@80: } joachim99@80: void setPen( const QPen& pen ) joachim99@80: { joachim99@80: if ( pen!=m_pen ) joachim99@80: { joachim99@80: draw(); joachim99@80: m_pen = pen; joachim99@80: } joachim99@80: } joachim99@80: void drawText( int x, int y, const QString& s ) joachim99@80: { joachim99@80: if ( y!=m_pos.y() || x != m_pos.x()+m_text.length()*m_fm.width("W") ) joachim99@80: { joachim99@80: draw(); joachim99@80: m_pos = QPoint(x,y); joachim99@80: } joachim99@80: m_text += s; joachim99@80: } joachim99@80: void end() joachim99@80: { joachim99@80: draw(); joachim99@80: } joachim99@80: }; joachim99@68: joachim99@69: void DiffTextWindowData::writeLine( joachim99@68: MyPainter& p, joachim99@8: const LineData* pld, joachim99@8: const DiffList* pLineDiff1, joachim99@8: const DiffList* pLineDiff2, joachim99@8: int line, joachim99@8: int whatChanged, joachim99@8: int whatChanged2, joachim99@69: int srcLineIdx, joachim99@66: int wrapLineOffset, joachim99@66: int wrapLineLength, joachim99@69: bool bWrapLine, joachim99@69: const QRect& invalidRect, joachim99@69: int deviceWidth joachim99@8: ) joachim99@8: { joachim99@69: QFont normalFont = p.font(); joachim99@8: QFont diffFont = normalFont; joachim99@8: diffFont.setItalic( m_pOptionDialog->m_bItalicForDeltas ); joachim99@69: const QFontMetrics& fm = p.fontMetrics(); joachim99@8: int fontHeight = fm.height(); joachim99@8: int fontAscent = fm.ascent(); joachim99@8: int fontDescent = fm.descent(); joachim99@8: int fontWidth = fm.width('W'); joachim99@8: joachim99@69: int xOffset = (leftInfoWidth() - m_firstColumn)*fontWidth; joachim99@69: int yOffset = (line-m_firstLine) * fontHeight; joachim99@8: joachim99@69: QRect lineRect( 0, yOffset, deviceWidth, fontHeight ); joachim99@69: if ( ! invalidRect.intersects( lineRect ) ) joachim99@69: { joachim99@8: return; joachim99@69: } joachim99@8: joachim99@69: int fastSelectorLine1 = m_pDiffTextWindow->convertDiff3LineIdxToLine(m_fastSelectorLine1); joachim99@69: int fastSelectorLine2 = m_pDiffTextWindow->convertDiff3LineIdxToLine(m_fastSelectorLine1+m_fastSelectorNofLines)-1; joachim99@69: joachim99@66: bool bFastSelectionRange = (line>=fastSelectorLine1 && line<= fastSelectorLine2 ); joachim99@8: QColor bgColor = m_pOptionDialog->m_bgColor; joachim99@8: QColor diffBgColor = m_pOptionDialog->m_diffBgColor; joachim99@8: joachim99@8: if ( bFastSelectionRange ) joachim99@8: { joachim99@8: bgColor = m_pOptionDialog->m_currentRangeBgColor; joachim99@8: diffBgColor = m_pOptionDialog->m_currentRangeDiffBgColor; joachim99@8: } joachim99@8: joachim99@69: if ( yOffset+fontHeightm_fgColor; joachim99@80: p.setPen(c); joachim99@8: if ( changed == 2 ) { joachim99@8: c = m_cDiff2; joachim99@8: } else if ( changed == 1 ) { joachim99@8: c = m_cDiff1; joachim99@8: } else if ( changed == 3 ) { joachim99@8: c = m_cDiffBoth; joachim99@8: } joachim99@8: joachim99@69: p.fillRect( leftInfoWidth()*fontWidth, yOffset, deviceWidth, fontHeight, bgColor ); joachim99@51: joachim99@8: if (pld!=0) joachim99@8: { joachim99@8: // First calculate the "changed" information for each character. joachim99@8: int i=0; joachim99@80: QString lineString( pld->pLine, pld->size ); joachim99@8: std::vector charChanged( pld->size ); joachim99@80: Merger merger( pLineDiff1, pLineDiff2 ); joachim99@80: while( ! merger.isEndReached() && isize ) joachim99@8: { joachim99@80: if ( i < pld->size ) joachim99@8: { joachim99@80: charChanged[i] = merger.whatChanged(); joachim99@80: ++i; joachim99@8: } joachim99@80: merger.next(); joachim99@8: } joachim99@8: joachim99@68: QString s=" "; joachim99@8: // Convert tabs joachim99@8: int outPos = 0; joachim99@69: joachim99@68: int lineLength = m_bWordWrap ? wrapLineOffset+wrapLineLength : lineString.length(); joachim99@69: joachim99@80: DrawTextOptimizer dto( &p ); joachim99@80: joachim99@66: for( i=wrapLineOffset; im_tabSize ); joachim99@8: s[0] = ' '; joachim99@8: } joachim99@8: else joachim99@8: { joachim99@68: s[0] = lineString[i]; joachim99@8: } joachim99@8: joachim99@8: QColor c = m_pOptionDialog->m_fgColor; joachim99@8: int cchanged = charChanged[i] | whatChanged; joachim99@8: joachim99@8: if ( cchanged == 2 ) { joachim99@8: c = m_cDiff2; joachim99@8: } else if ( cchanged == 1 ) { joachim99@8: c = m_cDiff1; joachim99@8: } else if ( cchanged == 3 ) { joachim99@8: c = m_cDiffBoth; joachim99@8: } joachim99@8: joachim99@51: if ( c!=m_pOptionDialog->m_fgColor && whatChanged2==0 && !m_pOptionDialog->m_bShowWhiteSpace ) joachim99@51: { joachim99@51: // The user doesn't want to see highlighted white space. joachim99@51: c = m_pOptionDialog->m_fgColor; joachim99@51: } joachim99@51: joachim99@8: QRect outRect( xOffset + fontWidth*outPos, yOffset, fontWidth*spaces, fontHeight ); joachim99@68: if ( m_pOptionDialog->m_bRightToLeftLanguage ) joachim99@75: outRect = QRect( deviceWidth-1-(xOffset + fontWidth*outPos), yOffset, -fontWidth*spaces, fontHeight ).normalized(); joachim99@69: if ( invalidRect.intersects( outRect ) ) joachim99@8: { joachim99@69: if( !m_selection.within( line, outPos ) ) joachim99@8: { joachim99@51: joachim99@8: if( c!=m_pOptionDialog->m_fgColor ) joachim99@8: { joachim99@8: QColor lightc = diffBgColor; joachim99@8: p.fillRect( xOffset + fontWidth*outPos, yOffset, joachim99@8: fontWidth*spaces, fontHeight, lightc ); joachim99@80: dto.setFont(diffFont); joachim99@8: } joachim99@8: joachim99@80: dto.setPen( c ); joachim99@8: if ( s[0]==' ' && c!=m_pOptionDialog->m_fgColor && charChanged[i]!=0 ) joachim99@8: { joachim99@51: if ( m_pOptionDialog->m_bShowWhiteSpaceCharacters && m_pOptionDialog->m_bShowWhiteSpace) joachim99@8: { joachim99@8: p.fillRect( xOffset + fontWidth*outPos, yOffset+fontAscent, joachim99@80: fontWidth*spaces-1, fontDescent, c ); joachim99@8: } joachim99@8: } joachim99@8: else joachim99@8: { joachim99@80: dto.drawText( xOffset + fontWidth*outPos, yOffset + fontAscent, s ); joachim99@8: } joachim99@80: dto.setFont(normalFont); joachim99@8: } joachim99@8: else joachim99@8: { joachim99@8: p.fillRect( xOffset + fontWidth*outPos, yOffset, joachim99@75: fontWidth*(spaces), fontHeight, m_pDiffTextWindow->palette().highlight() ); joachim99@8: joachim99@80: dto.setPen( m_pDiffTextWindow->palette().highlightedText().color() ); joachim99@80: dto.drawText( xOffset + fontWidth*outPos, yOffset + fontAscent, s ); joachim99@8: joachim99@69: m_selection.bSelectionContainsData = true; joachim99@8: } joachim99@8: } joachim99@8: joachim99@8: outPos += spaces; joachim99@80: } // end for joachim99@80: dto.end(); joachim99@69: if( m_selection.lineWithin( line ) && m_selection.lineWithin( line+1 ) ) joachim99@8: { joachim99@8: p.fillRect( xOffset + fontWidth*outPos, yOffset, joachim99@75: deviceWidth, fontHeight, m_pDiffTextWindow->palette().highlight() ); joachim99@8: } joachim99@8: } joachim99@8: joachim99@69: p.fillRect( 0, yOffset, leftInfoWidth()*fontWidth, fontHeight, m_pOptionDialog->m_bgColor ); joachim99@8: joachim99@8: xOffset = (m_lineNumberWidth+2)*fontWidth; joachim99@8: int xLeft = m_lineNumberWidth*fontWidth; joachim99@8: p.setPen( m_pOptionDialog->m_fgColor ); joachim99@8: if ( pld!=0 ) joachim99@8: { joachim99@66: if ( m_pOptionDialog->m_bShowLineNumbers && !bWrapLine ) joachim99@8: { joachim99@8: QString num; joachim99@69: num.sprintf( "%0*d", m_lineNumberWidth, srcLineIdx+1); joachim99@8: p.drawText( 0, yOffset + fontAscent, num ); joachim99@8: //p.drawLine( xLeft -1, yOffset, xLeft -1, yOffset+fontHeight-1 ); joachim99@8: } joachim99@66: if ( !bWrapLine || wrapLineLength>0 ) joachim99@66: { joachim99@69: p.setPen( QPen( m_pOptionDialog->m_fgColor, 0, bWrapLine ? Qt::DotLine : Qt::SolidLine) ); joachim99@66: p.drawLine( xOffset +1, yOffset, xOffset +1, yOffset+fontHeight-1 ); joachim99@69: p.setPen( QPen( m_pOptionDialog->m_fgColor, 0, Qt::SolidLine) ); joachim99@66: } joachim99@8: } joachim99@8: if ( c!=m_pOptionDialog->m_fgColor && whatChanged2==0 )//&& whatChanged==0 ) joachim99@8: { joachim99@51: if ( m_pOptionDialog->m_bShowWhiteSpace ) joachim99@51: { joachim99@51: p.setBrushOrigin(0,0); joachim99@69: p.fillRect( xLeft, yOffset, fontWidth*2-1, fontHeight, QBrush(c,Qt::Dense5Pattern) ); joachim99@51: } joachim99@8: } joachim99@8: else joachim99@8: { joachim99@8: p.fillRect( xLeft, yOffset, fontWidth*2-1, fontHeight, c==m_pOptionDialog->m_fgColor ? bgColor : c ); joachim99@8: } joachim99@8: joachim99@8: if ( bFastSelectionRange ) joachim99@8: { joachim99@8: p.fillRect( xOffset + fontWidth-1, yOffset, 3, fontHeight, m_pOptionDialog->m_fgColor ); joachim99@8: } joachim99@69: joachim99@69: // Check if line needs a manual diff help mark joachim99@69: ManualDiffHelpList::const_iterator ci; joachim99@69: for( ci = m_pManualDiffHelpList->begin(); ci!=m_pManualDiffHelpList->end(); ++ci) joachim99@69: { joachim99@69: const ManualDiffHelpEntry& mdhe=*ci; joachim99@69: int rangeLine1 = -1; joachim99@69: int rangeLine2 = -1; joachim99@69: if (m_winIdx==1 ) { rangeLine1 = mdhe.lineA1; rangeLine2= mdhe.lineA2; } joachim99@69: if (m_winIdx==2 ) { rangeLine1 = mdhe.lineB1; rangeLine2= mdhe.lineB2; } joachim99@69: if (m_winIdx==3 ) { rangeLine1 = mdhe.lineC1; rangeLine2= mdhe.lineC2; } joachim99@69: if ( rangeLine1>=0 && rangeLine2>=0 && srcLineIdx >= rangeLine1 && srcLineIdx <= rangeLine2 ) joachim99@69: { joachim99@69: p.fillRect( xOffset - fontWidth, yOffset, fontWidth-1, fontHeight, m_pOptionDialog->m_manualHelpRangeColor ); joachim99@69: break; joachim99@69: } joachim99@69: } joachim99@8: } joachim99@8: joachim99@8: void DiffTextWindow::paintEvent( QPaintEvent* e ) joachim99@8: { joachim99@98: QRect invalidRect = e->rect(); joachim99@98: if ( invalidRect.isEmpty() || ! d->m_bPaintingAllowed ) joachim99@66: return; joachim99@8: joachim99@98: if ( d->m_pDiff3LineVector==0 || ( d->m_diff3WrapLineVector.empty() && d->m_bWordWrap ) ) joachim99@98: { joachim99@98: QPainter p(this); joachim99@98: p.fillRect( invalidRect, d->m_pOptionDialog->m_bgColor ); joachim99@69: return; joachim99@98: } joachim99@98: joachim99@69: bool bOldSelectionContainsData = d->m_selection.bSelectionContainsData; joachim99@69: d->m_selection.bSelectionContainsData = false; joachim99@69: joachim99@69: int endLine = min2( d->m_firstLine + getNofVisibleLines()+2, getNofLines() ); joachim99@69: joachim99@69: //if ( invalidRect.size()==size() ) joachim99@69: { // double buffering, obsolete with Qt4 joachim99@70: //QPainter painter(this); // Remove for Qt4 joachim99@70: //QPixmap pixmap( invalidRect.size() );// Remove for Qt4 joachim99@69: joachim99@70: MyPainter p( this, d->m_pOptionDialog->m_bRightToLeftLanguage, width(), fontMetrics().width('W') ); // For Qt4 change pixmap to this joachim99@69: joachim99@70: //p.translate( -invalidRect.x(), -invalidRect.y() );// Remove for Qt4 joachim99@69: joachim99@69: p.setFont( font() ); joachim99@69: p.QPainter::fillRect( invalidRect, d->m_pOptionDialog->m_bgColor ); joachim99@69: joachim99@69: d->draw( p, invalidRect, width(), d->m_firstLine, endLine ); joachim99@69: // p.drawLine( m_invalidRect.x(), m_invalidRect.y(), m_invalidRect.right(), m_invalidRect.bottom() ); // For test only joachim99@69: p.end(); joachim99@69: joachim99@70: //painter.drawPixmap( invalidRect.x(), invalidRect.y(), pixmap );// Remove for Qt4 joachim99@69: } joachim99@69: // else joachim99@69: // { // no double buffering joachim99@69: // MyPainter p( this, d->m_pOptionDialog->m_bRightToLeftLanguage, width(), fontMetrics().width('W') ); joachim99@69: // p.setFont( font() ); joachim99@69: // p.QPainter::fillRect( invalidRect, d->m_pOptionDialog->m_bgColor ); joachim99@69: // d->draw( p, invalidRect, width(), d->m_firstLine, endLine ); joachim99@69: // } joachim99@69: joachim99@69: joachim99@69: d->m_oldFirstLine = d->m_firstLine; joachim99@69: d->m_oldFirstColumn = d->m_firstColumn; joachim99@69: d->m_selection.oldLastLine = -1; joachim99@69: if ( d->m_selection.oldFirstLine !=-1 ) joachim99@69: d->m_selection.oldFirstLine = -1; joachim99@69: joachim99@69: if( !bOldSelectionContainsData && d->m_selection.bSelectionContainsData ) joachim99@69: emit newSelection(); joachim99@69: } joachim99@69: joachim99@69: void DiffTextWindow::print( MyPainter& p, const QRect&, int firstLine, int nofLinesPerPage ) joachim99@69: { joachim99@69: if ( d->m_pDiff3LineVector==0 || ! d->m_bPaintingAllowed || joachim99@69: ( d->m_diff3WrapLineVector.empty() && d->m_bWordWrap ) ) joachim99@69: return; joachim99@69: resetSelection(); joachim99@69: // MyPainter p( this, d->m_pOptionDialog->m_bRightToLeftLanguage, width(), fontMetrics().width('W') ); joachim99@69: int oldFirstLine = d->m_firstLine; joachim99@69: d->m_firstLine = firstLine; joachim99@75: QRect invalidRect = QRect(0,0,1000000000,1000000000); joachim99@69: QColor bgColor = d->m_pOptionDialog->m_bgColor; joachim99@69: d->m_pOptionDialog->m_bgColor = Qt::white; joachim99@69: d->draw( p, invalidRect, p.window().width(), firstLine, min2(firstLine+nofLinesPerPage,getNofLines()) ); joachim99@69: d->m_pOptionDialog->m_bgColor = bgColor; joachim99@69: d->m_firstLine = oldFirstLine; joachim99@69: } joachim99@69: joachim99@69: void DiffTextWindowData::draw( MyPainter& p, const QRect& invalidRect, int deviceWidth, int beginLine, int endLine ) joachim99@69: { joachim99@95: m_lineNumberWidth = m_pOptionDialog->m_bShowLineNumbers ? (int)log10((double)qMax(m_size,1))+1 : 0; joachim99@8: joachim99@8: if ( m_winIdx==1 ) joachim99@8: { joachim99@8: m_cThis = m_pOptionDialog->m_colorA; joachim99@8: m_cDiff1 = m_pOptionDialog->m_colorB; joachim99@8: m_cDiff2 = m_pOptionDialog->m_colorC; joachim99@8: } joachim99@8: if ( m_winIdx==2 ) joachim99@8: { joachim99@8: m_cThis = m_pOptionDialog->m_colorB; joachim99@8: m_cDiff1 = m_pOptionDialog->m_colorC; joachim99@8: m_cDiff2 = m_pOptionDialog->m_colorA; joachim99@8: } joachim99@8: if ( m_winIdx==3 ) joachim99@8: { joachim99@8: m_cThis = m_pOptionDialog->m_colorC; joachim99@8: m_cDiff1 = m_pOptionDialog->m_colorA; joachim99@8: m_cDiff2 = m_pOptionDialog->m_colorB; joachim99@8: } joachim99@8: m_cDiffBoth = m_pOptionDialog->m_colorForConflict; // Conflict color joachim99@8: joachim99@69: p.setPen( m_cThis ); joachim99@8: joachim99@69: for ( int line = beginLine; line 0 && m_diff3WrapLineVector[line-1].pD3L == d3l; joachim99@66: } joachim99@66: else joachim99@66: { joachim99@66: d3l = (*m_pDiff3LineVector)[line]; joachim99@66: } joachim99@8: DiffList* pFineDiff1; joachim99@8: DiffList* pFineDiff2; joachim99@8: int changed=0; joachim99@8: int changed2=0; joachim99@8: joachim99@69: int srcLineIdx=-1; joachim99@69: getLineInfo( *d3l, srcLineIdx, pFineDiff1, pFineDiff2, changed, changed2 ); joachim99@8: joachim99@8: writeLine( joachim99@8: p, // QPainter joachim99@69: srcLineIdx == -1 ? 0 : &m_pLineData[srcLineIdx], // Text in this line joachim99@8: pFineDiff1, joachim99@8: pFineDiff2, joachim99@8: line, // Line on the screen joachim99@8: changed, joachim99@8: changed2, joachim99@69: srcLineIdx, joachim99@66: wrapLineOffset, joachim99@66: wrapLineLength, joachim99@69: bWrapLine, joachim99@69: invalidRect, joachim99@69: deviceWidth joachim99@8: ); joachim99@8: } joachim99@8: } joachim99@8: joachim99@69: QString DiffTextWindowData::getString( int d3lIdx ) joachim99@8: { joachim99@75: if ( d3lIdx<0 || d3lIdx>=(int)m_pDiff3LineVector->size() ) joachim99@75: return QString(); joachim99@66: const Diff3Line* d3l = (*m_pDiff3LineVector)[d3lIdx]; joachim99@8: DiffList* pFineDiff1; joachim99@8: DiffList* pFineDiff2; joachim99@8: int changed=0; joachim99@8: int changed2=0; joachim99@8: int lineIdx; joachim99@8: getLineInfo( *d3l, lineIdx, pFineDiff1, pFineDiff2, changed, changed2 ); joachim99@8: joachim99@68: if (lineIdx==-1) return QString(); joachim99@8: else joachim99@8: { joachim99@58: const LineData* ld = &m_pLineData[lineIdx]; joachim99@68: return QString( ld->pLine, ld->size ); joachim99@8: } joachim99@68: return QString(); joachim99@8: } joachim99@8: joachim99@69: QString DiffTextWindowData::getLineString( int line ) joachim99@66: { joachim99@66: if ( m_bWordWrap ) joachim99@66: { joachim99@69: int d3LIdx = m_pDiffTextWindow->convertLineToDiff3LineIdx(line); joachim99@66: return getString( d3LIdx ).mid( m_diff3WrapLineVector[line].wrapLineOffset, m_diff3WrapLineVector[line].wrapLineLength ); joachim99@66: } joachim99@66: else joachim99@66: { joachim99@66: return getString( line ); joachim99@66: } joachim99@66: } joachim99@8: joachim99@69: void DiffTextWindowData::getLineInfo( joachim99@69: const Diff3Line& d3l, joachim99@8: int& lineIdx, joachim99@8: DiffList*& pFineDiff1, DiffList*& pFineDiff2, // return values joachim99@8: int& changed, int& changed2 joachim99@8: ) joachim99@8: { joachim99@8: changed=0; joachim99@8: changed2=0; joachim99@69: bool bAEqB = d3l.bAEqB || ( d3l.bWhiteLineA && d3l.bWhiteLineB ); joachim99@69: bool bAEqC = d3l.bAEqC || ( d3l.bWhiteLineA && d3l.bWhiteLineC ); joachim99@69: bool bBEqC = d3l.bBEqC || ( d3l.bWhiteLineB && d3l.bWhiteLineC ); joachim99@8: if ( m_winIdx == 1 ) { joachim99@69: lineIdx=d3l.lineA; joachim99@69: pFineDiff1=d3l.pFineAB; joachim99@69: pFineDiff2=d3l.pFineCA; joachim99@69: changed |= ((d3l.lineB==-1)!=(lineIdx==-1) ? 1 : 0) + joachim99@69: ((d3l.lineC==-1)!=(lineIdx==-1) && m_bTriple ? 2 : 0); joachim99@8: changed2 |= ( bAEqB ? 0 : 1 ) + (bAEqC || !m_bTriple ? 0 : 2); joachim99@8: } joachim99@8: else if ( m_winIdx == 2 ) { joachim99@69: lineIdx=d3l.lineB; joachim99@69: pFineDiff1=d3l.pFineBC; joachim99@69: pFineDiff2=d3l.pFineAB; joachim99@69: changed |= ((d3l.lineC==-1)!=(lineIdx==-1) && m_bTriple ? 1 : 0) + joachim99@69: ((d3l.lineA==-1)!=(lineIdx==-1) ? 2 : 0); joachim99@8: changed2 |= ( bBEqC || !m_bTriple ? 0 : 1 ) + (bAEqB ? 0 : 2); joachim99@8: } joachim99@8: else if ( m_winIdx == 3 ) { joachim99@69: lineIdx=d3l.lineC; joachim99@69: pFineDiff1=d3l.pFineCA; joachim99@69: pFineDiff2=d3l.pFineBC; joachim99@69: changed |= ((d3l.lineA==-1)!=(lineIdx==-1) ? 1 : 0) + joachim99@69: ((d3l.lineB==-1)!=(lineIdx==-1) ? 2 : 0); joachim99@8: changed2 |= ( bAEqC ? 0 : 1 ) + (bBEqC ? 0 : 2); joachim99@8: } joachim99@8: else assert(false); joachim99@8: } joachim99@8: joachim99@8: joachim99@8: joachim99@8: void DiffTextWindow::resizeEvent( QResizeEvent* e ) joachim99@8: { joachim99@8: QSize s = e->size(); joachim99@8: QFontMetrics fm = fontMetrics(); joachim99@8: int visibleLines = s.height()/fm.height()-2; joachim99@69: int visibleColumns = s.width()/fm.width('W') - d->leftInfoWidth(); joachim99@8: emit resizeSignal( visibleColumns, visibleLines ); joachim99@8: QWidget::resizeEvent(e); joachim99@8: } joachim99@8: joachim99@8: int DiffTextWindow::getNofVisibleLines() joachim99@8: { joachim99@8: QFontMetrics fm = fontMetrics(); joachim99@8: int fmh = fm.height(); joachim99@8: int h = height(); joachim99@69: return h/fmh -1;//height()/fm.height()-2; joachim99@8: } joachim99@8: joachim99@8: int DiffTextWindow::getNofVisibleColumns() joachim99@8: { joachim99@8: QFontMetrics fm = fontMetrics(); joachim99@69: return width()/fm.width('W') - d->leftInfoWidth(); joachim99@8: } joachim99@8: joachim99@8: QString DiffTextWindow::getSelection() joachim99@8: { joachim99@80: if ( d->m_pLineData==0 ) joachim99@80: return QString(); joachim99@80: joachim99@8: QString selectionString; joachim99@8: joachim99@8: int line=0; joachim99@8: int lineIdx=0; joachim99@8: joachim99@8: int it; joachim99@69: int vectorSize = d->m_bWordWrap ? d->m_diff3WrapLineVector.size() : d->m_pDiff3LineVector->size(); joachim99@66: for( it=0; itm_bWordWrap ? d->m_diff3WrapLineVector[it].pD3L : (*d->m_pDiff3LineVector)[it]; joachim99@69: if ( d->m_winIdx == 1 ) { lineIdx=d3l->lineA; } joachim99@69: else if ( d->m_winIdx == 2 ) { lineIdx=d3l->lineB; } joachim99@69: else if ( d->m_winIdx == 3 ) { lineIdx=d3l->lineC; } joachim99@8: else assert(false); joachim99@8: joachim99@8: if( lineIdx != -1 ) joachim99@69: { joachim99@69: const QChar* pLine = d->m_pLineData[lineIdx].pLine; joachim99@69: int size = d->m_pLineData[lineIdx].size; joachim99@68: QString lineString = QString( pLine, size ); joachim99@69: joachim99@69: if ( d->m_bWordWrap ) joachim99@66: { joachim99@69: size = d->m_diff3WrapLineVector[it].wrapLineLength; joachim99@69: lineString = lineString.mid( d->m_diff3WrapLineVector[it].wrapLineOffset, size ); joachim99@66: } joachim99@8: joachim99@8: // Consider tabs joachim99@8: int outPos = 0; joachim99@8: for( int i=0; im_pOptionDialog->m_tabSize ); joachim99@8: } joachim99@8: joachim99@69: if( d->m_selection.within( line, outPos ) ) joachim99@8: { joachim99@68: selectionString += lineString[i]; joachim99@8: } joachim99@8: joachim99@8: outPos += spaces; joachim99@69: } joachim99@66: joachim99@69: if( d->m_selection.within( line, outPos ) && joachim99@69: !( d->m_bWordWrap && it+1m_diff3WrapLineVector[it+1].pD3L ) joachim99@66: ) joachim99@8: { joachim99@95: #if defined(_WIN32) || defined(Q_OS_OS2) joachim99@8: selectionString += '\r'; joachim99@8: #endif joachim99@8: selectionString += '\n'; joachim99@8: } joachim99@8: } joachim99@8: joachim99@8: ++line; joachim99@8: } joachim99@8: joachim99@8: return selectionString; joachim99@8: } joachim99@8: joachim99@68: bool DiffTextWindow::findString( const QString& s, int& d3vLine, int& posInLine, bool bDirDown, bool bCaseSensitive ) joachim99@8: { joachim99@8: int it = d3vLine; joachim99@69: int endIt = bDirDown ? (int)d->m_pDiff3LineVector->size() : -1; joachim99@8: int step = bDirDown ? 1 : -1; joachim99@8: int startPos = posInLine; joachim99@8: joachim99@8: for( ; it!=endIt; it+=step ) joachim99@8: { joachim99@69: QString line = d->getString( it ); joachim99@8: if ( !line.isEmpty() ) joachim99@8: { joachim99@75: int pos = line.indexOf( s, startPos, bCaseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive ); joachim99@8: if ( pos != -1 ) joachim99@8: { joachim99@8: d3vLine = it; joachim99@8: posInLine = pos; joachim99@8: return true; joachim99@8: } joachim99@8: joachim99@69: startPos = 0; joachim99@8: } joachim99@8: } joachim99@8: return false; joachim99@8: } joachim99@8: joachim99@66: void DiffTextWindow::convertD3LCoordsToLineCoords( int d3LIdx, int d3LPos, int& line, int& pos ) joachim99@66: { joachim99@69: if( d->m_bWordWrap ) joachim99@66: { joachim99@66: int wrapPos = d3LPos; joachim99@66: int wrapLine = convertDiff3LineIdxToLine(d3LIdx); joachim99@69: while ( wrapPos > d->m_diff3WrapLineVector[wrapLine].wrapLineLength ) joachim99@66: { joachim99@69: wrapPos -= d->m_diff3WrapLineVector[wrapLine].wrapLineLength; joachim99@66: ++wrapLine; joachim99@66: } joachim99@66: pos = wrapPos; joachim99@66: line = wrapLine; joachim99@66: } joachim99@66: else joachim99@66: { joachim99@66: pos = d3LPos; joachim99@66: line = d3LIdx; joachim99@66: } joachim99@66: } joachim99@66: joachim99@66: void DiffTextWindow::convertLineCoordsToD3LCoords( int line, int pos, int& d3LIdx, int& d3LPos ) joachim99@66: { joachim99@69: if( d->m_bWordWrap ) joachim99@66: { joachim99@66: d3LPos = pos; joachim99@66: d3LIdx = convertLineToDiff3LineIdx( line ); joachim99@66: int wrapLine = convertDiff3LineIdxToLine(d3LIdx); // First wrap line belonging to this d3LIdx joachim99@66: while ( wrapLine < line ) joachim99@66: { joachim99@69: d3LPos += d->m_diff3WrapLineVector[wrapLine].wrapLineLength; joachim99@66: ++wrapLine; joachim99@66: } joachim99@66: } joachim99@66: else joachim99@66: { joachim99@66: d3LPos = pos; joachim99@66: d3LIdx = line; joachim99@66: } joachim99@66: } joachim99@66: joachim99@66: joachim99@66: void DiffTextWindow::setSelection( int firstLine, int startPos, int lastLine, int endPos, int& l, int& p ) joachim99@8: { joachim99@69: d->m_selection.reset(); joachim99@69: if ( lastLine >= getNofLines() ) joachim99@69: { joachim99@69: lastLine = getNofLines()-1; joachim99@69: joachim99@69: const Diff3Line* d3l = (*d->m_pDiff3LineVector)[convertLineToDiff3LineIdx(lastLine)]; joachim99@69: int line = -1; joachim99@69: if ( d->m_winIdx==1 ) line = d3l->lineA; joachim99@69: if ( d->m_winIdx==2 ) line = d3l->lineB; joachim99@69: if ( d->m_winIdx==3 ) line = d3l->lineC; joachim99@69: if (line>=0) joachim99@69: endPos = d->m_pLineData[line].width( d->m_pOptionDialog->m_tabSize); joachim99@69: } joachim99@69: joachim99@69: if ( d->m_bWordWrap && d->m_pDiff3LineVector!=0 ) joachim99@69: { joachim99@69: QString s1 = d->getString(firstLine); joachim99@66: int firstWrapLine = convertDiff3LineIdxToLine(firstLine); joachim99@66: int wrapStartPos = startPos; joachim99@69: while ( wrapStartPos > d->m_diff3WrapLineVector[firstWrapLine].wrapLineLength ) joachim99@66: { joachim99@69: wrapStartPos -= d->m_diff3WrapLineVector[firstWrapLine].wrapLineLength; joachim99@69: s1 = s1.mid(d->m_diff3WrapLineVector[firstWrapLine].wrapLineLength); joachim99@66: ++firstWrapLine; joachim99@66: } joachim99@66: joachim99@69: QString s2 = d->getString(lastLine); joachim99@66: int lastWrapLine = convertDiff3LineIdxToLine(lastLine); joachim99@66: int wrapEndPos = endPos; joachim99@69: while ( wrapEndPos > d->m_diff3WrapLineVector[lastWrapLine].wrapLineLength ) joachim99@66: { joachim99@69: wrapEndPos -= d->m_diff3WrapLineVector[lastWrapLine].wrapLineLength; joachim99@69: s2 = s2.mid(d->m_diff3WrapLineVector[lastWrapLine].wrapLineLength); joachim99@66: ++lastWrapLine; joachim99@66: } joachim99@66: joachim99@69: d->m_selection.start( firstWrapLine, convertToPosOnScreen( s1, wrapStartPos, d->m_pOptionDialog->m_tabSize ) ); joachim99@69: d->m_selection.end( lastWrapLine, convertToPosOnScreen( s2, wrapEndPos, d->m_pOptionDialog->m_tabSize ) ); joachim99@66: l=firstWrapLine; joachim99@66: p=wrapStartPos; joachim99@66: } joachim99@66: else joachim99@66: { joachim99@69: d->m_selection.start( firstLine, convertToPosOnScreen( d->getString(firstLine), startPos, d->m_pOptionDialog->m_tabSize ) ); joachim99@69: d->m_selection.end( lastLine, convertToPosOnScreen( d->getString(lastLine), endPos, d->m_pOptionDialog->m_tabSize ) ); joachim99@66: l=firstLine; joachim99@66: p=startPos; joachim99@66: } joachim99@8: update(); joachim99@8: } joachim99@51: joachim99@69: int DiffTextWindowData::convertLineOnScreenToLineInSource( int lineOnScreen, e_CoordType coordType, bool bFirstLine ) joachim99@69: { joachim99@69: int line=-1; joachim99@69: if (lineOnScreen>=0) joachim99@69: { joachim99@69: if (coordType==eWrapCoords) return lineOnScreen; joachim99@69: int d3lIdx = m_pDiffTextWindow->convertLineToDiff3LineIdx( lineOnScreen ); joachim99@69: if ( !bFirstLine && d3lIdx >= (int)m_pDiff3LineVector->size() ) joachim99@69: d3lIdx = m_pDiff3LineVector->size()-1; joachim99@69: if (coordType==eD3LLineCoords) return d3lIdx; joachim99@69: while ( line<0 && d3lIdx<(int)m_pDiff3LineVector->size() && d3lIdx>=0 ) joachim99@69: { joachim99@69: const Diff3Line* d3l = (*m_pDiff3LineVector)[d3lIdx]; joachim99@69: if ( m_winIdx==1 ) line = d3l->lineA; joachim99@69: if ( m_winIdx==2 ) line = d3l->lineB; joachim99@69: if ( m_winIdx==3 ) line = d3l->lineC; joachim99@69: if ( bFirstLine ) joachim99@69: ++d3lIdx; joachim99@69: else joachim99@69: --d3lIdx; joachim99@69: } joachim99@69: if (coordType==eFileCoords) return line; joachim99@69: } joachim99@69: return line; joachim99@69: } joachim99@69: joachim99@69: joachim99@69: void DiffTextWindow::getSelectionRange( int* pFirstLine, int* pLastLine, e_CoordType coordType ) joachim99@69: { joachim99@69: if (pFirstLine) joachim99@69: *pFirstLine = d->convertLineOnScreenToLineInSource( d->m_selection.beginLine(), coordType, true ); joachim99@69: if (pLastLine) joachim99@69: *pLastLine = d->convertLineOnScreenToLineInSource( d->m_selection.endLine(), coordType, false ); joachim99@69: } joachim99@51: joachim99@66: // Returns the number of wrapped lines joachim99@66: // if pWrappedLines != 0 then the stringlist will contain the wrapped lines. joachim99@66: int wordWrap( const QString& origLine, int nofColumns, Diff3WrapLine* pDiff3WrapLine ) joachim99@69: { joachim99@66: if (nofColumns<=0) joachim99@66: nofColumns = 1; joachim99@69: joachim99@66: int nofNeededLines = 0; joachim99@66: int length = origLine.length(); joachim99@69: joachim99@66: if (length==0) joachim99@66: { joachim99@66: nofNeededLines = 1; joachim99@66: if( pDiff3WrapLine ) joachim99@66: { joachim99@66: pDiff3WrapLine->wrapLineOffset=0; joachim99@66: pDiff3WrapLine->wrapLineLength=0; joachim99@66: } joachim99@66: } joachim99@66: else joachim99@69: { joachim99@66: int pos = 0; joachim99@69: joachim99@66: while ( pos < length ) joachim99@66: { joachim99@66: int wrapPos = pos + nofColumns; joachim99@69: joachim99@66: if ( length-pos <= nofColumns ) joachim99@66: { joachim99@66: wrapPos = length; joachim99@66: } joachim99@66: else joachim99@69: { joachim99@75: int wsPos = max2( origLine.lastIndexOf( ' ', wrapPos ), origLine.lastIndexOf( '\t', wrapPos ) ); joachim99@69: joachim99@66: if ( wsPos > pos ) joachim99@66: { joachim99@66: // Wrap line at wsPos joachim99@66: wrapPos = wsPos; joachim99@66: } joachim99@66: } joachim99@69: joachim99@66: if ( pDiff3WrapLine ) joachim99@66: { joachim99@66: pDiff3WrapLine->wrapLineOffset = pos; joachim99@66: pDiff3WrapLine->wrapLineLength = wrapPos-pos; joachim99@66: ++pDiff3WrapLine; joachim99@66: } joachim99@69: joachim99@66: pos = wrapPos; joachim99@69: joachim99@66: ++nofNeededLines; joachim99@66: } joachim99@66: } joachim99@69: return nofNeededLines; joachim99@66: } joachim99@66: joachim99@66: void DiffTextWindow::convertSelectionToD3LCoords() joachim99@66: { joachim99@69: if ( d->m_pDiff3LineVector==0 || ! d->m_bPaintingAllowed || !isVisible() || d->m_selection.isEmpty() ) joachim99@66: { joachim99@66: return; joachim99@66: } joachim99@66: joachim99@69: // convert the d->m_selection to unwrapped coordinates: Later restore to new coords joachim99@66: int firstD3LIdx, firstD3LPos; joachim99@69: QString s = d->getLineString( d->m_selection.beginLine() ); joachim99@69: int firstPosInText = convertToPosInText( s, d->m_selection.beginPos(), d->m_pOptionDialog->m_tabSize ); joachim99@69: convertLineCoordsToD3LCoords( d->m_selection.beginLine(), firstPosInText, firstD3LIdx, firstD3LPos ); joachim99@69: joachim99@66: int lastD3LIdx, lastD3LPos; joachim99@69: s = d->getLineString( d->m_selection.endLine() ); joachim99@69: int lastPosInText = convertToPosInText( s, d->m_selection.endPos(), d->m_pOptionDialog->m_tabSize ); joachim99@69: convertLineCoordsToD3LCoords( d->m_selection.endLine(), lastPosInText, lastD3LIdx, lastD3LPos ); joachim99@69: joachim99@69: //d->m_selection.reset(); joachim99@69: d->m_selection.start( firstD3LIdx, firstD3LPos ); joachim99@69: d->m_selection.end( lastD3LIdx, lastD3LPos ); joachim99@66: } joachim99@66: joachim99@69: void DiffTextWindow::recalcWordWrap( bool bWordWrap, int wrapLineVectorSize, int nofVisibleColumns ) joachim99@69: { joachim99@69: if ( d->m_pDiff3LineVector==0 || ! d->m_bPaintingAllowed || !isVisible() ) joachim99@66: { joachim99@69: d->m_bWordWrap = bWordWrap; joachim99@69: if (!bWordWrap) d->m_diff3WrapLineVector.resize( 0 ); joachim99@66: return; joachim99@66: } joachim99@69: joachim99@69: d->m_bWordWrap = bWordWrap; joachim99@69: joachim99@66: if ( bWordWrap ) joachim99@69: { joachim99@69: d->m_diff3WrapLineVector.resize( wrapLineVectorSize ); joachim99@69: joachim99@69: if (nofVisibleColumns<0) joachim99@69: nofVisibleColumns = getNofVisibleColumns(); joachim99@69: else joachim99@69: nofVisibleColumns-= d->leftInfoWidth(); joachim99@66: int i; joachim99@66: int wrapLineIdx = 0; joachim99@69: int size = d->m_pDiff3LineVector->size(); joachim99@66: for( i=0; igetString( i ); joachim99@69: int linesNeeded = wordWrap( s, nofVisibleColumns, wrapLineVectorSize==0 ? 0 : &d->m_diff3WrapLineVector[wrapLineIdx] ); joachim99@69: Diff3Line& d3l = *(*d->m_pDiff3LineVector)[i]; joachim99@66: if ( d3l.linesNeededForDisplay0 ) joachim99@66: { joachim99@66: int j; joachim99@66: for( j=0; jm_diff3WrapLineVector[wrapLineIdx]; joachim99@66: d3wl.diff3LineIndex = i; joachim99@69: d3wl.pD3L = (*d->m_pDiff3LineVector)[i]; joachim99@66: if ( j>=linesNeeded ) joachim99@66: { joachim99@66: d3wl.wrapLineOffset=0; joachim99@66: d3wl.wrapLineLength=0; joachim99@66: } joachim99@66: } joachim99@66: } joachim99@69: } joachim99@69: joachim99@66: if ( wrapLineVectorSize>0 ) joachim99@69: { joachim99@69: d->m_firstLine = min2( d->m_firstLine, wrapLineVectorSize-1 ); joachim99@69: d->m_firstColumn = 0; joachim99@69: d->m_pDiffTextWindowFrame->setFirstLine( d->m_firstLine ); joachim99@66: } joachim99@66: } joachim99@66: else joachim99@66: { joachim99@69: d->m_diff3WrapLineVector.resize( 0 ); joachim99@66: } joachim99@69: joachim99@69: if ( !d->m_selection.isEmpty() && ( !d->m_bWordWrap || wrapLineVectorSize>0 ) ) joachim99@69: { joachim99@66: // Assume unwrapped coordinates joachim99@66: //( Why? ->Conversion to unwrapped coords happened a few lines above in this method. joachim99@66: // Also see KDiff3App::recalcWordWrap() on the role of wrapLineVectorSize) joachim99@69: joachim99@66: // Wrap them now. joachim99@69: joachim99@69: // convert the d->m_selection to unwrapped coordinates. joachim99@66: int firstLine, firstPos; joachim99@69: convertD3LCoordsToLineCoords( d->m_selection.beginLine(), d->m_selection.beginPos(), firstLine, firstPos ); joachim99@69: joachim99@66: int lastLine, lastPos; joachim99@69: convertD3LCoordsToLineCoords( d->m_selection.endLine(), d->m_selection.endPos(), lastLine, lastPos ); joachim99@69: joachim99@69: //d->m_selection.reset(); joachim99@69: d->m_selection.start( firstLine, convertToPosOnScreen( d->getLineString( firstLine ), firstPos, d->m_pOptionDialog->m_tabSize ) ); joachim99@69: d->m_selection.end( lastLine, convertToPosOnScreen( d->getLineString( lastLine ),lastPos, d->m_pOptionDialog->m_tabSize ) ); joachim99@69: } joachim99@66: } joachim99@66: joachim99@66: joachim99@69: class DiffTextWindowFrameData joachim99@69: { joachim99@69: public: joachim99@69: DiffTextWindow* m_pDiffTextWindow; joachim99@69: QLineEdit* m_pFileSelection; joachim99@69: QPushButton* m_pBrowseButton; joachim99@69: OptionDialog* m_pOptionDialog; joachim99@69: QLabel* m_pLabel; joachim99@69: QLabel* m_pTopLine; joachim99@92: QLabel* m_pEncoding; joachim99@92: QLabel* m_pLineEndStyle; joachim99@69: QWidget* m_pTopLineWidget; joachim99@80: int m_winIdx; joachim99@69: }; joachim99@66: joachim99@69: DiffTextWindowFrame::DiffTextWindowFrame( QWidget* pParent, QStatusBar* pStatusBar, OptionDialog* pOptionDialog, int winIdx ) joachim99@69: : QWidget( pParent ) joachim99@69: { joachim99@69: d = new DiffTextWindowFrameData; joachim99@80: d->m_winIdx = winIdx; joachim99@75: setAutoFillBackground(true); joachim99@69: d->m_pOptionDialog = pOptionDialog; joachim99@69: d->m_pTopLineWidget = new QWidget(this); joachim99@69: d->m_pFileSelection = new QLineEdit(d->m_pTopLineWidget); joachim99@69: d->m_pBrowseButton = new QPushButton( "...",d->m_pTopLineWidget ); joachim99@69: d->m_pBrowseButton->setFixedWidth( 30 ); joachim99@69: connect(d->m_pBrowseButton,SIGNAL(clicked()), this, SLOT(slotBrowseButtonClicked())); joachim99@69: connect(d->m_pFileSelection,SIGNAL(returnPressed()), this, SLOT(slotReturnPressed())); joachim99@66: joachim99@69: d->m_pLabel = new QLabel("A:",d->m_pTopLineWidget); joachim99@69: d->m_pTopLine = new QLabel(d->m_pTopLineWidget); joachim99@69: d->m_pDiffTextWindow = 0; joachim99@69: d->m_pDiffTextWindow = new DiffTextWindow( this, pStatusBar, pOptionDialog, winIdx ); joachim99@92: joachim99@92: QVBoxLayout* pVTopLayout = new QVBoxLayout(d->m_pTopLineWidget); joachim99@92: pVTopLayout->setMargin(2); joachim99@92: pVTopLayout->setSpacing(0); joachim99@92: QHBoxLayout* pHL = new QHBoxLayout(); joachim99@92: QHBoxLayout* pHL2 = new QHBoxLayout(); joachim99@92: pVTopLayout->addLayout(pHL); joachim99@92: pVTopLayout->addLayout(pHL2); joachim99@92: joachim99@92: // Upper line: joachim99@92: pHL->setMargin(0); joachim99@69: pHL->setSpacing(2); joachim99@51: joachim99@69: pHL->addWidget( d->m_pLabel, 0 ); joachim99@69: pHL->addWidget( d->m_pFileSelection, 1 ); joachim99@69: pHL->addWidget( d->m_pBrowseButton, 0 ); joachim99@69: pHL->addWidget( d->m_pTopLine, 0 ); joachim99@69: joachim99@92: // Lower line joachim99@92: pHL2->setMargin(0); joachim99@92: pHL2->setSpacing(2); joachim99@92: pHL2->addWidget( d->m_pTopLine, 0 ); joachim99@92: d->m_pEncoding = new QLabel(i18n("Encoding:")); joachim99@92: d->m_pLineEndStyle = new QLabel(i18n("Line end style:")); joachim99@92: pHL2->addWidget(d->m_pEncoding); joachim99@92: pHL2->addWidget(d->m_pLineEndStyle); joachim99@92: joachim99@75: QVBoxLayout* pVL = new QVBoxLayout( this ); joachim99@75: pVL->setMargin(0); joachim99@75: pVL->setSpacing(0); joachim99@69: pVL->addWidget( d->m_pTopLineWidget, 0 ); joachim99@69: pVL->addWidget( d->m_pDiffTextWindow, 1 ); joachim99@69: joachim99@69: d->m_pDiffTextWindow->installEventFilter( this ); joachim99@69: d->m_pFileSelection->installEventFilter( this ); joachim99@69: d->m_pBrowseButton->installEventFilter( this ); joachim99@69: init(); joachim99@69: } joachim99@69: joachim99@69: DiffTextWindowFrame::~DiffTextWindowFrame() joachim99@69: { joachim99@69: delete d; joachim99@69: } joachim99@69: joachim99@69: void DiffTextWindowFrame::init() joachim99@69: { joachim99@69: DiffTextWindow* pDTW = d->m_pDiffTextWindow; joachim99@69: if ( pDTW ) joachim99@69: { joachim99@75: QString s = QDir::toNativeSeparators( pDTW->d->m_filename ); joachim99@69: d->m_pFileSelection->setText( s ); joachim99@69: QString winId = pDTW->d->m_winIdx==1 ? joachim99@69: ( pDTW->d->m_bTriple?"A (Base)":"A") : joachim99@69: ( pDTW->d->m_winIdx==2 ? "B" : "C" ); joachim99@69: d->m_pLabel->setText( winId + ":" ); joachim99@92: d->m_pEncoding->setText( i18n("Encoding:") + " " + (pDTW->d->m_pTextCodec!=0 ? pDTW->d->m_pTextCodec->name() : QString()) ); joachim99@92: d->m_pLineEndStyle->setText( i18n("Line end style:") + " " + (pDTW->d->m_eLineEndStyle==eLineEndStyleDos ? i18n("DOS") : i18n("Unix")) ); joachim99@69: } joachim99@69: } joachim99@69: joachim99@69: // Search for the first visible line (search loop needed when no line exist for this file.) joachim99@69: int DiffTextWindow::calcTopLineInFile( int firstLine ) joachim99@69: { joachim99@69: int l=-1; joachim99@69: for ( int i = convertLineToDiff3LineIdx(firstLine); i<(int)d->m_pDiff3LineVector->size(); ++i ) joachim99@69: { joachim99@69: const Diff3Line* d3l = (*d->m_pDiff3LineVector)[i]; joachim99@69: l = d3l->getLineInFile(d->m_winIdx); joachim99@69: if (l!=-1) break; joachim99@69: } joachim99@69: return l; joachim99@69: } joachim99@69: joachim99@69: void DiffTextWindowFrame::setFirstLine( int firstLine ) joachim99@69: { joachim99@69: DiffTextWindow* pDTW = d->m_pDiffTextWindow; joachim99@69: if ( pDTW && pDTW->d->m_pDiff3LineVector ) joachim99@69: { joachim99@69: QString s= i18n("Top line"); joachim99@95: int lineNumberWidth = (int)log10((double)qMax(pDTW->d->m_size,1))+1; joachim99@69: joachim99@69: int l=pDTW->calcTopLineInFile(firstLine); joachim99@69: joachim99@69: int w = d->m_pTopLine->fontMetrics().width( joachim99@69: s+" "+QString().fill('0',lineNumberWidth)); joachim99@69: d->m_pTopLine->setMinimumWidth( w ); joachim99@69: joachim99@69: if (l==-1) joachim99@69: s = i18n("End"); joachim99@69: else joachim99@69: s += " " + QString::number( l+1 ); joachim99@69: joachim99@69: d->m_pTopLine->setText( s ); joachim99@69: d->m_pTopLine->repaint(); joachim99@69: } joachim99@69: } joachim99@69: joachim99@69: DiffTextWindow* DiffTextWindowFrame::getDiffTextWindow() joachim99@69: { joachim99@69: return d->m_pDiffTextWindow; joachim99@69: } joachim99@69: joachim99@69: bool DiffTextWindowFrame::eventFilter( QObject* o, QEvent* e ) joachim99@69: { joachim99@69: DiffTextWindow* pDTW = d->m_pDiffTextWindow; joachim99@69: if ( e->type()==QEvent::FocusIn || e->type()==QEvent::FocusOut ) joachim99@69: { joachim99@69: QColor c1 = d->m_pOptionDialog->m_bgColor; joachim99@80: QColor c2; joachim99@80: if ( d->m_winIdx==1 ) c2 = d->m_pOptionDialog->m_colorA; joachim99@80: else if ( d->m_winIdx==2 ) c2 = d->m_pOptionDialog->m_colorB; joachim99@80: else if ( d->m_winIdx==3 ) c2 = d->m_pOptionDialog->m_colorC; joachim99@80: joachim99@69: QPalette p = d->m_pTopLineWidget->palette(); joachim99@69: if ( e->type()==QEvent::FocusOut ) joachim99@69: std::swap(c1,c2); joachim99@69: joachim99@70: p.setColor(QPalette::Window, c2); joachim99@70: setPalette( p ); joachim99@69: joachim99@70: p.setColor(QPalette::WindowText, c1); joachim99@69: d->m_pLabel->setPalette( p ); joachim99@69: d->m_pTopLine->setPalette( p ); joachim99@92: d->m_pEncoding->setPalette( p ); joachim99@92: d->m_pLineEndStyle->setPalette( p ); joachim99@69: } joachim99@69: if (o == d->m_pFileSelection && e->type()==QEvent::Drop) joachim99@69: { joachim99@69: QDropEvent* d = static_cast(e); joachim99@92: joachim99@75: if ( d->mimeData()->hasUrls() ) joachim99@69: { joachim99@75: QList lst = d->mimeData()->urls(); joachim99@69: joachim99@69: if ( lst.count() > 0 ) joachim99@69: { joachim99@75: static_cast(o)->setText( lst[0].toString() ); joachim99@69: static_cast(o)->setFocus(); joachim99@75: emit fileNameChanged( lst[0].toString(), pDTW->d->m_winIdx ); joachim99@69: return true; joachim99@69: } joachim99@69: } joachim99@69: } joachim99@69: return false; joachim99@69: } joachim99@69: joachim99@69: void DiffTextWindowFrame::slotReturnPressed() joachim99@69: { joachim99@69: DiffTextWindow* pDTW = d->m_pDiffTextWindow; joachim99@69: if ( pDTW->d->m_filename != d->m_pFileSelection->text() ) joachim99@69: { joachim99@69: emit fileNameChanged( d->m_pFileSelection->text(), pDTW->d->m_winIdx ); joachim99@69: } joachim99@69: } joachim99@69: joachim99@69: void DiffTextWindowFrame::slotBrowseButtonClicked() joachim99@69: { joachim99@69: QString current = d->m_pFileSelection->text(); joachim99@69: joachim99@80: KUrl newURL = KFileDialog::getOpenUrl( current, 0, this); joachim99@69: if ( !newURL.isEmpty() ) joachim99@69: { joachim99@69: DiffTextWindow* pDTW = d->m_pDiffTextWindow; joachim99@69: emit fileNameChanged( newURL.url(), pDTW->d->m_winIdx ); joachim99@69: } joachim99@69: }