/*************************************************************************** difftextwindow.cpp - description ------------------- begin : Mon Apr 8 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. * * * ***************************************************************************/ #include "difftextwindow.h" #include "merger.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include class DiffTextWindowData { public: DiffTextWindowData( DiffTextWindow* p ) { m_pDiffTextWindow = p; m_bPaintingAllowed = false; m_pLineData = 0; m_size = 0; m_bWordWrap = false; m_delayedDrawTimer = 0; m_pDiff3LineVector = 0; m_pManualDiffHelpList = 0; m_pOptionDialog = 0; m_fastSelectorLine1 = 0; m_fastSelectorNofLines = 0; m_bTriple = 0; m_winIdx = 0; m_firstLine = 0; m_oldFirstLine = 0; m_oldFirstColumn = 0; m_firstColumn = 0; m_lineNumberWidth = 0; m_pStatusBar = 0; m_scrollDeltaX = 0; m_scrollDeltaY = 0; m_bMyUpdate = false; m_bSelectionInProgress = false; } DiffTextWindow* m_pDiffTextWindow; DiffTextWindowFrame* m_pDiffTextWindowFrame; bool m_bPaintingAllowed; const LineData* m_pLineData; int m_size; TQString m_filename; bool m_bWordWrap; int m_delayedDrawTimer; const Diff3LineVector* m_pDiff3LineVector; Diff3WrapLineVector m_diff3WrapLineVector; const ManualDiffHelpList* m_pManualDiffHelpList; OptionDialog* m_pOptionDialog; TQColor m_cThis; TQColor m_cDiff1; TQColor m_cDiff2; TQColor m_cDiffBoth; int m_fastSelectorLine1; int m_fastSelectorNofLines; bool m_bTriple; int m_winIdx; int m_firstLine; int m_oldFirstLine; int m_oldFirstColumn; int m_firstColumn; int m_lineNumberWidth; void getLineInfo( const Diff3Line& d, int& lineIdx, DiffList*& pFineDiff1, DiffList*& pFineDiff2, // return values int& changed, int& changed2 ); TQString getString( int d3lIdx ); TQString getLineString( int line ); void writeLine( MyPainter& p, const LineData* pld, const DiffList* pLineDiff1, const DiffList* pLineDiff2, int line, int whatChanged, int whatChanged2, int srcLineIdx, int wrapLineOffset, int wrapLineLength, bool bWrapLine, const TQRect& invalidRect, int deviceWidth ); void draw( MyPainter& p, const TQRect& invalidRect, int deviceWidth, int beginLine, int endLine ); TQStatusBar* m_pStatusBar; Selection m_selection; int m_scrollDeltaX; int m_scrollDeltaY; bool m_bMyUpdate; void myUpdate(int afterMilliSecs ); int leftInfoWidth() { return 4+m_lineNumberWidth; } // Nr of information columns on left side int convertLineOnScreenToLineInSource( int lineOnScreen, e_CoordType coordType, bool bFirstLine ); bool m_bSelectionInProgress; TQPoint m_lastKnownMousePos; }; DiffTextWindow::DiffTextWindow( DiffTextWindowFrame* pParent, TQStatusBar* pStatusBar, OptionDialog* pOptionDialog, int winIdx ) : TQWidget(pParent, 0, TQt::WResizeNoErase | TQt::WRepaintNoErase) { d = new DiffTextWindowData(this); d->m_pDiffTextWindowFrame = pParent; setFocusPolicy( TQWidget::ClickFocus ); setAcceptDrops( true ); d->m_pOptionDialog = pOptionDialog; init( 0, 0, 0, 0, 0, false ); setMinimumSize(TQSize(20,20)); d->m_pStatusBar = pStatusBar; d->m_bPaintingAllowed = true; d->m_bWordWrap = false; d->m_winIdx = winIdx; setFont(d->m_pOptionDialog->m_font); } DiffTextWindow::~DiffTextWindow() { delete d; } void DiffTextWindow::init( const TQString& filename, const LineData* pLineData, int size, const Diff3LineVector* pDiff3LineVector, const ManualDiffHelpList* pManualDiffHelpList, bool bTriple ) { d->m_filename = filename; d->m_pLineData = pLineData; d->m_size = size; d->m_pDiff3LineVector = pDiff3LineVector; d->m_diff3WrapLineVector.clear(); d->m_pManualDiffHelpList = pManualDiffHelpList; d->m_firstLine = 0; d->m_oldFirstLine = -1; d->m_firstColumn = 0; d->m_oldFirstColumn = -1; d->m_bTriple = bTriple; d->m_scrollDeltaX=0; d->m_scrollDeltaY=0; d->m_bMyUpdate = false; d->m_fastSelectorLine1 = 0; d->m_fastSelectorNofLines = 0; d->m_lineNumberWidth = 0; d->m_selection.reset(); d->m_selection.oldFirstLine = -1; // reset is not enough here. d->m_selection.oldLastLine = -1; d->m_selection.lastLine = -1; update(); d->m_pDiffTextWindowFrame->init(); } void DiffTextWindow::reset() { d->m_pLineData=0; d->m_size=0; d->m_pDiff3LineVector=0; d->m_filename=""; d->m_diff3WrapLineVector.clear(); } void DiffTextWindow::setPaintingAllowed( bool bAllowPainting ) { if (d->m_bPaintingAllowed != bAllowPainting) { d->m_bPaintingAllowed = bAllowPainting; if ( d->m_bPaintingAllowed ) update(); else reset(); } } void DiffTextWindow::dragEnterEvent( TQDragEnterEvent* e ) { e->accept( TQUriDrag::canDecode(e) || TQTextDrag::canDecode(e) ); // Note that the corresponding drop is handled in KDiff3App::eventFilter(). } void DiffTextWindow::setFirstLine(int firstLine) { int fontHeight = fontMetrics().height(); int newFirstLine = max2(0,firstLine); int deltaY = fontHeight * ( d->m_firstLine - newFirstLine ); d->m_firstLine = newFirstLine; if ( d->m_bSelectionInProgress && d->m_selection.firstLine != -1 ) { int line, pos; convertToLinePos( d->m_lastKnownMousePos.x(), d->m_lastKnownMousePos.y(), line, pos ); d->m_selection.end( line, pos ); update(); } else { TQWidget::scroll( 0, deltaY ); } d->m_pDiffTextWindowFrame->setFirstLine( d->m_firstLine ); } int DiffTextWindow::getFirstLine() { return d->m_firstLine; } void DiffTextWindow::setFirstColumn(int firstCol) { int fontWidth = fontMetrics().width('W'); int xOffset = d->leftInfoWidth() * fontWidth; int newFirstColumn = max2(0,firstCol); int deltaX = fontWidth * ( d->m_firstColumn - newFirstColumn ); d->m_firstColumn = newFirstColumn; TQRect r( xOffset, 0, width()-xOffset, height() ); if ( d->m_pOptionDialog->m_bRightToLeftLanguage ) { deltaX = -deltaX; r = TQRect( width()-1-xOffset, 0, -(width()-xOffset), height() ).normalize(); } if ( d->m_bSelectionInProgress && d->m_selection.firstLine != -1 ) { int line, pos; convertToLinePos( d->m_lastKnownMousePos.x(), d->m_lastKnownMousePos.y(), line, pos ); d->m_selection.end( line, pos ); update(); } else { TQWidget::scroll( deltaX, 0, r ); } } int DiffTextWindow::getNofColumns() { if (d->m_bWordWrap) { return getNofVisibleColumns(); } else { int nofColumns = 0; for( int i = 0; i< d->m_size; ++i ) { if ( d->m_pLineData[i].width( d->m_pOptionDialog->m_tabSize ) > nofColumns ) nofColumns = d->m_pLineData[i].width( d->m_pOptionDialog->m_tabSize ); } return nofColumns; } } int DiffTextWindow::getNofLines() { return d->m_bWordWrap ? d->m_diff3WrapLineVector.size() : d->m_pDiff3LineVector->size(); } int DiffTextWindow::convertLineToDiff3LineIdx( int line ) { if ( d->m_bWordWrap && d->m_diff3WrapLineVector.size()>0 ) return d->m_diff3WrapLineVector[ min2( line, (int)d->m_diff3WrapLineVector.size()-1 ) ].diff3LineIndex; else return line; } int DiffTextWindow::convertDiff3LineIdxToLine( int d3lIdx ) { if ( d->m_bWordWrap && d->m_pDiff3LineVector!=0 && d->m_pDiff3LineVector->size()>0 ) return (*d->m_pDiff3LineVector)[ min2( d3lIdx, (int)d->m_pDiff3LineVector->size()-1 ) ]->sumLinesNeededForDisplay; else return d3lIdx; } /** Returns a line number where the linerange [line, line+nofLines] can be displayed best. If it fits into the currently visible range then the returned value is the current firstLine. */ int getBestFirstLine( int line, int nofLines, int firstLine, int visibleLines ) { int newFirstLine = firstLine; if ( line < firstLine || line + nofLines + 2 > firstLine + visibleLines ) { if ( nofLines > visibleLines || nofLines <= ( 2*visibleLines / 3 - 1) ) newFirstLine = line - visibleLines/3; else newFirstLine = line - (visibleLines - nofLines); } return newFirstLine; } void DiffTextWindow::setFastSelectorRange( int line1, int nofLines ) { d->m_fastSelectorLine1 = line1; d->m_fastSelectorNofLines = nofLines; if ( isVisible() ) { int newFirstLine = getBestFirstLine( convertDiff3LineIdxToLine(d->m_fastSelectorLine1), convertDiff3LineIdxToLine(d->m_fastSelectorLine1+d->m_fastSelectorNofLines)-convertDiff3LineIdxToLine(d->m_fastSelectorLine1), d->m_firstLine, getNofVisibleLines() ); if ( newFirstLine != d->m_firstLine ) { scroll( 0, newFirstLine - d->m_firstLine ); } update(); } } void DiffTextWindow::showStatusLine(int line ) { int d3lIdx = convertLineToDiff3LineIdx( line ); if(d3lIdx >= 0 && d3lIdx<(int)d->m_pDiff3LineVector->size() ) { const Diff3Line* pD3l = (*d->m_pDiff3LineVector)[d3lIdx]; if ( pD3l != 0 ) { int l = pD3l->getLineInFile( d->m_winIdx ); TQString s; if ( l!=-1 ) s.sprintf("File %s: Line %d", d->m_filename.ascii(), l+1 ); else s.sprintf("File %s: Line not available", d->m_filename.ascii() ); if (d->m_pStatusBar!=0) d->m_pStatusBar->message(s); emit lineClicked( d->m_winIdx, l ); } } } void DiffTextWindow::focusInEvent(TQFocusEvent* e) { emit gotFocus(); TQWidget::focusInEvent(e); } void DiffTextWindow::mousePressEvent ( TQMouseEvent* e ) { if ( e->button() == TQt::LeftButton ) { int line; int pos; convertToLinePos( e->x(), e->y(), line, pos ); if ( pos < d->m_firstColumn ) { emit setFastSelectorLine( convertLineToDiff3LineIdx(line) ); d->m_selection.firstLine = -1; // Disable current d->m_selection } else { // Selection resetSelection(); d->m_selection.start( line, pos ); d->m_selection.end( line, pos ); d->m_bSelectionInProgress = true; d->m_lastKnownMousePos = e->pos(); showStatusLine( line ); } } } bool isCTokenChar( TQChar c ) { return (c=='_') || ( c.unicode()>='A' && c.unicode()<='Z' ) || ( c.unicode()>='a' && c.unicode()<='z' ) || (c.unicode()>='0' && c.unicode()<='9'); } /// Calculate where a token starts and ends, given the x-position on screen. void calcTokenPos( const TQString& s, int posOnScreen, int& pos1, int& pos2, int tabSize ) { // Cursor conversions that consider g_tabSize int pos = convertToPosInText( s, max2( 0, posOnScreen ), tabSize ); if ( pos>=(int)s.length() ) { pos1=s.length(); pos2=s.length(); return; } pos1 = pos; pos2 = pos+1; if( isCTokenChar( s[pos1] ) ) { while( pos1>=0 && isCTokenChar( s[pos1] ) ) --pos1; ++pos1; while( pos2<(int)s.length() && isCTokenChar( s[pos2] ) ) ++pos2; } } void DiffTextWindow::mouseDoubleClickEvent( TQMouseEvent* e ) { d->m_bSelectionInProgress = false; d->m_lastKnownMousePos = e->pos(); if ( e->button() == TQt::LeftButton ) { int line; int pos; convertToLinePos( e->x(), e->y(), line, pos ); // Get the string data of the current line TQString s; if ( d->m_bWordWrap ) { if ( line<0 || line >= (int)d->m_diff3WrapLineVector.size() ) return; const Diff3WrapLine& d3wl = d->m_diff3WrapLineVector[line]; s = d->getString( d3wl.diff3LineIndex ).mid( d3wl.wrapLineOffset, d3wl.wrapLineLength ); } else { if ( line<0 || line >= (int)d->m_pDiff3LineVector->size() ) return; s = d->getString( line ); } if ( ! s.isEmpty() ) { int pos1, pos2; calcTokenPos( s, pos, pos1, pos2, d->m_pOptionDialog->m_tabSize ); resetSelection(); d->m_selection.start( line, convertToPosOnScreen( s, pos1, d->m_pOptionDialog->m_tabSize ) ); d->m_selection.end( line, convertToPosOnScreen( s, pos2, d->m_pOptionDialog->m_tabSize ) ); update(); // emit d->m_selectionEnd() happens in the mouseReleaseEvent. showStatusLine( line ); } } } void DiffTextWindow::mouseReleaseEvent ( TQMouseEvent* e ) { d->m_bSelectionInProgress = false; d->m_lastKnownMousePos = e->pos(); //if ( e->button() == LeftButton ) { killTimer(d->m_delayedDrawTimer); d->m_delayedDrawTimer = 0; if (d->m_selection.firstLine != -1 ) { emit selectionEnd(); } } d->m_scrollDeltaX=0; d->m_scrollDeltaY=0; } inline int sqr(int x){return x*x;} void DiffTextWindow::mouseMoveEvent ( TQMouseEvent * e ) { int line; int pos; convertToLinePos( e->x(), e->y(), line, pos ); d->m_lastKnownMousePos = e->pos(); if (d->m_selection.firstLine != -1 ) { d->m_selection.end( line, pos ); showStatusLine( line ); // Scroll because mouse moved out of the window const TQFontMetrics& fm = fontMetrics(); int fontWidth = fm.width('W'); int deltaX=0; int deltaY=0; if ( ! d->m_pOptionDialog->m_bRightToLeftLanguage ) { if ( e->x() < d->leftInfoWidth()*fontWidth ) deltaX = -1 - abs(e->x()-d->leftInfoWidth()*fontWidth)/fontWidth; if ( e->x() > width() ) deltaX = +1 + abs(e->x()-width())/fontWidth; } else { if ( e->x() > width()-1-d->leftInfoWidth()*fontWidth ) deltaX=+1+ abs(e->x() - (width()-1-d->leftInfoWidth()*fontWidth)) / fontWidth; if ( e->x() < fontWidth ) deltaX=-1- abs(e->x()-fontWidth)/fontWidth; } if ( e->y() < 0 ) deltaY = -1 - sqr( e->y() ) / sqr(fm.height()); if ( e->y() > height() ) deltaY = +1 + sqr( e->y() - height() ) / sqr(fm.height()); if ( deltaX != 0 && d->m_scrollDeltaX!=deltaX || deltaY!= 0 && d->m_scrollDeltaY!=deltaY ) { d->m_scrollDeltaX = deltaX; d->m_scrollDeltaY = deltaY; emit scroll( deltaX, deltaY ); killTimer( d->m_delayedDrawTimer ); d->m_delayedDrawTimer = startTimer(50); } else { d->m_scrollDeltaX = deltaX; d->m_scrollDeltaY = deltaY; d->myUpdate(0); } } } void DiffTextWindowData::myUpdate(int afterMilliSecs) { m_pDiffTextWindow->killTimer( m_delayedDrawTimer ); m_bMyUpdate = true; m_delayedDrawTimer = m_pDiffTextWindow->startTimer( afterMilliSecs ); } void DiffTextWindow::timerEvent(TQTimerEvent*) { killTimer(d->m_delayedDrawTimer); d->m_delayedDrawTimer = 0; if ( d->m_bMyUpdate ) { int fontHeight = fontMetrics().height(); if ( d->m_selection.oldLastLine != -1 ) { int lastLine; int firstLine; if ( d->m_selection.oldFirstLine != -1 ) { firstLine = min3( d->m_selection.oldFirstLine, d->m_selection.lastLine, d->m_selection.oldLastLine ); lastLine = max3( d->m_selection.oldFirstLine, d->m_selection.lastLine, d->m_selection.oldLastLine ); } else { firstLine = min2( d->m_selection.lastLine, d->m_selection.oldLastLine ); lastLine = max2( d->m_selection.lastLine, d->m_selection.oldLastLine ); } int y1 = ( firstLine - d->m_firstLine ) * fontHeight; int y2 = min2( height(), ( lastLine - d->m_firstLine + 1 ) * fontHeight ); if ( y10 ) { TQRect invalidRect = TQRect( 0, y1, width(), y2-y1 ); update( invalidRect ); } } d->m_bMyUpdate = false; } if ( d->m_scrollDeltaX != 0 || d->m_scrollDeltaY != 0 ) { d->m_selection.end( d->m_selection.lastLine + d->m_scrollDeltaY, d->m_selection.lastPos + d->m_scrollDeltaX ); emit scroll( d->m_scrollDeltaX, d->m_scrollDeltaY ); killTimer(d->m_delayedDrawTimer); d->m_delayedDrawTimer = startTimer(50); } } void DiffTextWindow::resetSelection() { d->m_selection.reset(); update(); } void DiffTextWindow::convertToLinePos( int x, int y, int& line, int& pos ) { const TQFontMetrics& fm = fontMetrics(); int fontHeight = fm.height(); int fontWidth = fm.width('W'); int xOffset = ( d->leftInfoWidth() - d->m_firstColumn ) * fontWidth; int yOffset = - d->m_firstLine * fontHeight; line = ( y - yOffset ) / fontHeight; if ( ! d->m_pOptionDialog->m_bRightToLeftLanguage ) pos = ( x - xOffset ) / fontWidth; else pos = ( (width() - 1 - x) - xOffset ) / fontWidth; } int Selection::firstPosInLine(int l) { assert( firstLine != -1 ); int l1 = firstLine; int l2 = lastLine; int p1 = firstPos; int p2 = lastPos; if ( l1>l2 ){ std::swap(l1,l2); std::swap(p1,p2); } if ( l1==l2 && p1>p2 ){ std::swap(p1,p2); } if ( l==l1 ) return p1; return 0; } int Selection::lastPosInLine(int l) { assert( firstLine != -1 ); int l1 = firstLine; int l2 = lastLine; int p1 = firstPos; int p2 = lastPos; if ( l1>l2 ){ std::swap(l1,l2); std::swap(p1,p2); } if ( l1==l2 && p1>p2 ){ std::swap(p1,p2); } if ( l==l2 ) return p2; return INT_MAX; } bool Selection::within( int l, int p ) { if ( firstLine == -1 ) return false; int l1 = firstLine; int l2 = lastLine; int p1 = firstPos; int p2 = lastPos; if ( l1>l2 ){ std::swap(l1,l2); std::swap(p1,p2); } if ( l1==l2 && p1>p2 ){ std::swap(p1,p2); } if( l1 <= l && l <= l2 ) { if ( l1==l2 ) return p>=p1 && p=p1; if ( l==l2 ) return pl2 ){ std::swap(l1,l2); } return ( l1 <= l && l <= l2 ); } void DiffTextWindowData::writeLine( MyPainter& p, const LineData* pld, const DiffList* pLineDiff1, const DiffList* pLineDiff2, int line, int whatChanged, int whatChanged2, int srcLineIdx, int wrapLineOffset, int wrapLineLength, bool bWrapLine, const TQRect& invalidRect, int deviceWidth ) { TQFont normalFont = p.font(); TQFont diffFont = normalFont; diffFont.setItalic( m_pOptionDialog->m_bItalicForDeltas ); const TQFontMetrics& fm = p.fontMetrics(); int fontHeight = fm.height(); int fontAscent = fm.ascent(); int fontDescent = fm.descent(); int fontWidth = fm.width('W'); int xOffset = (leftInfoWidth() - m_firstColumn)*fontWidth; int yOffset = (line-m_firstLine) * fontHeight; TQRect lineRect( 0, yOffset, deviceWidth, fontHeight ); if ( ! invalidRect.intersects( lineRect ) ) { return; } int fastSelectorLine1 = m_pDiffTextWindow->convertDiff3LineIdxToLine(m_fastSelectorLine1); int fastSelectorLine2 = m_pDiffTextWindow->convertDiff3LineIdxToLine(m_fastSelectorLine1+m_fastSelectorNofLines)-1; bool bFastSelectionRange = (line>=fastSelectorLine1 && line<= fastSelectorLine2 ); TQColor bgColor = m_pOptionDialog->m_bgColor; TQColor diffBgColor = m_pOptionDialog->m_diffBgColor; if ( bFastSelectionRange ) { bgColor = m_pOptionDialog->m_currentRangeBgColor; diffBgColor = m_pOptionDialog->m_currentRangeDiffBgColor; } if ( yOffset+fontHeightm_fgColor; if ( changed == 2 ) { c = m_cDiff2; } else if ( changed == 1 ) { c = m_cDiff1; } else if ( changed == 3 ) { c = m_cDiffBoth; } p.fillRect( leftInfoWidth()*fontWidth, yOffset, deviceWidth, fontHeight, bgColor ); if (pld!=0) { // First calculate the "changed" information for each character. int i=0; std::vector charChanged( pld->size ); if ( pLineDiff1!=0 || pLineDiff2 != 0 ) { Merger merger( pLineDiff1, pLineDiff2 ); while( ! merger.isEndReached() && isize ) { if ( i < pld->size ) { charChanged[i] = merger.whatChanged(); ++i; } merger.next(); } } TQString s=" "; // Convert tabs int outPos = 0; TQString lineString( pld->pLine, pld->size ); int lineLength = m_bWordWrap ? wrapLineOffset+wrapLineLength : lineString.length(); for( i=wrapLineOffset; im_tabSize ); s[0] = ' '; } else { s[0] = lineString[i]; } TQColor c = m_pOptionDialog->m_fgColor; int cchanged = charChanged[i] | whatChanged; if ( cchanged == 2 ) { c = m_cDiff2; } else if ( cchanged == 1 ) { c = m_cDiff1; } else if ( cchanged == 3 ) { c = m_cDiffBoth; } if ( c!=m_pOptionDialog->m_fgColor && whatChanged2==0 && !m_pOptionDialog->m_bShowWhiteSpace ) { // The user doesn't want to see highlighted white space. c = m_pOptionDialog->m_fgColor; } TQRect outRect( xOffset + fontWidth*outPos, yOffset, fontWidth*spaces, fontHeight ); if ( m_pOptionDialog->m_bRightToLeftLanguage ) outRect = TQRect( deviceWidth-1-(xOffset + fontWidth*outPos), yOffset, -fontWidth*spaces, fontHeight ).normalize(); if ( invalidRect.intersects( outRect ) ) { if( !m_selection.within( line, outPos ) ) { if( c!=m_pOptionDialog->m_fgColor ) { TQColor lightc = diffBgColor; p.fillRect( xOffset + fontWidth*outPos, yOffset, fontWidth*spaces, fontHeight, lightc ); p.setFont(diffFont); } p.setPen( c ); if ( s[0]==' ' && c!=m_pOptionDialog->m_fgColor && charChanged[i]!=0 ) { if ( m_pOptionDialog->m_bShowWhiteSpaceCharacters && m_pOptionDialog->m_bShowWhiteSpace) { p.fillRect( xOffset + fontWidth*outPos, yOffset+fontAscent, fontWidth*spaces-1, fontDescent, c ); } } else { p.drawText( xOffset + fontWidth*outPos, yOffset + fontAscent, s ); } p.setFont(normalFont); } else { p.fillRect( xOffset + fontWidth*outPos, yOffset, fontWidth*(spaces), fontHeight, m_pDiffTextWindow->colorGroup().highlight() ); p.setPen( m_pDiffTextWindow->colorGroup().highlightedText() ); p.drawText( xOffset + fontWidth*outPos, yOffset + fontAscent, s ); m_selection.bSelectionContainsData = true; } } outPos += spaces; } if( m_selection.lineWithin( line ) && m_selection.lineWithin( line+1 ) ) { p.fillRect( xOffset + fontWidth*outPos, yOffset, deviceWidth, fontHeight, m_pDiffTextWindow->colorGroup().highlight() ); } } p.fillRect( 0, yOffset, leftInfoWidth()*fontWidth, fontHeight, m_pOptionDialog->m_bgColor ); xOffset = (m_lineNumberWidth+2)*fontWidth; int xLeft = m_lineNumberWidth*fontWidth; p.setPen( m_pOptionDialog->m_fgColor ); if ( pld!=0 ) { if ( m_pOptionDialog->m_bShowLineNumbers && !bWrapLine ) { TQString num; num.sprintf( "%0*d", m_lineNumberWidth, srcLineIdx+1); p.drawText( 0, yOffset + fontAscent, num ); //p.drawLine( xLeft -1, yOffset, xLeft -1, yOffset+fontHeight-1 ); } if ( !bWrapLine || wrapLineLength>0 ) { p.setPen( TQPen( m_pOptionDialog->m_fgColor, 0, bWrapLine ? TQt::DotLine : TQt::SolidLine) ); p.drawLine( xOffset +1, yOffset, xOffset +1, yOffset+fontHeight-1 ); p.setPen( TQPen( m_pOptionDialog->m_fgColor, 0, TQt::SolidLine) ); } } if ( c!=m_pOptionDialog->m_fgColor && whatChanged2==0 )//&& whatChanged==0 ) { if ( m_pOptionDialog->m_bShowWhiteSpace ) { p.setBrushOrigin(0,0); p.fillRect( xLeft, yOffset, fontWidth*2-1, fontHeight, TQBrush(c,TQt::Dense5Pattern) ); } } else { p.fillRect( xLeft, yOffset, fontWidth*2-1, fontHeight, c==m_pOptionDialog->m_fgColor ? bgColor : c ); } if ( bFastSelectionRange ) { p.fillRect( xOffset + fontWidth-1, yOffset, 3, fontHeight, m_pOptionDialog->m_fgColor ); } // Check if line needs a manual diff help mark ManualDiffHelpList::const_iterator ci; for( ci = m_pManualDiffHelpList->begin(); ci!=m_pManualDiffHelpList->end(); ++ci) { const ManualDiffHelpEntry& mdhe=*ci; int rangeLine1 = -1; int rangeLine2 = -1; if (m_winIdx==1 ) { rangeLine1 = mdhe.lineA1; rangeLine2= mdhe.lineA2; } if (m_winIdx==2 ) { rangeLine1 = mdhe.lineB1; rangeLine2= mdhe.lineB2; } if (m_winIdx==3 ) { rangeLine1 = mdhe.lineC1; rangeLine2= mdhe.lineC2; } if ( rangeLine1>=0 && rangeLine2>=0 && srcLineIdx >= rangeLine1 && srcLineIdx <= rangeLine2 ) { p.fillRect( xOffset - fontWidth, yOffset, fontWidth-1, fontHeight, m_pOptionDialog->m_manualHelpRangeColor ); break; } } } void DiffTextWindow::paintEvent( TQPaintEvent* e ) { if ( d->m_pDiff3LineVector==0 || ! d->m_bPaintingAllowed || ( d->m_diff3WrapLineVector.empty() && d->m_bWordWrap ) ) return; TQRect invalidRect = e->rect(); if ( invalidRect.isEmpty() ) return; bool bOldSelectionContainsData = d->m_selection.bSelectionContainsData; d->m_selection.bSelectionContainsData = false; int endLine = min2( d->m_firstLine + getNofVisibleLines()+2, getNofLines() ); //if ( invalidRect.size()==size() ) { TQPainter painter(this); TQPixmap pixmap( invalidRect.size() ); MyPainter p( &pixmap, d->m_pOptionDialog->m_bRightToLeftLanguage, width(), fontMetrics().width('W') ); p.translate( -invalidRect.x(), -invalidRect.y() ); p.setFont( font() ); p.TQPainter::fillRect( invalidRect, d->m_pOptionDialog->m_bgColor ); d->draw( p, invalidRect, width(), d->m_firstLine, endLine ); // p.drawLine( m_invalidRect.x(), m_invalidRect.y(), m_invalidRect.right(), m_invalidRect.bottom() ); // For test only p.end(); painter.drawPixmap( invalidRect.x(), invalidRect.y(), pixmap ); } // else // { // no double buffering // MyPainter p( this, d->m_pOptionDialog->m_bRightToLeftLanguage, width(), fontMetrics().width('W') ); // p.setFont( font() ); // p.TQPainter::fillRect( invalidRect, d->m_pOptionDialog->m_bgColor ); // d->draw( p, invalidRect, width(), d->m_firstLine, endLine ); // } d->m_oldFirstLine = d->m_firstLine; d->m_oldFirstColumn = d->m_firstColumn; d->m_selection.oldLastLine = -1; if ( d->m_selection.oldFirstLine !=-1 ) d->m_selection.oldFirstLine = -1; if( !bOldSelectionContainsData && d->m_selection.bSelectionContainsData ) emit newSelection(); } void DiffTextWindow::print( MyPainter& p, const TQRect&, int firstLine, int nofLinesPerPage ) { if ( d->m_pDiff3LineVector==0 || ! d->m_bPaintingAllowed || ( d->m_diff3WrapLineVector.empty() && d->m_bWordWrap ) ) return; resetSelection(); // MyPainter p( this, d->m_pOptionDialog->m_bRightToLeftLanguage, width(), fontMetrics().width('W') ); int oldFirstLine = d->m_firstLine; d->m_firstLine = firstLine; TQRect invalidRect = TQRect(0,0,TQCOORD_MAX,TQCOORD_MAX); TQColor bgColor = d->m_pOptionDialog->m_bgColor; d->m_pOptionDialog->m_bgColor = TQt::white; d->draw( p, invalidRect, p.window().width(), firstLine, min2(firstLine+nofLinesPerPage,getNofLines()) ); d->m_pOptionDialog->m_bgColor = bgColor; d->m_firstLine = oldFirstLine; } void DiffTextWindowData::draw( MyPainter& p, const TQRect& invalidRect, int deviceWidth, int beginLine, int endLine ) { m_lineNumberWidth = m_pOptionDialog->m_bShowLineNumbers ? (int)log10((double)m_size)+1 : 0; if ( m_winIdx==1 ) { m_cThis = m_pOptionDialog->m_colorA; m_cDiff1 = m_pOptionDialog->m_colorB; m_cDiff2 = m_pOptionDialog->m_colorC; } if ( m_winIdx==2 ) { m_cThis = m_pOptionDialog->m_colorB; m_cDiff1 = m_pOptionDialog->m_colorC; m_cDiff2 = m_pOptionDialog->m_colorA; } if ( m_winIdx==3 ) { m_cThis = m_pOptionDialog->m_colorC; m_cDiff1 = m_pOptionDialog->m_colorA; m_cDiff2 = m_pOptionDialog->m_colorB; } m_cDiffBoth = m_pOptionDialog->m_colorForConflict; // Conflict color p.setPen( m_cThis ); for ( int line = beginLine; line 0 && m_diff3WrapLineVector[line-1].pD3L == d3l; } else { d3l = (*m_pDiff3LineVector)[line]; } DiffList* pFineDiff1; DiffList* pFineDiff2; int changed=0; int changed2=0; int srcLineIdx=-1; getLineInfo( *d3l, srcLineIdx, pFineDiff1, pFineDiff2, changed, changed2 ); writeLine( p, // TQPainter srcLineIdx == -1 ? 0 : &m_pLineData[srcLineIdx], // Text in this line pFineDiff1, pFineDiff2, line, // Line on the screen changed, changed2, srcLineIdx, wrapLineOffset, wrapLineLength, bWrapLine, invalidRect, deviceWidth ); } } TQString DiffTextWindowData::getString( int d3lIdx ) { if ( d3lIdx<0 || d3lIdx>=(int)m_pDiff3LineVector->size() ) return TQString(); const Diff3Line* d3l = (*m_pDiff3LineVector)[d3lIdx]; DiffList* pFineDiff1; DiffList* pFineDiff2; int changed=0; int changed2=0; int lineIdx; getLineInfo( *d3l, lineIdx, pFineDiff1, pFineDiff2, changed, changed2 ); if (lineIdx==-1) return TQString(); else { const LineData* ld = &m_pLineData[lineIdx]; return TQString( ld->pLine, ld->size ); } return TQString(); } TQString DiffTextWindowData::getLineString( int line ) { if ( m_bWordWrap ) { int d3LIdx = m_pDiffTextWindow->convertLineToDiff3LineIdx(line); return getString( d3LIdx ).mid( m_diff3WrapLineVector[line].wrapLineOffset, m_diff3WrapLineVector[line].wrapLineLength ); } else { return getString( line ); } } void DiffTextWindowData::getLineInfo( const Diff3Line& d3l, int& lineIdx, DiffList*& pFineDiff1, DiffList*& pFineDiff2, // return values int& changed, int& changed2 ) { changed=0; changed2=0; bool bAEqB = d3l.bAEqB || ( d3l.bWhiteLineA && d3l.bWhiteLineB ); bool bAEqC = d3l.bAEqC || ( d3l.bWhiteLineA && d3l.bWhiteLineC ); bool bBEqC = d3l.bBEqC || ( d3l.bWhiteLineB && d3l.bWhiteLineC ); if ( m_winIdx == 1 ) { lineIdx=d3l.lineA; pFineDiff1=d3l.pFineAB; pFineDiff2=d3l.pFineCA; changed |= ((d3l.lineB==-1)!=(lineIdx==-1) ? 1 : 0) + ((d3l.lineC==-1)!=(lineIdx==-1) && m_bTriple ? 2 : 0); changed2 |= ( bAEqB ? 0 : 1 ) + (bAEqC || !m_bTriple ? 0 : 2); } else if ( m_winIdx == 2 ) { lineIdx=d3l.lineB; pFineDiff1=d3l.pFineBC; pFineDiff2=d3l.pFineAB; changed |= ((d3l.lineC==-1)!=(lineIdx==-1) && m_bTriple ? 1 : 0) + ((d3l.lineA==-1)!=(lineIdx==-1) ? 2 : 0); changed2 |= ( bBEqC || !m_bTriple ? 0 : 1 ) + (bAEqB ? 0 : 2); } else if ( m_winIdx == 3 ) { lineIdx=d3l.lineC; pFineDiff1=d3l.pFineCA; pFineDiff2=d3l.pFineBC; changed |= ((d3l.lineA==-1)!=(lineIdx==-1) ? 1 : 0) + ((d3l.lineB==-1)!=(lineIdx==-1) ? 2 : 0); changed2 |= ( bAEqC ? 0 : 1 ) + (bBEqC ? 0 : 2); } else assert(false); } void DiffTextWindow::resizeEvent( TQResizeEvent* e ) { TQSize s = e->size(); TQFontMetrics fm = fontMetrics(); int visibleLines = s.height()/fm.height()-2; int visibleColumns = s.width()/fm.width('W') - d->leftInfoWidth(); emit resizeSignal( visibleColumns, visibleLines ); TQWidget::resizeEvent(e); } int DiffTextWindow::getNofVisibleLines() { TQFontMetrics fm = fontMetrics(); int fmh = fm.height(); int h = height(); return h/fmh -1;//height()/fm.height()-2; } int DiffTextWindow::getNofVisibleColumns() { TQFontMetrics fm = fontMetrics(); return width()/fm.width('W') - d->leftInfoWidth(); } TQString DiffTextWindow::getSelection() { TQString selectionString; int line=0; int lineIdx=0; int it; int vectorSize = d->m_bWordWrap ? d->m_diff3WrapLineVector.size() : d->m_pDiff3LineVector->size(); for( it=0; itm_bWordWrap ? d->m_diff3WrapLineVector[it].pD3L : (*d->m_pDiff3LineVector)[it]; if ( d->m_winIdx == 1 ) { lineIdx=d3l->lineA; } else if ( d->m_winIdx == 2 ) { lineIdx=d3l->lineB; } else if ( d->m_winIdx == 3 ) { lineIdx=d3l->lineC; } else assert(false); if( lineIdx != -1 ) { const TQChar* pLine = d->m_pLineData[lineIdx].pLine; int size = d->m_pLineData[lineIdx].size; TQString lineString = TQString( pLine, size ); if ( d->m_bWordWrap ) { size = d->m_diff3WrapLineVector[it].wrapLineLength; lineString = lineString.mid( d->m_diff3WrapLineVector[it].wrapLineOffset, size ); } // Consider tabs int outPos = 0; for( int i=0; im_pOptionDialog->m_tabSize ); } if( d->m_selection.within( line, outPos ) ) { selectionString += lineString[i]; } outPos += spaces; } if( d->m_selection.within( line, outPos ) && !( d->m_bWordWrap && it+1m_diff3WrapLineVector[it+1].pD3L ) ) { #ifdef _WIN32 selectionString += '\r'; #endif selectionString += '\n'; } } ++line; } return selectionString; } bool DiffTextWindow::findString( const TQString& s, int& d3vLine, int& posInLine, bool bDirDown, bool bCaseSensitive ) { int it = d3vLine; int endIt = bDirDown ? (int)d->m_pDiff3LineVector->size() : -1; int step = bDirDown ? 1 : -1; int startPos = posInLine; for( ; it!=endIt; it+=step ) { TQString line = d->getString( it ); if ( !line.isEmpty() ) { int pos = line.find( s, startPos, bCaseSensitive ); if ( pos != -1 ) { d3vLine = it; posInLine = pos; return true; } startPos = 0; } } return false; } void DiffTextWindow::convertD3LCoordsToLineCoords( int d3LIdx, int d3LPos, int& line, int& pos ) { if( d->m_bWordWrap ) { int wrapPos = d3LPos; int wrapLine = convertDiff3LineIdxToLine(d3LIdx); while ( wrapPos > d->m_diff3WrapLineVector[wrapLine].wrapLineLength ) { wrapPos -= d->m_diff3WrapLineVector[wrapLine].wrapLineLength; ++wrapLine; } pos = wrapPos; line = wrapLine; } else { pos = d3LPos; line = d3LIdx; } } void DiffTextWindow::convertLineCoordsToD3LCoords( int line, int pos, int& d3LIdx, int& d3LPos ) { if( d->m_bWordWrap ) { d3LPos = pos; d3LIdx = convertLineToDiff3LineIdx( line ); int wrapLine = convertDiff3LineIdxToLine(d3LIdx); // First wrap line belonging to this d3LIdx while ( wrapLine < line ) { d3LPos += d->m_diff3WrapLineVector[wrapLine].wrapLineLength; ++wrapLine; } } else { d3LPos = pos; d3LIdx = line; } } void DiffTextWindow::setSelection( int firstLine, int startPos, int lastLine, int endPos, int& l, int& p ) { d->m_selection.reset(); if ( lastLine >= getNofLines() ) { lastLine = getNofLines()-1; const Diff3Line* d3l = (*d->m_pDiff3LineVector)[convertLineToDiff3LineIdx(lastLine)]; int line = -1; if ( d->m_winIdx==1 ) line = d3l->lineA; if ( d->m_winIdx==2 ) line = d3l->lineB; if ( d->m_winIdx==3 ) line = d3l->lineC; if (line>=0) endPos = d->m_pLineData[line].width( d->m_pOptionDialog->m_tabSize); } if ( d->m_bWordWrap && d->m_pDiff3LineVector!=0 ) { TQString s1 = d->getString(firstLine); int firstWrapLine = convertDiff3LineIdxToLine(firstLine); int wrapStartPos = startPos; while ( wrapStartPos > d->m_diff3WrapLineVector[firstWrapLine].wrapLineLength ) { wrapStartPos -= d->m_diff3WrapLineVector[firstWrapLine].wrapLineLength; s1 = s1.mid(d->m_diff3WrapLineVector[firstWrapLine].wrapLineLength); ++firstWrapLine; } TQString s2 = d->getString(lastLine); int lastWrapLine = convertDiff3LineIdxToLine(lastLine); int wrapEndPos = endPos; while ( wrapEndPos > d->m_diff3WrapLineVector[lastWrapLine].wrapLineLength ) { wrapEndPos -= d->m_diff3WrapLineVector[lastWrapLine].wrapLineLength; s2 = s2.mid(d->m_diff3WrapLineVector[lastWrapLine].wrapLineLength); ++lastWrapLine; } d->m_selection.start( firstWrapLine, convertToPosOnScreen( s1, wrapStartPos, d->m_pOptionDialog->m_tabSize ) ); d->m_selection.end( lastWrapLine, convertToPosOnScreen( s2, wrapEndPos, d->m_pOptionDialog->m_tabSize ) ); l=firstWrapLine; p=wrapStartPos; } else { d->m_selection.start( firstLine, convertToPosOnScreen( d->getString(firstLine), startPos, d->m_pOptionDialog->m_tabSize ) ); d->m_selection.end( lastLine, convertToPosOnScreen( d->getString(lastLine), endPos, d->m_pOptionDialog->m_tabSize ) ); l=firstLine; p=startPos; } update(); } int DiffTextWindowData::convertLineOnScreenToLineInSource( int lineOnScreen, e_CoordType coordType, bool bFirstLine ) { int line=-1; if (lineOnScreen>=0) { if (coordType==eWrapCoords) return lineOnScreen; int d3lIdx = m_pDiffTextWindow->convertLineToDiff3LineIdx( lineOnScreen ); if ( !bFirstLine && d3lIdx >= (int)m_pDiff3LineVector->size() ) d3lIdx = m_pDiff3LineVector->size()-1; if (coordType==eD3LLineCoords) return d3lIdx; while ( line<0 && d3lIdx<(int)m_pDiff3LineVector->size() && d3lIdx>=0 ) { const Diff3Line* d3l = (*m_pDiff3LineVector)[d3lIdx]; if ( m_winIdx==1 ) line = d3l->lineA; if ( m_winIdx==2 ) line = d3l->lineB; if ( m_winIdx==3 ) line = d3l->lineC; if ( bFirstLine ) ++d3lIdx; else --d3lIdx; } if (coordType==eFileCoords) return line; } return line; } void DiffTextWindow::getSelectionRange( int* pFirstLine, int* pLastLine, e_CoordType coordType ) { if (pFirstLine) *pFirstLine = d->convertLineOnScreenToLineInSource( d->m_selection.beginLine(), coordType, true ); if (pLastLine) *pLastLine = d->convertLineOnScreenToLineInSource( d->m_selection.endLine(), coordType, false ); } // Returns the number of wrapped lines // if pWrappedLines != 0 then the stringlist will contain the wrapped lines. int wordWrap( const TQString& origLine, int nofColumns, Diff3WrapLine* pDiff3WrapLine ) { if (nofColumns<=0) nofColumns = 1; int nofNeededLines = 0; int length = origLine.length(); if (length==0) { nofNeededLines = 1; if( pDiff3WrapLine ) { pDiff3WrapLine->wrapLineOffset=0; pDiff3WrapLine->wrapLineLength=0; } } else { int pos = 0; while ( pos < length ) { int wrapPos = pos + nofColumns; if ( length-pos <= nofColumns ) { wrapPos = length; } else { int wsPos = max2( origLine.findRev( ' ', wrapPos ), origLine.findRev( '\t', wrapPos ) ); if ( wsPos > pos ) { // Wrap line at wsPos wrapPos = wsPos; } } if ( pDiff3WrapLine ) { pDiff3WrapLine->wrapLineOffset = pos; pDiff3WrapLine->wrapLineLength = wrapPos-pos; ++pDiff3WrapLine; } pos = wrapPos; ++nofNeededLines; } } return nofNeededLines; } void DiffTextWindow::convertSelectionToD3LCoords() { if ( d->m_pDiff3LineVector==0 || ! d->m_bPaintingAllowed || !isVisible() || d->m_selection.isEmpty() ) { return; } // convert the d->m_selection to unwrapped coordinates: Later restore to new coords int firstD3LIdx, firstD3LPos; TQString s = d->getLineString( d->m_selection.beginLine() ); int firstPosInText = convertToPosInText( s, d->m_selection.beginPos(), d->m_pOptionDialog->m_tabSize ); convertLineCoordsToD3LCoords( d->m_selection.beginLine(), firstPosInText, firstD3LIdx, firstD3LPos ); int lastD3LIdx, lastD3LPos; s = d->getLineString( d->m_selection.endLine() ); int lastPosInText = convertToPosInText( s, d->m_selection.endPos(), d->m_pOptionDialog->m_tabSize ); convertLineCoordsToD3LCoords( d->m_selection.endLine(), lastPosInText, lastD3LIdx, lastD3LPos ); //d->m_selection.reset(); d->m_selection.start( firstD3LIdx, firstD3LPos ); d->m_selection.end( lastD3LIdx, lastD3LPos ); } void DiffTextWindow::recalcWordWrap( bool bWordWrap, int wrapLineVectorSize, int nofVisibleColumns ) { if ( d->m_pDiff3LineVector==0 || ! d->m_bPaintingAllowed || !isVisible() ) { d->m_bWordWrap = bWordWrap; if (!bWordWrap) d->m_diff3WrapLineVector.resize( 0 ); return; } d->m_bWordWrap = bWordWrap; if ( bWordWrap ) { d->m_diff3WrapLineVector.resize( wrapLineVectorSize ); if (nofVisibleColumns<0) nofVisibleColumns = getNofVisibleColumns(); else nofVisibleColumns-= d->leftInfoWidth(); int i; int wrapLineIdx = 0; int size = d->m_pDiff3LineVector->size(); for( i=0; igetString( i ); int linesNeeded = wordWrap( s, nofVisibleColumns, wrapLineVectorSize==0 ? 0 : &d->m_diff3WrapLineVector[wrapLineIdx] ); Diff3Line& d3l = *(*d->m_pDiff3LineVector)[i]; if ( d3l.linesNeededForDisplay0 ) { int j; for( j=0; jm_diff3WrapLineVector[wrapLineIdx]; d3wl.diff3LineIndex = i; d3wl.pD3L = (*d->m_pDiff3LineVector)[i]; if ( j>=linesNeeded ) { d3wl.wrapLineOffset=0; d3wl.wrapLineLength=0; } } } } if ( wrapLineVectorSize>0 ) { d->m_firstLine = min2( d->m_firstLine, wrapLineVectorSize-1 ); d->m_firstColumn = 0; d->m_pDiffTextWindowFrame->setFirstLine( d->m_firstLine ); } } else { d->m_diff3WrapLineVector.resize( 0 ); } if ( !d->m_selection.isEmpty() && ( !d->m_bWordWrap || wrapLineVectorSize>0 ) ) { // Assume unwrapped coordinates //( Why? ->Conversion to unwrapped coords happened a few lines above in this method. // Also see KDiff3App::recalcWordWrap() on the role of wrapLineVectorSize) // Wrap them now. // convert the d->m_selection to unwrapped coordinates. int firstLine, firstPos; convertD3LCoordsToLineCoords( d->m_selection.beginLine(), d->m_selection.beginPos(), firstLine, firstPos ); int lastLine, lastPos; convertD3LCoordsToLineCoords( d->m_selection.endLine(), d->m_selection.endPos(), lastLine, lastPos ); //d->m_selection.reset(); d->m_selection.start( firstLine, convertToPosOnScreen( d->getLineString( firstLine ), firstPos, d->m_pOptionDialog->m_tabSize ) ); d->m_selection.end( lastLine, convertToPosOnScreen( d->getLineString( lastLine ),lastPos, d->m_pOptionDialog->m_tabSize ) ); } } class DiffTextWindowFrameData { public: DiffTextWindow* m_pDiffTextWindow; TQLineEdit* m_pFileSelection; TQPushButton* m_pBrowseButton; OptionDialog* m_pOptionDialog; TQLabel* m_pLabel; TQLabel* m_pTopLine; TQWidget* m_pTopLineWidget; }; DiffTextWindowFrame::DiffTextWindowFrame( TQWidget* pParent, TQStatusBar* pStatusBar, OptionDialog* pOptionDialog, int winIdx ) : TQWidget( pParent ) { d = new DiffTextWindowFrameData; d->m_pOptionDialog = pOptionDialog; d->m_pTopLineWidget = new TQWidget(this); d->m_pFileSelection = new TQLineEdit(d->m_pTopLineWidget); d->m_pBrowseButton = new TQPushButton( "...",d->m_pTopLineWidget ); d->m_pBrowseButton->setFixedWidth( 30 ); connect(d->m_pBrowseButton,TQT_SIGNAL(clicked()), this, TQT_SLOT(slotBrowseButtonClicked())); connect(d->m_pFileSelection,TQT_SIGNAL(returnPressed()), this, TQT_SLOT(slotReturnPressed())); d->m_pLabel = new TQLabel("A:",d->m_pTopLineWidget); d->m_pTopLine = new TQLabel(d->m_pTopLineWidget); d->m_pDiffTextWindow = 0; d->m_pDiffTextWindow = new DiffTextWindow( this, pStatusBar, pOptionDialog, winIdx ); TQHBoxLayout* pHL = new TQHBoxLayout(d->m_pTopLineWidget); pHL->setMargin(2); pHL->setSpacing(2); pHL->addWidget( d->m_pLabel, 0 ); pHL->addWidget( d->m_pFileSelection, 1 ); pHL->addWidget( d->m_pBrowseButton, 0 ); pHL->addWidget( d->m_pTopLine, 0 ); TQVBoxLayout* pVL = new TQVBoxLayout( this, 0, 0 ); pVL->addWidget( d->m_pTopLineWidget, 0 ); pVL->addWidget( d->m_pDiffTextWindow, 1 ); d->m_pDiffTextWindow->installEventFilter( this ); d->m_pFileSelection->installEventFilter( this ); d->m_pBrowseButton->installEventFilter( this ); init(); } DiffTextWindowFrame::~DiffTextWindowFrame() { delete d; } void DiffTextWindowFrame::init() { DiffTextWindow* pDTW = d->m_pDiffTextWindow; if ( pDTW ) { TQString s = pDTW->d->m_filename ; d->m_pFileSelection->setText( TQDir::convertSeparators(s) ); TQString winId = pDTW->d->m_winIdx==1 ? ( pDTW->d->m_bTriple?"A (Base)":"A") : ( pDTW->d->m_winIdx==2 ? "B" : "C" ); d->m_pLabel->setText( winId + ":" ); } } // Search for the first visible line (search loop needed when no line exist for this file.) int DiffTextWindow::calcTopLineInFile( int firstLine ) { int l=-1; for ( int i = convertLineToDiff3LineIdx(firstLine); i<(int)d->m_pDiff3LineVector->size(); ++i ) { const Diff3Line* d3l = (*d->m_pDiff3LineVector)[i]; l = d3l->getLineInFile(d->m_winIdx); if (l!=-1) break; } return l; } void DiffTextWindowFrame::setFirstLine( int firstLine ) { DiffTextWindow* pDTW = d->m_pDiffTextWindow; if ( pDTW && pDTW->d->m_pDiff3LineVector ) { TQString s= i18n("Top line"); int lineNumberWidth = (int)log10((double)pDTW->d->m_size)+1; int l=pDTW->calcTopLineInFile(firstLine); int w = d->m_pTopLine->fontMetrics().width( s+" "+TQString().fill('0',lineNumberWidth)); d->m_pTopLine->setMinimumWidth( w ); if (l==-1) s = i18n("End"); else s += " " + TQString::number( l+1 ); d->m_pTopLine->setText( s ); d->m_pTopLine->repaint(); } } DiffTextWindow* DiffTextWindowFrame::getDiffTextWindow() { return d->m_pDiffTextWindow; } bool DiffTextWindowFrame::eventFilter( TQObject* o, TQEvent* e ) { DiffTextWindow* pDTW = d->m_pDiffTextWindow; if ( e->type()==TQEvent::FocusIn || e->type()==TQEvent::FocusOut ) { TQColor c1 = d->m_pOptionDialog->m_bgColor; TQColor c2 = pDTW->d->m_cThis; TQPalette p = d->m_pTopLineWidget->palette(); if ( e->type()==TQEvent::FocusOut ) std::swap(c1,c2); p.setColor(TQColorGroup::Background, c2); d->m_pTopLineWidget->setPalette( p ); d->m_pBrowseButton->setPalette( p ); d->m_pFileSelection->setPalette( p ); p.setColor(TQColorGroup::Foreground, c1); d->m_pLabel->setPalette( p ); d->m_pTopLine->setPalette( p ); } if (o == d->m_pFileSelection && e->type()==TQEvent::Drop) { TQDropEvent* d = static_cast(e); if ( TQUriDrag::canDecode( d ) ) { TQStringList lst; TQUriDrag::decodeLocalFiles( d, lst ); if ( lst.count() > 0 ) { static_cast(TQT_TQWIDGET(o))->setText( lst[0] ); static_cast(TQT_TQWIDGET(o))->setFocus(); emit fileNameChanged( lst[0], pDTW->d->m_winIdx ); return true; } } /* The following lines work for TQt>4.1 but not for 4.0.x*/ /*if ( d->mimeData()->hasUrls() ) { TQPtrList lst = d->mimeData()->urls(); if ( !lst.empty() ) { static_cast(o)->setText( lst[0].toLocalFile() ); static_cast(o)->setFocus(); emit fileNameChanged( lst[0], pDTW->d->m_winIdx ); return true; } }*/ } return false; } void DiffTextWindowFrame::slotReturnPressed() { DiffTextWindow* pDTW = d->m_pDiffTextWindow; if ( pDTW->d->m_filename != d->m_pFileSelection->text() ) { emit fileNameChanged( d->m_pFileSelection->text(), pDTW->d->m_winIdx ); } } void DiffTextWindowFrame::slotBrowseButtonClicked() { TQString current = d->m_pFileSelection->text(); KURL newURL = KFileDialog::getOpenURL( current, 0, this); if ( !newURL.isEmpty() ) { DiffTextWindow* pDTW = d->m_pDiffTextWindow; emit fileNameChanged( newURL.url(), pDTW->d->m_winIdx ); } } TQCString encodeString( const TQString& s ) { TQTextCodec* c = TQTextCodec::codecForLocale(); if (c!=0) return c->fromUnicode( s ); else return TQCString( s.latin1() ); } #include "difftextwindow.moc"