You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kdiff3/src/mergeresultwindow.cpp

3223 lines
94 KiB

/***************************************************************************
mergeresultwindow.cpp - description
-------------------
begin : Sun Apr 14 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 "mergeresultwindow.h"
#include "optiondialog.h"
#include <tqpainter.h>
#include <tqapplication.h>
#include <tqclipboard.h>
#include <tqdir.h>
#include <tqfile.h>
#include <tqcursor.h>
#include <tqpopupmenu.h>
#include <tqstatusbar.h>
#include <tqregexp.h>
#include <tqlabel.h>
#include <tqlineedit.h>
#include <tqcombobox.h>
#include <tqlayout.h>
#include <tqtextcodec.h>
#include <tqdragobject.h>
#include <tdelocale.h>
#include <tdemessagebox.h>
#include <iostream>
int g_bAutoSolve = true;
#undef leftInfoWidth
#define leftInfoWidth 3
MergeResultWindow::MergeResultWindow(
TQWidget* pParent,
OptionDialog* pOptionDialog,
TQStatusBar* pStatusBar
)
: TQWidget( pParent, 0, WRepaintNoErase )
{
setFocusPolicy( TQWidget::ClickFocus );
m_firstLine = 0;
m_firstColumn = 0;
m_nofColumns = 0;
m_nofLines = 0;
m_totalSize = 0;
m_bMyUpdate = false;
m_bInsertMode = true;
m_scrollDeltaX = 0;
m_scrollDeltaY = 0;
m_bModified = false;
m_eOverviewMode=Overview::eOMNormal;
m_pldA = 0;
m_pldB = 0;
m_pldC = 0;
m_sizeA = 0;
m_sizeB = 0;
m_sizeC = 0;
m_pDiff3LineList = 0;
m_pTotalDiffStatus = 0;
m_pStatusBar = pStatusBar;
m_pOptionDialog = pOptionDialog;
m_bPaintingAllowed = false;
m_delayedDrawTimer = 0;
m_cursorXPos=0;
m_cursorOldXPos=0;
m_cursorYPos=0;
m_bCursorOn = true;
m_bCursorUpdate = false;
connect( &m_cursorTimer, TQ_SIGNAL(timeout()), this, TQ_SLOT( slotCursorUpdate() ) );
m_cursorTimer.start( 500 /*ms*/, true /*single shot*/ );
m_selection.reset();
setMinimumSize( TQSize(20,20) );
setFont( m_pOptionDialog->m_font );
}
void MergeResultWindow::init(
const LineData* pLineDataA, int sizeA,
const LineData* pLineDataB, int sizeB,
const LineData* pLineDataC, int sizeC,
const Diff3LineList* pDiff3LineList,
TotalDiffStatus* pTotalDiffStatus
)
{
m_firstLine = 0;
m_firstColumn = 0;
m_nofColumns = 0;
m_nofLines = 0;
m_bMyUpdate = false;
m_bInsertMode = true;
m_scrollDeltaX = 0;
m_scrollDeltaY = 0;
setModified( false );
m_pldA = pLineDataA;
m_pldB = pLineDataB;
m_pldC = pLineDataC;
m_sizeA = sizeA;
m_sizeB = sizeB;
m_sizeC = sizeC;
m_pDiff3LineList = pDiff3LineList;
m_pTotalDiffStatus = pTotalDiffStatus;
m_selection.reset();
m_cursorXPos=0;
m_cursorOldXPos=0;
m_cursorYPos=0;
merge( g_bAutoSolve, -1 );
g_bAutoSolve = true;
update();
updateSourceMask();
int wsc;
int nofUnsolved = getNrOfUnsolvedConflicts(&wsc);
if (m_pStatusBar)
m_pStatusBar->message( i18n("Number of remaining unsolved conflicts: %1 (of which %2 are whitespace)")
.arg(nofUnsolved).arg(wsc) );
}
void MergeResultWindow::reset()
{
m_pDiff3LineList = 0;
m_pTotalDiffStatus = 0;
m_pldA = 0;
m_pldB = 0;
m_pldC = 0;
}
// Calculate the merge information for the given Diff3Line.
// Results will be stored in mergeDetails, bConflict, bLineRemoved and src.
void mergeOneLine(
const Diff3Line& d, e_MergeDetails& mergeDetails, bool& bConflict,
bool& bLineRemoved, int& src, bool bTwoInputs
)
{
mergeDetails = eDefault;
bConflict = false;
bLineRemoved = false;
src = 0;
if ( bTwoInputs ) // Only two input files
{
if ( d.lineA!=-1 && d.lineB!=-1 )
{
if ( d.pFineAB == 0 )
{
mergeDetails = eNoChange; src = A;
}
else
{
mergeDetails = eBChanged; bConflict = true;
}
}
else
{
if ( d.lineA!=-1 && d.lineB==-1 )
{
mergeDetails = eBDeleted; bConflict = true;
}
else if ( d.lineA==-1 && d.lineB!=-1 )
{
mergeDetails = eBDeleted; bConflict = true;
}
}
return;
}
// A is base.
if ( d.lineA!=-1 && d.lineB!=-1 && d.lineC!=-1 )
{
if ( d.pFineAB == 0 && d.pFineBC == 0 && d.pFineCA == 0)
{
mergeDetails = eNoChange; src = A;
}
else if( d.pFineAB == 0 && d.pFineBC != 0 && d.pFineCA != 0 )
{
mergeDetails = eCChanged; src = C;
}
else if( d.pFineAB != 0 && d.pFineBC != 0 && d.pFineCA == 0 )
{
mergeDetails = eBChanged; src = B;
}
else if( d.pFineAB != 0 && d.pFineBC == 0 && d.pFineCA != 0 )
{
mergeDetails = eBCChangedAndEqual; src = C;
}
else if( d.pFineAB != 0 && d.pFineBC != 0 && d.pFineCA != 0 )
{
mergeDetails = eBCChanged; bConflict = true;
}
else
assert(false);
}
else if ( d.lineA!=-1 && d.lineB!=-1 && d.lineC==-1 )
{
if( d.pFineAB != 0 )
{
mergeDetails = eBChanged_CDeleted; bConflict = true;
}
else
{
mergeDetails = eCDeleted; bLineRemoved = true; src = C;
}
}
else if ( d.lineA!=-1 && d.lineB==-1 && d.lineC!=-1 )
{
if( d.pFineCA != 0 )
{
mergeDetails = eCChanged_BDeleted; bConflict = true;
}
else
{
mergeDetails = eBDeleted; bLineRemoved = true; src = B;
}
}
else if ( d.lineA==-1 && d.lineB!=-1 && d.lineC!=-1 )
{
if( d.pFineBC != 0 )
{
mergeDetails = eBCAdded; bConflict = true;
}
else // B==C
{
mergeDetails = eBCAddedAndEqual; src = C;
}
}
else if ( d.lineA==-1 && d.lineB==-1 && d.lineC!= -1 )
{
mergeDetails = eCAdded; src = C;
}
else if ( d.lineA==-1 && d.lineB!=-1 && d.lineC== -1 )
{
mergeDetails = eBAdded; src = B;
}
else if ( d.lineA!=-1 && d.lineB==-1 && d.lineC==-1 )
{
mergeDetails = eBCDeleted; bLineRemoved = true; src = C;
}
else
assert(false);
}
bool MergeResultWindow::sameKindCheck( const MergeLine& ml1, const MergeLine& ml2 )
{
if ( ml1.bConflict && ml2.bConflict )
{
// Both lines have conflicts: If one is only a white space conflict and
// the other one is a real conflict, then this line returns false.
return ml1.id3l->bAEqC == ml2.id3l->bAEqC && ml1.id3l->bAEqB == ml2.id3l->bAEqB;
}
else
return (
!ml1.bConflict && !ml2.bConflict && ml1.bDelta && ml2.bDelta && ml1.srcSelect == ml2.srcSelect ||
!ml1.bDelta && !ml2.bDelta
);
}
void MergeResultWindow::merge(bool bAutoSolve, int defaultSelector, bool bConflictsOnly, bool bWhiteSpaceOnly )
{
if ( !bConflictsOnly )
{
if(m_bModified)
{
int result = KMessageBox::warningYesNo(this,
i18n("The output has been modified.\n"
"If you continue your changes will be lost."),
i18n("Warning"), i18n("C&ontinue"), i18n("&Cancel"));
if ( result==KMessageBox::No )
return;
}
m_mergeLineList.clear();
m_totalSize = 0;
int lineIdx = 0;
Diff3LineList::const_iterator it;
for( it=m_pDiff3LineList->begin(); it!=m_pDiff3LineList->end(); ++it, ++lineIdx )
{
const Diff3Line& d = *it;
MergeLine ml;
bool bLineRemoved;
mergeOneLine( d, ml.mergeDetails, ml.bConflict, bLineRemoved, ml.srcSelect, m_pldC==0 );
// Automatic solving for only whitespace changes.
if ( ml.bConflict &&
( m_pldC==0 && (d.bAEqB || d.bWhiteLineA && d.bWhiteLineB) ||
m_pldC!=0 && (d.bAEqB && d.bAEqC || d.bWhiteLineA && d.bWhiteLineB && d.bWhiteLineC ) ) )
{
ml.bWhiteSpaceConflict = true;
}
ml.d3lLineIdx = lineIdx;
ml.bDelta = ml.srcSelect != A;
ml.id3l = it;
ml.srcRangeLength = 1;
MergeLine* back = m_mergeLineList.empty() ? 0 : &m_mergeLineList.back();
bool bSame = back!=0 && sameKindCheck( ml, *back );
if( bSame )
{
++back->srcRangeLength;
if ( back->bWhiteSpaceConflict && !ml.bWhiteSpaceConflict )
back->bWhiteSpaceConflict = false;
}
else
{
if (back!=0 && back->bWhiteSpaceConflict )
{
if ( m_pldC==0 && m_pOptionDialog->m_whiteSpace2FileMergeDefault != 0 ) // Only two inputs
{
back->srcSelect = m_pOptionDialog->m_whiteSpace2FileMergeDefault;
back->bConflict = false;
}
else if ( m_pldC!=0 && m_pOptionDialog->m_whiteSpace3FileMergeDefault != 0 )
{
back->srcSelect = m_pOptionDialog->m_whiteSpace3FileMergeDefault;
back->bConflict = false;
}
}
ml.mergeEditLineList.setTotalSizePtr(&m_totalSize);
m_mergeLineList.push_back( ml );
}
if ( ! ml.bConflict )
{
MergeLine& tmpBack = m_mergeLineList.back();
MergeEditLine mel(ml.id3l);
mel.setSource( ml.srcSelect, bLineRemoved );
tmpBack.mergeEditLineList.push_back(mel);
}
else if ( back==0 || ! back->bConflict || !bSame )
{
MergeLine& tmpBack = m_mergeLineList.back();
MergeEditLine mel(ml.id3l);
mel.setConflict();
tmpBack.mergeEditLineList.push_back(mel);
}
}
}
if ( !bAutoSolve )
{
// Change all auto selections
MergeLineList::iterator mlIt;
for( mlIt=m_mergeLineList.begin(); mlIt!=m_mergeLineList.end(); ++mlIt )
{
MergeLine& ml = *mlIt;
bool bConflict = ml.mergeEditLineList.empty() || ml.mergeEditLineList.begin()->isConflict();
if ( ml.bDelta && ( !bConflictsOnly || bConflict ) && (!bWhiteSpaceOnly || ml.bWhiteSpaceConflict ))
{
ml.mergeEditLineList.clear();
if ( defaultSelector==-1 && ml.bDelta )
{
MergeEditLine mel(ml.id3l);;
mel.setConflict();
ml.bConflict = true;
ml.mergeEditLineList.push_back(mel);
}
else
{
Diff3LineList::const_iterator d3llit=ml.id3l;
int j;
for( j=0; j<ml.srcRangeLength; ++j )
{
MergeEditLine mel(d3llit);
mel.setSource( defaultSelector, false );
int srcLine = defaultSelector==1 ? d3llit->lineA :
defaultSelector==2 ? d3llit->lineB :
defaultSelector==3 ? d3llit->lineC : -1;
if ( srcLine != -1 )
{
ml.mergeEditLineList.push_back(mel);
}
++d3llit;
}
if ( ml.mergeEditLineList.empty() ) // Make a line nevertheless
{
MergeEditLine mel(ml.id3l);
mel.setRemoved( defaultSelector );
ml.mergeEditLineList.push_back(mel);
}
}
}
}
}
MergeLineList::iterator mlIt;
for( mlIt=m_mergeLineList.begin(); mlIt!=m_mergeLineList.end(); ++mlIt )
{
MergeLine& ml = *mlIt;
// Remove all lines that are empty, because no src lines are there.
int oldSrcLine = -1;
int oldSrc = -1;
MergeEditLineList::iterator melIt;
for( melIt = ml.mergeEditLineList.begin(); melIt != ml.mergeEditLineList.end(); )
{
MergeEditLine& mel = *melIt;
int melsrc = mel.src();
int srcLine = mel.isRemoved() ? -1 :
melsrc==1 ? mel.id3l()->lineA :
melsrc==2 ? mel.id3l()->lineB :
melsrc==3 ? mel.id3l()->lineC : -1;
// At least one line remains because oldSrc != melsrc for first line in list
// Other empty lines will be removed
if ( srcLine == -1 && oldSrcLine==-1 && oldSrc == melsrc )
melIt = ml.mergeEditLineList.erase( melIt );
else
++melIt;
oldSrcLine = srcLine;
oldSrc = melsrc;
}
}
if ( bAutoSolve && !bConflictsOnly )
{
if ( m_pOptionDialog->m_bRunHistoryAutoMergeOnMergeStart )
slotMergeHistory();
if ( m_pOptionDialog->m_bRunRegExpAutoMergeOnMergeStart )
slotRegExpAutoMerge();
if ( m_pldC != 0 && ! doRelevantChangesExist() )
emit noRelevantChangesDetected();
}
int nrOfSolvedConflicts = 0;
int nrOfUnsolvedConflicts = 0;
int nrOfWhiteSpaceConflicts = 0;
MergeLineList::iterator i;
for ( i = m_mergeLineList.begin(); i!=m_mergeLineList.end(); ++i )
{
if ( i->bConflict )
++nrOfUnsolvedConflicts;
else if ( i->bDelta )
++nrOfSolvedConflicts;
if ( i->bWhiteSpaceConflict )
++nrOfWhiteSpaceConflicts;
}
m_pTotalDiffStatus->nofUnsolvedConflicts = nrOfUnsolvedConflicts;
m_pTotalDiffStatus->nofSolvedConflicts = nrOfSolvedConflicts;
m_pTotalDiffStatus->nofWhitespaceConflicts = nrOfWhiteSpaceConflicts;
m_cursorXPos=0;
m_cursorOldXPos=0;
m_cursorYPos=0;
//m_firstLine = 0; // Must not set line/column without scrolling there
//m_firstColumn = 0;
setModified(false);
m_currentMergeLineIt = m_mergeLineList.begin();
slotGoTop();
updateAvailabilities();
update();
}
void MergeResultWindow::setFirstLine(int firstLine)
{
m_firstLine = max2(0,firstLine);
update();
}
void MergeResultWindow::setFirstColumn(int firstCol)
{
m_firstColumn = max2(0,firstCol);
update();
}
int MergeResultWindow::getNofColumns()
{
return m_nofColumns;
}
int MergeResultWindow::getNofLines()
{
return m_totalSize;
}
int MergeResultWindow::getNofVisibleColumns()
{
TQFontMetrics fm = fontMetrics();
return width()/fm.width('W')-4;
}
int MergeResultWindow::getNofVisibleLines()
{
TQFontMetrics fm = fontMetrics();
return (height()-3)/fm.height()-2;
}
void MergeResultWindow::resizeEvent( TQResizeEvent* e )
{
TQWidget::resizeEvent(e);
emit resizeSignal();
}
Overview::e_OverviewMode MergeResultWindow::getOverviewMode()
{
return m_eOverviewMode;
}
void MergeResultWindow::setOverviewMode( Overview::e_OverviewMode eOverviewMode )
{
m_eOverviewMode = eOverviewMode;
}
// Check whether we should ignore current delta when moving to next/previous delta
bool MergeResultWindow::checkOverviewIgnore(MergeLineList::iterator &i)
{
if (m_eOverviewMode == Overview::eOMNormal) return false;
if (m_eOverviewMode == Overview::eOMAvsB)
return i->mergeDetails == eCAdded || i->mergeDetails == eCDeleted || i->mergeDetails == eCChanged;
if (m_eOverviewMode == Overview::eOMAvsC)
return i->mergeDetails == eBAdded || i->mergeDetails == eBDeleted || i->mergeDetails == eBChanged;
if (m_eOverviewMode == Overview::eOMBvsC)
return i->mergeDetails == eBCAddedAndEqual || i->mergeDetails == eBCDeleted || i->mergeDetails == eBCChangedAndEqual;
return false;
}
// Go to prev/next delta/conflict or first/last delta.
void MergeResultWindow::go( e_Direction eDir, e_EndPoint eEndPoint )
{
assert( eDir==eUp || eDir==eDown );
MergeLineList::iterator i = m_currentMergeLineIt;
bool bSkipWhiteConflicts = ! m_pOptionDialog->m_bShowWhiteSpace;
if( eEndPoint==eEnd )
{
if (eDir==eUp) i = m_mergeLineList.begin(); // first mergeline
else i = --m_mergeLineList.end(); // last mergeline
while ( isItAtEnd(eDir==eUp, i) && ! i->bDelta )
{
if ( eDir==eUp ) ++i; // search downwards
else --i; // search upwards
}
}
else if ( eEndPoint == eDelta && isItAtEnd(eDir!=eUp, i) )
{
do
{
if ( eDir==eUp ) --i;
else ++i;
}
while ( isItAtEnd(eDir!=eUp, i) && ( i->bDelta == false || checkOverviewIgnore(i) || bSkipWhiteConflicts && i->bWhiteSpaceConflict ) );
}
else if ( eEndPoint == eConflict && isItAtEnd(eDir!=eUp, i) )
{
do
{
if ( eDir==eUp ) --i;
else ++i;
}
while ( isItAtEnd(eDir!=eUp, i) && (i->bConflict == false || bSkipWhiteConflicts && i->bWhiteSpaceConflict ) );
}
else if ( isItAtEnd(eDir!=eUp, i) && eEndPoint == eUnsolvedConflict )
{
do
{
if ( eDir==eUp ) --i;
else ++i;
}
while ( isItAtEnd(eDir!=eUp, i) && ! i->mergeEditLineList.begin()->isConflict() );
}
if ( isVisible() )
setFocus();
setFastSelector( i );
}
bool MergeResultWindow::isDeltaAboveCurrent()
{
bool bSkipWhiteConflicts = ! m_pOptionDialog->m_bShowWhiteSpace;
if (m_mergeLineList.empty()) return false;
MergeLineList::iterator i = m_currentMergeLineIt;
if (i == m_mergeLineList.begin()) return false;
do
{
--i;
if ( i->bDelta && !checkOverviewIgnore(i) && !( bSkipWhiteConflicts && i->bWhiteSpaceConflict ) ) return true;
}
while (i!=m_mergeLineList.begin());
return false;
}
bool MergeResultWindow::isDeltaBelowCurrent()
{
bool bSkipWhiteConflicts = ! m_pOptionDialog->m_bShowWhiteSpace;
if (m_mergeLineList.empty()) return false;
MergeLineList::iterator i = m_currentMergeLineIt;
if (i!=m_mergeLineList.end())
{
++i;
for( ; i!=m_mergeLineList.end(); ++i )
{
if ( i->bDelta && !checkOverviewIgnore(i) && !( bSkipWhiteConflicts && i->bWhiteSpaceConflict ) ) return true;
}
}
return false;
}
bool MergeResultWindow::isConflictAboveCurrent()
{
if (m_mergeLineList.empty()) return false;
MergeLineList::iterator i = m_currentMergeLineIt;
if (i == m_mergeLineList.begin()) return false;
bool bSkipWhiteConflicts = ! m_pOptionDialog->m_bShowWhiteSpace;
do
{
--i;
if ( i->bConflict && !(bSkipWhiteConflicts && i->bWhiteSpaceConflict) ) return true;
}
while (i!=m_mergeLineList.begin());
return false;
}
bool MergeResultWindow::isConflictBelowCurrent()
{
MergeLineList::iterator i = m_currentMergeLineIt;
if (m_mergeLineList.empty()) return false;
bool bSkipWhiteConflicts = ! m_pOptionDialog->m_bShowWhiteSpace;
if (i!=m_mergeLineList.end())
{
++i;
for( ; i!=m_mergeLineList.end(); ++i )
{
if ( i->bConflict && !(bSkipWhiteConflicts && i->bWhiteSpaceConflict) ) return true;
}
}
return false;
}
bool MergeResultWindow::isUnsolvedConflictAtCurrent()
{
if (m_mergeLineList.empty()) return false;
MergeLineList::iterator i = m_currentMergeLineIt;
return i->mergeEditLineList.begin()->isConflict();
}
bool MergeResultWindow::isUnsolvedConflictAboveCurrent()
{
if (m_mergeLineList.empty()) return false;
MergeLineList::iterator i = m_currentMergeLineIt;
if (i == m_mergeLineList.begin()) return false;
do
{
--i;
if ( i->mergeEditLineList.begin()->isConflict() ) return true;
}
while (i!=m_mergeLineList.begin());
return false;
}
bool MergeResultWindow::isUnsolvedConflictBelowCurrent()
{
MergeLineList::iterator i = m_currentMergeLineIt;
if (m_mergeLineList.empty()) return false;
if (i!=m_mergeLineList.end())
{
++i;
for( ; i!=m_mergeLineList.end(); ++i )
{
if ( i->mergeEditLineList.begin()->isConflict() ) return true;
}
}
return false;
}
void MergeResultWindow::slotGoTop()
{
go( eUp, eEnd );
}
void MergeResultWindow::slotGoCurrent()
{
setFastSelector( m_currentMergeLineIt );
}
void MergeResultWindow::slotGoBottom()
{
go( eDown, eEnd );
}
void MergeResultWindow::slotGoPrevDelta()
{
go( eUp, eDelta );
}
void MergeResultWindow::slotGoNextDelta()
{
go( eDown, eDelta );
}
void MergeResultWindow::slotGoPrevConflict()
{
go( eUp, eConflict );
}
void MergeResultWindow::slotGoNextConflict()
{
go( eDown, eConflict );
}
void MergeResultWindow::slotGoPrevUnsolvedConflict()
{
go( eUp, eUnsolvedConflict );
}
void MergeResultWindow::slotGoNextUnsolvedConflict()
{
go( eDown, eUnsolvedConflict );
}
/** The line is given as a index in the Diff3LineList.
The function calculates the corresponding iterator. */
void MergeResultWindow::slotSetFastSelectorLine( int line )
{
MergeLineList::iterator i;
for ( i = m_mergeLineList.begin(); i!=m_mergeLineList.end(); ++i )
{
if ( line>=i->d3lLineIdx && line < i->d3lLineIdx + i->srcRangeLength )
{
//if ( i->bDelta )
{
setFastSelector( i );
}
break;
}
}
}
int MergeResultWindow::getNrOfUnsolvedConflicts( int* pNrOfWhiteSpaceConflicts )
{
int nrOfUnsolvedConflicts = 0;
if (pNrOfWhiteSpaceConflicts!=0)
*pNrOfWhiteSpaceConflicts = 0;
MergeLineList::iterator mlIt = m_mergeLineList.begin();
for(mlIt = m_mergeLineList.begin();mlIt!=m_mergeLineList.end(); ++mlIt)
{
MergeLine& ml = *mlIt;
MergeEditLineList::iterator melIt = ml.mergeEditLineList.begin();
if ( melIt->isConflict() )
{
++nrOfUnsolvedConflicts;
if ( ml.bWhiteSpaceConflict && pNrOfWhiteSpaceConflicts!=0 )
++ *pNrOfWhiteSpaceConflicts;
}
}
return nrOfUnsolvedConflicts;
}
void MergeResultWindow::showNrOfConflicts()
{
int nrOfConflicts = 0;
MergeLineList::iterator i;
for ( i = m_mergeLineList.begin(); i!=m_mergeLineList.end(); ++i )
{
if ( i->bConflict || i->bDelta )
++nrOfConflicts;
}
TQString totalInfo;
if ( m_pTotalDiffStatus->bBinaryAEqB && m_pTotalDiffStatus->bBinaryAEqC )
totalInfo += i18n("All input files are binary equal.");
else if ( m_pTotalDiffStatus->bTextAEqB && m_pTotalDiffStatus->bTextAEqC )
totalInfo += i18n("All input files contain the same text.");
else {
if ( m_pTotalDiffStatus->bBinaryAEqB ) totalInfo += i18n("Files %1 and %2 are binary equal.\n").arg("A").arg("B");
else if ( m_pTotalDiffStatus->bTextAEqB ) totalInfo += i18n("Files %1 and %2 have equal text.\n").arg("A").arg("B");
if ( m_pTotalDiffStatus->bBinaryAEqC ) totalInfo += i18n("Files %1 and %2 are binary equal.\n").arg("A").arg("C");
else if ( m_pTotalDiffStatus->bTextAEqC ) totalInfo += i18n("Files %1 and %2 have equal text.\n").arg("A").arg("C");
if ( m_pTotalDiffStatus->bBinaryBEqC ) totalInfo += i18n("Files %1 and %2 are binary equal.\n").arg("B").arg("C");
else if ( m_pTotalDiffStatus->bTextBEqC ) totalInfo += i18n("Files %1 and %2 have equal text.\n").arg("B").arg("C");
}
int nrOfUnsolvedConflicts = getNrOfUnsolvedConflicts();
KMessageBox::information( this,
i18n("Total number of conflicts: ") + TQString::number(nrOfConflicts) +
i18n("\nNr of automatically solved conflicts: ") + TQString::number(nrOfConflicts-nrOfUnsolvedConflicts) +
i18n("\nNr of unsolved conflicts: ") + TQString::number(nrOfUnsolvedConflicts) +
"\n"+totalInfo,
i18n("Conflicts")
);
}
void MergeResultWindow::setFastSelector(MergeLineList::iterator i)
{
if ( i==m_mergeLineList.end() )
return;
m_currentMergeLineIt = i;
emit setFastSelectorRange( i->d3lLineIdx, i->srcRangeLength );
int line1 = 0;
MergeLineList::iterator mlIt = m_mergeLineList.begin();
for(mlIt = m_mergeLineList.begin();mlIt!=m_mergeLineList.end(); ++mlIt)
{
if(mlIt==m_currentMergeLineIt)
break;
line1 += mlIt->mergeEditLineList.size();
}
int nofLines = m_currentMergeLineIt->mergeEditLineList.size();
int newFirstLine = getBestFirstLine( line1, nofLines, m_firstLine, getNofVisibleLines() );
if ( newFirstLine != m_firstLine )
{
scroll( 0, newFirstLine - m_firstLine );
}
if ( m_selection.isEmpty() )
{
m_cursorXPos = 0;
m_cursorOldXPos = 0;
m_cursorYPos = line1;
}
update();
updateSourceMask();
emit updateAvailabilities();
}
void MergeResultWindow::choose( int selector )
{
if ( m_currentMergeLineIt==m_mergeLineList.end() )
return;
setModified();
// First find range for which this change works.
MergeLine& ml = *m_currentMergeLineIt;
MergeEditLineList::iterator melIt;
// Now check if selector is active for this range already.
bool bActive = false;
// Remove unneeded lines in the range.
for( melIt = ml.mergeEditLineList.begin(); melIt != ml.mergeEditLineList.end(); )
{
MergeEditLine& mel = *melIt;
if ( mel.src()==selector )
bActive = true;
if ( mel.src()==selector || !mel.isEditableText() || mel.isModified() )
melIt = ml.mergeEditLineList.erase( melIt );
else
++melIt;
}
if ( !bActive ) // Selected source wasn't active.
{ // Append the lines from selected source here at rangeEnd.
Diff3LineList::const_iterator d3llit=ml.id3l;
int j;
for( j=0; j<ml.srcRangeLength; ++j )
{
MergeEditLine mel(d3llit);
mel.setSource( selector, false );
ml.mergeEditLineList.push_back(mel);
++d3llit;
}
}
if ( ! ml.mergeEditLineList.empty() )
{
// Remove all lines that are empty, because no src lines are there.
for( melIt = ml.mergeEditLineList.begin(); melIt != ml.mergeEditLineList.end(); )
{
MergeEditLine& mel = *melIt;
int srcLine = mel.src()==1 ? mel.id3l()->lineA :
mel.src()==2 ? mel.id3l()->lineB :
mel.src()==3 ? mel.id3l()->lineC : -1;
if ( srcLine == -1 )
melIt = ml.mergeEditLineList.erase( melIt );
else
++melIt;
}
}
if ( ml.mergeEditLineList.empty() )
{
// Insert a dummy line:
MergeEditLine mel(ml.id3l);
if ( bActive ) mel.setConflict(); // All src entries deleted => conflict
else mel.setRemoved(selector); // No lines in corresponding src found.
ml.mergeEditLineList.push_back(mel);
}
if ( m_cursorYPos >= m_totalSize )
{
m_cursorYPos = m_totalSize-1;
m_cursorXPos = 0;
}
update();
updateSourceMask();
emit updateAvailabilities();
int wsc;
int nofUnsolved = getNrOfUnsolvedConflicts(&wsc);
m_pStatusBar->message( i18n("Number of remaining unsolved conflicts: %1 (of which %2 are whitespace)")
.arg(nofUnsolved).arg(wsc) );
}
// bConflictsOnly: automatically choose for conflicts only (true) or for everywhere (false)
void MergeResultWindow::chooseGlobal(int selector, bool bConflictsOnly, bool bWhiteSpaceOnly )
{
resetSelection();
merge( false, selector, bConflictsOnly, bWhiteSpaceOnly );
setModified( true );
update();
int wsc;
int nofUnsolved = getNrOfUnsolvedConflicts(&wsc);
m_pStatusBar->message( i18n("Number of remaining unsolved conflicts: %1 (of which %2 are whitespace)")
.arg(nofUnsolved).arg(wsc) );
}
void MergeResultWindow::slotAutoSolve()
{
resetSelection();
merge( true, -1 );
setModified( true );
update();
int wsc;
int nofUnsolved = getNrOfUnsolvedConflicts(&wsc);
m_pStatusBar->message( i18n("Number of remaining unsolved conflicts: %1 (of which %2 are whitespace)")
.arg(nofUnsolved).arg(wsc) );
}
void MergeResultWindow::slotUnsolve()
{
resetSelection();
merge( false, -1 );
setModified( true );
update();
int wsc;
int nofUnsolved = getNrOfUnsolvedConflicts(&wsc);
m_pStatusBar->message( i18n("Number of remaining unsolved conflicts: %1 (of which %2 are whitespace)")
.arg(nofUnsolved).arg(wsc) );
}
static TQString calcHistoryLead(const TQString& s )
{
// Return the start of the line until the first white char after the first non white char.
unsigned int i;
for( i=0; i<s.length(); ++i )
{
if (s[i]!=' ' && s[i]!='\t')
{
for( ; i<s.length(); ++i )
{
if (s[i]==' ' || s[i]=='\t')
{
return s.left(i);
}
}
return s; // Very unlikely
}
}
return ""; // Must be an empty string, not a null string.
}
static void findHistoryRange( const TQRegExp& historyStart, bool bThreeFiles, const Diff3LineList* pD3LList,
Diff3LineList::const_iterator& iBegin, Diff3LineList::const_iterator& iEnd, int& idxBegin, int& idxEnd )
{
TQString historyLead;
// Search for start of history
for( iBegin = pD3LList->begin(), idxBegin=0; iBegin!=pD3LList->end(); ++iBegin, ++idxBegin )
{
if ( historyStart.exactMatch( iBegin->getString(A) ) &&
historyStart.exactMatch( iBegin->getString(B) ) &&
( !bThreeFiles || historyStart.exactMatch( iBegin->getString(C) ) ) )
{
historyLead = calcHistoryLead( iBegin->getString(A) );
break;
}
}
// Search for end of history
for( iEnd = iBegin, idxEnd = idxBegin; iEnd!=pD3LList->end(); ++iEnd, ++idxEnd )
{
TQString sA = iEnd->getString(A);
TQString sB = iEnd->getString(B);
TQString sC = iEnd->getString(C);
if ( ! ((sA.isNull() || historyLead == calcHistoryLead(sA) ) &&
(sB.isNull() || historyLead == calcHistoryLead(sB) ) &&
(!bThreeFiles || sC.isNull() || historyLead == calcHistoryLead(sC) )
))
{
break; // End of the history
}
}
}
bool findParenthesesGroups( const TQString& s, TQStringList& sl )
{
sl.clear();
int i=0;
std::list<int> startPosStack;
int length = s.length();
for( i=0; i<length; ++i )
{
if ( s[i]=='\\' && i+1<length && ( s[i+1]=='\\' || s[i+1]=='(' || s[i+1]==')' ) )
{
++i;
continue;
}
if ( s[i]=='(' )
{
startPosStack.push_back(i);
}
else if ( s[i]==')' )
{
if (startPosStack.empty())
return false; // Parentheses don't match
int startPos = startPosStack.back();
startPosStack.pop_back();
sl.push_back( s.mid( startPos+1, i-startPos-1 ) );
}
}
return startPosStack.empty(); // false if parentheses don't match
}
TQString calcHistorySortKey( const TQString& keyOrder, TQRegExp& matchedRegExpr, const TQStringList& parenthesesGroupList )
{
TQStringList keyOrderList = TQStringList::split(',', keyOrder );
TQString key;
for ( TQStringList::iterator keyIt = keyOrderList.begin(); keyIt!=keyOrderList.end(); ++keyIt )
{
if ( (*keyIt).isEmpty() )
continue;
bool bOk=false;
int groupIdx = (*keyIt).toInt(&bOk);
if (!bOk || groupIdx<0 || groupIdx >(int)parenthesesGroupList.size() )
continue;
TQString s = matchedRegExpr.cap( groupIdx );
if ( groupIdx == 0 )
{
key += s + " ";
continue;
}
TQString groupRegExp = parenthesesGroupList[groupIdx-1];
if( groupRegExp.find('|')<0 || groupRegExp.find('(')>=0 )
{
bool bOk = false;
int i = s.toInt( &bOk );
if ( bOk && i>=0 && i<10000 )
s.sprintf("%04d", i); // This should help for correct sorting of numbers.
key += s + " ";
}
else
{
// Assume that the groupRegExp consists of something like "Jan|Feb|Mar|Apr"
// s is the string that managed to match.
// Now we want to know at which position it occurred. e.g. Jan=0, Feb=1, Mar=2, etc.
TQStringList sl = TQStringList::split( '|', groupRegExp );
int idx = sl.findIndex( s );
if (idx<0)
{
// Didn't match
}
else
{
TQString sIdx;
sIdx.sprintf("%02d", idx+1 ); // Up to 99 words in the groupRegExp (more than 12 aren't expected)
key += sIdx + " ";
}
}
}
return key;
}
void MergeResultWindow::collectHistoryInformation(
int src, Diff3LineList::const_iterator iHistoryBegin, Diff3LineList::const_iterator iHistoryEnd,
HistoryMap& historyMap,
std::list< HistoryMap::iterator >& hitList // list of iterators
)
{
std::list< HistoryMap::iterator >::iterator itHitListFront = hitList.begin();
Diff3LineList::const_iterator id3l = iHistoryBegin;
TQString historyLead;
{
const LineData* pld = id3l->getLineData(src);
TQString s( pld->pLine, pld->size );
historyLead = calcHistoryLead(s);
}
TQRegExp historyStart = m_pOptionDialog->m_historyStartRegExp;
++id3l; // Skip line with "$Log ... $"
TQRegExp newHistoryEntry = m_pOptionDialog->m_historyEntryStartRegExp;
TQStringList parenthesesGroups;
findParenthesesGroups( m_pOptionDialog->m_historyEntryStartRegExp, parenthesesGroups );
TQString key;
MergeEditLineList melList;
bool bPrevLineIsEmpty = true;
bool bUseRegExp = !m_pOptionDialog->m_historyEntryStartRegExp.isEmpty();
for(; id3l != iHistoryEnd; ++id3l )
{
const LineData* pld = id3l->getLineData(src);
if ( !pld ) continue;
TQString s( pld->pLine, pld->size );
if (historyLead.isNull()) historyLead = calcHistoryLead(s);
TQString sLine = s.mid(historyLead.length());
if ( ( !bUseRegExp && !sLine.stripWhiteSpace().isEmpty() && bPrevLineIsEmpty )
|| bUseRegExp && newHistoryEntry.exactMatch( sLine )
)
{
if ( !key.isEmpty() && !melList.empty() )
{
// Only insert new HistoryMapEntry if key not found; in either case p.first is a valid iterator to element key.
std::pair<HistoryMap::iterator, bool> p = historyMap.insert(HistoryMap::value_type(key,HistoryMapEntry()));
HistoryMapEntry& hme = p.first->second;
if ( src==A ) hme.mellA = melList;
if ( src==B ) hme.mellB = melList;
if ( src==C ) hme.mellC = melList;
if ( p.second ) // Not in list yet?
{
hitList.insert( itHitListFront, p.first );
}
}
if ( ! bUseRegExp )
key = sLine;
else
key = calcHistorySortKey(m_pOptionDialog->m_historyEntryStartSortKeyOrder,newHistoryEntry,parenthesesGroups);
melList.clear();
melList.push_back( MergeEditLine(id3l,src) );
}
else if ( ! historyStart.exactMatch( s ) )
{
melList.push_back( MergeEditLine(id3l,src) );
}
bPrevLineIsEmpty = sLine.stripWhiteSpace().isEmpty();
}
if ( !key.isEmpty() )
{
// Only insert new HistoryMapEntry if key not found; in either case p.first is a valid iterator to element key.
std::pair<HistoryMap::iterator, bool> p = historyMap.insert(HistoryMap::value_type(key,HistoryMapEntry()));
HistoryMapEntry& hme = p.first->second;
if ( src==A ) hme.mellA = melList;
if ( src==B ) hme.mellB = melList;
if ( src==C ) hme.mellC = melList;
if ( p.second ) // Not in list yet?
{
hitList.insert( itHitListFront, p.first );
}
}
// End of the history
}
MergeResultWindow::MergeEditLineList& MergeResultWindow::HistoryMapEntry::choice( bool bThreeInputs )
{
if ( !bThreeInputs )
return mellA.empty() ? mellB : mellA;
else
{
if ( mellA.empty() )
return mellC.empty() ? mellB : mellC; // A doesn't exist, return one that exists
else if ( ! mellB.empty() && ! mellC.empty() )
{ // A, B and C exist
return mellA;
}
else
return mellB.empty() ? mellB : mellC; // A exists, return the one that doesn't exist
}
}
bool MergeResultWindow::HistoryMapEntry::staysInPlace( bool bThreeInputs, Diff3LineList::const_iterator& iHistoryEnd )
{
// The entry should stay in place if the decision made by the automerger is correct.
Diff3LineList::const_iterator& iHistoryLast = iHistoryEnd;
--iHistoryLast;
if ( !bThreeInputs )
{
if ( !mellA.empty() && !mellB.empty() && mellA.begin()->id3l()==mellB.begin()->id3l() &&
mellA.back().id3l() == iHistoryLast && mellB.back().id3l() == iHistoryLast )
{
iHistoryEnd = mellA.begin()->id3l();
return true;
}
else
{
return false;
}
}
else
{
if ( !mellA.empty() && !mellB.empty() && !mellC.empty()
&& mellA.begin()->id3l()==mellB.begin()->id3l() && mellA.begin()->id3l()==mellC.begin()->id3l()
&& mellA.back().id3l() == iHistoryLast && mellB.back().id3l() == iHistoryLast && mellC.back().id3l() == iHistoryLast )
{
iHistoryEnd = mellA.begin()->id3l();
return true;
}
else
{
return false;
}
}
}
void MergeResultWindow::slotMergeHistory()
{
Diff3LineList::const_iterator iD3LHistoryBegin;
Diff3LineList::const_iterator iD3LHistoryEnd;
int d3lHistoryBeginLineIdx = -1;
int d3lHistoryEndLineIdx = -1;
// Search for history start, history end in the diff3LineList
findHistoryRange( m_pOptionDialog->m_historyStartRegExp, m_pldC!=0, m_pDiff3LineList, iD3LHistoryBegin, iD3LHistoryEnd, d3lHistoryBeginLineIdx, d3lHistoryEndLineIdx );
if ( iD3LHistoryBegin != m_pDiff3LineList->end() )
{
// Now collect the historyMap information
HistoryMap historyMap;
std::list< HistoryMap::iterator > hitList;
if (m_pldC==0)
{
collectHistoryInformation( A, iD3LHistoryBegin, iD3LHistoryEnd, historyMap, hitList );
collectHistoryInformation( B, iD3LHistoryBegin, iD3LHistoryEnd, historyMap, hitList );
}
else
{
collectHistoryInformation( A, iD3LHistoryBegin, iD3LHistoryEnd, historyMap, hitList );
collectHistoryInformation( B, iD3LHistoryBegin, iD3LHistoryEnd, historyMap, hitList );
collectHistoryInformation( C, iD3LHistoryBegin, iD3LHistoryEnd, historyMap, hitList );
}
Diff3LineList::const_iterator iD3LHistoryOrigEnd = iD3LHistoryEnd;
bool bHistoryMergeSorting = m_pOptionDialog->m_bHistoryMergeSorting && ! m_pOptionDialog->m_historyEntryStartSortKeyOrder.isEmpty() &&
! m_pOptionDialog->m_historyEntryStartRegExp.isEmpty();
if ( m_pOptionDialog->m_maxNofHistoryEntries==-1 )
{
// Remove parts from the historyMap and hitList that stay in place
if ( bHistoryMergeSorting )
{
while ( ! historyMap.empty() )
{
HistoryMap::iterator hMapIt = historyMap.begin();
if( hMapIt->second.staysInPlace( m_pldC!=0, iD3LHistoryEnd ) )
historyMap.erase(hMapIt);
else
break;
}
}
else
{
while ( ! hitList.empty() )
{
HistoryMap::iterator hMapIt = hitList.back();
if( hMapIt->second.staysInPlace( m_pldC!=0, iD3LHistoryEnd ) )
hitList.pop_back();
else
break;
}
}
while (iD3LHistoryOrigEnd != iD3LHistoryEnd)
{
--iD3LHistoryOrigEnd;
--d3lHistoryEndLineIdx;
}
}
MergeLineList::iterator iMLLStart = splitAtDiff3LineIdx(d3lHistoryBeginLineIdx);
MergeLineList::iterator iMLLEnd = splitAtDiff3LineIdx(d3lHistoryEndLineIdx);
// Now join all MergeLines in the history
MergeLineList::iterator i = iMLLStart;
if ( i != iMLLEnd )
{
++i;
while ( i!=iMLLEnd )
{
iMLLStart->join(*i);
i = m_mergeLineList.erase( i );
}
}
iMLLStart->mergeEditLineList.clear();
// Now insert the complete history into the first MergeLine of the history
iMLLStart->mergeEditLineList.push_back( MergeEditLine( iD3LHistoryBegin, m_pldC == 0 ? B : C ) );
TQString lead = calcHistoryLead( iD3LHistoryBegin->getString(A) );
MergeEditLine mel( m_pDiff3LineList->end() );
mel.setString( lead );
iMLLStart->mergeEditLineList.push_back(mel);
int historyCount = 0;
if ( bHistoryMergeSorting )
{
// Create a sorted history
HistoryMap::reverse_iterator hmit;
for ( hmit = historyMap.rbegin(); hmit != historyMap.rend(); ++hmit )
{
if ( historyCount==m_pOptionDialog->m_maxNofHistoryEntries )
break;
++historyCount;
HistoryMapEntry& hme = hmit->second;
MergeEditLineList& mell = hme.choice(m_pldC!=0);
if (!mell.empty())
iMLLStart->mergeEditLineList.splice( iMLLStart->mergeEditLineList.end(), mell, mell.begin(), mell.end() );
}
}
else
{
// Create history in order of appearance
std::list< HistoryMap::iterator >::iterator hlit;
for ( hlit = hitList.begin(); hlit != hitList.end(); ++hlit )
{
if ( historyCount==m_pOptionDialog->m_maxNofHistoryEntries )
break;
++historyCount;
HistoryMapEntry& hme = (*hlit)->second;
MergeEditLineList& mell = hme.choice(m_pldC!=0);
if (!mell.empty())
iMLLStart->mergeEditLineList.splice( iMLLStart->mergeEditLineList.end(), mell, mell.begin(), mell.end() );
}
}
setFastSelector( iMLLStart );
update();
}
}
void MergeResultWindow::slotRegExpAutoMerge()
{
if ( m_pOptionDialog->m_autoMergeRegExp.isEmpty() )
return;
TQRegExp vcsKeywords = m_pOptionDialog->m_autoMergeRegExp;
MergeLineList::iterator i;
for ( i=m_mergeLineList.begin(); i!=m_mergeLineList.end(); ++i )
{
if (i->bConflict )
{
Diff3LineList::const_iterator id3l = i->id3l;
if ( vcsKeywords.exactMatch( id3l->getString(A) ) &&
vcsKeywords.exactMatch( id3l->getString(B) ) &&
(m_pldC==0 || vcsKeywords.exactMatch( id3l->getString(C) )))
{
MergeEditLine& mel = *i->mergeEditLineList.begin();
mel.setSource( m_pldC==0 ? B : C, false );
splitAtDiff3LineIdx( i->d3lLineIdx+1 );
}
}
}
update();
}
// This doesn't detect user modifications and should only be called after automatic merge
// This will only do something for three file merge.
// Irrelevant changes are those where all contributions from B are already contained in C.
// Also irrelevant are conflicts automatically solved (automerge regexp and history automerge)
// Precondition: The VCS-keyword would also be C.
bool MergeResultWindow::doRelevantChangesExist()
{
if ( m_pldC==0 || m_mergeLineList.size() <= 1 )
return true;
MergeLineList::iterator i;
for ( i=m_mergeLineList.begin(); i!=m_mergeLineList.end(); ++i )
{
if ( ( i->bConflict && i->mergeEditLineList.begin()->src()!=C )
|| i->srcSelect == B )
{
return true;
}
}
return false;
}
// Returns the iterator to the MergeLine after the split
MergeResultWindow::MergeLineList::iterator MergeResultWindow::splitAtDiff3LineIdx( int d3lLineIdx )
{
MergeLineList::iterator i;
for ( i = m_mergeLineList.begin(); i!=m_mergeLineList.end(); ++i )
{
if ( i->d3lLineIdx==d3lLineIdx )
{
// No split needed, this is the beginning of a MergeLine
return i;
}
else if ( i->d3lLineIdx > d3lLineIdx )
{
// The split must be in the previous MergeLine
--i;
MergeLine& ml = *i;
MergeLine newML;
ml.split(newML,d3lLineIdx);
++i;
return m_mergeLineList.insert( i, newML );
}
}
// The split must be in the previous MergeLine
--i;
MergeLine& ml = *i;
MergeLine newML;
ml.split(newML,d3lLineIdx);
++i;
return m_mergeLineList.insert( i, newML );
}
void MergeResultWindow::slotSplitDiff( int firstD3lLineIdx, int lastD3lLineIdx )
{
if (lastD3lLineIdx>=0)
splitAtDiff3LineIdx( lastD3lLineIdx + 1 );
setFastSelector( splitAtDiff3LineIdx(firstD3lLineIdx) );
}
void MergeResultWindow::slotJoinDiffs( int firstD3lLineIdx, int lastD3lLineIdx )
{
MergeLineList::iterator i;
MergeLineList::iterator iMLLStart = m_mergeLineList.end();
MergeLineList::iterator iMLLEnd = m_mergeLineList.end();
for ( i=m_mergeLineList.begin(); i!=m_mergeLineList.end(); ++i )
{
MergeLine& ml = *i;
if ( firstD3lLineIdx >= ml.d3lLineIdx && firstD3lLineIdx < ml.d3lLineIdx + ml.srcRangeLength )
{
iMLLStart = i;
}
if ( lastD3lLineIdx >= ml.d3lLineIdx && lastD3lLineIdx < ml.d3lLineIdx + ml.srcRangeLength )
{
iMLLEnd = i;
++iMLLEnd;
break;
}
}
bool bJoined = false;
for( i=iMLLStart; i!=iMLLEnd && i!=m_mergeLineList.end(); )
{
if ( i==iMLLStart )
{
++i;
}
else
{
iMLLStart->join(*i);
i = m_mergeLineList.erase( i );
bJoined = true;
}
}
if (bJoined)
{
iMLLStart->mergeEditLineList.clear();
// Insert a conflict line as placeholder
iMLLStart->mergeEditLineList.push_back( MergeEditLine( iMLLStart->id3l ) );
}
setFastSelector( iMLLStart );
}
void MergeResultWindow::myUpdate(int afterMilliSecs)
{
killTimer(m_delayedDrawTimer);
m_bMyUpdate = true;
m_delayedDrawTimer = startTimer( afterMilliSecs );
}
void MergeResultWindow::timerEvent(TQTimerEvent*)
{
killTimer(m_delayedDrawTimer);
m_delayedDrawTimer = 0;
if ( m_bMyUpdate )
{
update();
m_bMyUpdate = false;
}
if ( m_scrollDeltaX != 0 || m_scrollDeltaY != 0 )
{
m_selection.end( m_selection.lastLine + m_scrollDeltaY, m_selection.lastPos + m_scrollDeltaX );
emit scroll( m_scrollDeltaX, m_scrollDeltaY );
killTimer(m_delayedDrawTimer);
m_delayedDrawTimer = startTimer(50);
}
}
TQString MergeResultWindow::MergeEditLine::getString( const MergeResultWindow* mrw )
{
if ( isRemoved() ) { return TQString(); }
if ( ! isModified() )
{
int src = m_src;
if ( src == 0 ) { return TQString(); }
const Diff3Line& d3l = *m_id3l;
const LineData* pld = 0;
assert( src == A || src == B || src == C );
if ( src == A && d3l.lineA!=-1 ) pld = &mrw->m_pldA[ d3l.lineA ];
else if ( src == B && d3l.lineB!=-1 ) pld = &mrw->m_pldB[ d3l.lineB ];
else if ( src == C && d3l.lineC!=-1 ) pld = &mrw->m_pldC[ d3l.lineC ];
if ( pld == 0 )
{
// assert(false); This is no error.
return TQString();
}
return TQString( pld->pLine, pld->size );
}
else
{
return m_str;
}
return 0;
}
/// Converts the cursor-posOnScreen into a text index, considering tabulators.
int convertToPosInText( const TQString& s, int posOnScreen, int tabSize )
{
int localPosOnScreen = 0;
int size=s.length();
for ( int i=0; i<size; ++i )
{
if ( localPosOnScreen>=posOnScreen )
return i;
// All letters except tabulator have width one.
int letterWidth = s[i]!='\t' ? 1 : tabber( localPosOnScreen, tabSize );
localPosOnScreen += letterWidth;
if ( localPosOnScreen>posOnScreen )
return i;
}
return size;
}
/// Converts the index into the text to a cursor-posOnScreen considering tabulators.
int convertToPosOnScreen( const TQString& p, int posInText, int tabSize )
{
int posOnScreen = 0;
for ( int i=0; i<posInText; ++i )
{
// All letters except tabulator have width one.
int letterWidth = p[i]!='\t' ? 1 : tabber( posOnScreen, tabSize );
posOnScreen += letterWidth;
}
return posOnScreen;
}
void MergeResultWindow::writeLine(
MyPainter& p, int line, const TQString& str,
int srcSelect, e_MergeDetails mergeDetails, int rangeMark, bool bUserModified, bool bLineRemoved, bool bWhiteSpaceConflict
)
{
const TQFontMetrics& fm = fontMetrics();
int fontHeight = fm.height();
int fontWidth = fm.width("W");
int fontAscent = fm.ascent();
int topLineYOffset = 0;
int xOffset = fontWidth * leftInfoWidth;
int yOffset = ( line-m_firstLine ) * fontHeight;
if ( yOffset < 0 || yOffset > height() )
return;
yOffset += topLineYOffset;
TQString srcName = " ";
if ( bUserModified ) srcName = "m";
else if ( srcSelect == A && mergeDetails != eNoChange ) srcName = "A";
else if ( srcSelect == B ) srcName = "B";
else if ( srcSelect == C ) srcName = "C";
if ( rangeMark & 4 )
{
p.fillRect( xOffset, yOffset, width(), fontHeight, m_pOptionDialog->m_currentRangeBgColor );
}
if( (srcSelect > 0 || bUserModified ) && !bLineRemoved )
{
int outPos = 0;
TQString s;
int size = str.length();
for ( int i=0; i<size; ++i )
{
int spaces = 1;
if ( str[i]=='\t' )
{
spaces = tabber( outPos, m_pOptionDialog->m_tabSize );
for( int j=0; j<spaces; ++j )
s+=' ';
}
else
{
s+=str[i];
}
outPos += spaces;
}
if ( m_selection.lineWithin( line ) )
{
int firstPosInLine = convertToPosOnScreen( str, convertToPosInText( str, m_selection.firstPosInLine(line), m_pOptionDialog->m_tabSize ),m_pOptionDialog->m_tabSize );
int lastPosInLine = convertToPosOnScreen( str, convertToPosInText( str, m_selection.lastPosInLine(line), m_pOptionDialog->m_tabSize ), m_pOptionDialog->m_tabSize );
int lengthInLine = max2(0,lastPosInLine - firstPosInLine);
if (lengthInLine>0) m_selection.bSelectionContainsData = true;
if ( lengthInLine < int(s.length()) )
{ // Draw a normal line first
p.setPen( m_pOptionDialog->m_fgColor );
p.drawText( xOffset, yOffset+fontAscent, s.mid(m_firstColumn), true );
}
int firstPosInLine2 = max2( firstPosInLine, m_firstColumn );
int lengthInLine2 = max2(0,lastPosInLine - firstPosInLine2);
if( m_selection.lineWithin( line+1 ) )
p.fillRect( xOffset + fontWidth*(firstPosInLine2-m_firstColumn), yOffset,
width(), fontHeight, colorGroup().highlight() );
else if ( lengthInLine2>0 )
p.fillRect( xOffset + fontWidth*(firstPosInLine2-m_firstColumn), yOffset,
fontWidth*lengthInLine2, fontHeight, colorGroup().highlight() );
p.setPen( colorGroup().highlightedText() );
p.drawText( xOffset + fontWidth*(firstPosInLine2-m_firstColumn), yOffset+fontAscent,
s.mid(firstPosInLine2,lengthInLine2), true );
}
else
{
p.setPen( m_pOptionDialog->m_fgColor );
p.drawText( xOffset, yOffset+fontAscent, s.mid(m_firstColumn), true );
}
p.setPen( m_pOptionDialog->m_fgColor );
if ( m_cursorYPos==line )
{
m_cursorXPos = minMaxLimiter( m_cursorXPos, 0, outPos );
m_cursorXPos = convertToPosOnScreen( str, convertToPosInText( str, m_cursorXPos, m_pOptionDialog->m_tabSize ),m_pOptionDialog->m_tabSize );
}
p.drawText( 1, yOffset+fontAscent, srcName, true );
}
else if ( bLineRemoved )
{
p.setPen( m_pOptionDialog->m_colorForConflict );
p.drawText( xOffset, yOffset+fontAscent, i18n("<No src line>") );
p.drawText( 1, yOffset+fontAscent, srcName );
if ( m_cursorYPos==line ) m_cursorXPos = 0;
}
else if ( srcSelect == 0 )
{
p.setPen( m_pOptionDialog->m_colorForConflict );
if ( bWhiteSpaceConflict )
p.drawText( xOffset, yOffset+fontAscent, i18n("<Merge Conflict (Whitespace only)>") );
else
p.drawText( xOffset, yOffset+fontAscent, i18n("<Merge Conflict>") );
p.drawText( 1, yOffset+fontAscent, "?" );
if ( m_cursorYPos==line ) m_cursorXPos = 0;
}
else assert(false);
xOffset -= fontWidth;
p.setPen( m_pOptionDialog->m_fgColor );
if ( rangeMark & 1 ) // begin mark
{
p.drawLine( xOffset, yOffset+1, xOffset, yOffset+fontHeight/2 );
p.drawLine( xOffset, yOffset+1, xOffset-2, yOffset+1 );
}
else
{
p.drawLine( xOffset, yOffset, xOffset, yOffset+fontHeight/2 );
}
if ( rangeMark & 2 ) // end mark
{
p.drawLine( xOffset, yOffset+fontHeight/2, xOffset, yOffset+fontHeight-1 );
p.drawLine( xOffset, yOffset+fontHeight-1, xOffset-2, yOffset+fontHeight-1 );
}
else
{
p.drawLine( xOffset, yOffset+fontHeight/2, xOffset, yOffset+fontHeight );
}
if ( rangeMark & 4 )
{
p.fillRect( xOffset + 3, yOffset, 3, fontHeight, m_pOptionDialog->m_fgColor );
/* p.setPen( blue );
p.drawLine( xOffset+2, yOffset, xOffset+2, yOffset+fontHeight-1 );
p.drawLine( xOffset+3, yOffset, xOffset+3, yOffset+fontHeight-1 );*/
}
}
void MergeResultWindow::setPaintingAllowed(bool bPaintingAllowed)
{
m_bPaintingAllowed = bPaintingAllowed;
if ( !m_bPaintingAllowed )
{
m_currentMergeLineIt = m_mergeLineList.end();
reset();
}
}
void MergeResultWindow::paintEvent( TQPaintEvent* )
{
if (m_pDiff3LineList==0 || !m_bPaintingAllowed) return;
bool bOldSelectionContainsData = m_selection.bSelectionContainsData;
const TQFontMetrics& fm = fontMetrics();
int fontHeight = fm.height();
int fontWidth = fm.width("W");
int fontAscent = fm.ascent();
if ( !m_bCursorUpdate ) // Don't redraw everything for blinking cursor?
{
m_selection.bSelectionContainsData = false;
if ( size() != m_pixmap.size() )
m_pixmap.resize(size());
MyPainter p(&m_pixmap, m_pOptionDialog->m_bRightToLeftLanguage, width(), fontWidth);
p.setFont( font() );
p.TQPainter::fillRect( rect(), m_pOptionDialog->m_bgColor );
//int visibleLines = height() / fontHeight;
int lastVisibleLine = m_firstLine + getNofVisibleLines() + 5;
int nofColumns = 0;
int line = 0;
MergeLineList::iterator mlIt = m_mergeLineList.begin();
for(mlIt = m_mergeLineList.begin();mlIt!=m_mergeLineList.end(); ++mlIt)
{
MergeLine& ml = *mlIt;
if ( line > lastVisibleLine || line + ml.mergeEditLineList.size() < m_firstLine)
{
line += ml.mergeEditLineList.size();
}
else
{
MergeEditLineList::iterator melIt;
for( melIt = ml.mergeEditLineList.begin(); melIt != ml.mergeEditLineList.end(); ++melIt )
{
if (line>=m_firstLine && line<=lastVisibleLine)
{
MergeEditLine& mel = *melIt;
MergeEditLineList::iterator melIt1 = melIt;
++melIt1;
int rangeMark = 0;
if ( melIt==ml.mergeEditLineList.begin() ) rangeMark |= 1; // Begin range mark
if ( melIt1==ml.mergeEditLineList.end() ) rangeMark |= 2; // End range mark
if ( mlIt == m_currentMergeLineIt ) rangeMark |= 4; // Mark of the current line
TQString s;
s = mel.getString( this );
if ( convertToPosOnScreen(s,s.length(),m_pOptionDialog->m_tabSize) >nofColumns)
nofColumns = s.length();
writeLine( p, line, s, mel.src(), ml.mergeDetails, rangeMark,
mel.isModified(), mel.isRemoved(), ml.bWhiteSpaceConflict );
}
++line;
}
}
}
if ( line != m_nofLines || nofColumns != m_nofColumns )
{
m_nofLines = line;
assert( m_nofLines == m_totalSize );
m_nofColumns = nofColumns;
emit resizeSignal();
}
p.end();
}
TQPainter painter(this);
int topLineYOffset = 0;
int xOffset = fontWidth * leftInfoWidth;
int yOffset = ( m_cursorYPos - m_firstLine ) * fontHeight + topLineYOffset;
int xCursor = ( m_cursorXPos - m_firstColumn ) * fontWidth + xOffset;
if ( !m_bCursorUpdate )
painter.drawPixmap(0,0, m_pixmap);
else
{
if (!m_pOptionDialog->m_bRightToLeftLanguage)
painter.drawPixmap(xCursor-2, yOffset, m_pixmap,
xCursor-2, yOffset, 5, fontAscent+2 );
else
painter.drawPixmap(width()-1-4-(xCursor-2), yOffset, m_pixmap,
width()-1-4-(xCursor-2), yOffset, 5, fontAscent+2 );
m_bCursorUpdate = false;
}
painter.end();
if ( m_bCursorOn && hasFocus() && m_cursorYPos>=m_firstLine )
{
MyPainter painter(this, m_pOptionDialog->m_bRightToLeftLanguage, width(), fontWidth);
int topLineYOffset = 0;
int xOffset = fontWidth * leftInfoWidth;
int yOffset = ( m_cursorYPos-m_firstLine ) * fontHeight + topLineYOffset;
int xCursor = ( m_cursorXPos - m_firstColumn ) * fontWidth + xOffset;
painter.setPen( m_pOptionDialog->m_fgColor );
painter.drawLine( xCursor, yOffset, xCursor, yOffset+fontAscent );
painter.drawLine( xCursor-2, yOffset, xCursor+2, yOffset );
painter.drawLine( xCursor-2, yOffset+fontAscent+1, xCursor+2, yOffset+fontAscent+1 );
}
if( !bOldSelectionContainsData && m_selection.bSelectionContainsData )
emit newSelection();
}
void MergeResultWindow::updateSourceMask()
{
int srcMask=0;
int enabledMask = 0;
if( !hasFocus() || m_pDiff3LineList==0 || !m_bPaintingAllowed || m_currentMergeLineIt == m_mergeLineList.end() )
{
srcMask = 0;
enabledMask = 0;
}
else
{
enabledMask = m_pldC==0 ? 3 : 7;
MergeLine& ml = *m_currentMergeLineIt;
srcMask = 0;
bool bModified = false;
MergeEditLineList::iterator melIt;
for( melIt = ml.mergeEditLineList.begin(); melIt != ml.mergeEditLineList.end(); ++melIt )
{
MergeEditLine& mel = *melIt;
if ( mel.src()==1 ) srcMask |= 1;
if ( mel.src()==2 ) srcMask |= 2;
if ( mel.src()==3 ) srcMask |= 4;
if ( mel.isModified() || !mel.isEditableText() ) bModified = true;
}
if ( ml.mergeDetails == eNoChange )
{
srcMask = 0;
enabledMask = bModified ? 1 : 0;
}
}
emit sourceMask( srcMask, enabledMask );
}
void MergeResultWindow::focusInEvent( TQFocusEvent* e )
{
updateSourceMask();
TQWidget::focusInEvent(e);
}
void MergeResultWindow::convertToLinePos( int x, int y, int& line, int& pos )
{
const TQFontMetrics& fm = fontMetrics();
int fontHeight = fm.height();
int fontWidth = fm.width('W');
int xOffset = (leftInfoWidth-m_firstColumn)*fontWidth;
int topLineYOffset = 0;
int yOffset = topLineYOffset - m_firstLine * fontHeight;
line = min2( ( y - yOffset ) / fontHeight, m_totalSize-1 );
if ( ! m_pOptionDialog->m_bRightToLeftLanguage )
pos = ( x - xOffset ) / fontWidth;
else
pos = ( (width() - 1 - x) - xOffset ) / fontWidth;
}
void MergeResultWindow::mousePressEvent ( TQMouseEvent* e )
{
m_bCursorOn = true;
int line;
int pos;
convertToLinePos( e->x(), e->y(), line, pos );
bool bLMB = e->button() == TQt::LeftButton;
bool bMMB = e->button() == TQt::MidButton;
bool bRMB = e->button() == TQt::RightButton;
if ( bLMB && pos < m_firstColumn || bRMB ) // Fast range selection
{
m_cursorXPos = 0;
m_cursorOldXPos = 0;
m_cursorYPos = max2(line,0);
int l = 0;
MergeLineList::iterator i = m_mergeLineList.begin();
for(i = m_mergeLineList.begin();i!=m_mergeLineList.end(); ++i)
{
if (l==line)
break;
l += i->mergeEditLineList.size();
if (l>line)
break;
}
m_selection.reset(); // Disable current selection
m_bCursorOn = true;
setFastSelector( i );
if (bRMB)
{
showPopupMenu( TQCursor::pos() );
}
}
else if ( bLMB ) // Normal cursor placement
{
pos = max2(pos,0);
line = max2(line,0);
if ( e->state() & TQt::ShiftButton )
{
if (m_selection.firstLine==-1)
m_selection.start( line, pos );
m_selection.end( line, pos );
}
else
{
// Selection
m_selection.reset();
m_selection.start( line, pos );
m_selection.end( line, pos );
}
m_cursorXPos = pos;
m_cursorOldXPos = pos;
m_cursorYPos = line;
update();
//showStatusLine( line, m_winIdx, m_pFilename, m_pDiff3LineList, m_pStatusBar );
}
else if ( bMMB ) // Paste clipboard
{
pos = max2(pos,0);
line = max2(line,0);
m_selection.reset();
m_cursorXPos = pos;
m_cursorOldXPos = pos;
m_cursorYPos = line;
pasteClipboard( true );
}
}
void MergeResultWindow::mouseDoubleClickEvent( TQMouseEvent* e )
{
if ( e->button() == TQt::LeftButton )
{
int line;
int pos;
convertToLinePos( e->x(), e->y(), line, pos );
m_cursorXPos = pos;
m_cursorOldXPos = pos;
m_cursorYPos = line;
// Get the string data of the current line
MergeLineList::iterator mlIt;
MergeEditLineList::iterator melIt;
calcIteratorFromLineNr( line, mlIt, melIt );
TQString s = melIt->getString( this );
if ( !s.isEmpty() )
{
int pos1, pos2;
calcTokenPos( s, pos, pos1, pos2, m_pOptionDialog->m_tabSize );
resetSelection();
m_selection.start( line, convertToPosOnScreen( s, pos1, m_pOptionDialog->m_tabSize ) );
m_selection.end( line, convertToPosOnScreen( s, pos2, m_pOptionDialog->m_tabSize ) );
update();
// emit selectionEnd() happens in the mouseReleaseEvent.
}
}
}
void MergeResultWindow::mouseReleaseEvent ( TQMouseEvent * e )
{
if ( e->button() == TQt::LeftButton )
{
killTimer(m_delayedDrawTimer);
m_delayedDrawTimer = 0;
if (m_selection.firstLine != -1 )
{
emit selectionEnd();
}
}
}
void MergeResultWindow::mouseMoveEvent ( TQMouseEvent * e )
{
int line;
int pos;
convertToLinePos( e->x(), e->y(), line, pos );
m_cursorXPos = pos;
m_cursorOldXPos = pos;
m_cursorYPos = line;
if (m_selection.firstLine != -1 )
{
m_selection.end( line, pos );
myUpdate(0);
//showStatusLine( line, m_winIdx, m_pFilename, m_pDiff3LineList, m_pStatusBar );
// Scroll because mouse moved out of the window
const TQFontMetrics& fm = fontMetrics();
int fontWidth = fm.width('W');
int topLineYOffset = 0;
int deltaX=0;
int deltaY=0;
if ( ! m_pOptionDialog->m_bRightToLeftLanguage )
{
if ( e->x() < leftInfoWidth*fontWidth ) deltaX=-1;
if ( e->x() > width() ) deltaX=+1;
}
else
{
if ( e->x() > width()-1-leftInfoWidth*fontWidth ) deltaX=-1;
if ( e->x() < fontWidth ) deltaX=+1;
}
if ( e->y() < topLineYOffset ) deltaY=-1;
if ( e->y() > height() ) deltaY=+1;
m_scrollDeltaX = deltaX;
m_scrollDeltaY = deltaY;
if ( deltaX != 0 || deltaY!= 0)
{
emit scroll( deltaX, deltaY );
}
}
}
void MergeResultWindow::slotCursorUpdate()
{
m_cursorTimer.stop();
m_bCursorOn = !m_bCursorOn;
if ( isVisible() )
{
m_bCursorUpdate = true;
const TQFontMetrics& fm = fontMetrics();
int fontWidth = fm.width("W");
int topLineYOffset = 0;
int xOffset = fontWidth * leftInfoWidth;
int yOffset = ( m_cursorYPos - m_firstLine ) * fm.height() + topLineYOffset;
int xCursor = ( m_cursorXPos - m_firstColumn ) * fontWidth + xOffset;
if (!m_pOptionDialog->m_bRightToLeftLanguage)
repaint( xCursor-2, yOffset, 5, fm.ascent()+2 );
else
repaint( width()-1-4-(xCursor-2), yOffset, 5, fm.ascent()+2 );
m_bCursorUpdate=false;
}
m_cursorTimer.start(500,true);
}
void MergeResultWindow::wheelEvent( TQWheelEvent* e )
{
int d = -e->delta()*TQApplication::wheelScrollLines()/120;
e->accept();
scroll( 0, min2(d, getNofVisibleLines()) );
}
void MergeResultWindow::keyPressEvent( TQKeyEvent* e )
{
int y = m_cursorYPos;
MergeLineList::iterator mlIt;
MergeEditLineList::iterator melIt;
calcIteratorFromLineNr( y, mlIt, melIt );
TQString str = melIt->getString( this );
int x = convertToPosInText( str, m_cursorXPos, m_pOptionDialog->m_tabSize );
bool bCtrl = ( e->state() & TQt::ControlButton ) != 0 ;
bool bShift = ( e->state() & TQt::ShiftButton ) != 0 ;
#ifdef _WIN32
bool bAlt = ( e->state() & TQt::AltButton ) != 0 ;
if ( bCtrl && bAlt ){ bCtrl=false; bAlt=false; } // AltGr-Key pressed.
#endif
bool bYMoveKey = false;
// Special keys
switch ( e->key() )
{
case TQt::Key_Escape: break;
//case Key_Tab: break;
case TQt::Key_Backtab: break;
case TQt::Key_Delete:
{
if ( deleteSelection2( str, x, y, mlIt, melIt )) break;
if( !melIt->isEditableText() ) break;
if (x>=(int)str.length())
{
if ( y<m_totalSize-1 )
{
setModified();
MergeLineList::iterator mlIt1;
MergeEditLineList::iterator melIt1;
calcIteratorFromLineNr( y+1, mlIt1, melIt1 );
if ( melIt1->isEditableText() )
{
TQString s2 = melIt1->getString( this );
melIt->setString( str + s2 );
// Remove the line
if ( mlIt1->mergeEditLineList.size()>1 )
mlIt1->mergeEditLineList.erase( melIt1 );
else
melIt1->setRemoved();
}
}
}
else
{
TQString s = str.left(x);
s += str.mid( x+1 );
melIt->setString( s );
setModified();
}
break;
}
case TQt::Key_Backspace:
{
if ( deleteSelection2( str, x, y, mlIt, melIt )) break;
if( !melIt->isEditableText() ) break;
if (x==0)
{
if ( y>0 )
{
setModified();
MergeLineList::iterator mlIt1;
MergeEditLineList::iterator melIt1;
calcIteratorFromLineNr( y-1, mlIt1, melIt1 );
if ( melIt1->isEditableText() )
{
TQString s1 = melIt1->getString( this );
melIt1->setString( s1 + str );
// Remove the previous line
if ( mlIt->mergeEditLineList.size()>1 )
mlIt->mergeEditLineList.erase( melIt );
else
melIt->setRemoved();
--y;
x=str.length();
}
}
}
else
{
TQString s = str.left( x-1 );
s += str.mid( x );
--x;
melIt->setString( s );
setModified();
}
break;
}
case TQt::Key_Return:
case TQt::Key_Enter:
{
if( !melIt->isEditableText() ) break;
deleteSelection2( str, x, y, mlIt, melIt );
setModified();
TQString indentation;
if ( m_pOptionDialog->m_bAutoIndentation )
{ // calc last indentation
MergeLineList::iterator mlIt1 = mlIt;
MergeEditLineList::iterator melIt1 = melIt;
for(;;) {
const TQString s = melIt1->getString(this);
if ( !s.isEmpty() ) {
unsigned int i;
for( i=0; i<s.length(); ++i ){ if(s[i]!=' ' && s[i]!='\t') break; }
if (i<s.length()) {
indentation = s.left(i);
break;
}
}
// Go back one line
if ( melIt1 != mlIt1->mergeEditLineList.begin() )
--melIt1;
else
{
if ( mlIt1 == m_mergeLineList.begin() ) break;
--mlIt1;
melIt1 = mlIt1->mergeEditLineList.end();
--melIt1;
}
}
}
MergeEditLine mel(mlIt->id3l); // Associate every mel with an id3l, even if not really valid.
mel.setString( indentation + str.mid(x) );
if ( x<(int)str.length() ) // Cut off the old line.
{
// Since ps possibly points into melIt->str, first copy it into a temporary.
TQString temp = str.left(x);
melIt->setString( temp );
}
++melIt;
mlIt->mergeEditLineList.insert( melIt, mel );
x = indentation.length();
++y;
break;
}
case TQt::Key_Insert: m_bInsertMode = !m_bInsertMode; break;
case TQt::Key_Pause: break;
case TQt::Key_Print: break;
case TQt::Key_SysReq: break;
case TQt::Key_Home: x=0; if(bCtrl){y=0; } break; // cursor movement
case TQt::Key_End: x=INT_MAX; if(bCtrl){y=INT_MAX;} break;
case TQt::Key_Left:
case TQt::Key_Right:
if ( (e->key()==TQt::Key_Left) ^ m_pOptionDialog->m_bRightToLeftLanguage ) // operator^: XOR
{
if ( !bCtrl )
{
--x;
if(x<0 && y>0){--y; x=INT_MAX;}
}
else
{
while( x>0 && (str[x-1]==' ' || str[x-1]=='\t') ) --x;
while( x>0 && (str[x-1]!=' ' && str[x-1]!='\t') ) --x;
}
}
else
{
if ( !bCtrl )
{
++x; if(x>(int)str.length() && y<m_totalSize-1){ ++y; x=0; }
}
else
{
while( x<(int)str.length() && (str[x]==' ' || str[x]=='\t') ) ++x;
while( x<(int)str.length() && (str[x]!=' ' && str[x]!='\t') ) ++x;
}
}
break;
case TQt::Key_Up: if (!bCtrl){ --y; bYMoveKey=true; } break;
case TQt::Key_Down: if (!bCtrl){ ++y; bYMoveKey=true; } break;
case TQt::Key_PageUp: if (!bCtrl){ y-=getNofVisibleLines(); bYMoveKey=true; } break;
case TQt::Key_PageDown: if (!bCtrl){ y+=getNofVisibleLines(); bYMoveKey=true; } break;
default:
{
TQString t = e->text();
if( t.isEmpty() || bCtrl )
{ e->ignore(); return; }
else
{
if( bCtrl )
{
e->ignore(); return;
}
else
{
if( !melIt->isEditableText() ) break;
deleteSelection2( str, x, y, mlIt, melIt );
setModified();
// Characters to insert
TQString s=str;
if ( t[0]=='\t' && m_pOptionDialog->m_bReplaceTabs )
{
int spaces = (m_cursorXPos / m_pOptionDialog->m_tabSize + 1)*m_pOptionDialog->m_tabSize - m_cursorXPos;
t.fill( ' ', spaces );
}
if ( m_bInsertMode )
s.insert( x, t );
else
s.replace( x, t.length(), t );
melIt->setString( s );
x += t.length();
bShift = false;
}
}
}
}
y = minMaxLimiter( y, 0, m_totalSize-1 );
calcIteratorFromLineNr( y, mlIt, melIt );
str = melIt->getString( this );
x = minMaxLimiter( x, 0, (int)str.length() );
int newFirstLine = m_firstLine;
int newFirstColumn = m_firstColumn;
if ( y<m_firstLine )
newFirstLine = y;
else if ( y > m_firstLine + getNofVisibleLines() )
newFirstLine = y - getNofVisibleLines();
if (bYMoveKey)
x=convertToPosInText( str, m_cursorOldXPos, m_pOptionDialog->m_tabSize );
int xOnScreen = convertToPosOnScreen( str, x, m_pOptionDialog->m_tabSize );
if ( xOnScreen<m_firstColumn )
newFirstColumn = xOnScreen;
else if ( xOnScreen > m_firstColumn + getNofVisibleColumns() )
newFirstColumn = xOnScreen - getNofVisibleColumns();
if ( bShift )
{
if (m_selection.firstLine==-1)
m_selection.start( m_cursorYPos, m_cursorXPos );
m_selection.end( y, xOnScreen );
}
else
m_selection.reset();
m_cursorYPos = y;
m_cursorXPos = xOnScreen;
if ( ! bYMoveKey )
m_cursorOldXPos = m_cursorXPos;
m_bCursorOn = false;
if ( newFirstLine!=m_firstLine || newFirstColumn!=m_firstColumn )
{
m_bCursorOn = true;
scroll( newFirstColumn-m_firstColumn, newFirstLine-m_firstLine );
return;
}
m_bCursorOn = true;
update();
}
void MergeResultWindow::calcIteratorFromLineNr(
int line,
MergeResultWindow::MergeLineList::iterator& mlIt,
MergeResultWindow::MergeEditLineList::iterator& melIt
)
{
for( mlIt = m_mergeLineList.begin(); mlIt!=m_mergeLineList.end(); ++mlIt)
{
MergeLine& ml = *mlIt;
if ( line > ml.mergeEditLineList.size() )
{
line -= ml.mergeEditLineList.size();
}
else
{
for( melIt = ml.mergeEditLineList.begin(); melIt != ml.mergeEditLineList.end(); ++melIt )
{
--line;
if (line<0) return;
}
}
}
assert(false);
}
TQString MergeResultWindow::getSelection()
{
TQString selectionString;
int line = 0;
MergeLineList::iterator mlIt = m_mergeLineList.begin();
for(mlIt = m_mergeLineList.begin();mlIt!=m_mergeLineList.end(); ++mlIt)
{
MergeLine& ml = *mlIt;
MergeEditLineList::iterator melIt;
for( melIt = ml.mergeEditLineList.begin(); melIt != ml.mergeEditLineList.end(); ++melIt )
{
MergeEditLine& mel = *melIt;
if ( m_selection.lineWithin(line) )
{
int outPos = 0;
if (mel.isEditableText())
{
const TQString str = mel.getString( this );
// Consider tabs
for( unsigned int i=0; i<str.length(); ++i )
{
int spaces = 1;
if ( str[i]=='\t' )
{
spaces = tabber( outPos, m_pOptionDialog->m_tabSize );
}
if( m_selection.within( line, outPos ) )
{
selectionString += str[i];
}
outPos += spaces;
}
}
else if ( mel.isConflict() )
{
selectionString += i18n("<Merge Conflict>");
}
if( m_selection.within( line, outPos ) )
{
#ifdef _WIN32
selectionString += '\r';
#endif
selectionString += '\n';
}
}
++line;
}
}
return selectionString;
}
bool MergeResultWindow::deleteSelection2( TQString& s, int& x, int& y,
MergeLineList::iterator& mlIt, MergeEditLineList::iterator& melIt )
{
if (m_selection.firstLine!=-1 && m_selection.bSelectionContainsData )
{
deleteSelection();
y = m_cursorYPos;
calcIteratorFromLineNr( y, mlIt, melIt );
s = melIt->getString( this );
x = convertToPosInText( s, m_cursorXPos, m_pOptionDialog->m_tabSize );
return true;
}
return false;
}
void MergeResultWindow::deleteSelection()
{
if ( m_selection.firstLine==-1 || !m_selection.bSelectionContainsData )
{
return;
}
setModified();
int line = 0;
MergeLineList::iterator mlItFirst;
MergeEditLineList::iterator melItFirst;
TQString firstLineString;
int firstLine = -1;
int lastLine = -1;
MergeLineList::iterator mlIt;
for(mlIt = m_mergeLineList.begin();mlIt!=m_mergeLineList.end(); ++mlIt)
{
MergeLine& ml = *mlIt;
MergeEditLineList::iterator melIt;
for( melIt = ml.mergeEditLineList.begin(); melIt != ml.mergeEditLineList.end(); ++melIt )
{
MergeEditLine& mel = *melIt;
if ( mel.isEditableText() && m_selection.lineWithin(line) )
{
if ( firstLine==-1 )
firstLine = line;
lastLine = line;
}
++line;
}
}
if ( firstLine == -1 )
{
return; // Nothing to delete.
}
line = 0;
for(mlIt = m_mergeLineList.begin();mlIt!=m_mergeLineList.end(); ++mlIt)
{
MergeLine& ml = *mlIt;
MergeEditLineList::iterator melIt, melIt1;
for( melIt = ml.mergeEditLineList.begin(); melIt != ml.mergeEditLineList.end(); )
{
MergeEditLine& mel = *melIt;
melIt1 = melIt;
++melIt1;
if ( mel.isEditableText() && m_selection.lineWithin(line) )
{
TQString lineString = mel.getString( this );
int firstPosInLine = m_selection.firstPosInLine(line);
int lastPosInLine = m_selection.lastPosInLine(line);
if ( line==firstLine )
{
mlItFirst = mlIt;
melItFirst = melIt;
int pos = convertToPosInText( lineString, firstPosInLine, m_pOptionDialog->m_tabSize );
firstLineString = lineString.left( pos );
}
if ( line==lastLine )
{
// This is the last line in the selection
int pos = convertToPosInText( lineString, lastPosInLine, m_pOptionDialog->m_tabSize );
firstLineString += lineString.mid( pos ); // rest of line
melItFirst->setString( firstLineString );
}
if ( line!=firstLine )
{
// Remove the line
if ( mlIt->mergeEditLineList.size()>1 )
mlIt->mergeEditLineList.erase( melIt );
else
melIt->setRemoved();
}
}
++line;
melIt = melIt1;
}
}
m_cursorYPos = m_selection.beginLine();
m_cursorXPos = m_selection.beginPos();
m_cursorOldXPos = m_cursorXPos;
m_selection.reset();
}
void MergeResultWindow::pasteClipboard( bool bFromSelection )
{
if (m_selection.firstLine != -1 )
deleteSelection();
setModified();
int y = m_cursorYPos;
MergeLineList::iterator mlIt;
MergeEditLineList::iterator melIt, melItAfter;
calcIteratorFromLineNr( y, mlIt, melIt );
melItAfter = melIt;
++melItAfter;
TQString str = melIt->getString( this );
int x = convertToPosInText( str, m_cursorXPos, m_pOptionDialog->m_tabSize );
if ( !TQApplication::clipboard()->supportsSelection() )
bFromSelection = false;
TQString clipBoard = TQApplication::clipboard()->text( bFromSelection ? TQClipboard::Selection : TQClipboard::Clipboard );
TQString currentLine = str.left(x);
TQString endOfLine = str.mid(x);
int i;
int len = clipBoard.length();
for( i=0; i<len; ++i )
{
TQChar c = clipBoard[i];
if ( c == '\r' ) continue;
if ( c == '\n' )
{
melIt->setString( currentLine );
MergeEditLine mel(mlIt->id3l); // Associate every mel with an id3l, even if not really valid.
melIt = mlIt->mergeEditLineList.insert( melItAfter, mel );
currentLine = "";
x=0;
++y;
}
else
{
currentLine += c;
++x;
}
}
currentLine += endOfLine;
melIt->setString( currentLine );
m_cursorYPos = y;
m_cursorXPos = convertToPosOnScreen( currentLine, x, m_pOptionDialog->m_tabSize );
m_cursorOldXPos = m_cursorXPos;
update();
}
void MergeResultWindow::resetSelection()
{
m_selection.reset();
update();
}
void MergeResultWindow::setModified(bool bModified)
{
if (bModified != m_bModified)
{
m_bModified = bModified;
emit modifiedChanged(m_bModified);
}
}
/// Saves and returns true when successful.
bool MergeResultWindow::saveDocument( const TQString& fileName, TQTextCodec* pEncoding )
{
// Are still conflicts somewhere?
if ( getNrOfUnsolvedConflicts()>0 )
{
KMessageBox::error( this,
i18n("Not all conflicts are solved yet.\n"
"File not saved.\n"),
i18n("Conflicts Left"));
return false;
}
update();
FileAccess file( fileName, true /*bWantToWrite*/ );
if ( m_pOptionDialog->m_bDmCreateBakFiles && file.exists() )
{
bool bSuccess = file.createBackup(".orig");
if ( !bSuccess )
{
KMessageBox::error( this, file.getStatusText() + i18n("\n\nCreating backup failed. File not saved."), i18n("File Save Error") );
return false;
}
}
TQByteArray dataArray;
TQTextStream textOutStream(dataArray, IO_WriteOnly);
textOutStream.setCodec( pEncoding );
int line = 0;
MergeLineList::iterator mlIt = m_mergeLineList.begin();
for(mlIt = m_mergeLineList.begin();mlIt!=m_mergeLineList.end(); ++mlIt)
{
MergeLine& ml = *mlIt;
MergeEditLineList::iterator melIt;
for( melIt = ml.mergeEditLineList.begin(); melIt != ml.mergeEditLineList.end(); ++melIt )
{
MergeEditLine& mel = *melIt;
if ( mel.isEditableText() )
{
TQString str = mel.getString( this );
if (line>0) // Prepend line feed, but not for first line
{
if ( m_pOptionDialog->m_lineEndStyle == eLineEndDos )
{ str.prepend("\r\n"); }
else
{ str.prepend("\n"); }
}
textOutStream << str;
++line;
}
}
}
bool bSuccess = file.writeFile( dataArray.data(), dataArray.size() );
if ( ! bSuccess )
{
KMessageBox::error( this, i18n("Error while writing."), i18n("File Save Error") );
return false;
}
setModified( false );
update();
return true;
}
TQString MergeResultWindow::getString( int lineIdx )
{
MergeResultWindow::MergeLineList::iterator mlIt;
MergeResultWindow::MergeEditLineList::iterator melIt;
calcIteratorFromLineNr( lineIdx, mlIt, melIt );
TQString s = melIt->getString( this );
return s;
}
bool MergeResultWindow::findString( const TQString& s, int& d3vLine, int& posInLine, bool bDirDown, bool bCaseSensitive )
{
int it = d3vLine;
int endIt = bDirDown ? getNofLines() : -1;
int step = bDirDown ? 1 : -1;
int startPos = posInLine;
for( ; it!=endIt; it+=step )
{
TQString line = 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 MergeResultWindow::setSelection( int firstLine, int startPos, int lastLine, int endPos )
{
if ( lastLine >= getNofLines() )
{
lastLine = getNofLines()-1;
TQString s = getString( lastLine );
endPos = s.length();
}
m_selection.reset();
m_selection.start( firstLine, convertToPosOnScreen( getString(firstLine), startPos, m_pOptionDialog->m_tabSize ) );
m_selection.end( lastLine, convertToPosOnScreen( getString(lastLine), endPos, m_pOptionDialog->m_tabSize ) );
update();
}
Overview::Overview( TQWidget* pParent, OptionDialog* pOptions )
: TQWidget( pParent, 0, WRepaintNoErase )
{
m_pDiff3LineList = 0;
m_pOptions = pOptions;
m_bTripleDiff = false;
m_eOverviewMode = eOMNormal;
m_nofLines = 1;
m_bPaintingAllowed = false;
setFixedWidth(20);
}
void Overview::init( Diff3LineList* pDiff3LineList, bool bTripleDiff )
{
m_pDiff3LineList = pDiff3LineList;
m_bTripleDiff = bTripleDiff;
m_pixmap.resize( TQSize(0,0) ); // make sure that a redraw happens
update();
}
void Overview::reset()
{
m_pDiff3LineList = 0;
}
void Overview::slotRedraw()
{
m_pixmap.resize( TQSize(0,0) ); // make sure that a redraw happens
update();
}
void Overview::setRange( int firstLine, int pageHeight )
{
m_firstLine = firstLine;
m_pageHeight = pageHeight;
update();
}
void Overview::setFirstLine( int firstLine )
{
m_firstLine = firstLine;
update();
}
void Overview::setOverviewMode( e_OverviewMode eOverviewMode )
{
m_eOverviewMode = eOverviewMode;
slotRedraw();
}
Overview::e_OverviewMode Overview::getOverviewMode()
{
return m_eOverviewMode;
}
void Overview::mousePressEvent( TQMouseEvent* e )
{
int h = height()-1;
int h1 = h * m_pageHeight / max2(1,m_nofLines)+3;
if ( h>0 )
emit setLine( ( e->y() - h1/2 )*m_nofLines/h );
}
void Overview::mouseMoveEvent( TQMouseEvent* e )
{
mousePressEvent(e);
}
void Overview::setPaintingAllowed( bool bAllowPainting )
{
if (m_bPaintingAllowed != bAllowPainting)
{
m_bPaintingAllowed = bAllowPainting;
if ( m_bPaintingAllowed ) update();
else reset();
}
}
void Overview::drawColumn( TQPainter& p, e_OverviewMode eOverviewMode, int x, int w, int h, int nofLines )
{
p.setPen(TQt::black);
p.drawLine( x, 0, x, h );
if (nofLines==0) return;
int line = 0;
int oldY = 0;
int oldConflictY = -1;
int wrapLineIdx=0;
Diff3LineList::const_iterator i;
for( i = m_pDiff3LineList->begin(); i!= m_pDiff3LineList->end(); )
{
const Diff3Line& d3l = *i;
int y = h * (line+1) / nofLines;
e_MergeDetails md;
bool bConflict;
bool bLineRemoved;
int src;
mergeOneLine( d3l, md, bConflict, bLineRemoved, src, !m_bTripleDiff );
TQColor c = m_pOptions->m_bgColor;
bool bWhiteSpaceChange = false;
//if( bConflict ) c=m_pOptions->m_colorForConflict;
//else
if ( eOverviewMode==eOMNormal )
{
switch( md )
{
case eDefault:
case eNoChange:
c = m_pOptions->m_bgColor;
break;
case eBAdded:
case eBDeleted:
case eBChanged:
c = bConflict ? m_pOptions->m_colorForConflict : m_pOptions->m_colorB;
bWhiteSpaceChange = d3l.bAEqB || d3l.bWhiteLineA && d3l.bWhiteLineB;
break;
case eCAdded:
case eCDeleted:
case eCChanged:
bWhiteSpaceChange = d3l.bAEqC || d3l.bWhiteLineA && d3l.bWhiteLineC;
c = bConflict ? m_pOptions->m_colorForConflict : m_pOptions->m_colorC;
break;
case eBCChanged: // conflict
case eBCChangedAndEqual: // possible conflict
case eBCDeleted: // possible conflict
case eBChanged_CDeleted: // conflict
case eCChanged_BDeleted: // conflict
case eBCAdded: // conflict
case eBCAddedAndEqual: // possible conflict
c=m_pOptions->m_colorForConflict;
break;
default: assert(false); break;
}
}
else if ( eOverviewMode==eOMAvsB )
{
switch( md )
{
case eDefault:
case eNoChange:
case eCAdded:
case eCDeleted:
case eCChanged: break;
default: c = m_pOptions->m_colorForConflict;
bWhiteSpaceChange = d3l.bAEqB || d3l.bWhiteLineA && d3l.bWhiteLineB;
break;
}
}
else if ( eOverviewMode==eOMAvsC )
{
switch( md )
{
case eDefault:
case eNoChange:
case eBAdded:
case eBDeleted:
case eBChanged: break;
default: c = m_pOptions->m_colorForConflict;
bWhiteSpaceChange = d3l.bAEqC || d3l.bWhiteLineA && d3l.bWhiteLineC;
break;
}
}
else if ( eOverviewMode==eOMBvsC )
{
switch( md )
{
case eDefault:
case eNoChange:
case eBCChangedAndEqual:
case eBCDeleted:
case eBCAddedAndEqual: break;
default: c=m_pOptions->m_colorForConflict;
bWhiteSpaceChange = d3l.bBEqC || d3l.bWhiteLineB && d3l.bWhiteLineC;
break;
}
}
if (!bWhiteSpaceChange || m_pOptions->m_bShowWhiteSpace )
{
// Make sure that lines with conflict are not overwritten.
if ( c == m_pOptions->m_colorForConflict )
{
p.fillRect(x+1, oldY, w, max2(1,y-oldY), bWhiteSpaceChange ? TQBrush(c,TQt::Dense4Pattern) : TQBrush(c) );
oldConflictY = oldY;
}
else if ( c!=m_pOptions->m_bgColor && oldY>oldConflictY )
{
p.fillRect(x+1, oldY, w, max2(1,y-oldY), bWhiteSpaceChange ? TQBrush(c,TQt::Dense4Pattern) : TQBrush(c) );
}
}
oldY = y;
++line;
if ( m_pOptions->m_bWordWrap )
{
++wrapLineIdx;
if(wrapLineIdx>=d3l.linesNeededForDisplay)
{
wrapLineIdx=0;
++i;
}
}
else
{
++i;
}
}
}
void Overview::paintEvent( TQPaintEvent* )
{
if (m_pDiff3LineList==0 || !m_bPaintingAllowed ) return;
int h = height()-1;
int w = width();
if ( m_pixmap.size() != size() )
{
if ( m_pOptions->m_bWordWrap )
{
m_nofLines = 0;
Diff3LineList::const_iterator i;
for( i = m_pDiff3LineList->begin(); i!= m_pDiff3LineList->end(); ++i )
{
m_nofLines += i->linesNeededForDisplay;
}
}
else
{
m_nofLines = m_pDiff3LineList->size();
}
m_pixmap.resize( size() );
TQPainter p(&m_pixmap);
p.fillRect( rect(), m_pOptions->m_bgColor );
if ( !m_bTripleDiff || m_eOverviewMode == eOMNormal )
{
drawColumn( p, eOMNormal, 0, w, h, m_nofLines );
}
else
{
drawColumn( p, eOMNormal, 0, w/2, h, m_nofLines );
drawColumn( p, m_eOverviewMode, w/2, w/2, h, m_nofLines );
}
}
TQPainter painter( this );
painter.drawPixmap( 0,0, m_pixmap );
int y1 = h * m_firstLine / m_nofLines-1;
int h1 = h * m_pageHeight / m_nofLines+3;
painter.setPen(TQt::black);
painter.drawRect( 1, y1, w-1, h1 );
}
WindowTitleWidget::WindowTitleWidget(OptionDialog* pOptionDialog, TQWidget* pParent)
:TQWidget(pParent)
{
m_pOptionDialog = pOptionDialog;
//setAutoFillBackground(true);
TQHBoxLayout* pHLayout = new TQHBoxLayout(this);
pHLayout->setMargin(2);
pHLayout->setSpacing(2);
m_pLabel = new TQLabel(i18n("Output")+":", this);
pHLayout->addWidget( m_pLabel );
m_pFileNameLineEdit = new TQLineEdit(this);
pHLayout->addWidget( m_pFileNameLineEdit, 6 );
m_pFileNameLineEdit->installEventFilter( this );
m_pFileNameLineEdit->setReadOnly( true );
//m_pBrowseButton = new TQPushButton("...");
//pHLayout->addWidget( m_pBrowseButton, 0 );
//connect( m_pBrowseButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(slotBrowseButtonClicked()));
m_pModifiedLabel = new TQLabel(i18n("[Modified]"),this);
pHLayout->addWidget( m_pModifiedLabel );
m_pModifiedLabel->setMinimumSize( m_pModifiedLabel->sizeHint() );
m_pModifiedLabel->setText("");
pHLayout->addStretch(1);
m_pEncodingLabel = new TQLabel(i18n("Encoding for saving")+":",this);
pHLayout->addWidget( m_pEncodingLabel );
m_pEncodingSelector = new TQComboBox(this);
pHLayout->addWidget( m_pEncodingSelector, 3 );
setEncodings(0,0,0);
}
void WindowTitleWidget::setFileName( const TQString& fileName )
{
m_pFileNameLineEdit->setText( TQDir::convertSeparators(fileName) );
}
TQString WindowTitleWidget::getFileName()
{
return m_pFileNameLineEdit->text();
}
void WindowTitleWidget::setEncodings( TQTextCodec* pCodecForA, TQTextCodec* pCodecForB, TQTextCodec* pCodecForC )
{
m_pEncodingSelector->clear();
m_codecMap.clear();
// First sort codec names:
std::map<TQString, TQTextCodec*> names;
int i;
for(i=0;;++i)
{
TQTextCodec* c = TQTextCodec::codecForIndex(i);
if ( c==0 ) break;
else names[TQString(c->name())]=c;
}
i=0;
if ( pCodecForA )
{
m_pEncodingSelector->insertItem( i18n("Codec from") + " A: " + pCodecForA->name(), i );
m_codecMap[i]=pCodecForA;
++i;
}
if ( pCodecForB )
{
m_pEncodingSelector->insertItem( i18n("Codec from") + " B: " + pCodecForB->name(), i );
m_codecMap[i]=pCodecForB;
++i;
}
if ( pCodecForC )
{
m_pEncodingSelector->insertItem( i18n("Codec from") + " C: " + pCodecForC->name(), i );
m_codecMap[i]=pCodecForC;
++i;
}
std::map<TQString, TQTextCodec*>::iterator it;
for(it=names.begin();it!=names.end();++it)
{
m_pEncodingSelector->insertItem( it->first, i );
m_codecMap[i]=it->second;
++i;
}
m_pEncodingSelector->setMinimumSize( m_pEncodingSelector->sizeHint() );
if ( pCodecForC && pCodecForB && pCodecForA )
{
if ( pCodecForA == pCodecForB )
m_pEncodingSelector->setCurrentItem( 2 ); // C
else if ( pCodecForA == pCodecForC )
m_pEncodingSelector->setCurrentItem( 1 ); // B
else
m_pEncodingSelector->setCurrentItem( 2 ); // C
}
else if ( pCodecForA && pCodecForB )
m_pEncodingSelector->setCurrentItem( 1 ); // B
else
m_pEncodingSelector->setCurrentItem( 0 );
}
TQTextCodec* WindowTitleWidget::getEncoding()
{
return m_codecMap[ m_pEncodingSelector->currentItem() ];
}
void WindowTitleWidget::setEncoding(TQTextCodec* pEncoding)
{
m_pEncodingSelector->setCurrentText( TQString( pEncoding->name() ) );
}
//void WindowTitleWidget::slotBrowseButtonClicked()
//{
// TQString current = m_pFileNameLineEdit->text();
//
// KURL newURL = KFileDialog::getSaveURL( current, 0, this, i18n("Select file (not saving yet)"));
// if ( !newURL.isEmpty() )
// {
// m_pFileNameLineEdit->setText( newURL.url() );
// }
//}
void WindowTitleWidget::slotSetModified( bool bModified )
{
m_pModifiedLabel->setText( bModified ? i18n("[Modified]") : "" );
}
bool WindowTitleWidget::eventFilter( TQObject* o, TQEvent* e )
{
if ( e->type()==TQEvent::FocusIn || e->type()==TQEvent::FocusOut )
{
TQPalette p = m_pLabel->palette();
TQColor c1 = m_pOptionDialog->m_fgColor;
TQColor c2 = TQt::lightGray;
if ( e->type()==TQEvent::FocusOut )
c2 = m_pOptionDialog->m_bgColor;
p.setColor(TQColorGroup::Background, c2);
setPalette( p );
p.setColor(TQColorGroup::Foreground, c1);
m_pLabel->setPalette( p );
m_pEncodingLabel->setPalette( p );
m_pEncodingSelector->setPalette( p );
}
if (o == m_pFileNameLineEdit && e->type()==TQEvent::Drop)
{
TQDropEvent* d = static_cast<TQDropEvent*>(e);
if ( TQUriDrag::canDecode( d ) )
{
TQStringList lst;
TQUriDrag::decodeLocalFiles( d, lst );
if ( lst.count() > 0 )
{
static_cast<TQLineEdit*>(o)->setText( lst[0] );
static_cast<TQLineEdit*>(o)->setFocus();
return true;
}
}
}
return false;
}
#include "mergeresultwindow.moc"