/* ==================================================================== * Copyright (c) 2003-2006, Martin Hauner * http://subcommander.tigris.org * * Subcommander is licensed as described in the file doc/COPYING, which * you should have received as part of this distribution. * ==================================================================== */ // sc #include "config.h" #include "Diff3Widget.h" #include "DiffInfoModel.h" #include "SingleTextWidget.h" #include "DoubleTextWidget.h" #include "TextWidget.h" #include "settings/FontSettings.h" #include "sublib/Line.h" #include "sublib/TextModel.h" #include "sublib/SplitLayout.h" #include "util/String.h" // qt #include #include #include #include #include #include // sys #include #include #include #include #include Diff3Widget::Diff3Widget( FontSettings* fs, QWidget *parent, const char *name ) : super( parent, name ), _diffInfo(0) { setCaption( _q("Subcommander ") ); setIconText( _q("Subcommander ") ); QFont font = fs->getEditorFont(); QApplication::setFont( font, false, "TextWidget" ); QApplication::setFont( font, false, "TextLineNrWidget" ); QApplication::setFont( font, false, "TextGlueWidget" ); setSizePolicy( QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding) ); //setFont( QFont("Courier New",10,QFont::Normal,false/*QFont::Unicode*/) ); QGridLayout* bl = new QGridLayout(this); { QWidget* vs = new QWidget(this); VSplitLayout* vsl = new VSplitLayout(vs); _splitMerge = vsl; bl->addWidget(vs,0,0); { QWidget* hs = new QWidget(vs); HSplitLayout* hsl = new HSplitLayout(hs); _splitOrg = hsl; vsl->addWidgetOne( hs, false ); { _single = new SingleTextWidget(hs); _single->setHScrollBarOff( SingleTextWidget::sboDisable ); _single->setAcceptDrops(true); hsl->addWidgetOne( _single, true, 1 ); _double = new DoubleTextWidget(hs); _double->setHScrollBarOff( SingleTextWidget::sboDisable ); _double->setAcceptDrops(true); hsl->addWidgetTwo( _double, false, 2 ); } _merged = new SingleTextWidget(vs); _merged->enableSelection( true ); _merged->setEditable( true ); vsl->addWidgetTwo( _merged, true ); } #if 0 // experimental vertical line display QFontMetrics m( font() ); QVBox* f1 = new QVBox(this); f1->setFrameStyle( QFrame::Panel | QFrame::Sunken ); f1->setMargin(1); f1->setSpacing(1); f1->setSizePolicy( QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed) ); bl->addWidget(f1,1,0); { TextWidget* tw1 = new TextWidget(f1); tw1->setFixedHeight( m.height() ); TextWidget* tw2 = new TextWidget(f1); tw2->setFixedHeight( m.height() ); } #endif } // sync v scrollbars connect(_single->getVScrollBar(), SIGNAL(valueChanged(int)), SLOT(vsbChange(int)) ); connect(_double->getVScrollBar(), SIGNAL(valueChanged(int)), SLOT(vsbChange(int)) ); // h scrollbars connect( _single, SIGNAL(updatedScrollBars()), SLOT(hsbChange()) ); connect( _double, SIGNAL(updatedScrollBars()), SLOT(hsbChange()) ); // block selection connect( _single->getText(), SIGNAL(blockChanged(int)), this, SLOT(blockChangeO(int)) ); connect( _double->getLeftText(), SIGNAL(blockChanged(int)), this, SLOT(blockChangeL(int)) ); connect( _double->getRightText(), SIGNAL(blockChanged(int)), this, SLOT(blockChangeR(int)) ); connect( _merged->getText(), SIGNAL(blockChanged(int)), this, SLOT(blockChangeM(int)) ); } Diff3Widget::~Diff3Widget() { } void Diff3Widget::setModel( TextModel* original, TextModel* modified, TextModel* latest ) { _single->setModel( original ); _double->setModel( modified, latest ); } void Diff3Widget::setModel( DiffInfoModel* info ) { _double->setModel(info); _diffInfo = info; } void Diff3Widget::setMergeModel( TextModel* merged ) { _merged->setModel(merged); } void Diff3Widget::setLeftLabel( const sc::String& l ) { _single->setLabel(l); } void Diff3Widget::setCenterLabel( const sc::String& l ) { _double->setLeftLabel(l); } void Diff3Widget::setRightLabel( const sc::String& l ) { _double->setRightLabel(l); } // todo move to "model" // selected original block void Diff3Widget::blockChangeO(int b) { setActiveDiffBlock(b); TextModel* om = _single->getText()->getModel(); TextModel* mm = _double->getLeftText()->getModel(); TextModel* lm = _double->getRightText()->getModel(); TextModel* me = _merged->getText()->getModel(); //TextModel* om = _diffInfo->getModel( DiffInfoModel::dmOriginal ); //TextModel* mm = _diffInfo->getModel( DiffInfoModel::dmModified ); //TextModel* lm = _diffInfo->getModel( DiffInfoModel::dmLatest ); //TextModel* me = _diffInfo->getModel( DiffInfoModel::dmMerged ); _double->getLeftText()->clearBlockSelection(); _double->getRightText()->clearBlockSelection(); int line = me->replaceBlock(b,om); _merged->setModel(me); // TODO that is getting strange here... // i think jumpToLine needs a better implementation, without // the processEvents() it often jumps to the wrong position // when a block get clicked. If it clicked a second time it // jumps again. See also nextDiff() in MainWindow, which has // the same problem. //_merged->updateGeometry(); //qApp->processEvents(); DiffInfo& di = _diffInfo->getInfo(b); di.setMergeType( msOriginal ); _merged->getText()->setBlockSelection(b); _merged->update(); _merged->jumpToLine(line-2); } // selected left block void Diff3Widget::blockChangeL(int b) { setActiveDiffBlock(b); TextModel* om = _single->getText()->getModel(); TextModel* mm = _double->getLeftText()->getModel(); TextModel* lm = _double->getRightText()->getModel(); TextModel* me = _merged->getText()->getModel(); //TextModel* om = _diffInfo->getModel( DiffInfoModel::dmOriginal ); //TextModel* mm = _diffInfo->getModel( DiffInfoModel::dmModified ); //TextModel* lm = _diffInfo->getModel( DiffInfoModel::dmLatest ); //TextModel* me = _diffInfo->getModel( DiffInfoModel::dmMerged ); _single->getText()->clearBlockSelection(); _double->getRightText()->clearBlockSelection(); int line = me->replaceBlock(b,mm); _merged->setModel(me); //_merged->updateGeometry(); //qApp->processEvents(); DiffInfo& di = _diffInfo->getInfo(b); di.setMergeType( msModified ); _merged->getText()->setBlockSelection(b); _merged->update(); _merged->jumpToLine(line-2); } // select right block void Diff3Widget::blockChangeR(int b) { setActiveDiffBlock(b); TextModel* om = _single->getText()->getModel(); TextModel* mm = _double->getLeftText()->getModel(); TextModel* lm = _double->getRightText()->getModel(); TextModel* me = _merged->getText()->getModel(); //TextModel* om = _diffInfo->getModel( DiffInfoModel::dmOriginal ); //TextModel* mm = _diffInfo->getModel( DiffInfoModel::dmModified ); //TextModel* lm = _diffInfo->getModel( DiffInfoModel::dmLatest ); //TextModel* me = _diffInfo->getModel( DiffInfoModel::dmMerged ); _single->getText()->clearBlockSelection(); _double->getLeftText()->clearBlockSelection(); int line = me->replaceBlock(b,lm); _merged->setModel(me); //_merged->updateGeometry(); //qApp->processEvents(); DiffInfo& di = _diffInfo->getInfo(b); di.setMergeType( msLatest ); _merged->getText()->setBlockSelection(b); _merged->update(); _merged->jumpToLine(line-2); } // selected merge block void Diff3Widget::blockChangeM(int b) { setActiveDiffBlock(b); TextModel* om = _single->getText()->getModel(); TextModel* mm = _double->getLeftText()->getModel(); TextModel* lm = _double->getRightText()->getModel(); TextModel* me = _merged->getText()->getModel(); //TextModel* om = _diffInfo->getModel( DiffInfoModel::dmOriginal ); //TextModel* mm = _diffInfo->getModel( DiffInfoModel::dmModified ); //TextModel* lm = _diffInfo->getModel( DiffInfoModel::dmLatest ); //TextModel* me = _diffInfo->getModel( DiffInfoModel::dmMerged ); const DiffInfo& di = _diffInfo->getInfo(b); switch( di.getMergeType() ) { case msOriginal: { _single->getText()->setBlockSelection(b); _double->getLeftText()->clearBlockSelection(); _double->getRightText()->clearBlockSelection(); break; } case msModified: { _single->getText()->clearBlockSelection(); _double->getLeftText()->setBlockSelection(b); _double->getRightText()->clearBlockSelection(); break; } case msLatest: { _single->getText()->clearBlockSelection(); _double->getLeftText()->clearBlockSelection(); _double->getRightText()->setBlockSelection(b); break; } case msNotMerged: { _single->getText()->setBlockSelection(b); _double->getLeftText()->setBlockSelection(b); _double->getRightText()->setBlockSelection(b); break; } } // TODO we need a way to get the line correction value // from one place so we don't repeat it all the time.... jumpToLine( di.getBlockInfo().getStart()-2 ); } void Diff3Widget::vsbChange(int y) { _single->getVScrollBar()->setValue(y); _double->getVScrollBar()->setValue(y); } void Diff3Widget::hsbChange() { QScrollBar* sh = _single->getHScrollBar(); QScrollBar* dh = _double->getHScrollBar(); bool sd = ! _single->isVisible(); bool dd = ! _double->isVisible(); if( _single->getHScrollBarOff() == TextViewWidget::sboDisable ) { sd |= ! sh->isEnabled(); dd |= ! dh->isEnabled(); } else { sd |= ! sh->isVisible(); dd |= ! dh->isVisible(); } if( sd && dd ) { sh->hide(); dh->hide(); } else { sh->show(); dh->show(); } } void Diff3Widget::jumpToLine( int line ) { if( line < 0 ) { line = 0; } _single->jumpToLine(line); _double->jumpToLine(line); //_merged->jumpToLine(line); } void Diff3Widget::jumpToBlock( int block ) { _single->jumpToBlock(block); _double->jumpToBlock(block); _merged->jumpToBlock(block); // set selection _merged->getText()->setBlockSelection(block); } void Diff3Widget::setActiveDiffBlock( int block ) { DiffInfo& bi = _diffInfo->getInfo(block); _double->setActiveDiff( bi.getDiffNumber() ); _diffInfo->setActiveDiff( bi.getDiffNumber() ); emit diffChanged( bi.getDiffNumber() ); } void Diff3Widget::setActiveDiff( int num ) { _double->setActiveDiff(num); } void Diff3Widget::enableOriginal( bool enable, bool open ) { _splitOrg->enableHandle(enable); _splitOrg->jumpPos(open); } void Diff3Widget::enableMerged( bool enable, bool open ) { _splitMerge->enableHandle(enable); _splitMerge->jumpPos(open); } void Diff3Widget::wheelEvent( QWheelEvent* e ) { if( ! _diffInfo ) { e->ignore(); return; } //printf( "wheel delta: %d (%p)\n", e->delta(), e ); int b = 0; if( e->delta() > 0 ) { // forward -> to screen if( _diffInfo->hasPrevDiff() ) { b = _diffInfo->prevDiff(); } } else { // backward -> to user if( _diffInfo->hasNextDiff() ) { b = _diffInfo->nextDiff(); } } if( b == 0 ) { e->ignore(); return; } jumpToBlock( b ); setActiveDiff( _diffInfo->getActiveDiff() ); emit diffChanged( _diffInfo->getActiveDiff() ); e->accept(); } void Diff3Widget::connectOriginalDrop( const QObject* receiver, const char* member ) { connect( _single->getText(), SIGNAL(fileDropped(const QString&)), receiver, member ); } void Diff3Widget::connectModifiedDrop( const QObject* receiver, const char* member ) { connect( _double->getLeftText(), SIGNAL(fileDropped(const QString&)), receiver, member ); } void Diff3Widget::connectLatestDrop( const QObject* receiver, const char* member ) { connect( _double->getRightText(), SIGNAL(fileDropped(const QString&)), receiver, member ); }