|
|
|
/***************************************************************************
|
|
|
|
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"
|