annotate kdiff3/src-QT4/directorymergewindow.cpp @ 95:6f42f5bd218e

- OS2-port by Silvan Scherrer - Fixed writing to KIO. - Fix crash on A/B-overview (infinite recursion)
author joachim99
date Sun, 28 Feb 2010 20:32:34 +0000
parents 4e6ebbbae925
children 9000a9763f6f
rev   line source
joachim99@8 1 /***************************************************************************
joachim99@8 2 directorymergewindow.cpp
joachim99@58 3 -----------------
joachim99@8 4 begin : Sat Oct 19 2002
joachim99@77 5 copyright : (C) 2002-2007 by Joachim Eibl
joachim99@69 6 email : joachim.eibl at gmx.de
joachim99@8 7 ***************************************************************************/
joachim99@8 8
joachim99@8 9 /***************************************************************************
joachim99@8 10 * *
joachim99@8 11 * This program is free software; you can redistribute it and/or modify *
joachim99@8 12 * it under the terms of the GNU General Public License as published by *
joachim99@8 13 * the Free Software Foundation; either version 2 of the License, or *
joachim99@8 14 * (at your option) any later version. *
joachim99@8 15 * *
joachim99@8 16 ***************************************************************************/
joachim99@8 17
joachim99@8 18 #include "directorymergewindow.h"
joachim99@8 19 #include "optiondialog.h"
joachim99@8 20 #include <vector>
joachim99@8 21 #include <map>
joachim99@8 22
joachim99@75 23 #include <QDir>
joachim99@75 24 #include <QApplication>
joachim99@75 25 #include <QPixmap>
joachim99@75 26 #include <QImage>
joachim99@70 27 #include <QTextStream>
joachim99@70 28 #include <QKeyEvent>
joachim99@75 29 #include <QMenu>
joachim99@75 30 #include <QRegExp>
joachim99@75 31 #include <QMessageBox>
joachim99@75 32 #include <QLayout>
joachim99@75 33 #include <QLabel>
joachim99@75 34 #include <QSplitter>
joachim99@75 35 #include <QTextEdit>
joachim99@75 36 #include <QItemDelegate>
joachim99@75 37
joachim99@75 38
joachim99@80 39 #include <kmenu.h>
joachim99@51 40 #include <kaction.h>
joachim99@8 41 #include <kmessagebox.h>
joachim99@69 42 #include <kfiledialog.h>
joachim99@8 43 #include <kiconloader.h>
joachim99@8 44 #include <klocale.h>
joachim99@80 45 #include <ktoggleaction.h>
joachim99@75 46
joachim99@8 47 #include <iostream>
joachim99@8 48 #include <assert.h>
joachim99@73 49 //#include <konq_popupmenu.h>
joachim99@8 50
joachim99@80 51 #include "guiutils.h"
joachim99@80 52
joachim99@51 53 static bool conflictingFileTypes(MergeFileInfos& mfi);
joachim99@80 54
joachim99@75 55 class StatusInfo : public QTextEdit
joachim99@69 56 {
joachim99@69 57 public:
joachim99@75 58 StatusInfo(QWidget* pParent) : QTextEdit( pParent )
joachim99@69 59 {
joachim99@75 60 setObjectName("StatusInfo");
joachim99@70 61 setWindowFlags(Qt::Dialog);
joachim99@75 62 setWordWrapMode(QTextOption::NoWrap);
joachim99@69 63 setReadOnly(true);
joachim99@80 64 setWindowModality( Qt::ApplicationModal );
joachim99@77 65 //showMaximized();
joachim99@69 66 }
joachim99@69 67
joachim99@75 68 bool isEmpty(){
joachim99@75 69 return toPlainText().isEmpty(); }
joachim99@69 70
joachim99@69 71 void addText(const QString& s )
joachim99@69 72 {
joachim99@69 73 append(s);
joachim99@69 74 }
joachim99@69 75
joachim99@80 76 void setVisible(bool bVisible)
joachim99@69 77 {
joachim99@80 78 if (bVisible)
joachim99@80 79 {
joachim99@80 80 moveCursor ( QTextCursor::End );
joachim99@80 81 moveCursor ( QTextCursor::StartOfLine );
joachim99@80 82 ensureCursorVisible();
joachim99@80 83 }
joachim99@80 84
joachim99@80 85 QTextEdit::setVisible(bVisible);
joachim99@69 86 }
joachim99@69 87 };
joachim99@8 88
joachim99@8 89
joachim99@8 90 class TempRemover
joachim99@8 91 {
joachim99@8 92 public:
joachim99@8 93 TempRemover( const QString& origName, FileAccess& fa );
joachim99@8 94 ~TempRemover();
joachim99@8 95 QString name() { return m_name; }
joachim99@8 96 bool success() { return m_bSuccess; }
joachim99@8 97 private:
joachim99@8 98 QString m_name;
joachim99@8 99 bool m_bTemp;
joachim99@8 100 bool m_bSuccess;
joachim99@8 101 };
joachim99@8 102 TempRemover::TempRemover(const QString& origName, FileAccess& fa)
joachim99@8 103 {
joachim99@8 104 if ( fa.isLocal() )
joachim99@8 105 {
joachim99@8 106 m_name = origName;
joachim99@8 107 m_bTemp = false;
joachim99@8 108 m_bSuccess = true;
joachim99@8 109 }
joachim99@8 110 else
joachim99@8 111 {
joachim99@8 112 m_name = FileAccess::tempFileName();
joachim99@8 113 m_bSuccess = fa.copyFile( m_name );
joachim99@8 114 m_bTemp = m_bSuccess;
joachim99@8 115 }
joachim99@8 116 }
joachim99@8 117 TempRemover::~TempRemover()
joachim99@8 118 {
joachim99@8 119 if ( m_bTemp && ! m_name.isEmpty() )
joachim99@73 120 FileAccess::removeTempFile(m_name);
joachim99@8 121 }
joachim99@8 122
joachim99@8 123 void DirectoryMergeWindow::fastFileComparison(
joachim99@8 124 FileAccess& fi1, FileAccess& fi2,
joachim99@8 125 bool& bEqual, bool& bError, QString& status )
joachim99@8 126 {
joachim99@66 127 ProgressProxy pp;
joachim99@8 128 status = "";
joachim99@8 129 bEqual = false;
joachim99@8 130 bError = true;
joachim99@8 131
joachim99@8 132 if ( !m_bFollowFileLinks )
joachim99@8 133 {
joachim99@8 134 if ( fi1.isSymLink() != fi2.isSymLink() )
joachim99@8 135 {
joachim99@51 136 status = i18n("Mix of links and normal files.");
joachim99@8 137 return;
joachim99@8 138 }
joachim99@8 139 else if ( fi1.isSymLink() && fi2.isSymLink() )
joachim99@8 140 {
joachim99@8 141 bError = false;
joachim99@8 142 bEqual = fi1.readLink() == fi2.readLink();
joachim99@51 143 status = i18n("Link: ");
joachim99@8 144 return;
joachim99@8 145 }
joachim99@8 146 }
joachim99@8 147
joachim99@8 148 if ( fi1.size()!=fi2.size() )
joachim99@8 149 {
joachim99@8 150 bEqual = false;
joachim99@51 151 status = i18n("Size. ");
joachim99@51 152 return;
joachim99@51 153 }
joachim99@51 154 else if ( m_pOptions->m_bDmTrustSize )
joachim99@51 155 {
joachim99@51 156 bEqual = true;
joachim99@8 157 return;
joachim99@8 158 }
joachim99@8 159
joachim99@8 160 if ( m_pOptions->m_bDmTrustDate )
joachim99@8 161 {
joachim99@8 162 bEqual = ( fi1.lastModified() == fi2.lastModified() && fi1.size()==fi2.size() );
joachim99@8 163 bError = false;
joachim99@51 164 status = i18n("Date & Size: ");
joachim99@8 165 return;
joachim99@8 166 }
joachim99@8 167
joachim99@77 168 if ( m_pOptions->m_bDmTrustDateFallbackToBinary )
joachim99@77 169 {
joachim99@77 170 bEqual = ( fi1.lastModified() == fi2.lastModified() && fi1.size()==fi2.size() );
joachim99@77 171 if ( bEqual )
joachim99@77 172 {
joachim99@77 173 bError = false;
joachim99@77 174 status = i18n("Date & Size: ");
joachim99@77 175 return;
joachim99@77 176 }
joachim99@77 177 }
joachim99@77 178
joachim99@80 179 QString fileName1 = fi1.absoluteFilePath();
joachim99@80 180 QString fileName2 = fi2.absoluteFilePath();
joachim99@8 181 TempRemover tr1( fileName1, fi1 );
joachim99@8 182 if ( !tr1.success() )
joachim99@8 183 {
joachim99@80 184 status = i18n("Creating temp copy of %1 failed.",fileName1);
joachim99@8 185 return;
joachim99@8 186 }
joachim99@8 187 TempRemover tr2( fileName2, fi2 );
joachim99@8 188 if ( !tr2.success() )
joachim99@8 189 {
joachim99@80 190 status = i18n("Creating temp copy of %1 failed.",fileName2);
joachim99@8 191 return;
joachim99@8 192 }
joachim99@8 193
joachim99@8 194 std::vector<char> buf1(100000);
joachim99@8 195 std::vector<char> buf2(buf1.size());
joachim99@8 196
joachim99@8 197 QFile file1( tr1.name() );
joachim99@8 198
joachim99@70 199 if ( ! file1.open(QIODevice::ReadOnly) )
joachim99@8 200 {
joachim99@80 201 status = i18n("Opening %1 failed.",fileName1);
joachim99@8 202 return;
joachim99@8 203 }
joachim99@8 204
joachim99@8 205 QFile file2( tr2.name() );
joachim99@8 206
joachim99@70 207 if ( ! file2.open(QIODevice::ReadOnly) )
joachim99@8 208 {
joachim99@80 209 status = i18n("Opening %1 failed.",fileName2);
joachim99@8 210 return;
joachim99@8 211 }
joachim99@8 212
joachim99@68 213 pp.setInformation( i18n("Comparing file..."), 0, false );
joachim99@75 214 typedef qint64 t_FileSize;
joachim99@66 215 t_FileSize fullSize = file1.size();
joachim99@66 216 t_FileSize sizeLeft = fullSize;
joachim99@8 217
joachim99@66 218 while( sizeLeft>0 && ! pp.wasCancelled() )
joachim99@8 219 {
joachim99@66 220 int len = min2( sizeLeft, (t_FileSize)buf1.size() );
joachim99@75 221 if( len != file1.read( &buf1[0], len ) )
joachim99@8 222 {
joachim99@80 223 status = i18n("Error reading from %1",fileName1);
joachim99@8 224 return;
joachim99@8 225 }
joachim99@8 226
joachim99@75 227 if( len != file2.read( &buf2[0], len ) )
joachim99@8 228 {
joachim99@80 229 status = i18n("Error reading from %1",fileName2);
joachim99@8 230 return;
joachim99@8 231 }
joachim99@8 232
joachim99@8 233 if ( memcmp( &buf1[0], &buf2[0], len ) != 0 )
joachim99@8 234 {
joachim99@8 235 bError = false;
joachim99@8 236 return;
joachim99@8 237 }
joachim99@66 238 sizeLeft-=len;
joachim99@66 239 pp.setCurrent(double(fullSize-sizeLeft)/fullSize, false );
joachim99@8 240 }
joachim99@8 241
joachim99@8 242 // If the program really arrives here, then the files are really equal.
joachim99@8 243 bError = false;
joachim99@8 244 bEqual = true;
joachim99@8 245 }
joachim99@8 246
joachim99@75 247 static int s_NameCol = 0;
joachim99@8 248 static int s_ACol = 1;
joachim99@8 249 static int s_BCol = 2;
joachim99@8 250 static int s_CCol = 3;
joachim99@8 251 static int s_OpCol = 4;
joachim99@8 252 static int s_OpStatusCol = 5;
joachim99@66 253 static int s_UnsolvedCol = 6; // Nr of unsolved conflicts (for 3 input files)
joachim99@66 254 static int s_SolvedCol = 7; // Nr of auto-solvable conflicts (for 3 input files)
joachim99@66 255 static int s_NonWhiteCol = 8; // Nr of nonwhite deltas (for 2 input files)
joachim99@66 256 static int s_WhiteCol = 9; // Nr of white deltas (for 2 input files)
joachim99@75 257
joachim99@75 258 // Previously Q3ListViewItem::paintCell(p,cg,column,width,align);
joachim99@75 259 class DirectoryMergeWindow::DirMergeItemDelegate : public QItemDelegate
joachim99@75 260 {
joachim99@75 261 DirectoryMergeWindow* m_pDMW;
joachim99@75 262 public:
joachim99@75 263 DirMergeItemDelegate(DirectoryMergeWindow* pParent)
joachim99@75 264 : QItemDelegate(pParent), m_pDMW(pParent)
joachim99@75 265 {
joachim99@75 266 }
joachim99@75 267 void paint( QPainter * p, const QStyleOptionViewItem & option, const QModelIndex & index ) const
joachim99@75 268 {
joachim99@75 269 int column = index.column();
joachim99@75 270 if (column == s_ACol || column == s_BCol || column == s_CCol )
joachim99@75 271 {
joachim99@75 272 QVariant value = index.data( Qt::DecorationRole );
joachim99@75 273 QPixmap icon;
joachim99@75 274 if ( value.isValid() )
joachim99@75 275 {
joachim99@75 276 if (value.type() == QVariant::Icon)
joachim99@75 277 {
joachim99@75 278 icon = qvariant_cast<QIcon>(value).pixmap(16,16);
joachim99@75 279 //icon = qvariant_cast<QIcon>(value);
joachim99@75 280 //decorationRect = QRect(QPoint(0, 0), icon.actualSize(option.decorationSize, iconMode, iconState));
joachim99@75 281 }
joachim99@75 282 else
joachim99@75 283 {
joachim99@75 284 icon = qvariant_cast<QPixmap>(value);
joachim99@75 285 //decorationRect = QRect(QPoint(0, 0), option.decorationSize).intersected(pixmap.rect());
joachim99@75 286 }
joachim99@75 287 }
joachim99@75 288
joachim99@75 289 int x = option.rect.left();
joachim99@75 290 int y = option.rect.top();
joachim99@75 291 //QPixmap icon = value.value<QPixmap>(); //pixmap(column);
joachim99@75 292 if ( !icon.isNull() )
joachim99@75 293 {
joachim99@75 294 int yOffset = (sizeHint(option,index).height() - icon.height()) / 2;
joachim99@75 295 p->drawPixmap( x+2, y+yOffset, icon );
joachim99@75 296
joachim99@75 297 QTreeWidgetItem* pTWI = reinterpret_cast<QTreeWidgetItem*>( index.internalPointer() );
joachim99@75 298 DirMergeItem* pDMI = static_cast<DirMergeItem*>(pTWI);
joachim99@75 299 int i = pDMI==m_pDMW->m_pSelection1Item && column == m_pDMW->m_selection1Column ? 1 :
joachim99@75 300 pDMI==m_pDMW->m_pSelection2Item && column == m_pDMW->m_selection2Column ? 2 :
joachim99@75 301 pDMI==m_pDMW->m_pSelection3Item && column == m_pDMW->m_selection3Column ? 3 :
joachim99@75 302 0;
joachim99@75 303 if ( i!=0 )
joachim99@75 304 {
joachim99@75 305 OptionDialog* pOD = m_pDMW->m_pOptions;
joachim99@75 306 QColor c ( i==1 ? pOD->m_colorA : i==2 ? pOD->m_colorB : pOD->m_colorC );
joachim99@75 307 p->setPen( c );// highlight() );
joachim99@75 308 p->drawRect( x+2, y+yOffset, icon.width(), icon.height());
joachim99@75 309 p->setPen( QPen( c, 0, Qt::DotLine) );
joachim99@75 310 p->drawRect( x+1, y+yOffset-1, icon.width()+2, icon.height()+2);
joachim99@75 311 p->setPen( Qt::white );
joachim99@75 312 QString s( QChar('A'+i-1) );
joachim99@75 313 p->drawText( x+2 + (icon.width() - p->fontMetrics().width(s))/2,
joachim99@75 314 y+yOffset + (icon.height() + p->fontMetrics().ascent())/2-1,
joachim99@75 315 s );
joachim99@75 316 }
joachim99@75 317 else
joachim99@75 318 {
joachim99@75 319 p->setPen( m_pDMW->palette().background().color() );
joachim99@75 320 p->drawRect( x+1, y+yOffset-1, icon.width()+2, icon.height()+2);
joachim99@75 321 }
joachim99@75 322 return;
joachim99@75 323 }
joachim99@75 324 }
joachim99@75 325 QStyleOptionViewItem option2 = option;
joachim99@75 326 if ( column>=s_UnsolvedCol )
joachim99@75 327 {
joachim99@75 328 option2.displayAlignment = Qt::AlignRight;
joachim99@75 329 }
joachim99@75 330 QItemDelegate::paint( p, option2, index );
joachim99@75 331 }
joachim99@75 332 };
joachim99@75 333
joachim99@75 334
joachim99@8 335 DirectoryMergeWindow::DirectoryMergeWindow( QWidget* pParent, OptionDialog* pOptions, KIconLoader* pIconLoader )
joachim99@75 336 : QTreeWidget( pParent )
joachim99@8 337 {
joachim99@75 338 setItemDelegate( new DirMergeItemDelegate(this) );
joachim99@75 339 connect( this, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), this, SLOT(onDoubleClick(QTreeWidgetItem*)));
joachim99@75 340 connect( this, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(onCurrentChanged(QTreeWidgetItem*)));
joachim99@75 341 connect( this, SIGNAL(expanded(const QModelIndex&)), this, SLOT(onExpanded()));
joachim99@8 342 m_pOptions = pOptions;
joachim99@8 343 m_pIconLoader = pIconLoader;
joachim99@8 344 m_pDirectoryMergeInfo = 0;
joachim99@8 345 m_bSimulatedMergeStarted=false;
joachim99@8 346 m_bRealMergeStarted=false;
joachim99@8 347 m_bError = false;
joachim99@8 348 m_bSyncMode = false;
joachim99@8 349 m_pStatusInfo = new StatusInfo(0);
joachim99@8 350 m_pStatusInfo->hide();
joachim99@66 351 m_bScanning = false;
joachim99@69 352 m_pSelection1Item = 0;
joachim99@69 353 m_pSelection2Item = 0;
joachim99@69 354 m_pSelection3Item = 0;
joachim99@69 355 m_bCaseSensitive = true;
joachim99@68 356
joachim99@75 357 QStringList sl;
joachim99@75 358 sl << i18n("Name") << "A" << "B" << "C" << i18n("Operation") << i18n("Status")
joachim99@75 359 << i18n("Unsolved") << i18n("Solved") << i18n("Nonwhite") << i18n("White") << "";
joachim99@75 360 setHeaderLabels(sl);
joachim99@75 361
joachim99@75 362 //TODO setColumnAlignment( s_UnsolvedCol, Qt::AlignRight );
joachim99@75 363 //setColumnAlignment( s_SolvedCol, Qt::AlignRight );
joachim99@75 364 //setColumnAlignment( s_NonWhiteCol, Qt::AlignRight );
joachim99@75 365 //setColumnAlignment( s_WhiteCol, Qt::AlignRight );
joachim99@8 366 }
joachim99@8 367
joachim99@8 368 DirectoryMergeWindow::~DirectoryMergeWindow()
joachim99@8 369 {
joachim99@8 370 }
joachim99@8 371
joachim99@8 372
joachim99@8 373 int DirectoryMergeWindow::totalColumnWidth()
joachim99@8 374 {
joachim99@8 375 int w=0;
joachim99@8 376 for (int i=0; i<s_OpStatusCol; ++i)
joachim99@8 377 {
joachim99@8 378 w += columnWidth(i);
joachim99@8 379 }
joachim99@8 380 return w;
joachim99@8 381 }
joachim99@8 382
joachim99@8 383 void DirectoryMergeWindow::reload()
joachim99@8 384 {
joachim99@8 385 if ( isDirectoryMergeInProgress() )
joachim99@8 386 {
joachim99@8 387 int result = KMessageBox::warningYesNo(this,
joachim99@8 388 i18n("You are currently doing a directory merge. Are you sure, you want to abort the merge and rescan the directory?"),
joachim99@80 389 i18n("Warning"),
joachim99@80 390 KGuiItem( i18n("Rescan") ),
joachim99@80 391 KGuiItem( i18n("Continue Merging") ) );
joachim99@8 392 if ( result!=KMessageBox::Yes )
joachim99@8 393 return;
joachim99@8 394 }
joachim99@68 395
joachim99@77 396 init( m_dirA, m_dirB, m_dirC, m_dirDest, m_bDirectoryMerge, true );
joachim99@8 397 }
joachim99@8 398
joachim99@8 399 // Copy pm2 onto pm1, but preserve the alpha value from pm1 where pm2 is transparent.
joachim99@69 400 static QPixmap pixCombiner( const QPixmap* pm1, const QPixmap* pm2 )
joachim99@8 401 {
joachim99@75 402 QImage img1 = pm1->toImage().convertToFormat(QImage::Format_ARGB32);
joachim99@75 403 QImage img2 = pm2->toImage().convertToFormat(QImage::Format_ARGB32);
joachim99@8 404
joachim99@8 405 for (int y = 0; y < img1.height(); y++)
joachim99@8 406 {
joachim99@75 407 quint32 *line1 = reinterpret_cast<quint32 *>(img1.scanLine(y));
joachim99@75 408 quint32 *line2 = reinterpret_cast<quint32 *>(img2.scanLine(y));
joachim99@8 409 for (int x = 0; x < img1.width(); x++)
joachim99@8 410 {
joachim99@8 411 if ( qAlpha( line2[x] ) >0 )
joachim99@8 412 line1[x] = (line2[x] | 0xff000000);
joachim99@8 413 }
joachim99@8 414 }
joachim99@75 415 return QPixmap::fromImage(img1);
joachim99@8 416 }
joachim99@8 417
joachim99@8 418 // like pixCombiner but let the pm1 color shine through
joachim99@69 419 static QPixmap pixCombiner2( const QPixmap* pm1, const QPixmap* pm2 )
joachim99@8 420 {
joachim99@75 421 QPixmap pix=*pm1;
joachim99@75 422 QPainter p(&pix);
joachim99@75 423 p.setOpacity(0.5);
joachim99@75 424 p.drawPixmap( 0,0,*pm2 );
joachim99@75 425 p.end();
joachim99@75 426
joachim99@8 427 return pix;
joachim99@8 428 }
joachim99@8 429
joachim99@8 430 static void calcDirStatus( bool bThreeDirs, DirMergeItem* i, int& nofFiles,
joachim99@8 431 int& nofDirs, int& nofEqualFiles, int& nofManualMerges )
joachim99@8 432 {
joachim99@8 433 if ( i->m_pMFI->m_bDirA || i->m_pMFI->m_bDirB || i->m_pMFI->m_bDirC )
joachim99@8 434 {
joachim99@8 435 ++nofDirs;
joachim99@8 436 }
joachim99@8 437 else
joachim99@8 438 {
joachim99@8 439 ++nofFiles;
joachim99@8 440 if ( i->m_pMFI->m_bEqualAB && (!bThreeDirs || i->m_pMFI->m_bEqualAC ))
joachim99@8 441 {
joachim99@8 442 ++nofEqualFiles;
joachim99@8 443 }
joachim99@8 444 else
joachim99@8 445 {
joachim99@8 446 if ( i->m_pMFI->m_eMergeOperation==eMergeABCToDest || i->m_pMFI->m_eMergeOperation==eMergeABToDest )
joachim99@8 447 ++nofManualMerges;
joachim99@8 448 }
joachim99@8 449 }
joachim99@75 450 for( int childIdx=0; childIdx<i->childCount(); ++childIdx )
joachim99@75 451 calcDirStatus( bThreeDirs, static_cast<DirMergeItem*>(i->child(childIdx)), nofFiles, nofDirs, nofEqualFiles, nofManualMerges );
joachim99@8 452 }
joachim99@8 453
joachim99@69 454 static QString sortString(const QString& s, bool bCaseSensitive)
joachim99@58 455 {
joachim99@69 456 if (bCaseSensitive)
joachim99@69 457 return s;
joachim99@69 458 else
joachim99@75 459 return s.toUpper();
joachim99@58 460 }
joachim99@58 461
joachim99@77 462 struct t_ItemInfo
joachim99@77 463 {
joachim99@77 464 bool bExpanded;
joachim99@77 465 bool bOperationComplete;
joachim99@77 466 QString status;
joachim99@77 467 e_MergeOperation eMergeOperation;
joachim99@77 468 };
joachim99@77 469
joachim99@8 470 bool DirectoryMergeWindow::init
joachim99@8 471 (
joachim99@8 472 FileAccess& dirA,
joachim99@8 473 FileAccess& dirB,
joachim99@8 474 FileAccess& dirC,
joachim99@8 475 FileAccess& dirDest,
joachim99@77 476 bool bDirectoryMerge,
joachim99@77 477 bool bReload
joachim99@8 478 )
joachim99@8 479 {
joachim99@66 480 if ( m_pOptions->m_bDmFullAnalysis )
joachim99@66 481 {
joachim99@68 482 // A full analysis uses the same ressources that a normal text-diff/merge uses.
joachim99@66 483 // So make sure that the user saves his data first.
joachim99@66 484 bool bCanContinue=false;
joachim99@66 485 checkIfCanContinue( &bCanContinue );
joachim99@66 486 if ( !bCanContinue )
joachim99@66 487 return false;
joachim99@68 488 startDiffMerge("","","","","","","",0); // hide main window
joachim99@66 489 }
joachim99@68 490
joachim99@66 491 show();
joachim99@80 492 setUpdatesEnabled(true);
joachim99@66 493
joachim99@77 494 std::map<QString,t_ItemInfo> expandedDirsMap;
joachim99@77 495
joachim99@77 496 if ( bReload )
joachim99@77 497 {
joachim99@77 498 // Remember expandes items
joachim99@77 499 QTreeWidgetItemIterator it( this );
joachim99@77 500 while ( *it )
joachim99@77 501 {
joachim99@77 502 DirMergeItem* pDMI = static_cast<DirMergeItem*>( *it );
joachim99@77 503 t_ItemInfo& ii = expandedDirsMap[ pDMI->m_pMFI->m_subPath ];
joachim99@77 504 ii.bExpanded = pDMI->isExpanded();
joachim99@77 505 ii.bOperationComplete = pDMI->m_pMFI->m_bOperationComplete;
joachim99@77 506 ii.status = pDMI->text( s_OpStatusCol );
joachim99@77 507 ii.eMergeOperation = pDMI->m_pMFI->m_eMergeOperation;
joachim99@77 508 ++it;
joachim99@77 509 }
joachim99@77 510 }
joachim99@77 511
joachim99@66 512 ProgressProxy pp;
joachim99@8 513 m_bFollowDirLinks = m_pOptions->m_bDmFollowDirLinks;
joachim99@8 514 m_bFollowFileLinks = m_pOptions->m_bDmFollowFileLinks;
joachim99@8 515 m_bSimulatedMergeStarted=false;
joachim99@8 516 m_bRealMergeStarted=false;
joachim99@8 517 m_bError=false;
joachim99@8 518 m_bDirectoryMerge = bDirectoryMerge;
joachim99@69 519 m_pSelection1Item = 0;
joachim99@69 520 m_pSelection2Item = 0;
joachim99@69 521 m_pSelection3Item = 0;
joachim99@69 522 m_bCaseSensitive = m_pOptions->m_bDmCaseSensitiveFilenameComparison;
joachim99@8 523
joachim99@8 524 clear();
joachim99@8 525
joachim99@53 526 m_mergeItemList.clear();
joachim99@51 527 m_currentItemForOperation = m_mergeItemList.end();
joachim99@8 528
joachim99@8 529 m_dirA = dirA;
joachim99@8 530 m_dirB = dirB;
joachim99@8 531 m_dirC = dirC;
joachim99@8 532 m_dirDest = dirDest;
joachim99@8 533
joachim99@77 534 if ( !bReload )
joachim99@77 535 {
joachim99@77 536 m_pDirShowIdenticalFiles->setChecked(true);
joachim99@77 537 m_pDirShowDifferentFiles->setChecked(true);
joachim99@77 538 m_pDirShowFilesOnlyInA->setChecked(true);
joachim99@77 539 m_pDirShowFilesOnlyInB->setChecked(true);
joachim99@77 540 m_pDirShowFilesOnlyInC->setChecked(true);
joachim99@77 541 }
joachim99@69 542
joachim99@8 543 // Check if all input directories exist and are valid. The dest dir is not tested now.
joachim99@8 544 // The test will happen only when we are going to write to it.
joachim99@8 545 if ( !m_dirA.isDir() || !m_dirB.isDir() ||
joachim99@8 546 (m_dirC.isValid() && !m_dirC.isDir()) )
joachim99@8 547 {
joachim99@8 548 QString text( i18n("Opening of directories failed:") );
joachim99@8 549 text += "\n\n";
joachim99@8 550 if ( !dirA.isDir() )
joachim99@80 551 { text += i18n("Dir A \"%1\" does not exist or is not a directory.\n",m_dirA.prettyAbsPath()); }
joachim99@8 552
joachim99@8 553 if ( !dirB.isDir() )
joachim99@80 554 { text += i18n("Dir B \"%1\" does not exist or is not a directory.\n",m_dirB.prettyAbsPath()); }
joachim99@8 555
joachim99@8 556 if ( m_dirC.isValid() && !m_dirC.isDir() )
joachim99@80 557 { text += i18n("Dir C \"%1\" does not exist or is not a directory.\n",m_dirC.prettyAbsPath()); }
joachim99@8 558
joachim99@51 559 KMessageBox::sorry( this, text, i18n("Directory Open Error") );
joachim99@8 560 return false;
joachim99@8 561 }
joachim99@8 562
joachim99@8 563 if ( m_dirC.isValid() &&
joachim99@8 564 (m_dirDest.prettyAbsPath() == m_dirA.prettyAbsPath() || m_dirDest.prettyAbsPath()==m_dirB.prettyAbsPath() ) )
joachim99@8 565 {
joachim99@8 566 KMessageBox::error(this,
joachim99@53 567 i18n( "The destination directory must not be the same as A or B when "
joachim99@8 568 "three directories are merged.\nCheck again before continuing."),
joachim99@51 569 i18n("Parameter Warning"));
joachim99@8 570 return false;
joachim99@8 571 }
joachim99@68 572
joachim99@66 573 m_bScanning = true;
joachim99@68 574 statusBarMessage(i18n("Scanning directories..."));
joachim99@8 575
joachim99@8 576 m_bSyncMode = m_pOptions->m_bDmSyncMode && !m_dirC.isValid() && !m_dirDest.isValid();
joachim99@8 577
joachim99@8 578 if ( m_dirDest.isValid() )
joachim99@8 579 m_dirDestInternal = m_dirDest;
joachim99@8 580 else
joachim99@8 581 m_dirDestInternal = m_dirC.isValid() ? m_dirC : m_dirB;
joachim99@8 582
joachim99@75 583 QString origCurrentDirectory = QDir::currentPath();
joachim99@8 584
joachim99@8 585 m_fileMergeMap.clear();
joachim99@8 586 t_DirectoryList::iterator i;
joachim99@8 587
joachim99@8 588 // calc how many directories will be read:
joachim99@8 589 double nofScans = ( m_dirA.isValid() ? 1 : 0 )+( m_dirB.isValid() ? 1 : 0 )+( m_dirC.isValid() ? 1 : 0 );
joachim99@8 590 int currentScan = 0;
joachim99@8 591
joachim99@75 592 //TODO setColumnWidthMode(s_UnsolvedCol, Q3ListView::Manual);
joachim99@75 593 // setColumnWidthMode(s_SolvedCol, Q3ListView::Manual);
joachim99@75 594 // setColumnWidthMode(s_WhiteCol, Q3ListView::Manual);
joachim99@75 595 // setColumnWidthMode(s_NonWhiteCol, Q3ListView::Manual);
joachim99@75 596 setColumnHidden( s_CCol, !m_dirC.isValid() );
joachim99@75 597 setColumnHidden( s_WhiteCol, !m_pOptions->m_bDmFullAnalysis );
joachim99@75 598 setColumnHidden( s_NonWhiteCol, !m_pOptions->m_bDmFullAnalysis );
joachim99@75 599 setColumnHidden( s_UnsolvedCol, !m_pOptions->m_bDmFullAnalysis );
joachim99@75 600 setColumnHidden( s_SolvedCol, !( m_pOptions->m_bDmFullAnalysis && m_dirC.isValid() ) );
joachim99@68 601
joachim99@8 602 bool bListDirSuccessA = true;
joachim99@8 603 bool bListDirSuccessB = true;
joachim99@8 604 bool bListDirSuccessC = true;
joachim99@8 605 if ( m_dirA.isValid() )
joachim99@8 606 {
joachim99@66 607 pp.setInformation(i18n("Reading Directory A"));
joachim99@66 608 pp.setSubRangeTransformation(currentScan/nofScans, (currentScan+1)/nofScans);
joachim99@8 609 ++currentScan;
joachim99@8 610
joachim99@8 611 t_DirectoryList dirListA;
joachim99@8 612 bListDirSuccessA = m_dirA.listDir( &dirListA,
joachim99@8 613 m_pOptions->m_bDmRecursiveDirs, m_pOptions->m_bDmFindHidden,
joachim99@8 614 m_pOptions->m_DmFilePattern, m_pOptions->m_DmFileAntiPattern,
joachim99@8 615 m_pOptions->m_DmDirAntiPattern, m_pOptions->m_bDmFollowDirLinks,
joachim99@8 616 m_pOptions->m_bDmUseCvsIgnore);
joachim99@8 617
joachim99@8 618 for (i=dirListA.begin(); i!=dirListA.end();++i )
joachim99@8 619 {
joachim99@69 620 MergeFileInfos& mfi = m_fileMergeMap[sortString(i->filePath(), m_bCaseSensitive)];
joachim99@8 621 //std::cout <<i->filePath()<<std::endl;
joachim99@8 622 mfi.m_bExistsInA = true;
joachim99@8 623 mfi.m_fileInfoA = *i;
joachim99@8 624 }
joachim99@8 625 }
joachim99@8 626
joachim99@8 627 if ( m_dirB.isValid() )
joachim99@8 628 {
joachim99@66 629 pp.setInformation(i18n("Reading Directory B"));
joachim99@66 630 pp.setSubRangeTransformation(currentScan/nofScans, (currentScan+1)/nofScans);
joachim99@8 631 ++currentScan;
joachim99@8 632
joachim99@8 633 t_DirectoryList dirListB;
joachim99@8 634 bListDirSuccessB = m_dirB.listDir( &dirListB,
joachim99@8 635 m_pOptions->m_bDmRecursiveDirs, m_pOptions->m_bDmFindHidden,
joachim99@8 636 m_pOptions->m_DmFilePattern, m_pOptions->m_DmFileAntiPattern,
joachim99@8 637 m_pOptions->m_DmDirAntiPattern, m_pOptions->m_bDmFollowDirLinks,
joachim99@8 638 m_pOptions->m_bDmUseCvsIgnore);
joachim99@8 639
joachim99@8 640 for (i=dirListB.begin(); i!=dirListB.end();++i )
joachim99@8 641 {
joachim99@69 642 MergeFileInfos& mfi = m_fileMergeMap[sortString(i->filePath(), m_bCaseSensitive)];
joachim99@8 643 mfi.m_bExistsInB = true;
joachim99@8 644 mfi.m_fileInfoB = *i;
joachim99@8 645 }
joachim99@8 646 }
joachim99@8 647
joachim99@8 648 e_MergeOperation eDefaultMergeOp;
joachim99@8 649 if ( m_dirC.isValid() )
joachim99@8 650 {
joachim99@66 651 pp.setInformation(i18n("Reading Directory C"));
joachim99@66 652 pp.setSubRangeTransformation(currentScan/nofScans, (currentScan+1)/nofScans);
joachim99@8 653 ++currentScan;
joachim99@8 654
joachim99@8 655 t_DirectoryList dirListC;
joachim99@8 656 bListDirSuccessC = m_dirC.listDir( &dirListC,
joachim99@8 657 m_pOptions->m_bDmRecursiveDirs, m_pOptions->m_bDmFindHidden,
joachim99@8 658 m_pOptions->m_DmFilePattern, m_pOptions->m_DmFileAntiPattern,
joachim99@8 659 m_pOptions->m_DmDirAntiPattern, m_pOptions->m_bDmFollowDirLinks,
joachim99@8 660 m_pOptions->m_bDmUseCvsIgnore);
joachim99@8 661
joachim99@8 662 for (i=dirListC.begin(); i!=dirListC.end();++i )
joachim99@8 663 {
joachim99@69 664 MergeFileInfos& mfi = m_fileMergeMap[sortString(i->filePath(),m_bCaseSensitive)];
joachim99@8 665 mfi.m_bExistsInC = true;
joachim99@8 666 mfi.m_fileInfoC = *i;
joachim99@8 667 }
joachim99@8 668
joachim99@8 669 eDefaultMergeOp = eMergeABCToDest;
joachim99@8 670 }
joachim99@8 671 else
joachim99@8 672 eDefaultMergeOp = m_bSyncMode ? eMergeToAB : eMergeABToDest;
joachim99@8 673
joachim99@8 674 bool bContinue = true;
joachim99@8 675 if ( !bListDirSuccessA || !bListDirSuccessB || !bListDirSuccessC )
joachim99@8 676 {
joachim99@8 677 QString s = i18n("Some subdirectories were not readable in");
joachim99@8 678 if ( !bListDirSuccessA ) s += "\nA: " + m_dirA.prettyAbsPath();
joachim99@8 679 if ( !bListDirSuccessB ) s += "\nB: " + m_dirB.prettyAbsPath();
joachim99@8 680 if ( !bListDirSuccessC ) s += "\nC: " + m_dirC.prettyAbsPath();
joachim99@8 681 s+="\n";
joachim99@8 682 s+= i18n("Check the permissions of the subdirectories.");
joachim99@8 683 bContinue = KMessageBox::Continue == KMessageBox::warningContinueCancel( this, s );
joachim99@8 684 }
joachim99@8 685
joachim99@8 686 if ( bContinue )
joachim99@8 687 {
joachim99@66 688 prepareListView(pp);
joachim99@8 689
joachim99@92 690 updateFileVisibilities();
joachim99@92 691
joachim99@92 692 for( int childIdx = 0; childIdx<topLevelItemCount(); ++childIdx )
joachim99@8 693 {
joachim99@75 694 DirMergeItem* pDMI = static_cast<DirMergeItem*>( topLevelItem(childIdx) );
joachim99@8 695 calcSuggestedOperation( *pDMI->m_pMFI, eDefaultMergeOp );
joachim99@8 696 }
joachim99@8 697 }
joachim99@92 698
joachim99@92 699 sortItems(0,Qt::AscendingOrder);
joachim99@75 700
joachim99@75 701 for (int i=0;i<columnCount();++i)
joachim99@75 702 resizeColumnToContents(i);
joachim99@8 703
joachim99@8 704 // Try to improve the view a little bit.
joachim99@8 705 QWidget* pParent = parentWidget();
joachim99@8 706 QSplitter* pSplitter = static_cast<QSplitter*>(pParent);
joachim99@8 707 if (pSplitter!=0)
joachim99@8 708 {
joachim99@75 709 QList<int> sizes = pSplitter->sizes();
joachim99@8 710 int total = sizes[0] + sizes[1];
joachim99@92 711 if ( total < 10 )
joachim99@92 712 total = 100;
joachim99@8 713 sizes[0]=total*6/10;
joachim99@8 714 sizes[1]=total - sizes[0];
joachim99@8 715 pSplitter->setSizes( sizes );
joachim99@8 716 }
joachim99@68 717
joachim99@92 718 QDir::setCurrent(origCurrentDirectory);
joachim99@75 719
joachim99@66 720 m_bScanning = false;
joachim99@66 721 statusBarMessage(i18n("Ready."));
joachim99@8 722
joachim99@8 723 if ( bContinue )
joachim99@8 724 {
joachim99@8 725 // Generate a status report
joachim99@8 726 int nofFiles=0;
joachim99@8 727 int nofDirs=0;
joachim99@8 728 int nofEqualFiles=0;
joachim99@8 729 int nofManualMerges=0;
joachim99@75 730 for( int childIdx = 0; childIdx<topLevelItemCount(); ++childIdx )
joachim99@75 731 calcDirStatus( m_dirC.isValid(), static_cast<DirMergeItem*>(topLevelItem(childIdx)),
joachim99@8 732 nofFiles, nofDirs, nofEqualFiles, nofManualMerges );
joachim99@8 733
joachim99@8 734 QString s;
joachim99@51 735 s = i18n("Directory Comparison Status") + "\n\n" +
joachim99@8 736 i18n("Number of subdirectories:") +" "+ QString::number(nofDirs) + "\n"+
joachim99@8 737 i18n("Number of equal files:") +" "+ QString::number(nofEqualFiles) + "\n"+
joachim99@8 738 i18n("Number of different files:") +" "+ QString::number(nofFiles-nofEqualFiles);
joachim99@8 739
joachim99@8 740 if ( m_dirC.isValid() )
joachim99@8 741 s += "\n" + i18n("Number of manual merges:") +" "+ QString::number(nofManualMerges);
joachim99@8 742 KMessageBox::information( this, s );
joachim99@75 743 if ( topLevelItemCount()>0 )
joachim99@75 744 topLevelItem(0)->setSelected(true);
joachim99@8 745 }
joachim99@68 746
joachim99@77 747 if ( bReload )
joachim99@77 748 {
joachim99@92 749 // Remember expanded items
joachim99@77 750 QTreeWidgetItemIterator it( this );
joachim99@77 751 while ( *it )
joachim99@77 752 {
joachim99@77 753 DirMergeItem* pDMI = static_cast<DirMergeItem*>( *it );
joachim99@77 754 std::map<QString,t_ItemInfo>::iterator i = expandedDirsMap.find( pDMI->m_pMFI->m_subPath );
joachim99@77 755 if ( i!=expandedDirsMap.end() )
joachim99@77 756 {
joachim99@77 757 t_ItemInfo& ii = i->second;
joachim99@77 758 pDMI->setExpanded( ii.bExpanded );
joachim99@92 759 //pDMI->m_pMFI->setMergeOperation( ii.eMergeOperation, false ); unsafe, might have changed
joachim99@77 760 pDMI->m_pMFI->m_bOperationComplete = ii.bOperationComplete;
joachim99@77 761 pDMI->setText( s_OpStatusCol, ii.status );
joachim99@77 762 }
joachim99@77 763 ++it;
joachim99@77 764 }
joachim99@77 765 }
joachim99@8 766 return true;
joachim99@8 767 }
joachim99@8 768
joachim99@75 769 void DirectoryMergeWindow::onExpanded()
joachim99@75 770 {
joachim99@75 771 resizeColumnToContents(s_NameCol);
joachim99@75 772 }
joachim99@8 773
joachim99@8 774
joachim99@8 775 void DirectoryMergeWindow::slotChooseAEverywhere(){ setAllMergeOperations( eCopyAToDest ); }
joachim99@8 776
joachim99@8 777 void DirectoryMergeWindow::slotChooseBEverywhere(){ setAllMergeOperations( eCopyBToDest ); }
joachim99@8 778
joachim99@8 779 void DirectoryMergeWindow::slotChooseCEverywhere(){ setAllMergeOperations( eCopyCToDest ); }
joachim99@8 780
joachim99@8 781 void DirectoryMergeWindow::slotAutoChooseEverywhere()
joachim99@8 782 {
joachim99@8 783 e_MergeOperation eDefaultMergeOp = m_dirC.isValid() ? eMergeABCToDest :
joachim99@8 784 m_bSyncMode ? eMergeToAB : eMergeABToDest;
joachim99@8 785 setAllMergeOperations(eDefaultMergeOp );
joachim99@8 786 }
joachim99@8 787
joachim99@8 788 void DirectoryMergeWindow::slotNoOpEverywhere(){ setAllMergeOperations(eNoOperation); }
joachim99@8 789
joachim99@75 790 static void setListViewItemOpen( QTreeWidgetItem* p, bool bOpen )
joachim99@8 791 {
joachim99@75 792 if ( p->childCount() > 0 )
joachim99@75 793 {
joachim99@75 794 for( int childIdx=0; childIdx<p->childCount(); ++childIdx )
joachim99@75 795 setListViewItemOpen( p->child(childIdx), bOpen );
joachim99@75 796
joachim99@75 797 p->setExpanded( bOpen );
joachim99@75 798 }
joachim99@8 799 }
joachim99@8 800
joachim99@8 801 void DirectoryMergeWindow::slotFoldAllSubdirs()
joachim99@8 802 {
joachim99@75 803 for( int i=0; i<topLevelItemCount(); ++i )
joachim99@75 804 setListViewItemOpen( topLevelItem(i), false );
joachim99@8 805 }
joachim99@8 806
joachim99@8 807 void DirectoryMergeWindow::slotUnfoldAllSubdirs()
joachim99@8 808 {
joachim99@75 809 for( int i=0; i<topLevelItemCount(); ++i )
joachim99@75 810 setListViewItemOpen( topLevelItem(i), true );
joachim99@8 811 }
joachim99@8 812
joachim99@75 813 static void setMergeOperation( QTreeWidgetItem* pLVI, e_MergeOperation eMergeOp )
joachim99@51 814 {
joachim99@51 815 if ( pLVI==0 ) return;
joachim99@51 816
joachim99@51 817 DirMergeItem* pDMI = static_cast<DirMergeItem*>(pLVI);
joachim99@51 818 MergeFileInfos& mfi = *pDMI->m_pMFI;
joachim99@51 819
joachim99@51 820 mfi.setMergeOperation(eMergeOp );
joachim99@51 821 }
joachim99@51 822
joachim99@51 823 // Merge current item (merge mode)
joachim99@51 824 void DirectoryMergeWindow::slotCurrentDoNothing() { setMergeOperation(currentItem(), eNoOperation ); }
joachim99@53 825 void DirectoryMergeWindow::slotCurrentChooseA() { setMergeOperation(currentItem(), m_bSyncMode ? eCopyAToB : eCopyAToDest ); }
joachim99@53 826 void DirectoryMergeWindow::slotCurrentChooseB() { setMergeOperation(currentItem(), m_bSyncMode ? eCopyBToA : eCopyBToDest ); }
joachim99@51 827 void DirectoryMergeWindow::slotCurrentChooseC() { setMergeOperation(currentItem(), eCopyCToDest ); }
joachim99@51 828 void DirectoryMergeWindow::slotCurrentMerge()
joachim99@51 829 {
joachim99@51 830 bool bThreeDirs = m_dirC.isValid();
joachim99@51 831 setMergeOperation(currentItem(), bThreeDirs ? eMergeABCToDest : eMergeABToDest );
joachim99@51 832 }
joachim99@51 833 void DirectoryMergeWindow::slotCurrentDelete() { setMergeOperation(currentItem(), eDeleteFromDest ); }
joachim99@51 834 // Sync current item
joachim99@51 835 void DirectoryMergeWindow::slotCurrentCopyAToB() { setMergeOperation(currentItem(), eCopyAToB ); }
joachim99@51 836 void DirectoryMergeWindow::slotCurrentCopyBToA() { setMergeOperation(currentItem(), eCopyBToA ); }
joachim99@51 837 void DirectoryMergeWindow::slotCurrentDeleteA() { setMergeOperation(currentItem(), eDeleteA ); }
joachim99@51 838 void DirectoryMergeWindow::slotCurrentDeleteB() { setMergeOperation(currentItem(), eDeleteB ); }
joachim99@51 839 void DirectoryMergeWindow::slotCurrentDeleteAAndB() { setMergeOperation(currentItem(), eDeleteAB ); }
joachim99@51 840 void DirectoryMergeWindow::slotCurrentMergeToA() { setMergeOperation(currentItem(), eMergeToA ); }
joachim99@51 841 void DirectoryMergeWindow::slotCurrentMergeToB() { setMergeOperation(currentItem(), eMergeToB ); }
joachim99@51 842 void DirectoryMergeWindow::slotCurrentMergeToAAndB() { setMergeOperation(currentItem(), eMergeToAB ); }
joachim99@51 843
joachim99@51 844
joachim99@51 845 void DirectoryMergeWindow::keyPressEvent( QKeyEvent* e )
joachim99@51 846 {
joachim99@75 847 if ( (e->QInputEvent::modifiers() & Qt::ControlModifier)!=0 )
joachim99@51 848 {
joachim99@51 849 bool bThreeDirs = m_dirC.isValid();
joachim99@51 850
joachim99@75 851 QTreeWidgetItem* lvi = currentItem();
joachim99@51 852 DirMergeItem* pDMI = lvi==0 ? 0 : static_cast<DirMergeItem*>(lvi);
joachim99@51 853 MergeFileInfos* pMFI = pDMI==0 ? 0 : pDMI->m_pMFI;
joachim99@51 854
joachim99@51 855 if ( pMFI==0 ) return;
joachim99@51 856 bool bMergeMode = bThreeDirs || !m_bSyncMode;
joachim99@51 857 bool bFTConflict = pMFI==0 ? false : conflictingFileTypes(*pMFI);
joachim99@51 858
joachim99@51 859 if ( bMergeMode )
joachim99@51 860 {
joachim99@51 861 switch(e->key())
joachim99@51 862 {
joachim99@70 863 case Qt::Key_1: if(pMFI->m_bExistsInA){ slotCurrentChooseA(); } return;
joachim99@70 864 case Qt::Key_2: if(pMFI->m_bExistsInB){ slotCurrentChooseB(); } return;
joachim99@70 865 case Qt::Key_3: if(pMFI->m_bExistsInC){ slotCurrentChooseC(); } return;
joachim99@70 866 case Qt::Key_Space: slotCurrentDoNothing(); return;
joachim99@70 867 case Qt::Key_4: if ( !bFTConflict ) { slotCurrentMerge(); } return;
joachim99@70 868 case Qt::Key_Delete: slotCurrentDelete(); return;
joachim99@51 869 default: break;
joachim99@51 870 }
joachim99@51 871 }
joachim99@51 872 else
joachim99@51 873 {
joachim99@51 874 switch(e->key())
joachim99@51 875 {
joachim99@70 876 case Qt::Key_1: if(pMFI->m_bExistsInA){ slotCurrentCopyAToB(); } return;
joachim99@70 877 case Qt::Key_2: if(pMFI->m_bExistsInB){ slotCurrentCopyBToA(); } return;
joachim99@70 878 case Qt::Key_Space: slotCurrentDoNothing(); return;
joachim99@70 879 case Qt::Key_4: if ( !bFTConflict ) { slotCurrentMergeToAAndB(); } return;
joachim99@70 880 case Qt::Key_Delete: if( pMFI->m_bExistsInA && pMFI->m_bExistsInB ) slotCurrentDeleteAAndB();
joachim99@51 881 else if( pMFI->m_bExistsInA ) slotCurrentDeleteA();
joachim99@51 882 else if( pMFI->m_bExistsInB ) slotCurrentDeleteB();
joachim99@51 883 return;
joachim99@51 884 default: break;
joachim99@51 885 }
joachim99@51 886 }
joachim99@51 887 }
joachim99@75 888 else if ( e->key()==Qt::Key_Return || e->key()==Qt::Key_Enter )
joachim99@75 889 {
joachim99@75 890 onDoubleClick( currentItem() );
joachim99@75 891 return;
joachim99@75 892 }
joachim99@75 893
joachim99@75 894 QTreeWidget::keyPressEvent(e);
joachim99@51 895 }
joachim99@51 896
joachim99@53 897 void DirectoryMergeWindow::focusInEvent(QFocusEvent*)
joachim99@53 898 {
joachim99@53 899 updateAvailabilities();
joachim99@53 900 }
joachim99@53 901 void DirectoryMergeWindow::focusOutEvent(QFocusEvent*)
joachim99@53 902 {
joachim99@53 903 updateAvailabilities();
joachim99@53 904 }
joachim99@51 905
joachim99@8 906 void DirectoryMergeWindow::setAllMergeOperations( e_MergeOperation eDefaultOperation )
joachim99@8 907 {
joachim99@8 908 if ( KMessageBox::Yes == KMessageBox::warningYesNo(this,
joachim99@8 909 i18n("This affects all merge operations."),
joachim99@80 910 i18n("Changing All Merge Operations"),
joachim99@80 911 KStandardGuiItem::cont(),
joachim99@80 912 KStandardGuiItem::cancel() ) )
joachim99@8 913 {
joachim99@75 914 for( int i=0; i<topLevelItemCount(); ++i )
joachim99@8 915 {
joachim99@75 916 DirMergeItem* pDMI = static_cast<DirMergeItem*>( topLevelItem(i) );
joachim99@8 917 calcSuggestedOperation( *pDMI->m_pMFI, eDefaultOperation );
joachim99@8 918 }
joachim99@8 919 }
joachim99@8 920 }
joachim99@8 921
joachim99@8 922
joachim99@8 923 void DirectoryMergeWindow::compareFilesAndCalcAges( MergeFileInfos& mfi )
joachim99@8 924 {
joachim99@8 925 std::map<QDateTime,int> dateMap;
joachim99@8 926
joachim99@8 927 if( mfi.m_bExistsInA )
joachim99@8 928 {
joachim99@8 929 mfi.m_bLinkA = mfi.m_fileInfoA.isSymLink();
joachim99@8 930 mfi.m_bDirA = mfi.m_fileInfoA.isDir();
joachim99@8 931 dateMap[ mfi.m_fileInfoA.lastModified() ] = 0;
joachim99@8 932 }
joachim99@8 933 if( mfi.m_bExistsInB )
joachim99@8 934 {
joachim99@8 935 mfi.m_bLinkB = mfi.m_fileInfoB.isSymLink();
joachim99@8 936 mfi.m_bDirB = mfi.m_fileInfoB.isDir();
joachim99@8 937 dateMap[ mfi.m_fileInfoB.lastModified() ] = 1;
joachim99@8 938 }
joachim99@8 939 if( mfi.m_bExistsInC )
joachim99@8 940 {
joachim99@8 941 mfi.m_bLinkC = mfi.m_fileInfoC.isSymLink();
joachim99@8 942 mfi.m_bDirC = mfi.m_fileInfoC.isDir();
joachim99@8 943 dateMap[ mfi.m_fileInfoC.lastModified() ] = 2;
joachim99@8 944 }
joachim99@8 945
joachim99@66 946 if ( m_pOptions->m_bDmFullAnalysis )
joachim99@8 947 {
joachim99@80 948 if( (mfi.m_bExistsInA && mfi.m_bDirA) || (mfi.m_bExistsInB && mfi.m_bDirB) || (mfi.m_bExistsInC && mfi.m_bDirC) )
joachim99@66 949 {
joachim99@66 950 // If any input is a directory, don't start any comparison.
joachim99@66 951 mfi.m_bEqualAB=mfi.m_bExistsInA && mfi.m_bExistsInB;
joachim99@66 952 mfi.m_bEqualAC=mfi.m_bExistsInA && mfi.m_bExistsInC;
joachim99@66 953 mfi.m_bEqualBC=mfi.m_bExistsInB && mfi.m_bExistsInC;
joachim99@66 954 }
joachim99@8 955 else
joachim99@8 956 {
joachim99@66 957 emit startDiffMerge(
joachim99@80 958 mfi.m_bExistsInA ? mfi.m_fileInfoA.absoluteFilePath() : QString(""),
joachim99@80 959 mfi.m_bExistsInB ? mfi.m_fileInfoB.absoluteFilePath() : QString(""),
joachim99@80 960 mfi.m_bExistsInC ? mfi.m_fileInfoC.absoluteFilePath() : QString(""),
joachim99@66 961 "",
joachim99@66 962 "","","",&mfi.m_totalDiffStatus
joachim99@66 963 );
joachim99@68 964 int nofNonwhiteConflicts = mfi.m_totalDiffStatus.nofUnsolvedConflicts +
joachim99@68 965 mfi.m_totalDiffStatus.nofSolvedConflicts - mfi.m_totalDiffStatus.nofWhitespaceConflicts;
joachim99@68 966
joachim99@68 967 if (m_pOptions->m_bDmWhiteSpaceEqual && nofNonwhiteConflicts == 0)
joachim99@68 968 {
joachim99@77 969 mfi.m_bEqualAB = mfi.m_bExistsInA && mfi.m_bExistsInB;
joachim99@77 970 mfi.m_bEqualAC = mfi.m_bExistsInA && mfi.m_bExistsInC;
joachim99@77 971 mfi.m_bEqualBC = mfi.m_bExistsInB && mfi.m_bExistsInC;
joachim99@68 972 }
joachim99@68 973 else
joachim99@68 974 {
joachim99@68 975 mfi.m_bEqualAB = mfi.m_totalDiffStatus.bBinaryAEqB;
joachim99@68 976 mfi.m_bEqualBC = mfi.m_totalDiffStatus.bBinaryBEqC;
joachim99@68 977 mfi.m_bEqualAC = mfi.m_totalDiffStatus.bBinaryAEqC;
joachim99@68 978 }
joachim99@66 979 }
joachim99@66 980 }
joachim99@66 981 else
joachim99@68 982 {
joachim99@66 983 bool bError;
joachim99@66 984 QString eqStatus;
joachim99@66 985 if( mfi.m_bExistsInA && mfi.m_bExistsInB )
joachim99@66 986 {
joachim99@66 987 if( mfi.m_bDirA ) mfi.m_bEqualAB=true;
joachim99@66 988 else fastFileComparison( mfi.m_fileInfoA, mfi.m_fileInfoB, mfi.m_bEqualAB, bError, eqStatus );
joachim99@66 989 }
joachim99@66 990 if( mfi.m_bExistsInA && mfi.m_bExistsInC )
joachim99@66 991 {
joachim99@66 992 if( mfi.m_bDirA ) mfi.m_bEqualAC=true;
joachim99@66 993 else fastFileComparison( mfi.m_fileInfoA, mfi.m_fileInfoC, mfi.m_bEqualAC, bError, eqStatus );
joachim99@66 994 }
joachim99@66 995 if( mfi.m_bExistsInB && mfi.m_bExistsInC )
joachim99@66 996 {
joachim99@66 997 if (mfi.m_bEqualAB && mfi.m_bEqualAC)
joachim99@66 998 mfi.m_bEqualBC = true;
joachim99@66 999 else
joachim99@66 1000 {
joachim99@66 1001 if( mfi.m_bDirB ) mfi.m_bEqualBC=true;
joachim99@66 1002 else fastFileComparison( mfi.m_fileInfoB, mfi.m_fileInfoC, mfi.m_bEqualBC, bError, eqStatus );
joachim99@66 1003 }
joachim99@8 1004 }
joachim99@8 1005 }
joachim99@8 1006
joachim99@8 1007 if (mfi.m_bLinkA!=mfi.m_bLinkB) mfi.m_bEqualAB=false;
joachim99@8 1008 if (mfi.m_bLinkA!=mfi.m_bLinkC) mfi.m_bEqualAC=false;
joachim99@8 1009 if (mfi.m_bLinkB!=mfi.m_bLinkC) mfi.m_bEqualBC=false;
joachim99@8 1010
joachim99@8 1011 if (mfi.m_bDirA!=mfi.m_bDirB) mfi.m_bEqualAB=false;
joachim99@8 1012 if (mfi.m_bDirA!=mfi.m_bDirC) mfi.m_bEqualAC=false;
joachim99@8 1013 if (mfi.m_bDirB!=mfi.m_bDirC) mfi.m_bEqualBC=false;
joachim99@8 1014
joachim99@8 1015 assert(eNew==0 && eMiddle==1 && eOld==2);
joachim99@8 1016
joachim99@8 1017 // The map automatically sorts the keys.
joachim99@8 1018 int age = eNew;
joachim99@8 1019 std::map<QDateTime,int>::reverse_iterator i;
joachim99@8 1020 for( i=dateMap.rbegin(); i!=dateMap.rend(); ++i )
joachim99@8 1021 {
joachim99@8 1022 int n = i->second;
joachim99@8 1023 if ( n==0 && mfi.m_ageA==eNotThere )
joachim99@8 1024 {
joachim99@8 1025 mfi.m_ageA = (e_Age)age; ++age;
joachim99@8 1026 if ( mfi.m_bEqualAB ) { mfi.m_ageB = mfi.m_ageA; ++age; }
joachim99@8 1027 if ( mfi.m_bEqualAC ) { mfi.m_ageC = mfi.m_ageA; ++age; }
joachim99@8 1028 }
joachim99@8 1029 else if ( n==1 && mfi.m_ageB==eNotThere )
joachim99@8 1030 {
joachim99@8 1031 mfi.m_ageB = (e_Age)age; ++age;
joachim99@8 1032 if ( mfi.m_bEqualAB ) { mfi.m_ageA = mfi.m_ageB; ++age; }
joachim99@8 1033 if ( mfi.m_bEqualBC ) { mfi.m_ageC = mfi.m_ageB; ++age; }
joachim99@8 1034 }
joachim99@8 1035 else if ( n==2 && mfi.m_ageC==eNotThere)
joachim99@8 1036 {
joachim99@8 1037 mfi.m_ageC = (e_Age)age; ++age;
joachim99@8 1038 if ( mfi.m_bEqualAC ) { mfi.m_ageA = mfi.m_ageC; ++age; }
joachim99@8 1039 if ( mfi.m_bEqualBC ) { mfi.m_ageB = mfi.m_ageC; ++age; }
joachim99@8 1040 }
joachim99@8 1041 }
joachim99@8 1042
joachim99@8 1043 // The checks below are necessary when the dates of the file are equal but the
joachim99@8 1044 // files are not. One wouldn't expect this to happen, yet it happens sometimes.
joachim99@8 1045 if ( mfi.m_bExistsInC && mfi.m_ageC==eNotThere )
joachim99@8 1046 {
joachim99@8 1047 mfi.m_ageC = (e_Age)age; ++age;
joachim99@8 1048 mfi.m_bConflictingAges = true;
joachim99@8 1049 }
joachim99@8 1050 if ( mfi.m_bExistsInB && mfi.m_ageB==eNotThere )
joachim99@8 1051 {
joachim99@8 1052 mfi.m_ageB = (e_Age)age; ++age;
joachim99@8 1053 mfi.m_bConflictingAges = true;
joachim99@8 1054 }
joachim99@8 1055 if ( mfi.m_bExistsInA && mfi.m_ageA==eNotThere )
joachim99@8 1056 {
joachim99@8 1057 mfi.m_ageA = (e_Age)age; ++age;
joachim99@8 1058 mfi.m_bConflictingAges = true;
joachim99@8 1059 }
joachim99@8 1060
joachim99@8 1061 if ( mfi.m_ageA != eOld && mfi.m_ageB != eOld && mfi.m_ageC != eOld )
joachim99@8 1062 {
joachim99@8 1063 if (mfi.m_ageA == eMiddle) mfi.m_ageA = eOld;
joachim99@8 1064 if (mfi.m_ageB == eMiddle) mfi.m_ageB = eOld;
joachim99@8 1065 if (mfi.m_ageC == eMiddle) mfi.m_ageC = eOld;
joachim99@8 1066 }
joachim99@8 1067 }
joachim99@8 1068
joachim99@8 1069 static QPixmap* s_pm_dir;
joachim99@8 1070 static QPixmap* s_pm_file;
joachim99@8 1071
joachim99@69 1072 static QPixmap* pmNotThere;
joachim99@69 1073 static QPixmap* pmNew;
joachim99@69 1074 static QPixmap* pmOld;
joachim99@69 1075 static QPixmap* pmMiddle;
joachim99@69 1076
joachim99@69 1077 static QPixmap* pmLink;
joachim99@69 1078
joachim99@69 1079 static QPixmap* pmDirLink;
joachim99@69 1080 static QPixmap* pmFileLink;
joachim99@69 1081
joachim99@69 1082 static QPixmap* pmNewLink;
joachim99@69 1083 static QPixmap* pmOldLink;
joachim99@69 1084 static QPixmap* pmMiddleLink;
joachim99@69 1085
joachim99@69 1086 static QPixmap* pmNewDir;
joachim99@69 1087 static QPixmap* pmMiddleDir;
joachim99@69 1088 static QPixmap* pmOldDir;
joachim99@69 1089
joachim99@69 1090 static QPixmap* pmNewDirLink;
joachim99@69 1091 static QPixmap* pmMiddleDirLink;
joachim99@69 1092 static QPixmap* pmOldDirLink;
joachim99@69 1093
joachim99@69 1094
joachim99@69 1095 static QPixmap colorToPixmap(QColor c)
joachim99@69 1096 {
joachim99@69 1097 QPixmap pm(16,16);
joachim99@69 1098 QPainter p(&pm);
joachim99@69 1099 p.setPen( Qt::black );
joachim99@69 1100 p.setBrush( c );
joachim99@69 1101 p.drawRect(0,0,pm.width(),pm.height());
joachim99@69 1102 return pm;
joachim99@69 1103 }
joachim99@69 1104
joachim99@69 1105 static void initPixmaps( QColor newest, QColor oldest, QColor middle, QColor notThere )
joachim99@69 1106 {
joachim99@69 1107 if (pmNew==0)
joachim99@69 1108 {
joachim99@69 1109 pmNotThere = new QPixmap;
joachim99@69 1110 pmNew = new QPixmap;
joachim99@69 1111 pmOld = new QPixmap;
joachim99@69 1112 pmMiddle = new QPixmap;
joachim99@69 1113
joachim99@69 1114 #include "xpm/link_arrow.xpm"
joachim99@69 1115 pmLink = new QPixmap(link_arrow);
joachim99@69 1116
joachim99@69 1117 pmDirLink = new QPixmap;
joachim99@69 1118 pmFileLink = new QPixmap;
joachim99@69 1119
joachim99@69 1120 pmNewLink = new QPixmap;
joachim99@69 1121 pmOldLink = new QPixmap;
joachim99@69 1122 pmMiddleLink = new QPixmap;
joachim99@69 1123
joachim99@69 1124 pmNewDir = new QPixmap;
joachim99@69 1125 pmMiddleDir = new QPixmap;
joachim99@69 1126 pmOldDir = new QPixmap;
joachim99@69 1127
joachim99@69 1128 pmNewDirLink = new QPixmap;
joachim99@69 1129 pmMiddleDirLink = new QPixmap;
joachim99@69 1130 pmOldDirLink = new QPixmap;
joachim99@69 1131 }
joachim99@69 1132
joachim99@69 1133
joachim99@69 1134 *pmNotThere = colorToPixmap(notThere);
joachim99@69 1135 *pmNew = colorToPixmap(newest);
joachim99@69 1136 *pmOld = colorToPixmap(oldest);
joachim99@69 1137 *pmMiddle = colorToPixmap(middle);
joachim99@69 1138
joachim99@69 1139 *pmDirLink = pixCombiner( s_pm_dir, pmLink);
joachim99@69 1140 *pmFileLink = pixCombiner( s_pm_file, pmLink );
joachim99@69 1141
joachim99@69 1142 *pmNewLink = pixCombiner( pmNew, pmLink);
joachim99@69 1143 *pmOldLink = pixCombiner( pmOld, pmLink);
joachim99@69 1144 *pmMiddleLink = pixCombiner( pmMiddle, pmLink);
joachim99@69 1145
joachim99@69 1146 *pmNewDir = pixCombiner2( pmNew, s_pm_dir);
joachim99@69 1147 *pmMiddleDir = pixCombiner2( pmMiddle, s_pm_dir);
joachim99@69 1148 *pmOldDir = pixCombiner2( pmOld, s_pm_dir);
joachim99@69 1149
joachim99@69 1150 *pmNewDirLink = pixCombiner( pmNewDir, pmLink);
joachim99@69 1151 *pmMiddleDirLink = pixCombiner( pmMiddleDir, pmLink);
joachim99@69 1152 *pmOldDirLink = pixCombiner( pmOldDir, pmLink);
joachim99@69 1153 }
joachim99@69 1154
joachim99@69 1155
joachim99@75 1156 static void setOnePixmap( QTreeWidgetItem* pLVI, int col, e_Age eAge, bool bLink, bool bDir )
joachim99@8 1157 {
joachim99@69 1158 static QPixmap* ageToPm[]= { pmNew, pmMiddle, pmOld, pmNotThere, s_pm_file };
joachim99@69 1159 static QPixmap* ageToPmLink[]= { pmNewLink, pmMiddleLink, pmOldLink, pmNotThere, pmFileLink };
joachim99@69 1160 static QPixmap* ageToPmDir[]= { pmNewDir, pmMiddleDir, pmOldDir, pmNotThere, s_pm_dir };
joachim99@69 1161 static QPixmap* ageToPmDirLink[]={ pmNewDirLink, pmMiddleDirLink, pmOldDirLink, pmNotThere, pmDirLink };
joachim99@8 1162
joachim99@8 1163 QPixmap** ppPm = bDir ? ( bLink ? ageToPmDirLink : ageToPmDir ):
joachim99@8 1164 ( bLink ? ageToPmLink : ageToPm );
joachim99@8 1165
joachim99@75 1166 pLVI->setIcon( col, *ppPm[eAge] );
joachim99@8 1167 }
joachim99@8 1168
joachim99@8 1169 static void setPixmaps( MergeFileInfos& mfi, bool bCheckC )
joachim99@8 1170 {
joachim99@75 1171 setOnePixmap( mfi.m_pDMI, s_NameCol, eAgeEnd,
joachim99@8 1172 mfi.m_bLinkA || mfi.m_bLinkB || mfi.m_bLinkC,
joachim99@8 1173 mfi.m_bDirA || mfi.m_bDirB || mfi.m_bDirC
joachim99@8 1174 );
joachim99@8 1175
joachim99@8 1176 if ( mfi.m_bDirA || mfi.m_bDirB || mfi.m_bDirC )
joachim99@8 1177 {
joachim99@8 1178 mfi.m_ageA=eNotThere;
joachim99@8 1179 mfi.m_ageB=eNotThere;
joachim99@8 1180 mfi.m_ageC=eNotThere;
joachim99@8 1181 int age = eNew;
joachim99@8 1182 if ( mfi.m_bExistsInC )
joachim99@8 1183 {
joachim99@8 1184 mfi.m_ageC = (e_Age)age;
joachim99@8 1185 if (mfi.m_bEqualAC) mfi.m_ageA = (e_Age)age;
joachim99@8 1186 if (mfi.m_bEqualBC) mfi.m_ageB = (e_Age)age;
joachim99@8 1187 ++age;
joachim99@8 1188 }
joachim99@8 1189 if ( mfi.m_bExistsInB && mfi.m_ageB==eNotThere )
joachim99@8 1190 {
joachim99@8 1191 mfi.m_ageB = (e_Age)age;
joachim99@8 1192 if (mfi.m_bEqualAB) mfi.m_ageA = (e_Age)age;
joachim99@8 1193 ++age;
joachim99@8 1194 }
joachim99@8 1195 if ( mfi.m_bExistsInA && mfi.m_ageA==eNotThere )
joachim99@8 1196 {
joachim99@8 1197 mfi.m_ageA = (e_Age)age;
joachim99@8 1198 }
joachim99@8 1199 if ( mfi.m_ageA != eOld && mfi.m_ageB != eOld && mfi.m_ageC != eOld )
joachim99@8 1200 {
joachim99@8 1201 if (mfi.m_ageA == eMiddle) mfi.m_ageA = eOld;
joachim99@8 1202 if (mfi.m_ageB == eMiddle) mfi.m_ageB = eOld;
joachim99@8 1203 if (mfi.m_ageC == eMiddle) mfi.m_ageC = eOld;
joachim99@8 1204 }
joachim99@8 1205 }
joachim99@8 1206
joachim99@8 1207 setOnePixmap( mfi.m_pDMI, s_ACol, mfi.m_ageA, mfi.m_bLinkA, mfi.m_bDirA );
joachim99@8 1208 setOnePixmap( mfi.m_pDMI, s_BCol, mfi.m_ageB, mfi.m_bLinkB, mfi.m_bDirB );
joachim99@8 1209 if ( bCheckC )
joachim99@8 1210 setOnePixmap( mfi.m_pDMI, s_CCol, mfi.m_ageC, mfi.m_bLinkC, mfi.m_bDirC );
joachim99@8 1211 }
joachim99@8 1212
joachim99@75 1213 static QTreeWidgetItem* nextSibling(const QTreeWidgetItem* p)
joachim99@75 1214 {
joachim99@75 1215 QTreeWidgetItem* pParent = p->parent();
joachim99@75 1216 if ( pParent )
joachim99@75 1217 {
joachim99@75 1218 int currentIdx = pParent->indexOfChild( const_cast<QTreeWidgetItem*>(p) );
joachim99@75 1219 if ( currentIdx+1 < pParent->childCount() )
joachim99@75 1220 return pParent->child(currentIdx+1);
joachim99@75 1221 }
joachim99@75 1222 else
joachim99@75 1223 {
joachim99@75 1224 QTreeWidget* pParentTreeWidget = p->treeWidget();
joachim99@75 1225 if ( pParentTreeWidget )
joachim99@75 1226 {
joachim99@75 1227 int currentIdx = pParentTreeWidget->indexOfTopLevelItem( const_cast<QTreeWidgetItem*>(p) );
joachim99@75 1228 if ( currentIdx+1 < pParentTreeWidget->topLevelItemCount() )
joachim99@75 1229 return pParentTreeWidget->topLevelItem(currentIdx+1);
joachim99@75 1230 }
joachim99@75 1231 }
joachim99@75 1232 return 0;
joachim99@75 1233 }
joachim99@75 1234
joachim99@8 1235 // Iterate through the complete tree. Start by specifying QListView::firstChild().
joachim99@75 1236 static QTreeWidgetItem* treeIterator( QTreeWidgetItem* p, bool bVisitChildren=true, bool bFindInvisible=false )
joachim99@8 1237 {
joachim99@8 1238 if( p!=0 )
joachim99@8 1239 {
joachim99@69 1240 do
joachim99@8 1241 {
joachim99@75 1242 if ( bVisitChildren && p->childCount() != 0 ) p = p->child(0);
joachim99@75 1243 else
joachim99@8 1244 {
joachim99@75 1245 QTreeWidgetItem* pNextSibling = nextSibling(p);
joachim99@75 1246 if ( pNextSibling )
joachim99@75 1247 p = pNextSibling;
joachim99@75 1248 else
joachim99@69 1249 {
joachim99@75 1250 p = p->parent();
joachim99@75 1251 while ( p!=0 )
joachim99@75 1252 {
joachim99@75 1253 QTreeWidgetItem* pNextSibling = nextSibling(p);
joachim99@75 1254 if( pNextSibling ) { p = pNextSibling; break; }
joachim99@75 1255 else { p = p->parent(); }
joachim99@75 1256 }
joachim99@69 1257 }
joachim99@8 1258 }
joachim99@8 1259 }
joachim99@75 1260 while( p && p->isHidden() && !bFindInvisible );
joachim99@8 1261 }
joachim99@8 1262 return p;
joachim99@8 1263 }
joachim99@8 1264
joachim99@66 1265 void DirectoryMergeWindow::prepareListView( ProgressProxy& pp )
joachim99@8 1266 {
joachim99@8 1267 static bool bFirstTime = true;
joachim99@8 1268 if (bFirstTime)
joachim99@8 1269 {
joachim99@8 1270 #include "xpm/file.xpm"
joachim99@8 1271 #include "xpm/folder.xpm"
joachim99@80 1272 // FIXME specify correct icon loader group
joachim99@80 1273 s_pm_dir = new QPixmap( m_pIconLoader->loadIcon("folder", KIconLoader::NoGroup, KIconLoader::Small ) );
joachim99@8 1274 if (s_pm_dir->size()!=QSize(16,16))
joachim99@8 1275 {
joachim99@8 1276 delete s_pm_dir;
joachim99@8 1277 s_pm_dir = new QPixmap( folder_pm );
joachim99@8 1278 }
joachim99@8 1279 s_pm_file= new QPixmap( file_pm );
joachim99@8 1280 bFirstTime=false;
joachim99@8 1281 }
joachim99@8 1282
joachim99@8 1283 clear();
joachim99@69 1284 initPixmaps( m_pOptions->m_newestFileColor, m_pOptions->m_oldestFileColor,
joachim99@69 1285 m_pOptions->m_midAgeFileColor, m_pOptions->m_missingFileColor );
joachim99@8 1286
joachim99@8 1287 setRootIsDecorated( true );
joachim99@8 1288
joachim99@8 1289 bool bCheckC = m_dirC.isValid();
joachim99@8 1290
joachim99@8 1291 std::map<QString, MergeFileInfos>::iterator j;
joachim99@8 1292 int nrOfFiles = m_fileMergeMap.size();
joachim99@8 1293 int currentIdx = 1;
joachim99@8 1294 QTime t;
joachim99@8 1295 t.start();
joachim99@8 1296 for( j=m_fileMergeMap.begin(); j!=m_fileMergeMap.end(); ++j )
joachim99@8 1297 {
joachim99@8 1298 MergeFileInfos& mfi = j->second;
joachim99@8 1299
joachim99@8 1300 mfi.m_subPath = mfi.m_fileInfoA.exists() ? mfi.m_fileInfoA.filePath() :
joachim99@8 1301 mfi.m_fileInfoB.exists() ? mfi.m_fileInfoB.filePath() :
joachim99@25 1302 mfi.m_fileInfoC.exists() ? mfi.m_fileInfoC.filePath() :
joachim99@25 1303 QString("");
joachim99@8 1304
joachim99@58 1305 // const QString& fileName = j->first;
joachim99@58 1306 const QString& fileName = mfi.m_subPath;
joachim99@58 1307
joachim99@66 1308 pp.setInformation(
joachim99@51 1309 i18n("Processing ") + QString::number(currentIdx) +" / "+ QString::number(nrOfFiles)
joachim99@8 1310 +"\n" + fileName, double(currentIdx) / nrOfFiles, false );
joachim99@66 1311 if ( pp.wasCancelled() ) break;
joachim99@8 1312 ++currentIdx;
joachim99@8 1313
joachim99@8 1314 // The comparisons and calculations for each file take place here.
joachim99@8 1315 compareFilesAndCalcAges( mfi );
joachim99@8 1316
joachim99@8 1317 // Get dirname from fileName: Search for "/" from end:
joachim99@75 1318 int pos = fileName.lastIndexOf('/');
joachim99@8 1319 QString dirPart;
joachim99@8 1320 QString filePart;
joachim99@8 1321 if (pos==-1)
joachim99@8 1322 {
joachim99@8 1323 // Top dir
joachim99@8 1324 filePart = fileName;
joachim99@8 1325 }
joachim99@8 1326 else
joachim99@8 1327 {
joachim99@8 1328 dirPart = fileName.left(pos);
joachim99@8 1329 filePart = fileName.mid(pos+1);
joachim99@8 1330 }
joachim99@8 1331
joachim99@8 1332 if ( dirPart.isEmpty() ) // Top level
joachim99@8 1333 {
joachim99@8 1334 new DirMergeItem( this, filePart, &mfi );
joachim99@8 1335 }
joachim99@8 1336 else
joachim99@8 1337 {
joachim99@69 1338 MergeFileInfos& dirMfi = m_fileMergeMap[sortString(dirPart, m_bCaseSensitive)]; // parent
joachim99@8 1339 assert(dirMfi.m_pDMI!=0);
joachim99@8 1340 new DirMergeItem( dirMfi.m_pDMI, filePart, &mfi );
joachim99@8 1341 mfi.m_pParent = &dirMfi;
joachim99@8 1342
joachim99@92 1343 // Equality for parent dirs is set in updateFileVisibilities()
joachim99@8 1344 }
joachim99@8 1345
joachim99@8 1346 setPixmaps( mfi, bCheckC );
joachim99@8 1347 }
joachim99@8 1348 }
joachim99@8 1349
joachim99@8 1350 static bool conflictingFileTypes(MergeFileInfos& mfi)
joachim99@8 1351 {
joachim99@8 1352 // Now check if file/dir-types fit.
joachim99@8 1353 if ( mfi.m_bLinkA || mfi.m_bLinkB || mfi.m_bLinkC )
joachim99@8 1354 {
joachim99@80 1355 if ( (mfi.m_bExistsInA && ! mfi.m_bLinkA) ||
joachim99@80 1356 (mfi.m_bExistsInB && ! mfi.m_bLinkB) ||
joachim99@80 1357 (mfi.m_bExistsInC && ! mfi.m_bLinkC) )
joachim99@8 1358 {
joachim99@8 1359 return true;
joachim99@8 1360 }
joachim99@8 1361 }
joachim99@8 1362
joachim99@8 1363 if ( mfi.m_bDirA || mfi.m_bDirB || mfi.m_bDirC )
joachim99@8 1364 {
joachim99@80 1365 if ( (mfi.m_bExistsInA && ! mfi.m_bDirA) ||
joachim99@80 1366 (mfi.m_bExistsInB && ! mfi.m_bDirB) ||
joachim99@80 1367 (mfi.m_bExistsInC && ! mfi.m_bDirC) )
joachim99@8 1368 {
joachim99@8 1369 return true;
joachim99@8 1370 }
joachim99@8 1371 }
joachim99@8 1372 return false;
joachim99@8 1373 }
joachim99@8 1374
joachim99@8 1375 void DirectoryMergeWindow::calcSuggestedOperation( MergeFileInfos& mfi, e_MergeOperation eDefaultMergeOp )
joachim99@8 1376 {
joachim99@8 1377 bool bCheckC = m_dirC.isValid();
joachim99@8 1378 bool bCopyNewer = m_pOptions->m_bDmCopyNewer;
joachim99@80 1379 bool bOtherDest = !( (m_dirDestInternal.absoluteFilePath() == m_dirA.absoluteFilePath()) ||
joachim99@80 1380 (m_dirDestInternal.absoluteFilePath() == m_dirB.absoluteFilePath()) ||
joachim99@80 1381 (bCheckC && m_dirDestInternal.absoluteFilePath() == m_dirC.absoluteFilePath()) );
joachim99@75 1382
joachim99@8 1383
joachim99@8 1384 if ( eDefaultMergeOp == eMergeABCToDest && !bCheckC ) { eDefaultMergeOp = eMergeABToDest; }
joachim99@8 1385 if ( eDefaultMergeOp == eMergeToAB && bCheckC ) { assert(false); }
joachim99@51 1386
joachim99@8 1387 if ( eDefaultMergeOp == eMergeToA || eDefaultMergeOp == eMergeToB ||
joachim99@8 1388 eDefaultMergeOp == eMergeABCToDest || eDefaultMergeOp == eMergeABToDest || eDefaultMergeOp == eMergeToAB )
joachim99@51 1389 {
joachim99@8 1390 if ( !bCheckC )
joachim99@8 1391 {
joachim99@8 1392 if ( mfi.m_bEqualAB )
joachim99@8 1393 {
joachim99@75 1394 mfi.setMergeOperation( bOtherDest ? eCopyBToDest : eNoOperation );
joachim99@8 1395 }
joachim99@8 1396 else if ( mfi.m_bExistsInA && mfi.m_bExistsInB )
joachim99@8 1397 {
joachim99@8 1398 if ( !bCopyNewer || mfi.m_bDirA )
joachim99@8 1399 mfi.setMergeOperation( eDefaultMergeOp );
joachim99@8 1400 else if ( bCopyNewer && mfi.m_bConflictingAges )
joachim99@8 1401 {
joachim99@8 1402 mfi.setMergeOperation( eConflictingAges );
joachim99@8 1403 }
joachim99@8 1404 else
joachim99@8 1405 {
joachim99@8 1406 if ( mfi.m_ageA == eNew )
joachim99@8 1407 mfi.setMergeOperation( eDefaultMergeOp == eMergeToAB ? eCopyAToB : eCopyAToDest );
joachim99@8 1408 else
joachim99@8 1409 mfi.setMergeOperation( eDefaultMergeOp == eMergeToAB ? eCopyBToA : eCopyBToDest );
joachim99@8 1410 }
joachim99@8 1411 }
joachim99@8 1412 else if ( !mfi.m_bExistsInA && mfi.m_bExistsInB )
joachim99@8 1413 {
joachim99@8 1414 if ( eDefaultMergeOp==eMergeABToDest ) mfi.setMergeOperation( eCopyBToDest );
joachim99@8 1415 else if ( eDefaultMergeOp==eMergeToB ) mfi.setMergeOperation( eNoOperation );
joachim99@8 1416 else mfi.setMergeOperation( eCopyBToA );
joachim99@8 1417 }
joachim99@8 1418 else if ( mfi.m_bExistsInA && !mfi.m_bExistsInB )
joachim99@8 1419 {
joachim99@8 1420 if ( eDefaultMergeOp==eMergeABToDest ) mfi.setMergeOperation( eCopyAToDest );
joachim99@8 1421 else if ( eDefaultMergeOp==eMergeToA ) mfi.setMergeOperation( eNoOperation );
joachim99@8 1422 else mfi.setMergeOperation( eCopyAToB );
joachim99@8 1423 }
joachim99@8 1424 else //if ( !mfi.m_bExistsInA && !mfi.m_bExistsInB )
joachim99@8 1425 {
joachim99@8 1426 mfi.setMergeOperation( eNoOperation ); assert(false);
joachim99@8 1427 }
joachim99@8 1428 }
joachim99@8 1429 else
joachim99@8 1430 {
joachim99@8 1431 if ( mfi.m_bEqualAB && mfi.m_bEqualAC )
joachim99@8 1432 {
joachim99@75 1433 mfi.setMergeOperation( bOtherDest ? eCopyCToDest : eNoOperation );
joachim99@8 1434 }
joachim99@8 1435 else if ( mfi.m_bExistsInA && mfi.m_bExistsInB && mfi.m_bExistsInC)
joachim99@8 1436 {
joachim99@8 1437 if ( mfi.m_bEqualAB )
joachim99@8 1438 mfi.setMergeOperation( eCopyCToDest );
joachim99@8 1439 else if ( mfi.m_bEqualAC )
joachim99@8 1440 mfi.setMergeOperation( eCopyBToDest );
joachim99@8 1441 else if ( mfi.m_bEqualBC )
joachim99@8 1442 mfi.setMergeOperation( eCopyCToDest );
joachim99@8 1443 else
joachim99@8 1444 mfi.setMergeOperation( eMergeABCToDest );
joachim99@8 1445 }
joachim99@8 1446 else if ( mfi.m_bExistsInA && mfi.m_bExistsInB && !mfi.m_bExistsInC )
joachim99@8 1447 {
joachim99@8 1448 if ( mfi.m_bEqualAB )
joachim99@8 1449 mfi.setMergeOperation( eDeleteFromDest );
joachim99@8 1450 else
joachim99@92 1451 mfi.setMergeOperation( eChangedAndDeleted );
joachim99@8 1452 }
joachim99@8 1453 else if ( mfi.m_bExistsInA && !mfi.m_bExistsInB && mfi.m_bExistsInC )
joachim99@8 1454 {
joachim99@8 1455 if ( mfi.m_bEqualAC )
joachim99@8 1456 mfi.setMergeOperation( eDeleteFromDest );
joachim99@8 1457 else
joachim99@92 1458 mfi.setMergeOperation( eChangedAndDeleted );
joachim99@8 1459 }
joachim99@8 1460 else if ( !mfi.m_bExistsInA && mfi.m_bExistsInB && mfi.m_bExistsInC )
joachim99@8 1461 {
joachim99@8 1462 if ( mfi.m_bEqualBC )
joachim99@8 1463 mfi.setMergeOperation( eCopyCToDest );
joachim99@8 1464 else
joachim99@8 1465 mfi.setMergeOperation( eMergeABCToDest );
joachim99@8 1466 }
joachim99@8 1467 else if ( !mfi.m_bExistsInA && !mfi.m_bExistsInB && mfi.m_bExistsInC )
joachim99@8 1468 {
joachim99@8 1469 mfi.setMergeOperation( eCopyCToDest );
joachim99@8 1470 }
joachim99@8 1471 else if ( !mfi.m_bExistsInA && mfi.m_bExistsInB && !mfi.m_bExistsInC )
joachim99@8 1472 {
joachim99@8 1473 mfi.setMergeOperation( eCopyBToDest );
joachim99@8 1474 }
joachim99@8 1475 else if ( mfi.m_bExistsInA && !mfi.m_bExistsInB && !mfi.m_bExistsInC)
joachim99@8 1476 {
joachim99@8 1477 mfi.setMergeOperation( eDeleteFromDest );
joachim99@8 1478 }
joachim99@8 1479 else //if ( !mfi.m_bExistsInA && !mfi.m_bExistsInB && !mfi.m_bExistsInC )
joachim99@8 1480 {
joachim99@8 1481 mfi.setMergeOperation( eNoOperation ); assert(false);
joachim99@8 1482 }
joachim99@8 1483 }
joachim99@8 1484
joachim99@8 1485 // Now check if file/dir-types fit.
joachim99@8 1486 if ( conflictingFileTypes(mfi) )
joachim99@8 1487 {
joachim99@8 1488 mfi.setMergeOperation( eConflictingFileTypes );
joachim99@8 1489 }
joachim99@8 1490 }
joachim99@8 1491 else
joachim99@8 1492 {
joachim99@8 1493 e_MergeOperation eMO = eDefaultMergeOp;
joachim99@8 1494 switch ( eDefaultMergeOp )
joachim99@8 1495 {
joachim99@8 1496 case eConflictingFileTypes:
joachim99@92 1497 case eChangedAndDeleted:
joachim99@8 1498 case eConflictingAges:
joachim99@8 1499 case eDeleteA:
joachim99@8 1500 case eDeleteB:
joachim99@8 1501 case eDeleteAB:
joachim99@8 1502 case eDeleteFromDest:
joachim99@8 1503 case eNoOperation: break;
joachim99@8 1504 case eCopyAToB: if ( !mfi.m_bExistsInA ) { eMO = eDeleteB; } break;
joachim99@8 1505 case eCopyBToA: if ( !mfi.m_bExistsInB ) { eMO = eDeleteA; } break;
joachim99@8 1506 case eCopyAToDest: if ( !mfi.m_bExistsInA ) { eMO = eDeleteFromDest; } break;
joachim99@8 1507 case eCopyBToDest: if ( !mfi.m_bExistsInB ) { eMO = eDeleteFromDest; } break;
joachim99@8 1508 case eCopyCToDest: if ( !mfi.m_bExistsInC ) { eMO = eDeleteFromDest; } break;
joachim99@8 1509
joachim99@8 1510 case eMergeToA:
joachim99@8 1511 case eMergeToB:
joachim99@8 1512 case eMergeToAB:
joachim99@8 1513 case eMergeABCToDest:
joachim99@8 1514 case eMergeABToDest:
joachim99@8 1515 default:
joachim99@8 1516 assert(false);
joachim99@8 1517 }
joachim99@8 1518 mfi.setMergeOperation( eMO );
joachim99@8 1519 }
joachim99@8 1520 }
joachim99@8 1521
joachim99@75 1522 void DirectoryMergeWindow::onDoubleClick( QTreeWidgetItem* lvi )
joachim99@8 1523 {
joachim99@8 1524 if (lvi==0) return;
joachim99@8 1525
joachim99@8 1526 if ( m_bDirectoryMerge )
joachim99@8 1527 mergeCurrentFile();
joachim99@8 1528 else
joachim99@8 1529 compareCurrentFile();
joachim99@8 1530 }
joachim99@8 1531
joachim99@75 1532 void DirectoryMergeWindow::onCurrentChanged(QTreeWidgetItem* lvi)
joachim99@8 1533 {
joachim99@8 1534 if ( lvi==0 ) return;
joachim99@8 1535
joachim99@8 1536 DirMergeItem* pDMI = static_cast<DirMergeItem*>(lvi);
joachim99@8 1537
joachim99@8 1538 MergeFileInfos& mfi = *pDMI->m_pMFI;
joachim99@8 1539 assert( mfi.m_pDMI==pDMI );
joachim99@8 1540
joachim99@8 1541 m_pDirectoryMergeInfo->setInfo( m_dirA, m_dirB, m_dirC, m_dirDestInternal, mfi );
joachim99@8 1542 }
joachim99@8 1543
joachim99@75 1544 void DirectoryMergeWindow::mousePressEvent( QMouseEvent* e )
joachim99@8 1545 {
joachim99@75 1546 QTreeWidget::mousePressEvent(e);
joachim99@75 1547 int c = columnAt( e->x() );
joachim99@75 1548 QTreeWidgetItem* lvi = itemAt( e->pos() );
joachim99@75 1549 QPoint p = e->globalPos();
joachim99@8 1550 if ( lvi==0 ) return;
joachim99@8 1551
joachim99@8 1552 DirMergeItem* pDMI = static_cast<DirMergeItem*>(lvi);
joachim99@8 1553
joachim99@8 1554 MergeFileInfos& mfi = *pDMI->m_pMFI;
joachim99@8 1555 assert( mfi.m_pDMI==pDMI );
joachim99@8 1556
joachim99@69 1557 if ( c==s_OpCol )
joachim99@8 1558 {
joachim99@69 1559 bool bThreeDirs = m_dirC.isValid();
joachim99@69 1560
joachim99@80 1561 KMenu m(this);
joachim99@69 1562 if ( bThreeDirs )
joachim99@8 1563 {
joachim99@80 1564 m.addAction( m_pDirCurrentDoNothing );
joachim99@69 1565 int count=0;
joachim99@80 1566 if ( mfi.m_bExistsInA ) { m.addAction( m_pDirCurrentChooseA ); ++count; }
joachim99@80 1567 if ( mfi.m_bExistsInB ) { m.addAction( m_pDirCurrentChooseB ); ++count; }
joachim99@80 1568 if ( mfi.m_bExistsInC ) { m.addAction( m_pDirCurrentChooseC ); ++count; }
joachim99@80 1569 if ( !conflictingFileTypes(mfi) && count>1 ) m.addAction( m_pDirCurrentMerge );
joachim99@80 1570 m.addAction( m_pDirCurrentDelete );
joachim99@69 1571 }
joachim99@69 1572 else if ( m_bSyncMode )
joachim99@69 1573 {
joachim99@80 1574 m.addAction( m_pDirCurrentSyncDoNothing );
joachim99@80 1575 if ( mfi.m_bExistsInA ) m.addAction( m_pDirCurrentSyncCopyAToB );
joachim99@80 1576 if ( mfi.m_bExistsInB ) m.addAction( m_pDirCurrentSyncCopyBToA );
joachim99@80 1577 if ( mfi.m_bExistsInA ) m.addAction( m_pDirCurrentSyncDeleteA );
joachim99@80 1578 if ( mfi.m_bExistsInB ) m.addAction( m_pDirCurrentSyncDeleteB );
joachim99@69 1579 if ( mfi.m_bExistsInA && mfi.m_bExistsInB )
joachim99@8 1580 {
joachim99@80 1581 m.addAction( m_pDirCurrentSyncDeleteAAndB );
joachim99@69 1582 if ( !conflictingFileTypes(mfi))
joachim99@69 1583 {
joachim99@80 1584 m.addAction( m_pDirCurrentSyncMergeToA );
joachim99@80 1585 m.addAction( m_pDirCurrentSyncMergeToB );
joachim99@80 1586 m.addAction( m_pDirCurrentSyncMergeToAAndB );
joachim99@69 1587 }
joachim99@8 1588 }
joachim99@8 1589 }
joachim99@69 1590 else
joachim99@69 1591 {
joachim99@80 1592 m.addAction( m_pDirCurrentDoNothing );
joachim99@80 1593 if ( mfi.m_bExistsInA ) { m.addAction( m_pDirCurrentChooseA ); }
joachim99@80 1594 if ( mfi.m_bExistsInB ) { m.addAction( m_pDirCurrentChooseB ); }
joachim99@80 1595 if ( !conflictingFileTypes(mfi) && mfi.m_bExistsInA && mfi.m_bExistsInB ) m.addAction( m_pDirCurrentMerge );
joachim99@80 1596 m.addAction( m_pDirCurrentDelete );
joachim99@69 1597 }
joachim99@69 1598
joachim99@69 1599 m.exec( p );
joachim99@8 1600 }
joachim99@69 1601 else if ( c == s_ACol || c==s_BCol || c==s_CCol )
joachim99@8 1602 {
joachim99@69 1603 QString itemPath;
joachim99@69 1604 if ( c == s_ACol && mfi.m_bExistsInA ){ itemPath = fullNameA(mfi); }
joachim99@69 1605 else if ( c == s_BCol && mfi.m_bExistsInB ){ itemPath = fullNameB(mfi); }
joachim99@69 1606 else if ( c == s_CCol && mfi.m_bExistsInC ){ itemPath = fullNameC(mfi); }
joachim99@69 1607
joachim99@69 1608 if (!itemPath.isEmpty())
joachim99@69 1609 {
joachim99@75 1610 selectItemAndColumn( pDMI, c, e->button()==Qt::RightButton );
joachim99@69 1611 }
joachim99@8 1612 }
joachim99@69 1613 }
joachim99@69 1614
joachim99@75 1615 void DirectoryMergeWindow::contextMenuEvent(QContextMenuEvent* e)
joachim99@69 1616 {
joachim99@75 1617 QTreeWidgetItem* lvi = itemAt( e->pos() );
joachim99@75 1618 int c = columnAt( e->x() );
joachim99@75 1619 QPoint p = e->globalPos();
joachim99@69 1620 if ( lvi==0 ) return;
joachim99@69 1621
joachim99@69 1622 DirMergeItem* pDMI = static_cast<DirMergeItem*>(lvi);
joachim99@69 1623
joachim99@69 1624 MergeFileInfos& mfi = *pDMI->m_pMFI;
joachim99@69 1625 assert( mfi.m_pDMI==pDMI );
joachim99@69 1626 if ( c == s_ACol || c==s_BCol || c==s_CCol )
joachim99@69 1627 {
joachim99@69 1628 QString itemPath;
joachim99@69 1629 if ( c == s_ACol && mfi.m_bExistsInA ){ itemPath = fullNameA(mfi); }
joachim99@69 1630 else if ( c == s_BCol && mfi.m_bExistsInB ){ itemPath = fullNameB(mfi); }
joachim99@69 1631 else if ( c == s_CCol && mfi.m_bExistsInC ){ itemPath = fullNameC(mfi); }
joachim99@69 1632
joachim99@69 1633 if (!itemPath.isEmpty())
joachim99@69 1634 {
joachim99@69 1635 selectItemAndColumn(pDMI, c, true);
joachim99@80 1636 KMenu m(this);
joachim99@80 1637 m.addAction( m_pDirCompareExplicit );
joachim99@80 1638 m.addAction( m_pDirMergeExplicit );
joachim99@69 1639
joachim99@69 1640 #ifndef _WIN32
joachim99@69 1641 m.exec( p );
joachim99@69 1642 #else
joachim99@70 1643 void showShellContextMenu( const QString&, QPoint, QWidget*, QMenu* );
joachim99@69 1644 showShellContextMenu( itemPath, p, this, &m );
joachim99@69 1645 #endif
joachim99@69 1646 }
joachim99@69 1647 }
joachim99@69 1648 }
joachim99@69 1649
joachim99@69 1650 static QString getFileName( DirMergeItem* pDMI, int column )
joachim99@69 1651 {
joachim99@69 1652 if ( pDMI != 0 )
joachim99@69 1653 {
joachim99@69 1654 MergeFileInfos& mfi = *pDMI->m_pMFI;
joachim99@80 1655 return column == s_ACol ? mfi.m_fileInfoA.absoluteFilePath() :
joachim99@80 1656 column == s_BCol ? mfi.m_fileInfoB.absoluteFilePath() :
joachim99@80 1657 column == s_CCol ? mfi.m_fileInfoC.absoluteFilePath() :
joachim99@69 1658 QString("");
joachim99@69 1659 }
joachim99@69 1660 return "";
joachim99@69 1661 }
joachim99@69 1662
joachim99@69 1663 static bool isDir( DirMergeItem* pDMI, int column )
joachim99@69 1664 {
joachim99@69 1665 if ( pDMI != 0 )
joachim99@69 1666 {
joachim99@69 1667 MergeFileInfos& mfi = *pDMI->m_pMFI;
joachim99@69 1668 return column == s_ACol ? mfi.m_bDirA :
joachim99@69 1669 column == s_BCol ? mfi.m_bDirB :
joachim99@69 1670 mfi.m_bDirC;
joachim99@69 1671 }
joachim99@69 1672 return false;
joachim99@69 1673 }
joachim99@69 1674
joachim99@69 1675
joachim99@69 1676 void DirectoryMergeWindow::selectItemAndColumn(DirMergeItem* pDMI, int c, bool bContextMenu)
joachim99@69 1677 {
joachim99@69 1678 if ( bContextMenu && (
joachim99@80 1679 (pDMI==m_pSelection1Item && c==m_selection1Column) ||
joachim99@80 1680 (pDMI==m_pSelection2Item && c==m_selection2Column) ||
joachim99@80 1681 (pDMI==m_pSelection3Item && c==m_selection3Column) ) )
joachim99@69 1682 return;
joachim99@69 1683
joachim99@69 1684 DirMergeItem* pOld1=m_pSelection1Item;
joachim99@69 1685 DirMergeItem* pOld2=m_pSelection2Item;
joachim99@69 1686 DirMergeItem* pOld3=m_pSelection3Item;
joachim99@69 1687
joachim99@69 1688 bool bReset = false;
joachim99@69 1689
joachim99@69 1690 if ( m_pSelection1Item )
joachim99@69 1691 {
joachim99@69 1692 if (isDir( m_pSelection1Item, m_selection1Column )!=isDir( pDMI, c ))
joachim99@69 1693 bReset = true;
joachim99@69 1694 }
joachim99@69 1695
joachim99@69 1696 if ( bReset || m_pSelection3Item!=0 ||
joachim99@80 1697 (pDMI==m_pSelection1Item && c==m_selection1Column) ||
joachim99@80 1698 (pDMI==m_pSelection2Item && c==m_selection2Column) ||
joachim99@80 1699 (pDMI==m_pSelection3Item && c==m_selection3Column))
joachim99@69 1700 {
joachim99@69 1701 m_pSelection1Item = 0;
joachim99@69 1702 m_pSelection2Item = 0;
joachim99@69 1703 m_pSelection3Item = 0;
joachim99@69 1704 }
joachim99@69 1705 else if ( m_pSelection1Item==0 )
joachim99@69 1706 {
joachim99@69 1707 m_pSelection1Item = pDMI;
joachim99@69 1708 m_selection1Column = c;
joachim99@69 1709 m_pSelection2Item = 0;
joachim99@69 1710 m_pSelection3Item = 0;
joachim99@69 1711 }
joachim99@69 1712 else if ( m_pSelection2Item==0 )
joachim99@69 1713 {
joachim99@69 1714 m_pSelection2Item = pDMI;
joachim99@69 1715 m_selection2Column = c;
joachim99@69 1716 m_pSelection3Item = 0;
joachim99@69 1717 }
joachim99@69 1718 else if ( m_pSelection3Item==0 )
joachim99@69 1719 {
joachim99@69 1720 m_pSelection3Item = pDMI;
joachim99@69 1721 m_selection3Column = c;
joachim99@69 1722 }
joachim99@75 1723 if (pOld1) dataChanged( indexFromItem( pOld1, s_ACol ), indexFromItem( pOld1, s_CCol ) );
joachim99@75 1724 if (pOld2) dataChanged( indexFromItem( pOld2, s_ACol ), indexFromItem( pOld2, s_CCol ) );
joachim99@75 1725 if (pOld3) dataChanged( indexFromItem( pOld3, s_ACol ), indexFromItem( pOld3, s_CCol ) );
joachim99@75 1726 if (m_pSelection1Item) dataChanged( indexFromItem( m_pSelection1Item, s_ACol ), indexFromItem( m_pSelection1Item, s_CCol ) );
joachim99@75 1727 if (m_pSelection2Item) dataChanged( indexFromItem( m_pSelection2Item, s_ACol ), indexFromItem( m_pSelection2Item, s_CCol ) );
joachim99@75 1728 if (m_pSelection3Item) dataChanged( indexFromItem( m_pSelection3Item, s_ACol ), indexFromItem( m_pSelection3Item, s_CCol ) );
joachim99@69 1729 emit updateAvailabilities();
joachim99@8 1730 }
joachim99@8 1731
joachim99@75 1732 DirMergeItem::DirMergeItem( QTreeWidget* pParent, const QString& fileName, MergeFileInfos* pMFI )
joachim99@75 1733 : QTreeWidgetItem( pParent, QStringList() << fileName << "" << "" << "" << i18n("To do.") << "" )
joachim99@66 1734 {
joachim99@66 1735 init(pMFI);
joachim99@66 1736 }
joachim99@66 1737
joachim99@66 1738 DirMergeItem::DirMergeItem( DirMergeItem* pParent, const QString& fileName, MergeFileInfos* pMFI )
joachim99@75 1739 : QTreeWidgetItem( pParent, QStringList() << fileName << "" << "" << "" << i18n("To do.") << "" )
joachim99@66 1740 {
joachim99@66 1741 init(pMFI);
joachim99@66 1742 }
joachim99@66 1743
joachim99@66 1744
joachim99@66 1745 void DirMergeItem::init(MergeFileInfos* pMFI)
joachim99@8 1746 {
joachim99@8 1747 pMFI->m_pDMI = this;
joachim99@8 1748 m_pMFI = pMFI;
joachim99@66 1749 TotalDiffStatus& tds = pMFI->m_totalDiffStatus;
joachim99@66 1750 if ( m_pMFI->m_bDirA || m_pMFI->m_bDirB || m_pMFI->m_bDirC )
joachim99@66 1751 {
joachim99@66 1752 }
joachim99@66 1753 else
joachim99@66 1754 {
joachim99@66 1755 setText( s_UnsolvedCol, QString::number( tds.nofUnsolvedConflicts ) );
joachim99@66 1756 setText( s_SolvedCol, QString::number( tds.nofSolvedConflicts ) );
joachim99@66 1757 setText( s_NonWhiteCol, QString::number( tds.nofUnsolvedConflicts + tds.nofSolvedConflicts - tds.nofWhitespaceConflicts ) );
joachim99@66 1758 setText( s_WhiteCol, QString::number( tds.nofWhitespaceConflicts ) );
joachim99@66 1759 }
joachim99@80 1760 setSizeHint( s_ACol, QSize(17,17) ); // Iconsize
joachim99@80 1761 setSizeHint( s_BCol, QSize(17,17) ); // Iconsize
joachim99@80 1762 setSizeHint( s_CCol, QSize(17,17) ); // Iconsize
joachim99@8 1763 }
joachim99@8 1764
joachim99@75 1765 bool DirMergeItem::operator<(const QTreeWidgetItem& i) const
joachim99@8 1766 {
joachim99@75 1767 int col = treeWidget()->sortColumn();
joachim99@75 1768 const DirMergeItem* pDMI = static_cast<const DirMergeItem*>(&i);
joachim99@66 1769 bool bDir1 = m_pMFI->m_bDirA || m_pMFI->m_bDirB || m_pMFI->m_bDirC;
joachim99@66 1770 bool bDir2 = pDMI->m_pMFI->m_bDirA || pDMI->m_pMFI->m_bDirB || pDMI->m_pMFI->m_bDirC;
joachim99@66 1771 if ( m_pMFI==0 || pDMI->m_pMFI==0 || bDir1 == bDir2 )
joachim99@66 1772 {
joachim99@66 1773 if(col==s_UnsolvedCol || col==s_SolvedCol || col==s_NonWhiteCol || col==s_WhiteCol)
joachim99@75 1774 return text(col).toInt() > i.text(col).toInt();
joachim99@80 1775 else if ( col == s_NameCol )
joachim99@80 1776 return text(col).compare( i.text(col), Qt::CaseInsensitive )<0;
joachim99@66 1777 else
joachim99@75 1778 return QTreeWidgetItem::operator<(i);
joachim99@80 1779
joachim99@66 1780 }
joachim99@66 1781 else
joachim99@75 1782 return bDir1;
joachim99@8 1783 }
joachim99@8 1784
joachim99@66 1785
joachim99@8 1786 DirMergeItem::~DirMergeItem()
joachim99@8 1787 {
joachim99@8 1788 m_pMFI->m_pDMI = 0;
joachim99@8 1789 }
joachim99@8 1790
joachim99@77 1791 void MergeFileInfos::setMergeOperation( e_MergeOperation eMOp, bool bRecursive )
joachim99@8 1792 {
joachim99@51 1793 if ( eMOp != m_eMergeOperation )
joachim99@51 1794 {
joachim99@51 1795 m_bOperationComplete = false;
joachim99@51 1796 m_pDMI->setText( s_OpStatusCol, "" );
joachim99@51 1797 }
joachim99@51 1798
joachim99@8 1799 m_eMergeOperation = eMOp;
joachim99@51 1800 QString s;
joachim99@8 1801 bool bDir = m_bDirA || m_bDirB || m_bDirC;
joachim99@8 1802 if( m_pDMI!=0 )
joachim99@8 1803 {
joachim99@8 1804 switch( m_eMergeOperation )
joachim99@8 1805 {
joachim99@8 1806 case eNoOperation: s=""; m_pDMI->setText(s_OpCol,""); break;
joachim99@51 1807 case eCopyAToB: s=i18n("Copy A to B"); break;
joachim99@51 1808 case eCopyBToA: s=i18n("Copy B to A"); break;
joachim99@51 1809 case eDeleteA: s=i18n("Delete A"); break;
joachim99@51 1810 case eDeleteB: s=i18n("Delete B"); break;
joachim99@51 1811 case eDeleteAB: s=i18n("Delete A & B"); break;
joachim99@51 1812 case eMergeToA: s=i18n("Merge to A"); break;
joachim99@51 1813 case eMergeToB: s=i18n("Merge to B"); break;
joachim99@51 1814 case eMergeToAB: s=i18n("Merge to A & B"); break;
joachim99@8 1815 case eCopyAToDest: s="A"; break;
joachim99@8 1816 case eCopyBToDest: s="B"; break;
joachim99@8 1817 case eCopyCToDest: s="C"; break;
joachim99@51 1818 case eDeleteFromDest: s=i18n("Delete (if exists)"); break;
joachim99@51 1819 case eMergeABCToDest: s= bDir ? i18n("Merge") : i18n("Merge (manual)"); break;
joachim99@51 1820 case eMergeABToDest: s= bDir ? i18n("Merge") : i18n("Merge (manual)"); break;
joachim99@51 1821 case eConflictingFileTypes: s=i18n("Error: Conflicting File Types"); break;
joachim99@92 1822 case eChangedAndDeleted: s=i18n("Error: Changed and Deleted"); break;
joachim99@51 1823 case eConflictingAges: s=i18n("Error: Dates are equal but files are not."); break;
joachim99@8 1824 default: assert(false); break;
joachim99@8 1825 }
joachim99@8 1826 m_pDMI->setText(s_OpCol,s);
joachim99@8 1827
joachim99@77 1828 if ( bRecursive )
joachim99@8 1829 {
joachim99@77 1830 e_MergeOperation eChildrenMergeOp = m_eMergeOperation;
joachim99@77 1831 if ( eChildrenMergeOp == eConflictingFileTypes ) eChildrenMergeOp = eMergeABCToDest;
joachim99@77 1832 for( int childIdx=0; childIdx<m_pDMI->childCount(); ++childIdx )
joachim99@77 1833 {
joachim99@77 1834 QTreeWidgetItem* p = m_pDMI->child(childIdx);
joachim99@77 1835 DirMergeItem* pDMI = static_cast<DirMergeItem*>( p );
joachim99@77 1836 DirectoryMergeWindow* pDMW = static_cast<DirectoryMergeWindow*>( p->treeWidget() );
joachim99@77 1837 pDMW->calcSuggestedOperation( *pDMI->m_pMFI, eChildrenMergeOp );
joachim99@77 1838 }
joachim99@8 1839 }
joachim99@8 1840 }
joachim99@8 1841 }
joachim99@8 1842
joachim99@8 1843 void DirectoryMergeWindow::compareCurrentFile()
joachim99@8 1844 {
joachim99@8 1845 if (!canContinue()) return;
joachim99@8 1846
joachim99@8 1847 if ( m_bRealMergeStarted )
joachim99@8 1848 {
joachim99@51 1849 KMessageBox::sorry(this,i18n("This operation is currently not possible."),i18n("Operation Not Possible"));
joachim99@8 1850 return;
joachim99@8 1851 }
joachim99@8 1852
joachim99@75 1853 if ( currentItem() != 0 )
joachim99@8 1854 {
joachim99@75 1855 DirMergeItem* pDMI = static_cast<DirMergeItem*>( currentItem() );
joachim99@8 1856 MergeFileInfos& mfi = *pDMI->m_pMFI;
joachim99@8 1857 if ( !(mfi.m_bDirA || mfi.m_bDirB || mfi.m_bDirC) )
joachim99@8 1858 {
joachim99@8 1859 emit startDiffMerge(
joachim99@80 1860 mfi.m_bExistsInA ? mfi.m_fileInfoA.absoluteFilePath() : QString(""),
joachim99@80 1861 mfi.m_bExistsInB ? mfi.m_fileInfoB.absoluteFilePath() : QString(""),
joachim99@80 1862 mfi.m_bExistsInC ? mfi.m_fileInfoC.absoluteFilePath() : QString(""),
joachim99@8 1863 "",
joachim99@66 1864 "","","",0
joachim99@8 1865 );
joachim99@8 1866 }
joachim99@8 1867 }
joachim99@8 1868 emit updateAvailabilities();
joachim99@8 1869 }
joachim99@8 1870
joachim99@8 1871
joachim99@69 1872 void DirectoryMergeWindow::slotCompareExplicitlySelectedFiles()
joachim99@69 1873 {
joachim99@69 1874 if ( ! isDir(m_pSelection1Item,m_selection1Column) && !canContinue() ) return;
joachim99@69 1875
joachim99@69 1876 if ( m_bRealMergeStarted )
joachim99@69 1877 {
joachim99@69 1878 KMessageBox::sorry(this,i18n("This operation is currently not possible."),i18n("Operation Not Possible"));
joachim99@69 1879 return;
joachim99@69 1880 }
joachim99@69 1881
joachim99@69 1882 emit startDiffMerge(
joachim99@69 1883 getFileName( m_pSelection1Item, m_selection1Column ),
joachim99@69 1884 getFileName( m_pSelection2Item, m_selection2Column ),
joachim99@69 1885 getFileName( m_pSelection3Item, m_selection3Column ),
joachim99@69 1886 "",
joachim99@69 1887 "","","",0
joachim99@69 1888 );
joachim99@69 1889 m_pSelection1Item=0;
joachim99@69 1890 m_pSelection2Item=0;
joachim99@69 1891 m_pSelection3Item=0;
joachim99@69 1892
joachim99@69 1893 emit updateAvailabilities();
joachim99@75 1894 update();
joachim99@69 1895 }
joachim99@69 1896
joachim99@69 1897 void DirectoryMergeWindow::slotMergeExplicitlySelectedFiles()
joachim99@69 1898 {
joachim99@69 1899 if ( ! isDir(m_pSelection1Item,m_selection1Column) && !canContinue() ) return;
joachim99@69 1900
joachim99@69 1901 if ( m_bRealMergeStarted )
joachim99@69 1902 {
joachim99@69 1903 KMessageBox::sorry(this,i18n("This operation is currently not possible."),i18n("Operation Not Possible"));
joachim99@69 1904 return;
joachim99@69 1905 }
joachim99@69 1906
joachim99@69 1907 QString fn1 = getFileName( m_pSelection1Item, m_selection1Column );
joachim99@69 1908 QString fn2 = getFileName( m_pSelection2Item, m_selection2Column );
joachim99@69 1909 QString fn3 = getFileName( m_pSelection3Item, m_selection3Column );
joachim99@69 1910
joachim99@69 1911 emit startDiffMerge( fn1, fn2, fn3,
joachim99@69 1912 fn3.isEmpty() ? fn2 : fn3,
joachim99@69 1913 "","","",0
joachim99@69 1914 );
joachim99@69 1915 m_pSelection1Item=0;
joachim99@69 1916 m_pSelection2Item=0;
joachim99@69 1917 m_pSelection3Item=0;
joachim99@69 1918
joachim99@69 1919 emit updateAvailabilities();
joachim99@75 1920 update();
joachim99@69 1921 }
joachim99@8 1922
joachim99@8 1923 bool DirectoryMergeWindow::isFileSelected()
joachim99@8 1924 {
joachim99@75 1925 if ( currentItem() != 0 )
joachim99@8 1926 {
joachim99@75 1927 DirMergeItem* pDMI = static_cast<DirMergeItem*>( currentItem() );
joachim99@8 1928 MergeFileInfos& mfi = *pDMI->m_pMFI;
joachim99@8 1929 return ! (mfi.m_bDirA || mfi.m_bDirB || mfi.m_bDirC || conflictingFileTypes(mfi) );
joachim99@8 1930 }
joachim99@8 1931 return false;
joachim99@8 1932 }
joachim99@8 1933
joachim99@8 1934 void DirectoryMergeWindow::mergeResultSaved(const QString& fileName)
joachim99@8 1935 {
joachim99@51 1936 DirMergeItem* pCurrentItemForOperation = (m_mergeItemList.empty() || m_currentItemForOperation==m_mergeItemList.end() )
joachim99@51 1937 ? 0
joachim99@51 1938 : *m_currentItemForOperation;
joachim99@51 1939
joachim99@51 1940 if ( pCurrentItemForOperation!=0 && pCurrentItemForOperation->m_pMFI==0 )
joachim99@8 1941 {
joachim99@51 1942 KMessageBox::error( this, i18n("This should never happen: \n\nmergeResultSaved: m_pMFI=0\n\nIf you know how to reproduce this, please contact the program author."),i18n("Program Error") );
joachim99@8 1943 return;
joachim99@8 1944 }
joachim99@51 1945 if ( pCurrentItemForOperation!=0 && fileName == fullNameDest(*pCurrentItemForOperation->m_pMFI) )
joachim99@8 1946 {
joachim99@51 1947 if ( pCurrentItemForOperation->m_pMFI->m_eMergeOperation==eMergeToAB )
joachim99@8 1948 {
joachim99@51 1949 MergeFileInfos& mfi = *pCurrentItemForOperation->m_pMFI;
joachim99@8 1950 bool bSuccess = copyFLD( fullNameB(mfi), fullNameA(mfi) );
joachim99@8 1951 if (!bSuccess)
joachim99@8 1952 {
joachim99@51 1953 KMessageBox::error(this, i18n("An error occurred while copying.\n"), i18n("Error") );
joachim99@75 1954 m_pStatusInfo->setWindowTitle(i18n("Merge Error"));
joachim99@80 1955 m_pStatusInfo->showMaximized();
joachim99@69 1956 //if ( m_pStatusInfo->firstChild()!=0 )
joachim99@69 1957 // m_pStatusInfo->ensureItemVisible( m_pStatusInfo->last() );
joachim99@8 1958 m_bError = true;
joachim99@51 1959 pCurrentItemForOperation->setText( s_OpStatusCol, i18n("Error.") );
joachim99@8 1960 mfi.m_eMergeOperation = eCopyBToA;
joachim99@8 1961 return;
joachim99@8 1962 }
joachim99@8 1963 }
joachim99@51 1964 pCurrentItemForOperation->setText( s_OpStatusCol, i18n("Done.") );
joachim99@51 1965 pCurrentItemForOperation->m_pMFI->m_bOperationComplete = true;
joachim99@51 1966 if ( m_mergeItemList.size()==1 )
joachim99@51 1967 {
joachim99@51 1968 m_mergeItemList.clear();
joachim99@51 1969 m_bRealMergeStarted=false;
joachim99@51 1970 }
joachim99@8 1971 }
joachim99@8 1972
joachim99@8 1973 emit updateAvailabilities();
joachim99@8 1974 }
joachim99@8 1975
joachim99@8 1976 bool DirectoryMergeWindow::canContinue()
joachim99@8 1977 {
joachim99@8 1978 bool bCanContinue=false;
joachim99@8 1979 checkIfCanContinue( &bCanContinue );
joachim99@8 1980 if ( bCanContinue && !m_bError )
joachim99@8 1981 {
joachim99@51 1982 DirMergeItem* pCurrentItemForOperation =
joachim99@51 1983 (m_mergeItemList.empty() || m_currentItemForOperation==m_mergeItemList.end() ) ? 0 : *m_currentItemForOperation;
joachim99@51 1984
joachim99@51 1985 if ( pCurrentItemForOperation!=0 && ! pCurrentItemForOperation->m_pMFI->m_bOperationComplete )
joachim99@8 1986 {
joachim99@51 1987 pCurrentItemForOperation->setText( s_OpStatusCol, i18n("Not saved.") );
joachim99@51 1988 pCurrentItemForOperation->m_pMFI->m_bOperationComplete = true;
joachim99@51 1989 if ( m_mergeItemList.size()==1 )
joachim99@51 1990 {
joachim99@51 1991 m_mergeItemList.clear();
joachim99@51 1992 m_bRealMergeStarted=false;
joachim99@51 1993 }
joachim99@8 1994 }
joachim99@8 1995 }
joachim99@8 1996 return bCanContinue;
joachim99@8 1997 }
joachim99@8 1998
joachim99@51 1999 bool DirectoryMergeWindow::executeMergeOperation( MergeFileInfos& mfi, bool& bSingleFileMerge )
joachim99@8 2000 {
joachim99@51 2001 bool bCreateBackups = m_pOptions->m_bDmCreateBakFiles;
joachim99@51 2002 // First decide destname
joachim99@51 2003 QString destName;
joachim99@51 2004 switch( mfi.m_eMergeOperation )
joachim99@51 2005 {
joachim99@51 2006 case eNoOperation: break;
joachim99@51 2007 case eDeleteAB: break;
joachim99@51 2008 case eMergeToAB: // let the user save in B. In mergeResultSaved() the file will be copied to A.
joachim99@51 2009 case eMergeToB:
joachim99@51 2010 case eDeleteB:
joachim99@51 2011 case eCopyAToB: destName = fullNameB(mfi); break;
joachim99@51 2012 case eMergeToA:
joachim99@51 2013 case eDeleteA:
joachim99@51 2014 case eCopyBToA: destName = fullNameA(mfi); break;
joachim99@51 2015 case eMergeABToDest:
joachim99@51 2016 case eMergeABCToDest:
joachim99@51 2017 case eCopyAToDest:
joachim99@51 2018 case eCopyBToDest:
joachim99@51 2019 case eCopyCToDest:
joachim99@51 2020 case eDeleteFromDest: destName = fullNameDest(mfi); break;
joachim99@51 2021 default:
joachim99@51 2022 KMessageBox::error( this, i18n("Unknown merge operation. (This must never happen!)"), i18n("Error") );
joachim99@51 2023 assert(false);
joachim99@51 2024 }
joachim99@8 2025
joachim99@51 2026 bool bSuccess = false;
joachim99@51 2027 bSingleFileMerge = false;
joachim99@51 2028 switch( mfi.m_eMergeOperation )
joachim99@51 2029 {
joachim99@51 2030 case eNoOperation: bSuccess = true; break;
joachim99@51 2031 case eCopyAToDest:
joachim99@51 2032 case eCopyAToB: bSuccess = copyFLD( fullNameA(mfi), destName ); break;
joachim99@51 2033 case eCopyBToDest:
joachim99@51 2034 case eCopyBToA: bSuccess = copyFLD( fullNameB(mfi), destName ); break;
joachim99@51 2035 case eCopyCToDest: bSuccess = copyFLD( fullNameC(mfi), destName ); break;
joachim99@51 2036 case eDeleteFromDest:
joachim99@51 2037 case eDeleteA:
joachim99@51 2038 case eDeleteB: bSuccess = deleteFLD( destName, bCreateBackups ); break;
joachim99@51 2039 case eDeleteAB: bSuccess = deleteFLD( fullNameA(mfi), bCreateBackups ) &&
joachim99@51 2040 deleteFLD( fullNameB(mfi), bCreateBackups ); break;
joachim99@51 2041 case eMergeABToDest:
joachim99@51 2042 case eMergeToA:
joachim99@51 2043 case eMergeToAB:
joachim99@51 2044 case eMergeToB: bSuccess = mergeFLD( fullNameA(mfi), fullNameB(mfi), "",
joachim99@51 2045 destName, bSingleFileMerge );
joachim99@51 2046 break;
joachim99@51 2047 case eMergeABCToDest:bSuccess = mergeFLD(
joachim99@51 2048 mfi.m_bExistsInA ? fullNameA(mfi) : QString(""),
joachim99@51 2049 mfi.m_bExistsInB ? fullNameB(mfi) : QString(""),
joachim99@51 2050 mfi.m_bExistsInC ? fullNameC(mfi) : QString(""),
joachim99@51 2051 destName, bSingleFileMerge );
joachim99@51 2052 break;
joachim99@51 2053 default:
joachim99@51 2054 KMessageBox::error( this, i18n("Unknown merge operation."), i18n("Error") );
joachim99@51 2055 assert(false);
joachim99@51 2056 }
joachim99@8 2057
joachim99@51 2058 return bSuccess;
joachim99@51 2059 }
joachim99@8 2060
joachim99@51 2061
joachim99@51 2062 // Check if the merge can start, and prepare the m_mergeItemList which then contains all
joachim99@51 2063 // items that must be merged.
joachim99@75 2064 void DirectoryMergeWindow::prepareMergeStart( QTreeWidgetItem* pBegin, QTreeWidgetItem* pEnd, bool bVerbose )
joachim99@51 2065 {
joachim99@51 2066 if ( bVerbose )
joachim99@8 2067 {
joachim99@51 2068 int status = KMessageBox::warningYesNoCancel(this,
joachim99@51 2069 i18n("The merge is about to begin.\n\n"
joachim99@51 2070 "Choose \"Do it\" if you have read the instructions and know what you are doing.\n"
joachim99@51 2071 "Choosing \"Simulate it\" will tell you what would happen.\n\n"
joachim99@51 2072 "Be aware that this program still has beta status "
joachim99@51 2073 "and there is NO WARRANTY whatsoever! Make backups of your vital data!"),
joachim99@80 2074 i18n("Starting Merge"),
joachim99@80 2075 KGuiItem( i18n("Do It") ),
joachim99@80 2076 KGuiItem( i18n("Simulate It") ) );
joachim99@51 2077 if (status==KMessageBox::Yes) m_bRealMergeStarted = true;
joachim99@51 2078 else if (status==KMessageBox::No ) m_bSimulatedMergeStarted = true;
joachim99@51 2079 else return;
joachim99@51 2080 }
joachim99@51 2081 else
joachim99@51 2082 {
joachim99@51 2083 m_bRealMergeStarted = true;
joachim99@51 2084 }
joachim99@51 2085
joachim99@51 2086 m_mergeItemList.clear();
joachim99@51 2087 if (pBegin == 0)
joachim99@51 2088 return;
joachim99@51 2089
joachim99@75 2090 for( QTreeWidgetItem* p = pBegin; p!= pEnd; p = treeIterator( p ) )
joachim99@51 2091 {
joachim99@51 2092 DirMergeItem* pDMI = static_cast<DirMergeItem*>(p);
joachim99@51 2093
joachim99@69 2094 if ( pDMI && ! pDMI->m_pMFI->m_bOperationComplete )
joachim99@8 2095 {
joachim99@51 2096 m_mergeItemList.push_back(pDMI);
joachim99@51 2097
joachim99@8 2098 if (pDMI!=0 && pDMI->m_pMFI->m_eMergeOperation == eConflictingFileTypes )
joachim99@8 2099 {
joachim99@75 2100 scrollToItem( pDMI, QAbstractItemView::EnsureVisible );
joachim99@75 2101 pDMI->setSelected( true );
joachim99@51 2102 KMessageBox::error(this, i18n("The highlighted item has a different type in the different directories. Select what to do."), i18n("Error"));
joachim99@51 2103 m_mergeItemList.clear();
joachim99@51 2104 m_bRealMergeStarted=false;
joachim99@8 2105 return;
joachim99@8 2106 }
joachim99@8 2107 if (pDMI!=0 && pDMI->m_pMFI->m_eMergeOperation == eConflictingAges )
joachim99@8 2108 {
joachim99@75 2109 scrollToItem ( pDMI, QAbstractItemView::EnsureVisible );
joachim99@75 2110 pDMI->setSelected( true );
joachim99@51 2111 KMessageBox::error(this, i18n("The modification dates of the file are equal but the files are not. Select what to do."), i18n("Error"));
joachim99@51 2112 m_mergeItemList.clear();
joachim99@51 2113 m_bRealMergeStarted=false;
joachim99@8 2114 return;
joachim99@8 2115 }
joachim99@92 2116 if (pDMI!=0 && pDMI->m_pMFI->m_eMergeOperation == eChangedAndDeleted )
joachim99@92 2117 {
joachim99@92 2118 scrollToItem( pDMI, QAbstractItemView::EnsureVisible );
joachim99@92 2119 pDMI->setSelected( true );
joachim99@92 2120 KMessageBox::error(this, i18n("The highlighted item was changed in one directory and deleted in the other. Select what to do."), i18n("Error"));
joachim99@92 2121 m_mergeItemList.clear();
joachim99@92 2122 m_bRealMergeStarted=false;
joachim99@92 2123 return;
joachim99@92 2124 }
joachim99@8 2125 }
joachim99@8 2126 }
joachim99@8 2127
joachim99@51 2128 m_currentItemForOperation = m_mergeItemList.begin();
joachim99@51 2129 return;
joachim99@51 2130 }
joachim99@51 2131
joachim99@51 2132 void DirectoryMergeWindow::slotRunOperationForCurrentItem()
joachim99@51 2133 {
joachim99@51 2134 if ( ! canContinue() ) return;
joachim99@51 2135
joachim99@51 2136 bool bVerbose = false;
joachim99@51 2137 if ( m_mergeItemList.empty() )
joachim99@51 2138 {
joachim99@75 2139 QTreeWidgetItem* pBegin = currentItem();
joachim99@75 2140 QTreeWidgetItem* pEnd = treeIterator(pBegin,false,false); // find next visible sibling (no children)
joachim99@51 2141
joachim99@53 2142 prepareMergeStart( pBegin, pEnd, bVerbose );
joachim99@51 2143 mergeContinue(true, bVerbose);
joachim99@51 2144 }
joachim99@51 2145 else
joachim99@51 2146 mergeContinue(false, bVerbose);
joachim99@51 2147 }
joachim99@51 2148
joachim99@51 2149 void DirectoryMergeWindow::slotRunOperationForAllItems()
joachim99@51 2150 {
joachim99@51 2151 if ( ! canContinue() ) return;
joachim99@51 2152
joachim99@51 2153 bool bVerbose = true;
joachim99@51 2154 if ( m_mergeItemList.empty() )
joachim99@51 2155 {
joachim99@75 2156 QTreeWidgetItem* pBegin = topLevelItemCount()>0 ? topLevelItem(0) : 0;
joachim99@51 2157
joachim99@51 2158 prepareMergeStart( pBegin, 0, bVerbose );
joachim99@51 2159 mergeContinue(true, bVerbose);
joachim99@51 2160 }
joachim99@51 2161 else
joachim99@51 2162 mergeContinue(false, bVerbose);
joachim99@51 2163 }
joachim99@51 2164
joachim99@51 2165 void DirectoryMergeWindow::mergeCurrentFile()
joachim99@51 2166 {
joachim99@51 2167 if (!canContinue()) return;
joachim99@51 2168
joachim99@51 2169 if ( m_bRealMergeStarted )
joachim99@51 2170 {
joachim99@66 2171 KMessageBox::sorry(this,i18n("This operation is currently not possible because directory merge is currently running."),i18n("Operation Not Possible"));
joachim99@51 2172 return;
joachim99@51 2173 }
joachim99@51 2174
joachim99@51 2175 if ( isFileSelected() )
joachim99@51 2176 {
joachim99@75 2177 DirMergeItem* pDMI = static_cast<DirMergeItem*>( currentItem() );
joachim99@51 2178 if ( pDMI != 0 )
joachim99@51 2179 {
joachim99@51 2180 MergeFileInfos& mfi = *pDMI->m_pMFI;
joachim99@51 2181 m_mergeItemList.clear();
joachim99@51 2182 m_mergeItemList.push_back( pDMI );
joachim99@51 2183 m_currentItemForOperation=m_mergeItemList.begin();
joachim99@51 2184 bool bDummy=false;
joachim99@51 2185 mergeFLD(
joachim99@80 2186 mfi.m_bExistsInA ? mfi.m_fileInfoA.absoluteFilePath() : QString(""),
joachim99@80 2187 mfi.m_bExistsInB ? mfi.m_fileInfoB.absoluteFilePath() : QString(""),
joachim99@80 2188 mfi.m_bExistsInC ? mfi.m_fileInfoC.absoluteFilePath() : QString(""),
joachim99@51 2189 fullNameDest(mfi),
joachim99@51 2190 bDummy
joachim99@51 2191 );
joachim99@51 2192 }
joachim99@51 2193 }
joachim99@51 2194 emit updateAvailabilities();
joachim99@51 2195 }
joachim99@51 2196
joachim99@51 2197
joachim99@51 2198 // When bStart is true then m_currentItemForOperation must still be processed.
joachim99@51 2199 // When bVerbose is true then a messagebox will tell when the merge is complete.
joachim99@51 2200 void DirectoryMergeWindow::mergeContinue(bool bStart, bool bVerbose)
joachim99@51 2201 {
joachim99@66 2202 ProgressProxy pp;
joachim99@51 2203 if ( m_mergeItemList.empty() )
joachim99@51 2204 return;
joachim99@51 2205
joachim99@51 2206 int nrOfItems = 0;
joachim99@51 2207 int nrOfCompletedItems = 0;
joachim99@51 2208 int nrOfCompletedSimItems = 0;
joachim99@51 2209
joachim99@51 2210 // Count the number of completed items (for the progress bar).
joachim99@51 2211 for( MergeItemList::iterator i = m_mergeItemList.begin(); i!=m_mergeItemList.end(); ++i )
joachim99@51 2212 {
joachim99@53 2213 DirMergeItem* pDMI = *i;
joachim99@51 2214 ++nrOfItems;
joachim99@51 2215 if ( pDMI->m_pMFI->m_bOperationComplete )
joachim99@51 2216 ++nrOfCompletedItems;
joachim99@51 2217 if ( pDMI->m_pMFI->m_bSimOpComplete )
joachim99@51 2218 ++nrOfCompletedSimItems;
joachim99@51 2219 }
joachim99@51 2220
joachim99@51 2221 m_pStatusInfo->hide();
joachim99@51 2222 m_pStatusInfo->clear();
joachim99@51 2223
joachim99@51 2224 DirMergeItem* pCurrentItemForOperation = m_currentItemForOperation==m_mergeItemList.end() ? 0 : *m_currentItemForOperation;
joachim99@51 2225
joachim99@51 2226 bool bContinueWithCurrentItem = bStart; // true for first item, else false
joachim99@8 2227 bool bSkipItem = false;
joachim99@51 2228 if ( !bStart && m_bError && pCurrentItemForOperation!=0 )
joachim99@8 2229 {
joachim99@8 2230 int status = KMessageBox::warningYesNoCancel(this,
joachim99@8 2231 i18n("There was an error in the last step.\n"
joachim99@8 2232 "Do you want to continue with the item that caused the error or do you want to skip this item?"),
joachim99@80 2233 i18n("Continue merge after an error"),
joachim99@80 2234 KGuiItem( i18n("Continue With Last Item") ),
joachim99@80 2235 KGuiItem( i18n("Skip Item") ) );
joachim99@51 2236 if (status==KMessageBox::Yes) bContinueWithCurrentItem = true;
joachim99@8 2237 else if (status==KMessageBox::No ) bSkipItem = true;
joachim99@8 2238 else return;
joachim99@8 2239 m_bError = false;
joachim99@8 2240 }
joachim99@8 2241
joachim99@8 2242 bool bSuccess = true;
joachim99@8 2243 bool bSingleFileMerge = false;
joachim99@8 2244 bool bSim = m_bSimulatedMergeStarted;
joachim99@8 2245 while( bSuccess )
joachim99@8 2246 {
joachim99@51 2247 if ( pCurrentItemForOperation==0 )
joachim99@51 2248 {
joachim99@51 2249 m_mergeItemList.clear();
joachim99@51 2250 m_bRealMergeStarted=false;
joachim99@51 2251 break;
joachim99@51 2252 }
joachim99@51 2253
joachim99@51 2254 if ( pCurrentItemForOperation!=0 && !bContinueWithCurrentItem )
joachim99@8 2255 {
joachim99@8 2256 if ( bSim )
joachim99@8 2257 {
joachim99@75 2258 if( pCurrentItemForOperation->childCount()==0 )
joachim99@8 2259 {
joachim99@51 2260 pCurrentItemForOperation->m_pMFI->m_bSimOpComplete = true;
joachim99@8 2261 }
joachim99@8 2262 }
joachim99@8 2263 else
joachim99@8 2264 {
joachim99@75 2265 if( pCurrentItemForOperation->childCount()==0 )
joachim99@8 2266 {
joachim99@51 2267 if( !pCurrentItemForOperation->m_pMFI->m_bOperationComplete )
joachim99@8 2268 {
joachim99@51 2269 pCurrentItemForOperation->setText( s_OpStatusCol, bSkipItem ? i18n("Skipped.") : i18n("Done.") );
joachim99@51 2270 pCurrentItemForOperation->m_pMFI->m_bOperationComplete = true;
joachim99@8 2271 bSkipItem = false;
joachim99@8 2272 }
joachim99@8 2273 }
joachim99@8 2274 else
joachim99@8 2275 {
joachim99@51 2276 pCurrentItemForOperation->setText( s_OpStatusCol, i18n("In progress...") );
joachim99@8 2277 }
joachim99@8 2278 }
joachim99@8 2279 }
joachim99@8 2280
joachim99@51 2281 if ( ! bContinueWithCurrentItem )
joachim99@8 2282 {
joachim99@51 2283 // Depth first
joachim99@75 2284 QTreeWidgetItem* pPrevItem = pCurrentItemForOperation;
joachim99@51 2285 ++m_currentItemForOperation;
joachim99@51 2286 pCurrentItemForOperation = m_currentItemForOperation==m_mergeItemList.end() ? 0 : *m_currentItemForOperation;
joachim99@51 2287 if ( (pCurrentItemForOperation==0 || pCurrentItemForOperation->parent()!=pPrevItem->parent()) && pPrevItem->parent()!=0 )
joachim99@8 2288 {
joachim99@51 2289 // Check if the parent may be set to "Done"
joachim99@75 2290 QTreeWidgetItem* pParent = pPrevItem->parent();
joachim99@51 2291 bool bDone = true;
joachim99@51 2292 while ( bDone && pParent!=0 )
joachim99@8 2293 {
joachim99@75 2294 for( int childIdx = 0; childIdx<pParent->childCount(); ++childIdx )
joachim99@8 2295 {
joachim99@75 2296 DirMergeItem* pDMI = static_cast<DirMergeItem*>(pParent->child(childIdx));
joachim99@80 2297 if ( (!bSim && ! pDMI->m_pMFI->m_bOperationComplete) || (bSim && pDMI->m_pMFI->m_bSimOpComplete) )
joachim99@8 2298 {
joachim99@51 2299 bDone=false;
joachim99@51 2300 break;
joachim99@8 2301 }
joachim99@8 2302 }
joachim99@51 2303 if ( bDone )
joachim99@51 2304 {
joachim99@51 2305 if (bSim)
joachim99@51 2306 static_cast<DirMergeItem*>(pParent)->m_pMFI->m_bSimOpComplete = bDone;
joachim99@51 2307 else
joachim99@51 2308 {
joachim99@51 2309 pParent->setText( s_OpStatusCol, i18n("Done.") );
joachim99@51 2310 static_cast<DirMergeItem*>(pParent)->m_pMFI->m_bOperationComplete = bDone;
joachim99@51 2311 }
joachim99@51 2312 }
joachim99@51 2313 pParent = pParent->parent();
joachim99@8 2314 }
joachim99@8 2315 }
joachim99@8 2316 }
joachim99@8 2317
joachim99@51 2318 if ( pCurrentItemForOperation == 0 ) // end?
joachim99@8 2319 {
joachim99@8 2320 if ( m_bRealMergeStarted )
joachim99@8 2321 {
joachim99@51 2322 if (bVerbose)
joachim99@51 2323 {
joachim99@51 2324 KMessageBox::information( this, i18n("Merge operation complete."), i18n("Merge Complete") );
joachim99@51 2325 }
joachim99@8 2326 m_bRealMergeStarted = false;
joachim99@75 2327 m_pStatusInfo->setWindowTitle(i18n("Merge Complete"));
joachim99@8 2328 }
joachim99@8 2329 if ( m_bSimulatedMergeStarted )
joachim99@8 2330 {
joachim99@8 2331 m_bSimulatedMergeStarted = false;
joachim99@75 2332 QTreeWidgetItem* p = topLevelItemCount()>0 ? topLevelItem(0) : 0;
joachim99@75 2333 for( ; p!=0; p=treeIterator(p) )
joachim99@8 2334 {
joachim99@8 2335 static_cast<DirMergeItem*>(p)->m_pMFI->m_bSimOpComplete = false;
joachim99@8 2336 }
joachim99@75 2337 m_pStatusInfo->setWindowTitle(i18n("Simulated merge complete: Check if you agree with the proposed operations."));
joachim99@80 2338 m_pStatusInfo->showMaximized();
joachim99@8 2339 }
joachim99@51 2340 m_mergeItemList.clear();
joachim99@51 2341 m_bRealMergeStarted=false;
joachim99@8 2342 return;
joachim99@8 2343 }
joachim99@8 2344
joachim99@51 2345 MergeFileInfos& mfi = *pCurrentItemForOperation->m_pMFI;
joachim99@8 2346
joachim99@66 2347 pp.setInformation( mfi.m_subPath,
joachim99@8 2348 bSim ? double(nrOfCompletedSimItems)/nrOfItems : double(nrOfCompletedItems)/nrOfItems,
joachim99@51 2349 false // bRedrawUpdate
joachim99@8 2350 );
joachim99@8 2351
joachim99@51 2352 bSuccess = executeMergeOperation( mfi, bSingleFileMerge ); // Here the real operation happens.
joachim99@8 2353
joachim99@8 2354 if ( bSuccess )
joachim99@8 2355 {
joachim99@8 2356 if(bSim) ++nrOfCompletedSimItems;
joachim99@8 2357 else ++nrOfCompletedItems;
joachim99@8 2358 bContinueWithCurrentItem = false;
joachim99@8 2359 }
joachim99@51 2360
joachim99@66 2361 if( pp.wasCancelled() )
joachim99@51 2362 break;
joachim99@8 2363 } // end while
joachim99@8 2364
joachim99@66 2365 //g_pProgressDialog->hide();
joachim99@8 2366
joachim99@51 2367 setCurrentItem( pCurrentItemForOperation );
joachim99@75 2368 scrollToItem( pCurrentItemForOperation, EnsureVisible );
joachim99@8 2369 if ( !bSuccess && !bSingleFileMerge )
joachim99@8 2370 {
joachim99@51 2371 KMessageBox::error(this, i18n("An error occurred. Press OK to see detailed information.\n"), i18n("Error") );
joachim99@75 2372 m_pStatusInfo->setWindowTitle(i18n("Merge Error"));
joachim99@80 2373 m_pStatusInfo->showMaximized();
joachim99@69 2374 //if ( m_pStatusInfo->firstChild()!=0 )
joachim99@69 2375 // m_pStatusInfo->ensureItemVisible( m_pStatusInfo->last() );
joachim99@8 2376 m_bError = true;
joachim99@51 2377 pCurrentItemForOperation->setText( s_OpStatusCol, i18n("Error.") );
joachim99@8 2378 }
joachim99@8 2379 else
joachim99@8 2380 {
joachim99@8 2381 m_bError = false;
joachim99@8 2382 }
joachim99@8 2383 emit updateAvailabilities();
joachim99@51 2384
joachim99@51 2385 if ( m_currentItemForOperation==m_mergeItemList.end() )
joachim99@51 2386 {
joachim99@51 2387 m_mergeItemList.clear();
joachim99@51 2388 m_bRealMergeStarted=false;
joachim99@51 2389 }
joachim99@8 2390 }
joachim99@8 2391
joachim99@8 2392 bool DirectoryMergeWindow::deleteFLD( const QString& name, bool bCreateBackup )
joachim99@8 2393 {
joachim99@8 2394 FileAccess fi(name, true);
joachim99@8 2395 if ( !fi.exists() )
joachim99@8 2396 return true;
joachim99@8 2397
joachim99@8 2398 if ( bCreateBackup )
joachim99@8 2399 {
joachim99@8 2400 bool bSuccess = renameFLD( name, name+".orig" );
joachim99@8 2401 if (!bSuccess)
joachim99@8 2402 {
joachim99@80 2403 m_pStatusInfo->addText( i18n("Error: While deleting %1: Creating backup failed.",name) );
joachim99@8 2404 return false;
joachim99@8 2405 }
joachim99@8 2406 }
joachim99@8 2407 else
joachim99@8 2408 {
joachim99@8 2409 if ( fi.isDir() && !fi.isSymLink() )
joachim99@80 2410 m_pStatusInfo->addText(i18n("delete directory recursively( %1 )",name));
joachim99@8 2411 else
joachim99@80 2412 m_pStatusInfo->addText(i18n("delete( %1 )",name));
joachim99@8 2413
joachim99@8 2414 if ( m_bSimulatedMergeStarted )
joachim99@8 2415 {
joachim99@8 2416 return true;
joachim99@8 2417 }
joachim99@8 2418
joachim99@8 2419 if ( fi.isDir() && !fi.isSymLink() )// recursive directory delete only for real dirs, not symlinks
joachim99@8 2420 {
joachim99@8 2421 t_DirectoryList dirList;
joachim99@8 2422 bool bSuccess = fi.listDir( &dirList, false, true, "*", "", "", false, false ); // not recursive, find hidden files
joachim99@8 2423
joachim99@8 2424 if ( !bSuccess )
joachim99@8 2425 {
joachim99@8 2426 // No Permission to read directory or other error.
joachim99@51 2427 m_pStatusInfo->addText( i18n("Error: delete dir operation failed while trying to read the directory.") );
joachim99@8 2428 return false;
joachim99@8 2429 }
joachim99@8 2430
joachim99@8 2431 t_DirectoryList::iterator it; // create list iterator
joachim99@8 2432
joachim99@8 2433 for ( it=dirList.begin(); it!=dirList.end(); ++it ) // for each file...
joachim99@8 2434 {
joachim99@8 2435 FileAccess& fi2 = *it;
joachim99@8 2436 if ( fi2.fileName() == "." || fi2.fileName()==".." )
joachim99@8 2437 continue;
joachim99@80 2438 bSuccess = deleteFLD( fi2.absoluteFilePath(), false );
joachim99@8 2439 if (!bSuccess) break;
joachim99@8 2440 }
joachim99@8 2441 if (bSuccess)
joachim99@8 2442 {
joachim99@8 2443 bSuccess = FileAccess::removeDir( name );
joachim99@8 2444 if ( !bSuccess )
joachim99@8 2445 {
joachim99@80 2446 m_pStatusInfo->addText( i18n("Error: rmdir( %1 ) operation failed.",name));
joachim99@8 2447 return false;
joachim99@8 2448 }
joachim99@8 2449 }
joachim99@8 2450 }
joachim99@8 2451 else
joachim99@8 2452 {
joachim99@8 2453 bool bSuccess = FileAccess::removeFile( name );
joachim99@8 2454 if ( !bSuccess )
joachim99@8 2455 {
joachim99@51 2456 m_pStatusInfo->addText( i18n("Error: delete operation failed.") );
joachim99@8 2457 return false;
joachim99@8 2458 }
joachim99@8 2459 }
joachim99@8 2460 }
joachim99@8 2461 return true;
joachim99@8 2462 }
joachim99@8 2463
joachim99@8 2464 bool DirectoryMergeWindow::mergeFLD( const QString& nameA,const QString& nameB,const QString& nameC,const QString& nameDest, bool& bSingleFileMerge )
joachim99@8 2465 {
joachim99@8 2466 FileAccess fi(nameA);
joachim99@8 2467 if (fi.isDir())
joachim99@8 2468 {
joachim99@8 2469 return makeDir(nameDest);
joachim99@8 2470 }
joachim99@8 2471
joachim99@8 2472 // Make sure that the dir exists, into which we will save the file later.
joachim99@75 2473 int pos=nameDest.lastIndexOf('/');
joachim99@8 2474 if ( pos>0 )
joachim99@8 2475 {
joachim99@8 2476 QString parentName = nameDest.left(pos);
joachim99@8 2477 bool bSuccess = makeDir(parentName, true /*quiet*/);
joachim99@8 2478 if (!bSuccess)
joachim99@8 2479 return false;
joachim99@8 2480 }
joachim99@8 2481
joachim99@80 2482 m_pStatusInfo->addText(i18n("manual merge( %1, %2, %3 -> %4)",nameA,nameB,nameC,nameDest));
joachim99@8 2483 if ( m_bSimulatedMergeStarted )
joachim99@8 2484 {
joachim99@66 2485 m_pStatusInfo->addText(i18n(" Note: After a manual merge the user should continue by pressing F7.") );
joachim99@8 2486 return true;
joachim99@8 2487 }
joachim99@8 2488
joachim99@8 2489 bSingleFileMerge = true;
joachim99@51 2490 (*m_currentItemForOperation)->setText( s_OpStatusCol, i18n("In progress...") );
joachim99@75 2491 scrollToItem( *m_currentItemForOperation, EnsureVisible );
joachim99@8 2492
joachim99@66 2493 emit startDiffMerge( nameA, nameB, nameC, nameDest, "","","",0 );
joachim99@8 2494
joachim99@8 2495 return false;
joachim99@8 2496 }
joachim99@8 2497
joachim99@8 2498 bool DirectoryMergeWindow::copyFLD( const QString& srcName, const QString& destName )
joachim99@8 2499 {
joachim99@8 2500 if ( srcName == destName )
joachim99@8 2501 return true;
joachim99@8 2502
joachim99@8 2503 if ( FileAccess(destName, true).exists() )
joachim99@8 2504 {
joachim99@8 2505 bool bSuccess = deleteFLD( destName, m_pOptions->m_bDmCreateBakFiles );
joachim99@8 2506 if ( !bSuccess )
joachim99@8 2507 {
joachim99@51 2508 m_pStatusInfo->addText(i18n("Error: copy( %1 -> %2 ) failed."
joachim99@80 2509 "Deleting existing destination failed.",srcName,destName));
joachim99@8 2510 return false;
joachim99@8 2511 }
joachim99@8 2512 }
joachim99@8 2513
joachim99@8 2514 FileAccess fi( srcName );
joachim99@8 2515
joachim99@80 2516 if ( fi.isSymLink() && ((fi.isDir() && !m_bFollowDirLinks) || (!fi.isDir() && !m_bFollowFileLinks)) )
joachim99@8 2517 {
joachim99@80 2518 m_pStatusInfo->addText(i18n("copyLink( %1 -> %2 )",srcName,destName));
joachim99@95 2519 #if defined(_WIN32) || defined(Q_OS_OS2)
joachim99@8 2520 // What are links?
joachim99@8 2521 #else
joachim99@8 2522 if ( m_bSimulatedMergeStarted )
joachim99@8 2523 {
joachim99@8 2524 return true;
joachim99@8 2525 }
joachim99@8 2526 FileAccess destFi(destName);
joachim99@8 2527 if ( !destFi.isLocal() || !fi.isLocal() )
joachim99@8 2528 {
joachim99@51 2529 m_pStatusInfo->addText(i18n("Error: copyLink failed: Remote links are not yet supported."));
joachim99@8 2530 return false;
joachim99@8 2531 }
joachim99@8 2532 QString linkTarget = fi.readLink();
joachim99@8 2533 bool bSuccess = FileAccess::symLink( linkTarget, destName );
joachim99@8 2534 if (!bSuccess)
joachim99@51 2535 m_pStatusInfo->addText(i18n("Error: copyLink failed."));
joachim99@8 2536 return bSuccess;
joachim99@8 2537 #endif
joachim99@8 2538 }
joachim99@8 2539
joachim99@8 2540 if ( fi.isDir() )
joachim99@8 2541 {
joachim99@8 2542 bool bSuccess = makeDir( destName );
joachim99@8 2543 return bSuccess;
joachim99@8 2544 }
joachim99@8 2545
joachim99@75 2546 int pos=destName.lastIndexOf('/');
joachim99@8 2547 if ( pos>0 )
joachim99@8 2548 {
joachim99@8 2549 QString parentName = destName.left(pos);
joachim99@8 2550 bool bSuccess = makeDir(parentName, true /*quiet*/);
joachim99@8 2551 if (!bSuccess)
joachim99@8 2552 return false;
joachim99@8 2553 }
joachim99@8 2554
joachim99@80 2555 m_pStatusInfo->addText(i18n("copy( %1 -> %2 )",srcName,destName));
joachim99@8 2556
joachim99@8 2557 if ( m_bSimulatedMergeStarted )
joachim99@8 2558 {
joachim99@8 2559 return true;
joachim99@8 2560 }
joachim99@8 2561
joachim99@8 2562 FileAccess faSrc ( srcName );
joachim99@8 2563 bool bSuccess = faSrc.copyFile( destName );
joachim99@8 2564 if (! bSuccess ) m_pStatusInfo->addText( faSrc.getStatusText() );
joachim99@8 2565 return bSuccess;
joachim99@8 2566 }
joachim99@8 2567
joachim99@8 2568 // Rename is not an operation that can be selected by the user.
joachim99@8 2569 // It will only be used to create backups.
joachim99@8 2570 // Hence it will delete an existing destination without making a backup (of the old backup.)
joachim99@8 2571 bool DirectoryMergeWindow::renameFLD( const QString& srcName, const QString& destName )
joachim99@8 2572 {
joachim99@8 2573 if ( srcName == destName )
joachim99@8 2574 return true;
joachim99@8 2575
joachim99@8 2576 if ( FileAccess(destName, true).exists() )
joachim99@8 2577 {
joachim99@8 2578 bool bSuccess = deleteFLD( destName, false /*no backup*/ );
joachim99@8 2579 if (!bSuccess)
joachim99@8 2580 {
joachim99@51 2581 m_pStatusInfo->addText( i18n("Error during rename( %1 -> %2 ): "
joachim99@80 2582 "Cannot delete existing destination." ,srcName,destName));
joachim99@8 2583 return false;
joachim99@8 2584 }
joachim99@8 2585 }
joachim99@8 2586
joachim99@80 2587 m_pStatusInfo->addText(i18n("rename( %1 -> %2 )",srcName,destName));
joachim99@8 2588 if ( m_bSimulatedMergeStarted )
joachim99@8 2589 {
joachim99@8 2590 return true;
joachim99@8 2591 }
joachim99@8 2592
joachim99@8 2593 bool bSuccess = FileAccess( srcName ).rename( destName );
joachim99@8 2594 if (!bSuccess)
joachim99@8 2595 {
joachim99@51 2596 m_pStatusInfo->addText( i18n("Error: Rename failed.") );
joachim99@8 2597 return false;
joachim99@8 2598 }
joachim99@8 2599
joachim99@8 2600 return true;
joachim99@8 2601 }
joachim99@8 2602
joachim99@8 2603 bool DirectoryMergeWindow::makeDir( const QString& name, bool bQuiet )
joachim99@8 2604 {
joachim99@8 2605 FileAccess fi(name, true);
joachim99@8 2606 if( fi.exists() && fi.isDir() )
joachim99@8 2607 return true;
joachim99@8 2608
joachim99@8 2609 if( fi.exists() && !fi.isDir() )
joachim99@8 2610 {
joachim99@8 2611 bool bSuccess = deleteFLD( name, true );
joachim99@8 2612 if (!bSuccess)
joachim99@8 2613 {
joachim99@51 2614 m_pStatusInfo->addText( i18n("Error during makeDir of %1. "
joachim99@80 2615 "Cannot delete existing file." ,name));
joachim99@8 2616 return false;
joachim99@8 2617 }
joachim99@8 2618 }
joachim99@8 2619
joachim99@75 2620 int pos=name.lastIndexOf('/');
joachim99@8 2621 if ( pos>0 )
joachim99@8 2622 {
joachim99@8 2623 QString parentName = name.left(pos);
joachim99@8 2624 bool bSuccess = makeDir(parentName,true);
joachim99@8 2625 if (!bSuccess)
joachim99@8 2626 return false;
joachim99@8 2627 }
joachim99@8 2628
joachim99@8 2629 if ( ! bQuiet )
joachim99@80 2630 m_pStatusInfo->addText(i18n("makeDir( %1 )",name));
joachim99@8 2631
joachim99@8 2632 if ( m_bSimulatedMergeStarted )
joachim99@8 2633 {
joachim99@8 2634 return true;
joachim99@8 2635 }
joachim99@8 2636
joachim99@8 2637 bool bSuccess = FileAccess::makeDir( name );
joachim99@8 2638 if ( bSuccess == false )
joachim99@8 2639 {
joachim99@51 2640 m_pStatusInfo->addText( i18n("Error while creating directory.") );
joachim99@8 2641 return false;
joachim99@8 2642 }
joachim99@8 2643 return true;
joachim99@8 2644 }
joachim99@8 2645
joachim99@8 2646
joachim99@8 2647 DirectoryMergeInfo::DirectoryMergeInfo( QWidget* pParent )
joachim99@75 2648 : QFrame(pParent)
joachim99@8 2649 {
joachim99@75 2650 QVBoxLayout *topLayout = new QVBoxLayout( this );
joachim99@75 2651 topLayout->setMargin(0);
joachim99@75 2652
joachim99@75 2653 QGridLayout *grid = new QGridLayout();
joachim99@75 2654 topLayout->addLayout(grid);
joachim99@75 2655 grid->setColumnStretch(1,10);
joachim99@8 2656
joachim99@8 2657 int line=0;
joachim99@8 2658
joachim99@8 2659 m_pA = new QLabel("A",this); grid->addWidget( m_pA,line, 0 );
joachim99@8 2660 m_pInfoA = new QLabel(this); grid->addWidget( m_pInfoA,line,1 ); ++line;
joachim99@8 2661 m_pB = new QLabel("B",this); grid->addWidget( m_pB,line, 0 );
joachim99@8 2662 m_pInfoB = new QLabel(this); grid->addWidget( m_pInfoB,line,1 ); ++line;
joachim99@8 2663 m_pC = new QLabel("C",this); grid->addWidget( m_pC,line, 0 );
joachim99@8 2664 m_pInfoC = new QLabel(this); grid->addWidget( m_pInfoC,line,1 ); ++line;
joachim99@51 2665 m_pDest = new QLabel(i18n("Dest"),this); grid->addWidget( m_pDest,line, 0 );
joachim99@8 2666 m_pInfoDest = new QLabel(this); grid->addWidget( m_pInfoDest,line,1 ); ++line;
joachim99@8 2667
joachim99@75 2668 m_pInfoList = new QTreeWidget(this); topLayout->addWidget( m_pInfoList );
joachim99@75 2669 m_pInfoList->setHeaderLabels( QStringList() << i18n("Dir") << i18n("Type") << i18n("Size")
joachim99@75 2670 << i18n("Attr") << i18n("Last Modification") << i18n("Link-Destination") );
joachim99@8 2671 setMinimumSize( 100,100 );
joachim99@68 2672
joachim99@66 2673 m_pInfoList->installEventFilter(this);
joachim99@75 2674 m_pInfoList->setRootIsDecorated( false );
joachim99@66 2675 }
joachim99@66 2676
joachim99@66 2677 bool DirectoryMergeInfo::eventFilter(QObject*o, QEvent* e)
joachim99@66 2678 {
joachim99@66 2679 if ( e->type()==QEvent::FocusIn && o==m_pInfoList )
joachim99@66 2680 emit gotFocus();
joachim99@66 2681 return false;
joachim99@8 2682 }
joachim99@8 2683
joachim99@75 2684 static void addListViewItem( QTreeWidget* pListView, const QString& dir,
joachim99@8 2685 const QString& basePath, FileAccess& fi )
joachim99@8 2686 {
joachim99@8 2687 if ( basePath.isEmpty() )
joachim99@8 2688 {
joachim99@8 2689 return;
joachim99@8 2690 }
joachim99@8 2691 else
joachim99@8 2692 {
joachim99@8 2693 if ( fi.exists() )
joachim99@8 2694 {
joachim99@8 2695 QString dateString = fi.lastModified().toString("yyyy-MM-dd hh:mm:ss");
joachim99@75 2696
joachim99@75 2697 new QTreeWidgetItem(
joachim99@8 2698 pListView,
joachim99@75 2699 QStringList() << dir <<
joachim99@75 2700 QString( fi.isDir() ? i18n("Dir") : i18n("File") ) + (fi.isSymLink() ? "-Link" : "") <<
joachim99@75 2701 QString::number(fi.size()) <<
joachim99@8 2702 QString(fi.isReadable() ? "r" : " ") + (fi.isWritable()?"w" : " ")
joachim99@8 2703 #ifdef _WIN32
joachim99@75 2704 /*Future: Use GetFileAttributes()*/ <<
joachim99@8 2705 #else
joachim99@75 2706 + (fi.isExecutable()?"x" : " ") <<
joachim99@8 2707 #endif
joachim99@75 2708 dateString <<
joachim99@8 2709 QString(fi.isSymLink() ? (" -> " + fi.readLink()) : QString(""))
joachim99@8 2710 );
joachim99@8 2711 }
joachim99@8 2712 else
joachim99@8 2713 {
joachim99@75 2714 new QTreeWidgetItem(
joachim99@8 2715 pListView,
joachim99@75 2716 QStringList() << dir <<
joachim99@75 2717 i18n("not available") <<
joachim99@75 2718 "" <<
joachim99@75 2719 "" <<
joachim99@75 2720 "" <<
joachim99@8 2721 ""
joachim99@8 2722 );
joachim99@8 2723 }
joachim99@8 2724 }
joachim99@8 2725 }
joachim99@8 2726
joachim99@8 2727 void DirectoryMergeInfo::setInfo(
joachim99@8 2728 const FileAccess& dirA,
joachim99@8 2729 const FileAccess& dirB,
joachim99@8 2730 const FileAccess& dirC,
joachim99@8 2731 const FileAccess& dirDest,
joachim99@8 2732 MergeFileInfos& mfi )
joachim99@8 2733 {
joachim99@8 2734 bool bHideDest = false;
joachim99@80 2735 if ( dirA.absoluteFilePath()==dirDest.absoluteFilePath() )
joachim99@8 2736 {
joachim99@51 2737 m_pA->setText( i18n("A (Dest): ") ); bHideDest=true;
joachim99@8 2738 }
joachim99@8 2739 else
joachim99@51 2740 m_pA->setText( !dirC.isValid() ? QString("A: ") : i18n("A (Base): "));
joachim99@8 2741
joachim99@8 2742 m_pInfoA->setText( dirA.prettyAbsPath() );
joachim99@8 2743
joachim99@80 2744 if ( dirB.absoluteFilePath()==dirDest.absoluteFilePath() )
joachim99@8 2745 {
joachim99@51 2746 m_pB->setText( i18n("B (Dest): ") ); bHideDest=true;
joachim99@8 2747 }
joachim99@8 2748 else
joachim99@8 2749 m_pB->setText( "B: " );
joachim99@8 2750 m_pInfoB->setText( dirB.prettyAbsPath() );
joachim99@8 2751
joachim99@80 2752 if ( dirC.absoluteFilePath()==dirDest.absoluteFilePath() )
joachim99@8 2753 {
joachim99@51 2754 m_pC->setText( i18n("C (Dest): ") ); bHideDest=true;
joachim99@8 2755 }
joachim99@8 2756 else
joachim99@8 2757 m_pC->setText( "C: " );
joachim99@8 2758 m_pInfoC->setText( dirC.prettyAbsPath() );
joachim99@8 2759
joachim99@51 2760 m_pDest->setText( i18n("Dest: ") ); m_pInfoDest->setText( dirDest.prettyAbsPath() );
joachim99@8 2761
joachim99@8 2762 if (!dirC.isValid()) { m_pC->hide(); m_pInfoC->hide(); }
joachim99@8 2763 else { m_pC->show(); m_pInfoC->show(); }
joachim99@8 2764
joachim99@8 2765 if (!dirDest.isValid()||bHideDest) { m_pDest->hide(); m_pInfoDest->hide(); }
joachim99@8 2766 else { m_pDest->show(); m_pInfoDest->show(); }
joachim99@8 2767
joachim99@8 2768 m_pInfoList->clear();
joachim99@8 2769 addListViewItem( m_pInfoList, "A", dirA.prettyAbsPath(), mfi.m_fileInfoA );
joachim99@8 2770 addListViewItem( m_pInfoList, "B", dirB.prettyAbsPath(), mfi.m_fileInfoB );
joachim99@8 2771 addListViewItem( m_pInfoList, "C", dirC.prettyAbsPath(), mfi.m_fileInfoC );
joachim99@8 2772 if (!bHideDest)
joachim99@8 2773 {
joachim99@8 2774 FileAccess fiDest( dirDest.prettyAbsPath() + "/" + mfi.m_subPath, true );
joachim99@51 2775 addListViewItem( m_pInfoList, i18n("Dest"), dirDest.prettyAbsPath(), fiDest );
joachim99@8 2776 }
joachim99@75 2777 for (int i=0;i<m_pInfoList->columnCount();++i)
joachim99@75 2778 m_pInfoList->resizeColumnToContents ( i );
joachim99@8 2779 }
joachim99@8 2780
joachim99@69 2781 QTextStream& operator<<( QTextStream& ts, MergeFileInfos& mfi )
joachim99@69 2782 {
joachim99@69 2783 ts << "{\n";
joachim99@69 2784 ValueMap vm;
joachim99@69 2785 vm.writeEntry( "SubPath", mfi.m_subPath );
joachim99@69 2786 vm.writeEntry( "ExistsInA", mfi.m_bExistsInA );
joachim99@69 2787 vm.writeEntry( "ExistsInB", mfi.m_bExistsInB );
joachim99@69 2788 vm.writeEntry( "ExistsInC", mfi.m_bExistsInC );
joachim99@69 2789 vm.writeEntry( "EqualAB", mfi.m_bEqualAB );
joachim99@69 2790 vm.writeEntry( "EqualAC", mfi.m_bEqualAC );
joachim99@69 2791 vm.writeEntry( "EqualBC", mfi.m_bEqualBC );
joachim99@69 2792 //DirMergeItem* m_pDMI;
joachim99@69 2793 //MergeFileInfos* m_pParent;
joachim99@69 2794 vm.writeEntry( "MergeOperation", (int) mfi.m_eMergeOperation );
joachim99@69 2795 vm.writeEntry( "DirA", mfi.m_bDirA );
joachim99@69 2796 vm.writeEntry( "DirB", mfi.m_bDirB );
joachim99@69 2797 vm.writeEntry( "DirC", mfi.m_bDirC );
joachim99@69 2798 vm.writeEntry( "LinkA", mfi.m_bLinkA );
joachim99@69 2799 vm.writeEntry( "LinkB", mfi.m_bLinkB );
joachim99@69 2800 vm.writeEntry( "LinkC", mfi.m_bLinkC );
joachim99@69 2801 vm.writeEntry( "OperationComplete", mfi.m_bOperationComplete );
joachim99@69 2802 //bool m_bSimOpComplete );
joachim99@69 2803
joachim99@69 2804 vm.writeEntry( "AgeA", (int) mfi.m_ageA );
joachim99@69 2805 vm.writeEntry( "AgeB", (int) mfi.m_ageB );
joachim99@69 2806 vm.writeEntry( "AgeC", (int) mfi.m_ageC );
joachim99@69 2807 vm.writeEntry( "ConflictingAges", mfi.m_bConflictingAges ); // Equal age but files are not!
joachim99@69 2808
joachim99@69 2809 //FileAccess m_fileInfoA;
joachim99@69 2810 //FileAccess m_fileInfoB;
joachim99@69 2811 //FileAccess m_fileInfoC;
joachim99@69 2812
joachim99@69 2813 //TotalDiffStatus m_totalDiffStatus;
joachim99@69 2814
joachim99@69 2815 vm.save(ts);
joachim99@69 2816
joachim99@69 2817 ts << "}\n";
joachim99@69 2818
joachim99@69 2819 return ts;
joachim99@69 2820 }
joachim99@69 2821
joachim99@69 2822 void DirectoryMergeWindow::slotSaveMergeState()
joachim99@69 2823 {
joachim99@69 2824 //slotStatusMsg(i18n("Saving Directory Merge State ..."));
joachim99@69 2825
joachim99@80 2826 //QString s = KFileDialog::getSaveUrl( QDir::currentPath(), 0, this, i18n("Save As...") ).url();
joachim99@75 2827 QString s = KFileDialog::getSaveFileName( QDir::currentPath(), 0, this, i18n("Save Directory Merge State As...") );
joachim99@69 2828 if(!s.isEmpty())
joachim99@69 2829 {
joachim99@69 2830 m_dirMergeStateFilename = s;
joachim99@69 2831
joachim99@69 2832
joachim99@69 2833 QFile file(m_dirMergeStateFilename);
joachim99@70 2834 bool bSuccess = file.open( QIODevice::WriteOnly );
joachim99@69 2835 if ( bSuccess )
joachim99@69 2836 {
joachim99@69 2837 QTextStream ts( &file );
joachim99@69 2838
joachim99@75 2839 QTreeWidgetItemIterator it( this );
joachim99@75 2840 while ( *it ) {
joachim99@75 2841 DirMergeItem* item = static_cast<DirMergeItem*>(*it);
joachim99@69 2842 MergeFileInfos* pMFI = item->m_pMFI;
joachim99@69 2843 ts << *pMFI;
joachim99@69 2844 ++it;
joachim99@69 2845 }
joachim99@69 2846 }
joachim99@69 2847 }
joachim99@69 2848
joachim99@69 2849 //slotStatusMsg(i18n("Ready."));
joachim99@69 2850
joachim99@69 2851 }
joachim99@69 2852
joachim99@69 2853 void DirectoryMergeWindow::slotLoadMergeState()
joachim99@69 2854 {
joachim99@69 2855 }
joachim99@69 2856
joachim99@69 2857 void DirectoryMergeWindow::updateFileVisibilities()
joachim99@69 2858 {
joachim99@69 2859 bool bShowIdentical = m_pDirShowIdenticalFiles->isChecked();
joachim99@69 2860 bool bShowDifferent = m_pDirShowDifferentFiles->isChecked();
joachim99@69 2861 bool bShowOnlyInA = m_pDirShowFilesOnlyInA->isChecked();
joachim99@69 2862 bool bShowOnlyInB = m_pDirShowFilesOnlyInB->isChecked();
joachim99@69 2863 bool bShowOnlyInC = m_pDirShowFilesOnlyInC->isChecked();
joachim99@69 2864 bool bThreeDirs = m_dirC.isValid();
joachim99@69 2865 m_pSelection1Item = 0;
joachim99@69 2866 m_pSelection2Item = 0;
joachim99@69 2867 m_pSelection3Item = 0;
joachim99@69 2868
joachim99@92 2869 // in first run set all dirs to equal and determine if they are not equal.
joachim99@92 2870 // on second run don't change the equal-status anymore; it is needed to
joachim99@92 2871 // set the visibility (when bShowIdentical is false).
joachim99@92 2872 for( int loop=0; loop<2; ++loop )
joachim99@69 2873 {
joachim99@92 2874 QTreeWidgetItem* p = topLevelItemCount()>0 ? topLevelItem(0) : 0;
joachim99@92 2875 while(p)
joachim99@92 2876 {
joachim99@92 2877 DirMergeItem* pDMI = static_cast<DirMergeItem*>(p);
joachim99@92 2878 MergeFileInfos* pMFI = pDMI->m_pMFI;
joachim99@92 2879 bool bDir = pMFI->m_bDirA || pMFI->m_bDirB || pMFI->m_bDirC;
joachim99@92 2880 if ( loop==0 && bDir )
joachim99@92 2881 {
joachim99@92 2882 bool bChange = false;
joachim99@92 2883 if ( !pMFI->m_bEqualAB ){ pMFI->m_bEqualAB = true; bChange=true; }
joachim99@92 2884 if ( !pMFI->m_bEqualBC ){ pMFI->m_bEqualBC = true; bChange=true; }
joachim99@92 2885 if ( !pMFI->m_bEqualAC ){ pMFI->m_bEqualAC = true; bChange=true; }
joachim99@92 2886
joachim99@92 2887 if ( bChange )
joachim99@92 2888 setPixmaps( *pMFI, bThreeDirs );
joachim99@92 2889 }
joachim99@92 2890 bool bExistsEverywhere = pMFI->m_bExistsInA && pMFI->m_bExistsInB && (pMFI->m_bExistsInC || !bThreeDirs);
joachim99@92 2891 int existCount = int(pMFI->m_bExistsInA) + int(pMFI->m_bExistsInB) + int(pMFI->m_bExistsInC);
joachim99@92 2892 bool bVisible =
joachim99@92 2893 ( bShowIdentical && bExistsEverywhere && pMFI->m_bEqualAB && (pMFI->m_bEqualAC || !bThreeDirs) )
joachim99@92 2894 || ( (bShowDifferent||bDir) && existCount>=2 && (!pMFI->m_bEqualAB || !(pMFI->m_bEqualAC || !bThreeDirs)))
joachim99@92 2895 || ( bShowOnlyInA && pMFI->m_bExistsInA && !pMFI->m_bExistsInB && !pMFI->m_bExistsInC )
joachim99@92 2896 || ( bShowOnlyInB && !pMFI->m_bExistsInA && pMFI->m_bExistsInB && !pMFI->m_bExistsInC )
joachim99@92 2897 || ( bShowOnlyInC && !pMFI->m_bExistsInA && !pMFI->m_bExistsInB && pMFI->m_bExistsInC );
joachim99@92 2898
joachim99@92 2899 QString fileName = pMFI->m_subPath.section( '/', -1 );
joachim99@92 2900 bVisible = bVisible && (
joachim99@92 2901 (bDir && ! wildcardMultiMatch( m_pOptions->m_DmDirAntiPattern, fileName, m_bCaseSensitive ))
joachim99@92 2902 || (wildcardMultiMatch( m_pOptions->m_DmFilePattern, fileName, m_bCaseSensitive )
joachim99@92 2903 && !wildcardMultiMatch( m_pOptions->m_DmFileAntiPattern, fileName, m_bCaseSensitive )) );
joachim99@92 2904
joachim99@92 2905 p->setHidden(!bVisible);
joachim99@92 2906
joachim99@92 2907 bool bEqual = bThreeDirs ? pMFI->m_bEqualAB && pMFI->m_bEqualAC : pMFI->m_bEqualAB;
joachim99@92 2908 if ( !bEqual && bVisible && loop==0 ) // Set all parents to "not equal"
joachim99@92 2909 {
joachim99@92 2910 MergeFileInfos* p2 = pMFI->m_pParent;
joachim99@92 2911 while(p2!=0)
joachim99@92 2912 {
joachim99@92 2913 bool bChange = false;
joachim99@92 2914 if ( !pMFI->m_bEqualAB && p2->m_bEqualAB ){ p2->m_bEqualAB = false; bChange=true; }
joachim99@92 2915 if ( !pMFI->m_bEqualAC && p2->m_bEqualAC ){ p2->m_bEqualAC = false; bChange=true; }
joachim99@92 2916 if ( !pMFI->m_bEqualBC && p2->m_bEqualBC ){ p2->m_bEqualBC = false; bChange=true; }
joachim99@92 2917
joachim99@92 2918 if ( bChange )
joachim99@92 2919 setPixmaps( *p2, bThreeDirs );
joachim99@92 2920 else
joachim99@92 2921 break;
joachim99@92 2922
joachim99@92 2923 p2 = p2->m_pParent;
joachim99@92 2924 }
joachim99@92 2925 }
joachim99@92 2926 p = treeIterator( p, true, true );
joachim99@92 2927 }
joachim99@69 2928 }
joachim99@69 2929 }
joachim99@69 2930
joachim99@69 2931 void DirectoryMergeWindow::slotShowIdenticalFiles() { m_pOptions->m_bDmShowIdenticalFiles=m_pDirShowIdenticalFiles->isChecked();
joachim99@69 2932 updateFileVisibilities(); }
joachim99@69 2933 void DirectoryMergeWindow::slotShowDifferentFiles() { updateFileVisibilities(); }
joachim99@69 2934 void DirectoryMergeWindow::slotShowFilesOnlyInA() { updateFileVisibilities(); }
joachim99@69 2935 void DirectoryMergeWindow::slotShowFilesOnlyInB() { updateFileVisibilities(); }
joachim99@69 2936 void DirectoryMergeWindow::slotShowFilesOnlyInC() { updateFileVisibilities(); }
joachim99@69 2937
joachim99@69 2938 void DirectoryMergeWindow::slotSynchronizeDirectories() { }
joachim99@69 2939 void DirectoryMergeWindow::slotChooseNewerFiles() { }
joachim99@51 2940
joachim99@51 2941 void DirectoryMergeWindow::initDirectoryMergeActions( QObject* pKDiff3App, KActionCollection* ac )
joachim99@51 2942 {
joachim99@51 2943 #include "xpm/startmerge.xpm"
joachim99@69 2944 #include "xpm/showequalfiles.xpm"
joachim99@69 2945 #include "xpm/showfilesonlyina.xpm"
joachim99@69 2946 #include "xpm/showfilesonlyinb.xpm"
joachim99@69 2947 #include "xpm/showfilesonlyinc.xpm"
joachim99@51 2948 DirectoryMergeWindow* p = this;
joachim99@51 2949
joachim99@80 2950 m_pDirStartOperation = KDiff3::createAction< KAction >(i18n("Start/Continue Directory Merge"), KShortcut( Qt::Key_F7 ), p, SLOT(slotRunOperationForAllItems()), ac, "dir_start_operation");
joachim99@80 2951 m_pDirRunOperationForCurrentItem = KDiff3::createAction< KAction >(i18n("Run Operation for Current Item"), KShortcut( Qt::Key_F6 ), p, SLOT(slotRunOperationForCurrentItem()), ac, "dir_run_operation_for_current_item");
joachim99@80 2952 m_pDirCompareCurrent = KDiff3::createAction< KAction >(i18n("Compare Selected File"), p, SLOT(compareCurrentFile()), ac, "dir_compare_current");
joachim99@80 2953 m_pDirMergeCurrent = KDiff3::createAction< KAction >(i18n("Merge Current File"), QIcon(QPixmap(startmerge)), i18n("Merge\nFile"), pKDiff3App, SLOT(slotMergeCurrentFile()), ac, "merge_current");
joachim99@80 2954 m_pDirFoldAll = KDiff3::createAction< KAction >(i18n("Fold All Subdirs"), p, SLOT(slotFoldAllSubdirs()), ac, "dir_fold_all");
joachim99@80 2955 m_pDirUnfoldAll = KDiff3::createAction< KAction >(i18n("Unfold All Subdirs"), p, SLOT(slotUnfoldAllSubdirs()), ac, "dir_unfold_all");
joachim99@80 2956 m_pDirRescan = KDiff3::createAction< KAction >(i18n("Rescan"), KShortcut( Qt::SHIFT+Qt::Key_F5 ), p, SLOT(reload()), ac, "dir_rescan");
joachim99@80 2957 m_pDirSaveMergeState = 0; //KDiff3::createAction< KAction >(i18n("Save Directory Merge State ..."), 0, p, SLOT(slotSaveMergeState()), ac, "dir_save_merge_state");
joachim99@80 2958 m_pDirLoadMergeState = 0; //KDiff3::createAction< KAction >(i18n("Load Directory Merge State ..."), 0, p, SLOT(slotLoadMergeState()), ac, "dir_load_merge_state");
joachim99@80 2959 m_pDirChooseAEverywhere = KDiff3::createAction< KAction >(i18n("Choose A for All Items"), p, SLOT(slotChooseAEverywhere()), ac, "dir_choose_a_everywhere");
joachim99@80 2960 m_pDirChooseBEverywhere = KDiff3::createAction< KAction >(i18n("Choose B for All Items"), p, SLOT(slotChooseBEverywhere()), ac, "dir_choose_b_everywhere");
joachim99@80 2961 m_pDirChooseCEverywhere = KDiff3::createAction< KAction >(i18n("Choose C for All Items"), p, SLOT(slotChooseCEverywhere()), ac, "dir_choose_c_everywhere");
joachim99@80 2962 m_pDirAutoChoiceEverywhere = KDiff3::createAction< KAction >(i18n("Auto-Choose Operation for All Items"), p, SLOT(slotAutoChooseEverywhere()), ac, "dir_autochoose_everywhere");
joachim99@80 2963 m_pDirDoNothingEverywhere = KDiff3::createAction< KAction >(i18n("No Operation for All Items"), p, SLOT(slotNoOpEverywhere()), ac, "dir_nothing_everywhere");
joachim99@80 2964
joachim99@80 2965 // m_pDirSynchronizeDirectories = KDiff3::createAction< KToggleAction >(i18n("Synchronize Directories"), 0, this, SLOT(slotSynchronizeDirectories()), ac, "dir_synchronize_directories");
joachim99@80 2966 // m_pDirChooseNewerFiles = KDiff3::createAction< KToggleAction >(i18n("Copy Newer Files Instead of Merging"), 0, this, SLOT(slotChooseNewerFiles()), ac, "dir_choose_newer_files");
joachim99@80 2967
joachim99@80 2968 m_pDirShowIdenticalFiles = KDiff3::createAction< KToggleAction >(i18n("Show Identical Files"), QIcon(QPixmap(showequalfiles)), i18n("Identical\nFiles"), this, SLOT(slotShowIdenticalFiles()), ac, "dir_show_identical_files");
joachim99@80 2969 m_pDirShowDifferentFiles = KDiff3::createAction< KToggleAction >(i18n("Show Different Files"), this, SLOT(slotShowDifferentFiles()), ac, "dir_show_different_files");
joachim99@80 2970 m_pDirShowFilesOnlyInA = KDiff3::createAction< KToggleAction >(i18n("Show Files only in A"), QIcon(QPixmap(showfilesonlyina)), i18n("Files\nonly in A"), this, SLOT(slotShowFilesOnlyInA()), ac, "dir_show_files_only_in_a");
joachim99@80 2971 m_pDirShowFilesOnlyInB = KDiff3::createAction< KToggleAction >(i18n("Show Files only in B"), QIcon(QPixmap(showfilesonlyinb)), i18n("Files\nonly in B"), this, SLOT(slotShowFilesOnlyInB()), ac, "dir_show_files_only_in_b");
joachim99@80 2972 m_pDirShowFilesOnlyInC = KDiff3::createAction< KToggleAction >(i18n("Show Files only in C"), QIcon(QPixmap(showfilesonlyinc)), i18n("Files\nonly in C"), this, SLOT(slotShowFilesOnlyInC()), ac, "dir_show_files_only_in_c");
joachim99@69 2973
joachim99@69 2974 m_pDirShowIdenticalFiles->setChecked( m_pOptions->m_bDmShowIdenticalFiles );
joachim99@69 2975
joachim99@80 2976 m_pDirCompareExplicit = KDiff3::createAction< KAction >(i18n("Compare Explicitly Selected Files"), p, SLOT(slotCompareExplicitlySelectedFiles()), ac, "dir_compare_explicitly_selected_files");
joachim99@80 2977 m_pDirMergeExplicit = KDiff3::createAction< KAction >(i18n("Merge Explicitly Selected Files"), p, SLOT(slotMergeExplicitlySelectedFiles()), ac, "dir_merge_explicitly_selected_files");
joachim99@80 2978
joachim99@80 2979 m_pDirCurrentDoNothing = KDiff3::createAction< KAction >(i18n("Do Nothing"), p, SLOT(slotCurrentDoNothing()), ac, "dir_current_do_nothing");
joachim99@80 2980 m_pDirCurrentChooseA = KDiff3::createAction< KAction >(i18n("A"), p, SLOT(slotCurrentChooseA()), ac, "dir_current_choose_a");
joachim99@80 2981 m_pDirCurrentChooseB = KDiff3::createAction< KAction >(i18n("B"), p, SLOT(slotCurrentChooseB()), ac, "dir_current_choose_b");
joachim99@80 2982 m_pDirCurrentChooseC = KDiff3::createAction< KAction >(i18n("C"), p, SLOT(slotCurrentChooseC()), ac, "dir_current_choose_c");
joachim99@80 2983 m_pDirCurrentMerge = KDiff3::createAction< KAction >(i18n("Merge"), p, SLOT(slotCurrentMerge()), ac, "dir_current_merge");
joachim99@80 2984 m_pDirCurrentDelete = KDiff3::createAction< KAction >(i18n("Delete (if exists)"), p, SLOT(slotCurrentDelete()), ac, "dir_current_delete");
joachim99@80 2985
joachim99@80 2986 m_pDirCurrentSyncDoNothing = KDiff3::createAction< KAction >(i18n("Do Nothing"), p, SLOT(slotCurrentDoNothing()), ac, "dir_current_sync_do_nothing");
joachim99@80 2987 m_pDirCurrentSyncCopyAToB = KDiff3::createAction< KAction >(i18n("Copy A to B"), p, SLOT(slotCurrentCopyAToB()), ac, "dir_current_sync_copy_a_to_b" );
joachim99@80 2988 m_pDirCurrentSyncCopyBToA = KDiff3::createAction< KAction >(i18n("Copy B to A"), p, SLOT(slotCurrentCopyBToA()), ac, "dir_current_sync_copy_b_to_a" );
joachim99@80 2989 m_pDirCurrentSyncDeleteA = KDiff3::createAction< KAction >(i18n("Delete A"), p, SLOT(slotCurrentDeleteA()), ac,"dir_current_sync_delete_a");
joachim99@80 2990 m_pDirCurrentSyncDeleteB = KDiff3::createAction< KAction >(i18n("Delete B"), p, SLOT(slotCurrentDeleteB()), ac,"dir_current_sync_delete_b");
joachim99@80 2991 m_pDirCurrentSyncDeleteAAndB = KDiff3::createAction< KAction >(i18n("Delete A && B"), p, SLOT(slotCurrentDeleteAAndB()), ac,"dir_current_sync_delete_a_and_b");
joachim99@80 2992 m_pDirCurrentSyncMergeToA = KDiff3::createAction< KAction >(i18n("Merge to A"), p, SLOT(slotCurrentMergeToA()), ac,"dir_current_sync_merge_to_a");
joachim99@80 2993 m_pDirCurrentSyncMergeToB = KDiff3::createAction< KAction >(i18n("Merge to B"), p, SLOT(slotCurrentMergeToB()), ac,"dir_current_sync_merge_to_b");
joachim99@80 2994 m_pDirCurrentSyncMergeToAAndB = KDiff3::createAction< KAction >(i18n("Merge to A && B"), p, SLOT(slotCurrentMergeToAAndB()), ac,"dir_current_sync_merge_to_a_and_b");
joachim99@51 2995 }
joachim99@51 2996
joachim99@51 2997
joachim99@53 2998 void DirectoryMergeWindow::updateAvailabilities( bool bDirCompare, bool bDiffWindowVisible,
joachim99@53 2999 KToggleAction* chooseA, KToggleAction* chooseB, KToggleAction* chooseC )
joachim99@51 3000 {
joachim99@69 3001 m_pDirStartOperation->setEnabled( bDirCompare );
joachim99@69 3002 m_pDirRunOperationForCurrentItem->setEnabled( bDirCompare );
joachim99@69 3003 m_pDirFoldAll->setEnabled( bDirCompare );
joachim99@69 3004 m_pDirUnfoldAll->setEnabled( bDirCompare );
joachim99@69 3005
joachim99@69 3006 m_pDirCompareCurrent->setEnabled( bDirCompare && isVisible() && isFileSelected() );
joachim99@69 3007
joachim99@80 3008 m_pDirMergeCurrent->setEnabled( (bDirCompare && isVisible() && isFileSelected())
joachim99@51 3009 || bDiffWindowVisible );
joachim99@51 3010
joachim99@69 3011 m_pDirRescan->setEnabled( bDirCompare );
joachim99@69 3012
joachim99@69 3013 m_pDirAutoChoiceEverywhere->setEnabled( bDirCompare && isVisible() );
joachim99@69 3014 m_pDirDoNothingEverywhere->setEnabled( bDirCompare && isVisible() );
joachim99@69 3015 m_pDirChooseAEverywhere->setEnabled( bDirCompare && isVisible() );
joachim99@69 3016 m_pDirChooseBEverywhere->setEnabled( bDirCompare && isVisible() );
joachim99@69 3017 m_pDirChooseCEverywhere->setEnabled( bDirCompare && isVisible() );
joachim99@51 3018
joachim99@51 3019 bool bThreeDirs = m_dirC.isValid();
joachim99@51 3020
joachim99@75 3021 QTreeWidgetItem* lvi = currentItem();
joachim99@51 3022 DirMergeItem* pDMI = lvi==0 ? 0 : static_cast<DirMergeItem*>(lvi);
joachim99@51 3023 MergeFileInfos* pMFI = pDMI==0 ? 0 : pDMI->m_pMFI;
joachim99@51 3024
joachim99@51 3025 bool bItemActive = bDirCompare && isVisible() && pMFI!=0;// && hasFocus();
joachim99@51 3026 bool bMergeMode = bThreeDirs || !m_bSyncMode;
joachim99@51 3027 bool bFTConflict = pMFI==0 ? false : conflictingFileTypes(*pMFI);
joachim99@51 3028
joachim99@53 3029 bool bDirWindowHasFocus = isVisible() && hasFocus();
joachim99@68 3030
joachim99@69 3031 m_pDirShowIdenticalFiles->setEnabled( bDirCompare && isVisible() );
joachim99@69 3032 m_pDirShowDifferentFiles->setEnabled( bDirCompare && isVisible() );
joachim99@69 3033 m_pDirShowFilesOnlyInA->setEnabled( bDirCompare && isVisible() );
joachim99@69 3034 m_pDirShowFilesOnlyInB->setEnabled( bDirCompare && isVisible() );
joachim99@69 3035 m_pDirShowFilesOnlyInC->setEnabled( bDirCompare && isVisible() && bThreeDirs );
joachim99@69 3036
joachim99@69 3037 m_pDirCompareExplicit->setEnabled( bDirCompare && isVisible() && m_pSelection2Item!=0 );
joachim99@69 3038 m_pDirMergeExplicit->setEnabled( bDirCompare && isVisible() && m_pSelection2Item!=0 );
joachim99@69 3039
joachim99@69 3040 m_pDirCurrentDoNothing->setEnabled( bItemActive && bMergeMode );
joachim99@69 3041 m_pDirCurrentChooseA->setEnabled( bItemActive && bMergeMode && pMFI->m_bExistsInA );
joachim99@69 3042 m_pDirCurrentChooseB->setEnabled( bItemActive && bMergeMode && pMFI->m_bExistsInB );
joachim99@69 3043 m_pDirCurrentChooseC->setEnabled( bItemActive && bMergeMode && pMFI->m_bExistsInC );
joachim99@69 3044 m_pDirCurrentMerge->setEnabled( bItemActive && bMergeMode && !bFTConflict );
joachim99@69 3045 m_pDirCurrentDelete->setEnabled( bItemActive && bMergeMode );
joachim99@53 3046 if ( bDirWindowHasFocus )
joachim99@53 3047 {
joachim99@53 3048 chooseA->setEnabled( bItemActive && pMFI->m_bExistsInA );
joachim99@53 3049 chooseB->setEnabled( bItemActive && pMFI->m_bExistsInB );
joachim99@53 3050 chooseC->setEnabled( bItemActive && pMFI->m_bExistsInC );
joachim99@53 3051 chooseA->setChecked( false );
joachim99@53 3052 chooseB->setChecked( false );
joachim99@53 3053 chooseC->setChecked( false );
joachim99@53 3054 }
joachim99@68 3055
joachim99@69 3056 m_pDirCurrentSyncDoNothing->setEnabled( bItemActive && !bMergeMode );
joachim99@69 3057 m_pDirCurrentSyncCopyAToB->setEnabled( bItemActive && !bMergeMode && pMFI->m_bExistsInA );
joachim99@69 3058 m_pDirCurrentSyncCopyBToA->setEnabled( bItemActive && !bMergeMode && pMFI->m_bExistsInB );
joachim99@69 3059 m_pDirCurrentSyncDeleteA->setEnabled( bItemActive && !bMergeMode && pMFI->m_bExistsInA );
joachim99@69 3060 m_pDirCurrentSyncDeleteB->setEnabled( bItemActive && !bMergeMode && pMFI->m_bExistsInB );
joachim99@69 3061 m_pDirCurrentSyncDeleteAAndB->setEnabled( bItemActive && !bMergeMode && pMFI->m_bExistsInB && pMFI->m_bExistsInB );
joachim99@69 3062 m_pDirCurrentSyncMergeToA->setEnabled( bItemActive && !bMergeMode && !bFTConflict );
joachim99@69 3063 m_pDirCurrentSyncMergeToB->setEnabled( bItemActive && !bMergeMode && !bFTConflict );
joachim99@69 3064 m_pDirCurrentSyncMergeToAAndB->setEnabled( bItemActive && !bMergeMode && !bFTConflict );
joachim99@51 3065 }
joachim99@51 3066
joachim99@51 3067
joachim99@70 3068 //#include "directorymergewindow.moc"