/****************************************************************************
**
** Copyright (C) 2002-2006 Frank Hemer <frank@hemer.org>,
** Tilo Riemer <riemer@crossvc.com>
**
**
**----------------------------------------------------------------------------
**
**----------------------------------------------------------------------------
**
** CrossVC is available under two different licenses:
**
** If CrossVC is linked against the GPLed version of Qt
** CrossVC is released under the terms of GPL also.
**
** If CrossVC is linked against a nonGPLed version of Qt
** CrossVC is released under the terms of the
** CrossVC License for non-Unix platforms (CLNU)
**
**
** CrossVC License for non-Unix platforms (CLNU):
**
** Redistribution and use in binary form, without modification,
** are permitted provided that the following conditions are met:
**
** 1. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 2. It is not permitted to distribute the binary package under a name
** different than CrossVC.
** 3. The name of the authors may not be used to endorse or promote
** products derived from this software without specific prior written
** permission.
** 4. The source code is the creative property of the authors.
** Extensions and development under the terms of the Gnu Public License
** are limited to the Unix platform. Any distribution or compilation of
** the source code against libraries licensed other than gpl requires
** the written permission of the authors.
**
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
** GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
**
**
** CrossVC License for Unix platforms:
**
** 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, version 2 of the License.
** This program is distributed in
** the hope that it will be useful, but WITHOUT ANY WARRANTY; without
** even the implied warranty of MERCHANTABILITY or FITNESS FOR A
** PARTICULAR PURPOSE.
**
** See the GNU General Public License version 2 for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software Foundation,
** Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
**
*****************************************************************************/
#include "config.h"
#include <qapplication.h>
#include <qtimer.h>
#include <qfile.h>
#include <qpainter.h>
#include <qmessagebox.h>
#include <qfont.h>
#include <qwhatsthis.h>
#include <qpushbutton.h>
#include <qlayout.h>
#include <qsplitter.h>
#include <qsizegrip.h>
#include "ResolvDialogImpl.h"
#include "globals.h"
#include "FileTableImpl.h"
//FileTable ID's
const int LEFT = 0;
const int RIGHT = 1;
const int MERGE = 2;
//colors for the tables
const QColor sourceBg(255,255,255);//white ffffff
const QColor mergeBg(255,255,255);//white ffffff
const QColor numBg(140,140,140);//dark gray 8c8c8c
const QColor numSelect(0,255,0);//green 00ff00
const QColor conflict(255,80,60);//light red ff503c
const QColor conflictSelect(120,160,215);//light blue 78a0d7 | selected 78a0d7
const QColor merge(60,225,255);//light blue 3cffff
const QColor marker(140,140,140);//dark gray 8c8c8c
const QColor fillColor(240,240,240);//light gray dcdcdc
//The width of the splitter
const unsigned int ResolvDialogImpl::SplitterStyle::SPLITTER_WIDTH = 4;
ResolvDialogImpl::Block::Block() :
from(-1),
to(-1),
mergeMap(NULL) {
fileMap[LEFT] = NULL;
fileMap[RIGHT] = NULL;
}
ResolvDialogImpl::Block::~Block() {
delete [] fileMap[LEFT];
delete [] fileMap[RIGHT];
delete [] mergeMap;
}
ResolvDialogImpl::CBlock::CBlock(int _from, int _to) :
from(_from), to(_to) {
}
ResolvDialogImpl::ResolvDialogImpl( QString fileName,
const QIconSet & whatsThisIconSet,
QWidget* parent,
WFlags fl,
QString revision)
: ResolvDialog( LookAndFeel::g_b0AsParent ? 0 : parent, "ResolvDialog", fl)
{
setCaption (tr("Resolve") + " - " + fileName.mid(fileName.findRev("/")+1) + " " + revision);
Splitter->setStyle(new SplitterStyle(this));
TextLabel1->setText(tr("Sandbox (partly merged)"));
TextLabel3->setText(tr("Result (preview)"));
init(whatsThisIconSet,fileName);
if (setFile()) {
show();
render();
} else close();
}
ResolvDialogImpl::~ResolvDialogImpl() {
}
void ResolvDialogImpl::init(const QIconSet & whatsThisIconSet,QString & fileName) {
m_blockVector.setAutoDelete(false);//there are multiple references to the same object
m_blockTracker.setAutoDelete(true);//so we got this
m_conflictVector.setAutoDelete(true);
m_currentBlock = NULL;
m_pWhatsThis->setIconSet(whatsThisIconSet);
#ifdef Q_WS_MAC
m_pWhatsThis->setMaximumWidth(m_pWhatsThis->height() * 2);
#else
m_pWhatsThis->setMaximumWidth(m_pWhatsThis->height());
#endif
ButtonLayout->addWidget(new QSizeGrip(this),0,Qt::AlignRight|Qt::AlignBottom);
ButtonLabel->setAlignment(Qt::AlignHCenter|AlignVCenter);
m_stop = false;
m_fileName = fileName;
installEventFilter( this);//get rid of the anoying whatsthis popup menu on a rightclick
if (!Font::g_diff.isEmpty()) {
QFont f;
if (f.fromString(Font::g_diff)) {
m_FileLeft->setFont(f);
m_FileRight->setFont(f);
m_FileMerged->setFont(f);
} else Font::g_diff = QString::null;
}
m_FileLeft->setBackground(sourceBg);
m_FileRight->setBackground(sourceBg);
m_FileMerged->setBackground(mergeBg);
m_FileLeft->setID(LEFT);
m_FileRight->setID(RIGHT);
m_FileMerged->setID(MERGE);
connect(m_FileLeft,SIGNAL(xScrollValueChanged(int)),m_FileRight,SLOT(setXScrollPos(int)));
connect(m_FileLeft,SIGNAL(xScrollValueChanged(int)),m_FileMerged,SLOT(setXScrollPos(int)));
connect(m_FileRight,SIGNAL(xScrollValueChanged(int)),m_FileLeft,SLOT(setXScrollPos(int)));
connect(m_FileRight,SIGNAL(xScrollValueChanged(int)),m_FileMerged,SLOT(setXScrollPos(int)));
connect(m_FileMerged,SIGNAL(xScrollValueChanged(int)),m_FileLeft,SLOT(setXScrollPos(int)));
connect(m_FileMerged,SIGNAL(xScrollValueChanged(int)),m_FileRight,SLOT(setXScrollPos(int)));
connect(m_FileLeft,SIGNAL(yScrollValueChanged(int)),m_FileRight,SLOT(setYScrollPos(int)));
connect(m_FileRight,SIGNAL(yScrollValueChanged(int)),m_FileMerged,SLOT(setYScrollPos(int)));
connect(m_FileMerged,SIGNAL(yScrollValueChanged(int)),m_FileLeft,SLOT(setYScrollPos(int)));
connect(m_FileLeft,SIGNAL(focused(int,int)),m_FileRight,SLOT(setFocus(int,int)));
connect(m_FileLeft,SIGNAL(focused(int,int)),m_FileMerged,SLOT(setFocus(int,int)));
connect(m_FileRight,SIGNAL(focused(int,int)),m_FileLeft,SLOT(setFocus(int,int)));
connect(m_FileRight,SIGNAL(focused(int,int)),m_FileMerged,SLOT(setFocus(int,int)));
connect(m_FileMerged,SIGNAL(focused(int,int)),m_FileLeft,SLOT(setFocus(int,int)));
connect(m_FileMerged,SIGNAL(focused(int,int)),m_FileRight,SLOT(setFocus(int,int)));
connect(m_FileLeft,SIGNAL(unselected(int,int)),this,SLOT(unselected(int,int)));
connect(m_FileLeft,SIGNAL(unSelectedBlock(int,int,int)),this,SLOT(unSelectedBlock(int,int,int)));
connect(m_FileLeft,SIGNAL(selectionChanged(int,int,QString)),this,SLOT(selected(int,int,QString)));
connect(m_FileLeft,SIGNAL(selectedBlock(int,int,int)),this,SLOT(selectedBlock(int,int,int)));
connect(m_FileRight,SIGNAL(unselected(int,int)),this,SLOT(unselected(int,int)));
connect(m_FileRight,SIGNAL(unSelectedBlock(int,int,int)),this,SLOT(unSelectedBlock(int,int,int)));
connect(m_FileRight,SIGNAL(selectionChanged(int,int,QString)),this,SLOT(selected(int,int,QString)));
connect(m_FileRight,SIGNAL(selectedBlock(int,int,int)),this,SLOT(selectedBlock(int,int,int)));
connect(m_FileMerged,SIGNAL(clear(int,int)),this,SLOT(clear(int,int)));
connect(m_FileMerged,SIGNAL(clicked(int,int)),this,SLOT(clear(int,int)));
QWhatsThis::add( m_FileLeft,
tr( "This file holds the state the file was in before the conflict causing cvs call.\n"
"\n"
"Resolve Dialog howto:\n"
"\n"
"left click into the line-number bar:\n"
"-on a selected line: deselects the whole block\n"
"-on an unselected line: select the whole block\n"
"\n"
"left click into a conflict block:\n"
"select/unselect a line\n"
"\n"
"right click into a conflict block:\n"
"selects the region between the last left click and the current click position\n"
"\n"
"Keyboard:\n"
"move Focus: tab/<shift>tab\n"
"select/unselect line: spacebar\n"
"select region: <shift>spacebar\n"
"goto next/previous line: arrow down/up\n"
"goto next/previous block: <ctrl>arrow down/up\n"
"scroll half page up/down: page up/down\n"
"goto beginning/end: Home/End\n"
"\n"
"Special feature for the merged file:\n"
"remove a line: Delete\n"
"\n"
"=======================================\n"
"Colors:\n"
"\n"
"white: non-conflicting code segments\n"
"dark gray: conflict markers and line numbers\n"
"red: conflicting code parts\n"
"light gray: space added for clarity\n"
"blue: selected lines" ) );
QWhatsThis::add( m_FileRight,
tr( "This file represents the part of the file that was merged in by the conflict-causing cvs call.\n"
"\n"
"Resolve Dialog howto:\n"
"\n"
"left click into the line-number bar:\n"
"-on a selected line: deselects the whole block\n"
"-on an unselected line: select the whole block\n"
"\n"
"left click into a conflict block:\n"
"select/unselect a line\n"
"\n"
"right click into a conflict block:\n"
"selects the region between the last left click and the current click position\n"
"\n"
"Keyboard:\n"
"move Focus: tab/<shift>tab\n"
"select/unselect line: spacebar\n"
"select region: <shift>spacebar\n"
"goto next/previous line: arrow down/up\n"
"goto next/previous block: <ctrl>arrow down/up\n"
"scroll half page up/down: page up/down\n"
"goto beginning/end: Home/End\n"
"\n"
"Special feature for the merged file:\n"
"remove a line: Delete\n"
"\n"
"=======================================\n"
"Colors:\n"
"\n"
"white: non-conflicting code segments\n"
"dark gray: conflict markers and line numbers\n"
"red: conflicting code parts\n"
"light gray: space added for clarity\n"
"blue: selected lines" ) );
QWhatsThis::add( m_FileMerged,
tr( "This file holds the merged state. The conflict markers of solved conflicts will be removed when the file is saved.\n"
"\n"
"Resolve Dialog howto:\n"
"\n"
"left click into the line-number bar:\n"
"-on a selected line: deselects the whole block\n"
"-on an unselected line: select the whole block\n"
"\n"
"left click into a conflict block:\n"
"select/unselect a line\n"
"\n"
"right click into a conflict block:\n"
"selects the region between the last left click and the current click position\n"
"\n"
"Keyboard:\n"
"move Focus: tab/<shift>tab\n"
"select/unselect line: spacebar\n"
"select region: <shift>spacebar\n"
"goto next/previous line: arrow down/up\n"
"goto next/previous block: <ctrl>arrow down/up\n"
"scroll half page up/down: page up/down\n"
"goto beginning/end: Home/End\n"
"\n"
"Special feature for the merged file:\n"
"remove a line: Delete\n"
"\n"
"============================================\n"
"Colors:\n"
"\n"
"white: non-conflicting code segments\n"
"dark gray: conflict markers and line numbers (will not be saved if conflict was solved)\n"
"light blue: Preview of conflicting segment as it will be saved" ) );
}
bool ResolvDialogImpl::eventFilter( QObject *o, QEvent *e ) {
if ( e->type() == QEvent::ContextMenu ) {
return TRUE; // eat event
} else {
// standard event processing
return QWidget::eventFilter( o, e );
}
}
void ResolvDialogImpl::render() {
m_FileLeft->render();
m_FileRight->render();
m_FileMerged->render();
m_FileLeft->setXScrollPos(0);
m_FileLeft->setYScrollPos(0);
}
void ResolvDialogImpl::cancelRead() {
m_stop = true;
m_FileLeft->cancelRead();
m_FileRight->cancelRead();
m_FileMerged->cancelRead();
}
bool ResolvDialogImpl::setFile() {
QApplication::setOverrideCursor(waitCursor);
QString fName = m_fileName.mid(m_fileName.findRev("/")+1);
ProgressDialog* progressDlg = new ProgressDialog(this, "ProgressDialog", true,
Qt::WStyle_Customize | Qt::WStyle_NoBorder | WDestructiveClose);
connect(progressDlg->CancelButton,SIGNAL(clicked()),this,SLOT(cancelRead()));
progressDlg->m_InfoMessage->setText(tr("Please wait ...")+"\n");
progressDlg->m_InfoText->setText(tr("Analyzing file: ")+fName);
progressDlg->show();
progressDlg->update();
FileTableImpl* fL = m_FileLeft;
FileTableImpl* fR = m_FileRight;
FileTableImpl* fM = m_FileMerged;
QString parse = "";
int mode = 0;
int lineCount = 0;
int confCount = 0;
QFile f;
QString line;
f.setName(m_fileName);
if(f.open(IO_ReadOnly)) {
QTextStream textStream(&f);
m_linesTotal = 0;
int blockStart = 0;
int lineNum = 0;
int leftLineCount = 0;
int rightLineCount = 0;
int mergeLineCount = 0;
QString leftBlock = "";
QString rightBlock = "";
QString mergeBlock = "";
QString conflictSeparator;
while(!textStream.atEnd()) {
line = textStream.readLine();
m_linesTotal++;
}
f.reset();
fL->reserveLines(m_linesTotal);
fR->reserveLines(m_linesTotal);
fM->reserveLines(m_linesTotal);
while(!textStream.atEnd()) {
qApp->processEvents();
if (m_stop) break;
line = textStream.readLine();
switch (mode) {
case 0: {
if (line.startsWith("<<<<<<<")) {
QString numString;
if (!parse.isEmpty()) {
numString = QString::number(lineNum+1);
fL->addLine(numString,parse,true,numSelect,numBg);
fR->addLine(numString,parse,true,numSelect,numBg);
fM->addLine(numString,parse,true,numSelect,numBg);
}
numString = QString::number(lineCount+1);
fL->addLine(numString,line+"\n",true,numSelect,numBg,marker,marker);
fM->addLine(numString,line+"\n",true,numSelect,numBg,marker,marker);
blockStart = lineCount+1;
addLine(lineCount);
initBlock();
mode = 1;
++confCount;
parse = "";
} else {
parse += line+"\n";
addLine(lineCount);
}
break;
}
case 1: {
if (line.startsWith("=======")) {
QString numString = QString::number(lineCount+1);
conflictSeparator = line+"\n";
fR->addLine(numString,conflictSeparator,true,numSelect,numBg,marker,marker);
leftBlock += parse;
mergeBlock += parse+line+"\n";
mode = 2;
addLine(lineCount);
parse = "";
lineNum = lineCount+1;
} else {
parse += line+"\n";
addLine(lineCount);
leftLineCount++;
mergeLineCount++;
}
break;
}
case 2: {
if (line.startsWith(">>>>>>>")) {
TextLabel2->setText(tr("Revision: ")+line.mid(8));
rightBlock += parse;
if (leftBlock.isEmpty()) {
leftBlock += "\n";
leftLineCount++;
}
if (rightBlock.isEmpty()) {
rightBlock += "\n";
rightLineCount++;
}
QString numString = QString::number(blockStart+1);
QString xNumString = QString::number(lineNum+1);
fL->addLine(numString,leftBlock,false,numSelect,numBg,conflictSelect,conflict);
fR->addLine(xNumString,rightBlock,false,numSelect,numBg,conflictSelect,conflict);
fM->addLine(numString,mergeBlock,true,numSelect,numBg,merge,merge);
leftBlock = "";
rightBlock = "";
int i = 0;
int l = 0;
int r = 0;
for (i=leftLineCount;i<=mergeLineCount;i++) {
leftBlock += "\n";
l++;
}
for (i=rightLineCount;i<=mergeLineCount;i++) {
rightBlock += "\n";
r++;
}
fL->addLine("",leftBlock,true,numSelect,numBg,fillColor,fillColor);
fR->addLine("",rightBlock,true,numSelect,numBg,fillColor,fillColor);
numString = QString::number(lineCount+1);
xNumString = QString::number(lineNum);
fL->addLine(xNumString,conflictSeparator,true,numSelect,numBg,marker,marker);
fR->addLine(numString,line+"\n",true,numSelect,numBg,marker,marker);
fM->addLine(numString,line+"\n",true,numSelect,numBg,marker,marker);
setCurrentBlock(blockStart,lineCount-1);
m_currentBlock = NULL;
addLine(lineCount);
leftBlock = "";
rightBlock = "";
mergeBlock = "";
leftLineCount = 0;
rightLineCount = 0;
mergeLineCount = 0;
lineNum = lineCount+1;
mode = 0;
parse = "";
} else {
parse += line+"\n";
mergeBlock += line+"\n";
addLine(lineCount);
rightLineCount++;
mergeLineCount++;
}
break;
}
}
lineCount++;
}
if (!parse.isEmpty() ) {
QString numString = QString::number(lineNum+1);
fL->addLine(numString,parse,true,numSelect,numBg);
fR->addLine(numString,parse,true,numSelect,numBg);
fM->addLine(numString,parse,true,numSelect,numBg);
}
f.close();
}
ButtonLabel->setText(tr("conflicts")+" "+QString::number(confCount));
progressDlg->hide();
delete(progressDlg);
update();
QApplication::restoreOverrideCursor();
if ( (m_linesTotal != lineCount) || (mode != 0) ) {//parser error
QString msg = (mode!=0) ? tr("Unbalanced conflict markers, cannot resolve") : tr("Parser error");
QMessageBox::critical(this, tr("Error"), msg,
QMessageBox::Ok,QMessageBox::NoButton,QMessageBox::NoButton);
return false;
}
if (m_stop) return false;
else return true;
}
void ResolvDialogImpl::addLine(unsigned int line) {
if (line >= m_blockVector.size()) m_blockVector.resize(m_blockVector.size()+100);
m_blockVector.insert(line,m_currentBlock);
}
void ResolvDialogImpl::initBlock() {
m_currentBlock = new Block();
m_blockTracker.push(m_currentBlock);
}
void ResolvDialogImpl::setCurrentBlock(int from, int to) {
m_currentBlock->from = from;
m_currentBlock->to = to;
m_currentBlock->fileMap[LEFT] = new int[to-from+1];
m_currentBlock->fileMap[RIGHT] = new int[to-from+1];
m_currentBlock->mergeMap = new Reference[to-from+1];
m_currentBlock->pos = 0;
CBlock* cbl = new CBlock(from,to);
if (m_conflictVector.count() >= m_conflictVector.size()) m_conflictVector.resize(m_conflictVector.size()+10);
m_conflictVector.insert(m_conflictVector.count(),cbl);
}
int ResolvDialogImpl::appendLine(int fileTable, int line) {
Block* hlpBlock = m_blockVector.at((unsigned int)line);
int mergePos = hlpBlock->pos;
hlpBlock->mergeMap[mergePos].fileTable = fileTable;
hlpBlock->mergeMap[mergePos].line = line;
hlpBlock->fileMap[fileTable][line-hlpBlock->from] = mergePos;
hlpBlock->pos++;
return mergePos;
}
void ResolvDialogImpl::clear(int, int row) {
Block* hlp = m_blockVector.at((unsigned int)row);
if (hlp) {
if (row >= hlp->from+hlp->pos) return;
int pos = row-hlp->from;
if (hlp->mergeMap[pos].fileTable == LEFT) {
m_FileLeft->setSelected(hlp->mergeMap[pos].line,false);
} else {
m_FileRight->setSelected(hlp->mergeMap[pos].line,false);
}
unselected(hlp->mergeMap[pos].fileTable,hlp->mergeMap[pos].line);
}
}
void ResolvDialogImpl::selected(int id,int row,QString txt) {
Block* hlp = m_blockVector.at((unsigned int)row);
if (hlp) {
int pos = appendLine(id,row);
if (!pos) {//clear Block
int i = 0;
for (i=hlp->from;i<=hlp->to;i++) {
hlp->oriTxt += m_FileMerged->getText(i)+"\n";
m_FileMerged->setText(i,"");
}
}
m_FileMerged->setText(hlp->from+pos,txt);
}
}
void ResolvDialogImpl::unselected(int id,int row) {
Block* hlp = m_blockVector.at((unsigned int)row);
if (hlp) {
int pos = hlp->fileMap[id][row-hlp->from];
int i = 0;
int j = 0;
m_FileMerged->move(pos+hlp->from+1,-1,hlp->pos-pos-1);
for (i=pos+hlp->from,j=pos;j<hlp->pos-1;i++,j++) {
hlp->mergeMap[j] = hlp->mergeMap[j+1];
hlp->fileMap[hlp->mergeMap[j].fileTable][hlp->mergeMap[j].line-hlp->from]--;
}
hlp->pos--;
if (hlp->pos == 0) {
i = hlp->from;
j = 0;
while ( (j = hlp->oriTxt.find("\n"))>-1) {
m_FileMerged->setText(i++,hlp->oriTxt.mid(0,j));
hlp->oriTxt = hlp->oriTxt.mid(j+1);
}
hlp->oriTxt = "";
} else {
m_FileMerged->setText(i,"");
}
}
}
void ResolvDialogImpl::selectedBlock(int id, int from, int to) {
QString txt;
int range = to-from+1;
Block* hlp = m_blockVector.at((unsigned int)from);
if (!hlp->pos) {//clear
int i = 0;
for (i=hlp->from;i<hlp->from+range;i++) {
hlp->oriTxt += m_FileMerged->getText(i)+"\n";
}
for (i=hlp->from+range;i<=hlp->to;i++) {
hlp->oriTxt += m_FileMerged->getText(i)+"\n";
m_FileMerged->setText(i,"");
}
}
int hFrom = hlp->from;
switch( id) {
case LEFT: {
for (int i = from;i<=to; i++) {
txt = m_FileLeft->getText(i);
int pos = appendLine(id,i);
m_FileMerged->setText(hFrom+pos,txt);
}
break;
}
case RIGHT: {
for (int i = from;i<=to; i++) {
txt = m_FileRight->getText(i);
int pos = appendLine(id,i);
m_FileMerged->setText(hFrom+pos,txt);
}
break;
}
}
}
void ResolvDialogImpl::unSelectedBlock(int id, int from, int to) {
Block* hlp = m_blockVector.at((unsigned int)from);
if (hlp) {
int j;
int blockPos;
int lower = hlp->pos;
for ( blockPos=from; blockPos <= to; blockPos++) {//reorganize mergeFile lines
int mappedMergePos = hlp->fileMap[id][blockPos-hlp->from];
if (mappedMergePos < lower) lower = mappedMergePos;//find startpoint for rewrite
for (j=mappedMergePos;j<hlp->pos-1;j++) {//update pointers
hlp->mergeMap[j] = hlp->mergeMap[j+1];
hlp->fileMap[hlp->mergeMap[j].fileTable][hlp->mergeMap[j].line-hlp->from]--;
}
hlp->pos--;
}
if (hlp->pos == 0) {//reset to unchanged
int i = hlp->from;
j = 0;
while ( (j = hlp->oriTxt.find("\n"))>-1) {
m_FileMerged->setText(i++,hlp->oriTxt.mid(0,j));
hlp->oriTxt = hlp->oriTxt.mid(j+1);
}
hlp->oriTxt = "";
} else {//modify m_FileMerged
for (j=lower;j<hlp->pos;j++) {
switch(hlp->mergeMap[j].fileTable) {
case LEFT: {
m_FileMerged->setText(hlp->from+j,m_FileLeft->getText(hlp->mergeMap[j].line));
break;
}
case RIGHT: {
m_FileMerged->setText(hlp->from+j,m_FileRight->getText(hlp->mergeMap[j].line));
break;
}
}
}
for (j=hlp->from+hlp->pos;j<=hlp->from+hlp->pos+to-from;j++) {
m_FileMerged->setText(j,"");
}
}
}
}
void ResolvDialogImpl::writeFile() {
QFile f(m_fileName);
QString line;
QString lf = getSystemLF();
Block* hlp = NULL;
int maxLines = m_blockVector.size();
if(f.open(IO_WriteOnly)) {
QTextStream textStream(&f);
int i = 0;
int to = -1;
int skipLines = 0;
while (true) {
line = m_FileMerged->getText(i++);
if (line.isNull()) break;
if (i == to) {
continue;
}
if (i>to && (skipLines)) {
skipLines--;
continue;
}
if ( (i < maxLines) && (hlp = m_blockVector.at(i))) {//one in advance
if (hlp->pos) {
if (i == hlp->from) {
to = hlp->from+hlp->pos+1;
skipLines = hlp->to+2-to;//skip empty lines
continue;
}
}
}
textStream << line;
textStream << lf;
}
f.flush();
f.close();
close();
} else {
QString fName = m_fileName.mid(m_fileName.findRev("/")+1);
QMessageBox::warning(this, tr("Warning"), tr("Cannot save:\n") +
fName +
tr(",\nthe file is write-protected.\nPlease run edit first."),
QMessageBox::Ok,QMessageBox::NoButton,QMessageBox::NoButton);
}
}
void ResolvDialogImpl::SplitterStyle::drawPrimitive(PrimitiveElement pe, QPainter *p,
const QRect &r, const QColorGroup &cg, SFlags flags /*= Style_Default*/,
const QStyleOption &StyleOption /*= QStyleOption::Default*/) const
{
if (pe != PE_Splitter) {
QApplication::style().drawPrimitive(pe, p, r, cg, flags, StyleOption);
} else if (dlg->m_linesTotal) {
int top = dlg->TextLabel1->height();
int h = 0;
dlg->m_FileLeft->adjustScrollBarOffsets(top,h);
double ppl = (double)h/(double)dlg->m_linesTotal;
p->setPen(conflict);
p->setBrush(conflict);
unsigned int i;
for (i=0;i<dlg->m_conflictVector.count();i++) {
CBlock* bl = dlg->m_conflictVector.at(i);
int y = (int)((bl->from)*ppl);
int height = (int)((bl->to - bl->from)*ppl);
if (height<1) {
height = 1;
}
p->drawRect(0,top+y,r.width(),height);
}
}
}
void ResolvDialogImpl::nextClicked() {
int line = m_FileLeft->getFocusedLine();
if (line == -1) line = m_FileLeft->getTopLine();
int i;
for (i=0;i<(int)m_conflictVector.count();i++) {
CBlock* bl = m_conflictVector.at(i);
if (bl->from <= line) continue;
else {
m_FileLeft->setFocusRow(bl->from);
break;
}
}
}
void ResolvDialogImpl::previousClicked() {
int line = m_FileLeft->getFocusedLine();
if (line == -1) line = m_FileLeft->getTopLine();
int i;
for (i=(int)m_conflictVector.count()-1;i>=0;i--) {
CBlock* bl = m_conflictVector.at(i);
if (bl->from >= line) continue;
else {
m_FileLeft->setFocusRow(bl->from);
break;
}
}
}
void ResolvDialogImpl::enterWhatsThisMode()
{
QWhatsThis::enterWhatsThisMode();
}
syntax highlighted by Code2HTML, v. 0.9.1