annotate kdiff3/src/directorymergewindow.cpp @ 25:d101155f5c52

Fix for gcc 2.95
author joachim99
date Sat, 11 Oct 2003 12:41:57 +0000
parents 86d21651c8db
children bf8fa177e5a1
rev   line source
joachim99@8 1 /***************************************************************************
joachim99@8 2 directorymergewindow.cpp
joachim99@8 3 -------------------
joachim99@8 4 begin : Sat Oct 19 2002
joachim99@8 5 copyright : (C) 2002 by Joachim Eibl
joachim99@8 6 email : joachim.eibl@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 /***************************************************************************
joachim99@8 19 * $Log$
joachim99@25 20 * Revision 1.2 2003/10/11 12:41:57 joachim99
joachim99@25 21 * Fix for gcc 2.95
joachim99@25 22 *
joachim99@8 23 * Revision 1.1 2003/10/06 18:38:48 joachim99
joachim99@8 24 * KDiff3 version 0.9.70
joachim99@8 25 ***************************************************************************/
joachim99@8 26
joachim99@8 27 #include "directorymergewindow.h"
joachim99@8 28 #include "optiondialog.h"
joachim99@8 29 #include <vector>
joachim99@8 30 #include <map>
joachim99@8 31
joachim99@8 32 #include <qdir.h>
joachim99@8 33 #include <qapplication.h>
joachim99@8 34 #include <qpixmap.h>
joachim99@8 35 #include <qimage.h>
joachim99@8 36 #include <kpopupmenu.h>
joachim99@8 37 #include <qregexp.h>
joachim99@8 38 #include <qmessagebox.h>
joachim99@8 39 #include <qlayout.h>
joachim99@8 40 #include <qlabel.h>
joachim99@8 41 #include <qtable.h>
joachim99@8 42 #include <qsplitter.h>
joachim99@8 43 #include <qprogressdialog.h>
joachim99@8 44 #include <kmessagebox.h>
joachim99@8 45 #include <kiconloader.h>
joachim99@8 46 #include <klocale.h>
joachim99@8 47 #include <iostream>
joachim99@8 48 #include <assert.h>
joachim99@8 49
joachim99@8 50
joachim99@8 51 class StatusInfo : public QListView
joachim99@8 52 {
joachim99@8 53 public:
joachim99@8 54 StatusInfo(QWidget* pParent) : QListView( pParent )
joachim99@8 55 {
joachim99@8 56 addColumn("");
joachim99@8 57 setSorting(-1); //disable sorting
joachim99@8 58 }
joachim99@8 59
joachim99@8 60 QListViewItem* m_pLast;
joachim99@8 61 QListViewItem* last()
joachim99@8 62 {
joachim99@8 63 if (firstChild()==0) return 0;
joachim99@8 64 else return m_pLast;
joachim99@8 65 }
joachim99@8 66
joachim99@8 67 void addText(const QString& s )
joachim99@8 68 {
joachim99@8 69 if (firstChild()==0) m_pLast = new QListViewItem( this, s );
joachim99@8 70 else m_pLast = new QListViewItem( this, last(), s );
joachim99@8 71 }
joachim99@8 72 };
joachim99@8 73
joachim99@8 74
joachim99@8 75 class TempRemover
joachim99@8 76 {
joachim99@8 77 public:
joachim99@8 78 TempRemover( const QString& origName, FileAccess& fa );
joachim99@8 79 ~TempRemover();
joachim99@8 80 QString name() { return m_name; }
joachim99@8 81 bool success() { return m_bSuccess; }
joachim99@8 82 private:
joachim99@8 83 QString m_name;
joachim99@8 84 bool m_bTemp;
joachim99@8 85 bool m_bSuccess;
joachim99@8 86 };
joachim99@8 87 TempRemover::TempRemover(const QString& origName, FileAccess& fa)
joachim99@8 88 {
joachim99@8 89 if ( fa.isLocal() )
joachim99@8 90 {
joachim99@8 91 m_name = origName;
joachim99@8 92 m_bTemp = false;
joachim99@8 93 m_bSuccess = true;
joachim99@8 94 }
joachim99@8 95 else
joachim99@8 96 {
joachim99@8 97 m_name = FileAccess::tempFileName();
joachim99@8 98 m_bSuccess = fa.copyFile( m_name );
joachim99@8 99 m_bTemp = m_bSuccess;
joachim99@8 100 }
joachim99@8 101 }
joachim99@8 102 TempRemover::~TempRemover()
joachim99@8 103 {
joachim99@8 104 if ( m_bTemp && ! m_name.isEmpty() )
joachim99@8 105 FileAccess::removeFile(m_name);
joachim99@8 106 }
joachim99@8 107
joachim99@8 108 void DirectoryMergeWindow::fastFileComparison(
joachim99@8 109 FileAccess& fi1, FileAccess& fi2,
joachim99@8 110 bool& bEqual, bool& bError, QString& status )
joachim99@8 111 {
joachim99@8 112 status = "";
joachim99@8 113 bEqual = false;
joachim99@8 114 bError = true;
joachim99@8 115
joachim99@8 116 if ( !m_bFollowFileLinks )
joachim99@8 117 {
joachim99@8 118 if ( fi1.isSymLink() != fi2.isSymLink() )
joachim99@8 119 {
joachim99@8 120 status = "Mix of links and normal files.";
joachim99@8 121 return;
joachim99@8 122 }
joachim99@8 123 else if ( fi1.isSymLink() && fi2.isSymLink() )
joachim99@8 124 {
joachim99@8 125 bError = false;
joachim99@8 126 bEqual = fi1.readLink() == fi2.readLink();
joachim99@8 127 status = "Link: ";
joachim99@8 128 return;
joachim99@8 129 }
joachim99@8 130 }
joachim99@8 131
joachim99@8 132 if ( fi1.size()!=fi2.size() )
joachim99@8 133 {
joachim99@8 134 bEqual = false;
joachim99@8 135 status = "Size. ";
joachim99@8 136 return;
joachim99@8 137 }
joachim99@8 138
joachim99@8 139 if ( m_pOptions->m_bDmTrustDate )
joachim99@8 140 {
joachim99@8 141 bEqual = ( fi1.lastModified() == fi2.lastModified() && fi1.size()==fi2.size() );
joachim99@8 142 bError = false;
joachim99@8 143 status = "Date&Size: ";
joachim99@8 144 return;
joachim99@8 145 }
joachim99@8 146
joachim99@8 147 QString fileName1 = fi1.absFilePath();
joachim99@8 148 QString fileName2 = fi2.absFilePath();
joachim99@8 149 TempRemover tr1( fileName1, fi1 );
joachim99@8 150 if ( !tr1.success() )
joachim99@8 151 {
joachim99@8 152 status = "Creating temp copy of " + fileName1 + " failed.";
joachim99@8 153 return;
joachim99@8 154 }
joachim99@8 155 TempRemover tr2( fileName2, fi2 );
joachim99@8 156 if ( !tr2.success() )
joachim99@8 157 {
joachim99@8 158 status = "Creating temp copy of " + fileName2 + " failed.";
joachim99@8 159 return;
joachim99@8 160 }
joachim99@8 161
joachim99@8 162 std::vector<char> buf1(100000);
joachim99@8 163 std::vector<char> buf2(buf1.size());
joachim99@8 164
joachim99@8 165 QFile file1( tr1.name() );
joachim99@8 166
joachim99@8 167 if ( ! file1.open(IO_ReadOnly) )
joachim99@8 168 {
joachim99@8 169 status = "Opening " + fileName1 + " failed.";
joachim99@8 170 return;
joachim99@8 171 }
joachim99@8 172
joachim99@8 173 QFile file2( tr2.name() );
joachim99@8 174
joachim99@8 175 if ( ! file2.open(IO_ReadOnly) )
joachim99@8 176 {
joachim99@8 177 status = "Opening " + fileName2 + " failed.";
joachim99@8 178 return;
joachim99@8 179 }
joachim99@8 180
joachim99@8 181 #if QT_VERSION==230
joachim99@8 182 typedef int t_FileSize;
joachim99@8 183 #else
joachim99@8 184 typedef QFile::Offset t_FileSize;
joachim99@8 185 #endif
joachim99@8 186 t_FileSize size = file1.size();
joachim99@8 187
joachim99@8 188 while( size>0 )
joachim99@8 189 {
joachim99@8 190 int len = min2( size, (t_FileSize)buf1.size() );
joachim99@8 191 if( len != file1.readBlock( &buf1[0], len ) )
joachim99@8 192 {
joachim99@8 193 status = "Error reading from " + fileName1;
joachim99@8 194 return;
joachim99@8 195 }
joachim99@8 196
joachim99@8 197 if( len != file2.readBlock( &buf2[0], len ) )
joachim99@8 198 {
joachim99@8 199 status = "Error reading from " + fileName2;
joachim99@8 200 return;
joachim99@8 201 }
joachim99@8 202
joachim99@8 203 if ( memcmp( &buf1[0], &buf2[0], len ) != 0 )
joachim99@8 204 {
joachim99@8 205 bError = false;
joachim99@8 206 return;
joachim99@8 207 }
joachim99@8 208 size-=len;
joachim99@8 209 }
joachim99@8 210
joachim99@8 211 // If the program really arrives here, then the files are really equal.
joachim99@8 212 bError = false;
joachim99@8 213 bEqual = true;
joachim99@8 214 }
joachim99@8 215
joachim99@8 216
joachim99@8 217
joachim99@8 218
joachim99@8 219
joachim99@8 220 static int s_nameCol = 0;
joachim99@8 221 static int s_ACol = 1;
joachim99@8 222 static int s_BCol = 2;
joachim99@8 223 static int s_CCol = 3;
joachim99@8 224 static int s_OpCol = 4;
joachim99@8 225 static int s_OpStatusCol = 5;
joachim99@8 226 DirectoryMergeWindow::DirectoryMergeWindow( QWidget* pParent, OptionDialog* pOptions, KIconLoader* pIconLoader )
joachim99@8 227 : QListView( pParent )
joachim99@8 228 {
joachim99@8 229 connect( this, SIGNAL(doubleClicked(QListViewItem*)), this, SLOT(onDoubleClick(QListViewItem*)));
joachim99@8 230 connect( this, SIGNAL(returnPressed(QListViewItem*)), this, SLOT(onDoubleClick(QListViewItem*)));
joachim99@8 231 connect( this, SIGNAL( pressed(QListViewItem*,const QPoint&, int)),
joachim99@8 232 this, SLOT( onClick(QListViewItem*,const QPoint&, int)) );
joachim99@8 233 connect( this, SIGNAL(selectionChanged(QListViewItem*)), this, SLOT(onSelectionChanged(QListViewItem*)));
joachim99@8 234 m_pOptions = pOptions;
joachim99@8 235 m_pIconLoader = pIconLoader;
joachim99@8 236 m_pDirectoryMergeInfo = 0;
joachim99@8 237 m_bAllowResizeEvents = true;
joachim99@8 238 m_bSimulatedMergeStarted=false;
joachim99@8 239 m_bRealMergeStarted=false;
joachim99@8 240 m_bSingleFileOperationStarted=false;
joachim99@8 241 m_bError = false;
joachim99@8 242 m_bSyncMode = false;
joachim99@8 243 m_pStatusInfo = new StatusInfo(0);
joachim99@8 244 m_pStatusInfo->hide();
joachim99@8 245
joachim99@8 246 addColumn("Name");
joachim99@8 247 addColumn("A");
joachim99@8 248 addColumn("B");
joachim99@8 249 addColumn("C");
joachim99@8 250 addColumn("Operation");
joachim99@8 251 addColumn("Status");
joachim99@8 252 }
joachim99@8 253
joachim99@8 254 DirectoryMergeWindow::~DirectoryMergeWindow()
joachim99@8 255 {
joachim99@8 256 }
joachim99@8 257
joachim99@8 258
joachim99@8 259 int DirectoryMergeWindow::totalColumnWidth()
joachim99@8 260 {
joachim99@8 261 int w=0;
joachim99@8 262 for (int i=0; i<s_OpStatusCol; ++i)
joachim99@8 263 {
joachim99@8 264 w += columnWidth(i);
joachim99@8 265 }
joachim99@8 266 return w;
joachim99@8 267 }
joachim99@8 268
joachim99@8 269 void DirectoryMergeWindow::reload()
joachim99@8 270 {
joachim99@8 271 if ( isDirectoryMergeInProgress() )
joachim99@8 272 {
joachim99@8 273 int result = KMessageBox::warningYesNo(this,
joachim99@8 274 i18n("You are currently doing a directory merge. Are you sure, you want to abort the merge and rescan the directory?"),
joachim99@8 275 i18n("Warning"), i18n("Yes - Rescan"), i18n("No - Continue merging") );
joachim99@8 276 if ( result!=KMessageBox::Yes )
joachim99@8 277 return;
joachim99@8 278 }
joachim99@8 279 init( m_dirA, m_dirB, m_dirC, m_dirDest, m_bDirectoryMerge );
joachim99@8 280 }
joachim99@8 281
joachim99@8 282 // Copy pm2 onto pm1, but preserve the alpha value from pm1 where pm2 is transparent.
joachim99@8 283 static QPixmap pixCombiner( const QPixmap& pm1, const QPixmap& pm2 )
joachim99@8 284 {
joachim99@8 285 QImage img1 = pm1.convertToImage().convertDepth(32);
joachim99@8 286 QImage img2 = pm2.convertToImage().convertDepth(32);
joachim99@8 287
joachim99@8 288 for (int y = 0; y < img1.height(); y++)
joachim99@8 289 {
joachim99@8 290 Q_UINT32 *line1 = reinterpret_cast<Q_UINT32 *>(img1.scanLine(y));
joachim99@8 291 Q_UINT32 *line2 = reinterpret_cast<Q_UINT32 *>(img2.scanLine(y));
joachim99@8 292 for (int x = 0; x < img1.width(); x++)
joachim99@8 293 {
joachim99@8 294 if ( qAlpha( line2[x] ) >0 )
joachim99@8 295 line1[x] = (line2[x] | 0xff000000);
joachim99@8 296 }
joachim99@8 297 }
joachim99@8 298 QPixmap pix;
joachim99@8 299 pix.convertFromImage(img1);
joachim99@8 300 return pix;
joachim99@8 301 }
joachim99@8 302
joachim99@8 303 // like pixCombiner but let the pm1 color shine through
joachim99@8 304 static QPixmap pixCombiner2( const QPixmap& pm1, const QPixmap& pm2 )
joachim99@8 305 {
joachim99@8 306 QImage img1 = pm1.convertToImage().convertDepth(32);
joachim99@8 307 QImage img2 = pm2.convertToImage().convertDepth(32);
joachim99@8 308
joachim99@8 309 for (int y = 0; y < img1.height(); y++)
joachim99@8 310 {
joachim99@8 311 Q_UINT32 *line1 = reinterpret_cast<Q_UINT32 *>(img1.scanLine(y));
joachim99@8 312 Q_UINT32 *line2 = reinterpret_cast<Q_UINT32 *>(img2.scanLine(y));
joachim99@8 313 for (int x = 0; x < img1.width(); x++)
joachim99@8 314 {
joachim99@8 315 if ( qAlpha( line2[x] ) >0 )
joachim99@8 316 {
joachim99@8 317 int r = ( qRed( line1[x] ) + qRed( line2[x] ))/2;
joachim99@8 318 int g = ( qGreen( line1[x] ) + qGreen( line2[x] ))/2;
joachim99@8 319 int b = ( qBlue( line1[x] ) + qBlue( line2[x] ))/2;
joachim99@8 320 line1[x] = qRgba( r,g,b, 0xff );
joachim99@8 321 }
joachim99@8 322 }
joachim99@8 323 }
joachim99@8 324 QPixmap pix;
joachim99@8 325 pix.convertFromImage(img1);
joachim99@8 326 return pix;
joachim99@8 327 }
joachim99@8 328
joachim99@8 329 static void calcDirStatus( bool bThreeDirs, DirMergeItem* i, int& nofFiles,
joachim99@8 330 int& nofDirs, int& nofEqualFiles, int& nofManualMerges )
joachim99@8 331 {
joachim99@8 332 if ( i->m_pMFI->m_bDirA || i->m_pMFI->m_bDirB || i->m_pMFI->m_bDirC )
joachim99@8 333 {
joachim99@8 334 ++nofDirs;
joachim99@8 335 }
joachim99@8 336 else
joachim99@8 337 {
joachim99@8 338 ++nofFiles;
joachim99@8 339 if ( i->m_pMFI->m_bEqualAB && (!bThreeDirs || i->m_pMFI->m_bEqualAC ))
joachim99@8 340 {
joachim99@8 341 ++nofEqualFiles;
joachim99@8 342 }
joachim99@8 343 else
joachim99@8 344 {
joachim99@8 345 if ( i->m_pMFI->m_eMergeOperation==eMergeABCToDest || i->m_pMFI->m_eMergeOperation==eMergeABToDest )
joachim99@8 346 ++nofManualMerges;
joachim99@8 347 }
joachim99@8 348 }
joachim99@8 349 for( QListViewItem* p = i->firstChild(); p!=0; p = p->nextSibling() )
joachim99@8 350 calcDirStatus( bThreeDirs, static_cast<DirMergeItem*>(p), nofFiles, nofDirs, nofEqualFiles, nofManualMerges );
joachim99@8 351 }
joachim99@8 352
joachim99@8 353 bool DirectoryMergeWindow::init
joachim99@8 354 (
joachim99@8 355 FileAccess& dirA,
joachim99@8 356 FileAccess& dirB,
joachim99@8 357 FileAccess& dirC,
joachim99@8 358 FileAccess& dirDest,
joachim99@8 359 bool bDirectoryMerge
joachim99@8 360 )
joachim99@8 361 {
joachim99@8 362 m_bFollowDirLinks = m_pOptions->m_bDmFollowDirLinks;
joachim99@8 363 m_bFollowFileLinks = m_pOptions->m_bDmFollowFileLinks;
joachim99@8 364 m_bSimulatedMergeStarted=false;
joachim99@8 365 m_bRealMergeStarted=false;
joachim99@8 366 m_bError=false;
joachim99@8 367 m_bDirectoryMerge = bDirectoryMerge;
joachim99@8 368
joachim99@8 369 clear();
joachim99@8 370
joachim99@8 371 m_pCurrentItemForOperation = 0;
joachim99@8 372
joachim99@8 373 m_dirA = dirA;
joachim99@8 374 m_dirB = dirB;
joachim99@8 375 m_dirC = dirC;
joachim99@8 376 m_dirDest = dirDest;
joachim99@8 377
joachim99@8 378 // Check if all input directories exist and are valid. The dest dir is not tested now.
joachim99@8 379 // The test will happen only when we are going to write to it.
joachim99@8 380 if ( !m_dirA.isDir() || !m_dirB.isDir() ||
joachim99@8 381 (m_dirC.isValid() && !m_dirC.isDir()) )
joachim99@8 382 {
joachim99@8 383 QString text( i18n("Opening of directories failed:") );
joachim99@8 384 text += "\n\n";
joachim99@8 385 if ( !dirA.isDir() )
joachim99@8 386 { text += "Dir A \"" + m_dirA.prettyAbsPath() + "\" does not exist or is not a directory.\n"; }
joachim99@8 387
joachim99@8 388 if ( !dirB.isDir() )
joachim99@8 389 { text += "Dir B \"" + m_dirB.prettyAbsPath() + "\" does not exist or is not a directory.\n"; }
joachim99@8 390
joachim99@8 391 if ( m_dirC.isValid() && !m_dirC.isDir() )
joachim99@8 392 { text += "Dir C \"" + m_dirC.prettyAbsPath() + "\" does not exist or is not a directory.\n"; }
joachim99@8 393
joachim99@8 394 KMessageBox::sorry( this, text, i18n("Directory open error") );
joachim99@8 395 return false;
joachim99@8 396 }
joachim99@8 397
joachim99@8 398 if ( m_dirC.isValid() &&
joachim99@8 399 (m_dirDest.prettyAbsPath() == m_dirA.prettyAbsPath() || m_dirDest.prettyAbsPath()==m_dirB.prettyAbsPath() ) )
joachim99@8 400 {
joachim99@8 401 KMessageBox::error(this,
joachim99@8 402 i18n( "The destination directory must not be the same as A or B when"
joachim99@8 403 "three directories are merged.\nCheck again before continuing."),
joachim99@8 404 "KDiff3: Parameter warning");
joachim99@8 405 return false;
joachim99@8 406 }
joachim99@8 407
joachim99@8 408 m_bSyncMode = m_pOptions->m_bDmSyncMode && !m_dirC.isValid() && !m_dirDest.isValid();
joachim99@8 409
joachim99@8 410 if ( m_dirDest.isValid() )
joachim99@8 411 m_dirDestInternal = m_dirDest;
joachim99@8 412 else
joachim99@8 413 m_dirDestInternal = m_dirC.isValid() ? m_dirC : m_dirB;
joachim99@8 414
joachim99@8 415 QString origCurrentDirectory = QDir::currentDirPath();
joachim99@8 416
joachim99@8 417 g_pProgressDialog->start();
joachim99@8 418
joachim99@8 419 m_fileMergeMap.clear();
joachim99@8 420 t_DirectoryList::iterator i;
joachim99@8 421
joachim99@8 422 // calc how many directories will be read:
joachim99@8 423 double nofScans = ( m_dirA.isValid() ? 1 : 0 )+( m_dirB.isValid() ? 1 : 0 )+( m_dirC.isValid() ? 1 : 0 );
joachim99@8 424 int currentScan = 0;
joachim99@8 425
joachim99@8 426 bool bListDirSuccessA = true;
joachim99@8 427 bool bListDirSuccessB = true;
joachim99@8 428 bool bListDirSuccessC = true;
joachim99@8 429 if ( m_dirA.isValid() )
joachim99@8 430 {
joachim99@8 431 g_pProgressDialog->setInformation("Reading Directory A");
joachim99@8 432 g_pProgressDialog->setSubRangeTransformation(currentScan/nofScans, (currentScan+1)/nofScans);
joachim99@8 433 ++currentScan;
joachim99@8 434
joachim99@8 435 t_DirectoryList dirListA;
joachim99@8 436 bListDirSuccessA = m_dirA.listDir( &dirListA,
joachim99@8 437 m_pOptions->m_bDmRecursiveDirs, m_pOptions->m_bDmFindHidden,
joachim99@8 438 m_pOptions->m_DmFilePattern, m_pOptions->m_DmFileAntiPattern,
joachim99@8 439 m_pOptions->m_DmDirAntiPattern, m_pOptions->m_bDmFollowDirLinks,
joachim99@8 440 m_pOptions->m_bDmUseCvsIgnore);
joachim99@8 441
joachim99@8 442 for (i=dirListA.begin(); i!=dirListA.end();++i )
joachim99@8 443 {
joachim99@8 444 MergeFileInfos& mfi = m_fileMergeMap[i->filePath()];
joachim99@8 445 //std::cout <<i->filePath()<<std::endl;
joachim99@8 446 mfi.m_bExistsInA = true;
joachim99@8 447 mfi.m_fileInfoA = *i;
joachim99@8 448 }
joachim99@8 449 }
joachim99@8 450
joachim99@8 451 if ( m_dirB.isValid() )
joachim99@8 452 {
joachim99@8 453 g_pProgressDialog->setInformation("Reading Directory B");
joachim99@8 454 g_pProgressDialog->setSubRangeTransformation(currentScan/nofScans, (currentScan+1)/nofScans);
joachim99@8 455 ++currentScan;
joachim99@8 456
joachim99@8 457 t_DirectoryList dirListB;
joachim99@8 458 bListDirSuccessB = m_dirB.listDir( &dirListB,
joachim99@8 459 m_pOptions->m_bDmRecursiveDirs, m_pOptions->m_bDmFindHidden,
joachim99@8 460 m_pOptions->m_DmFilePattern, m_pOptions->m_DmFileAntiPattern,
joachim99@8 461 m_pOptions->m_DmDirAntiPattern, m_pOptions->m_bDmFollowDirLinks,
joachim99@8 462 m_pOptions->m_bDmUseCvsIgnore);
joachim99@8 463
joachim99@8 464 for (i=dirListB.begin(); i!=dirListB.end();++i )
joachim99@8 465 {
joachim99@8 466 MergeFileInfos& mfi = m_fileMergeMap[i->filePath()];
joachim99@8 467 mfi.m_bExistsInB = true;
joachim99@8 468 mfi.m_fileInfoB = *i;
joachim99@8 469 }
joachim99@8 470 }
joachim99@8 471
joachim99@8 472 e_MergeOperation eDefaultMergeOp;
joachim99@8 473 if ( m_dirC.isValid() )
joachim99@8 474 {
joachim99@8 475 g_pProgressDialog->setInformation("Reading Directory C");
joachim99@8 476 g_pProgressDialog->setSubRangeTransformation(currentScan/nofScans, (currentScan+1)/nofScans);
joachim99@8 477 ++currentScan;
joachim99@8 478
joachim99@8 479 t_DirectoryList dirListC;
joachim99@8 480 bListDirSuccessC = m_dirC.listDir( &dirListC,
joachim99@8 481 m_pOptions->m_bDmRecursiveDirs, m_pOptions->m_bDmFindHidden,
joachim99@8 482 m_pOptions->m_DmFilePattern, m_pOptions->m_DmFileAntiPattern,
joachim99@8 483 m_pOptions->m_DmDirAntiPattern, m_pOptions->m_bDmFollowDirLinks,
joachim99@8 484 m_pOptions->m_bDmUseCvsIgnore);
joachim99@8 485
joachim99@8 486 for (i=dirListC.begin(); i!=dirListC.end();++i )
joachim99@8 487 {
joachim99@8 488 MergeFileInfos& mfi = m_fileMergeMap[i->filePath()];
joachim99@8 489 mfi.m_bExistsInC = true;
joachim99@8 490 mfi.m_fileInfoC = *i;
joachim99@8 491 }
joachim99@8 492
joachim99@8 493 eDefaultMergeOp = eMergeABCToDest;
joachim99@8 494 }
joachim99@8 495 else
joachim99@8 496 eDefaultMergeOp = m_bSyncMode ? eMergeToAB : eMergeABToDest;
joachim99@8 497
joachim99@8 498 bool bContinue = true;
joachim99@8 499 if ( !bListDirSuccessA || !bListDirSuccessB || !bListDirSuccessC )
joachim99@8 500 {
joachim99@8 501 QString s = i18n("Some subdirectories were not readable in");
joachim99@8 502 if ( !bListDirSuccessA ) s += "\nA: " + m_dirA.prettyAbsPath();
joachim99@8 503 if ( !bListDirSuccessB ) s += "\nB: " + m_dirB.prettyAbsPath();
joachim99@8 504 if ( !bListDirSuccessC ) s += "\nC: " + m_dirC.prettyAbsPath();
joachim99@8 505 s+="\n";
joachim99@8 506 s+= i18n("Check the permissions of the subdirectories.");
joachim99@8 507 bContinue = KMessageBox::Continue == KMessageBox::warningContinueCancel( this, s );
joachim99@8 508 }
joachim99@8 509
joachim99@8 510 if ( bContinue )
joachim99@8 511 {
joachim99@8 512 prepareListView();
joachim99@8 513 g_pProgressDialog->hide();
joachim99@8 514
joachim99@8 515 for( QListViewItem* p = firstChild(); p!=0; p = p->nextSibling() )
joachim99@8 516 {
joachim99@8 517 DirMergeItem* pDMI = static_cast<DirMergeItem*>( p );
joachim99@8 518 calcSuggestedOperation( *pDMI->m_pMFI, eDefaultMergeOp );
joachim99@8 519 }
joachim99@8 520 }
joachim99@8 521 else
joachim99@8 522 {
joachim99@8 523 g_pProgressDialog->hide();
joachim99@8 524 setSelected( 0, true );
joachim99@8 525 }
joachim99@8 526
joachim99@8 527 QDir::setCurrent(origCurrentDirectory);
joachim99@8 528
joachim99@8 529 // Try to improve the view a little bit.
joachim99@8 530 QWidget* pParent = parentWidget();
joachim99@8 531 QSplitter* pSplitter = static_cast<QSplitter*>(pParent);
joachim99@8 532 if (pSplitter!=0)
joachim99@8 533 {
joachim99@8 534 QValueList<int> sizes = pSplitter->sizes();
joachim99@8 535 int total = sizes[0] + sizes[1];
joachim99@8 536 sizes[0]=total*6/10;
joachim99@8 537 sizes[1]=total - sizes[0];
joachim99@8 538 pSplitter->setSizes( sizes );
joachim99@8 539 }
joachim99@8 540
joachim99@8 541 if ( bContinue )
joachim99@8 542 {
joachim99@8 543 // Generate a status report
joachim99@8 544 int nofFiles=0;
joachim99@8 545 int nofDirs=0;
joachim99@8 546 int nofEqualFiles=0;
joachim99@8 547 int nofManualMerges=0;
joachim99@8 548 for( QListViewItem* p = firstChild(); p!=0; p = p->nextSibling() )
joachim99@8 549 calcDirStatus( m_dirC.isValid(), static_cast<DirMergeItem*>(p),
joachim99@8 550 nofFiles, nofDirs, nofEqualFiles, nofManualMerges );
joachim99@8 551
joachim99@8 552 QString s;
joachim99@8 553 s = i18n("Directory Comparison Status:") + "\n\n" +
joachim99@8 554 i18n("Number of subdirectories:") +" "+ QString::number(nofDirs) + "\n"+
joachim99@8 555 i18n("Number of equal files:") +" "+ QString::number(nofEqualFiles) + "\n"+
joachim99@8 556 i18n("Number of different files:") +" "+ QString::number(nofFiles-nofEqualFiles);
joachim99@8 557
joachim99@8 558 if ( m_dirC.isValid() )
joachim99@8 559 s += "\n" + i18n("Number of manual merges:") +" "+ QString::number(nofManualMerges);
joachim99@8 560 KMessageBox::information( this, s );
joachim99@8 561 setSelected( firstChild(), true );
joachim99@8 562 }
joachim99@8 563
joachim99@8 564 return true;
joachim99@8 565 }
joachim99@8 566
joachim99@8 567
joachim99@8 568
joachim99@8 569 void DirectoryMergeWindow::slotChooseAEverywhere(){ setAllMergeOperations( eCopyAToDest ); }
joachim99@8 570
joachim99@8 571 void DirectoryMergeWindow::slotChooseBEverywhere(){ setAllMergeOperations( eCopyBToDest ); }
joachim99@8 572
joachim99@8 573 void DirectoryMergeWindow::slotChooseCEverywhere(){ setAllMergeOperations( eCopyCToDest ); }
joachim99@8 574
joachim99@8 575 void DirectoryMergeWindow::slotAutoChooseEverywhere()
joachim99@8 576 {
joachim99@8 577 e_MergeOperation eDefaultMergeOp = m_dirC.isValid() ? eMergeABCToDest :
joachim99@8 578 m_bSyncMode ? eMergeToAB : eMergeABToDest;
joachim99@8 579 setAllMergeOperations(eDefaultMergeOp );
joachim99@8 580 }
joachim99@8 581
joachim99@8 582 void DirectoryMergeWindow::slotNoOpEverywhere(){ setAllMergeOperations(eNoOperation); }
joachim99@8 583
joachim99@8 584 static void setListViewItemOpen( QListViewItem* p, bool bOpen )
joachim99@8 585 {
joachim99@8 586 for( QListViewItem* pChild = p->firstChild(); pChild!=0; pChild = pChild->nextSibling() )
joachim99@8 587 setListViewItemOpen( pChild, bOpen );
joachim99@8 588
joachim99@8 589 p->setOpen( bOpen );
joachim99@8 590 }
joachim99@8 591
joachim99@8 592 void DirectoryMergeWindow::slotFoldAllSubdirs()
joachim99@8 593 {
joachim99@8 594 for( QListViewItem* p = firstChild(); p!=0; p = p->nextSibling() )
joachim99@8 595 setListViewItemOpen( p, false );
joachim99@8 596 }
joachim99@8 597
joachim99@8 598 void DirectoryMergeWindow::slotUnfoldAllSubdirs()
joachim99@8 599 {
joachim99@8 600 for( QListViewItem* p = firstChild(); p!=0; p = p->nextSibling() )
joachim99@8 601 setListViewItemOpen( p, true );
joachim99@8 602 }
joachim99@8 603
joachim99@8 604 void DirectoryMergeWindow::setAllMergeOperations( e_MergeOperation eDefaultOperation )
joachim99@8 605 {
joachim99@8 606 if ( KMessageBox::Yes == KMessageBox::warningYesNo(this,
joachim99@8 607 i18n("This affects all merge operations."),
joachim99@8 608 i18n("KDiff3: Changing all merge operations"),i18n("Continue"), i18n("Cancel") ) )
joachim99@8 609 {
joachim99@8 610 for( QListViewItem* p = firstChild(); p!=0; p = p->nextSibling() )
joachim99@8 611 {
joachim99@8 612 DirMergeItem* pDMI = static_cast<DirMergeItem*>( p );
joachim99@8 613 calcSuggestedOperation( *pDMI->m_pMFI, eDefaultOperation );
joachim99@8 614 }
joachim99@8 615 }
joachim99@8 616 }
joachim99@8 617
joachim99@8 618
joachim99@8 619 void DirectoryMergeWindow::compareFilesAndCalcAges( MergeFileInfos& mfi )
joachim99@8 620 {
joachim99@8 621 std::map<QDateTime,int> dateMap;
joachim99@8 622
joachim99@8 623 if( mfi.m_bExistsInA )
joachim99@8 624 {
joachim99@8 625 mfi.m_bLinkA = mfi.m_fileInfoA.isSymLink();
joachim99@8 626 mfi.m_bDirA = mfi.m_fileInfoA.isDir();
joachim99@8 627 dateMap[ mfi.m_fileInfoA.lastModified() ] = 0;
joachim99@8 628 }
joachim99@8 629 if( mfi.m_bExistsInB )
joachim99@8 630 {
joachim99@8 631 mfi.m_bLinkB = mfi.m_fileInfoB.isSymLink();
joachim99@8 632 mfi.m_bDirB = mfi.m_fileInfoB.isDir();
joachim99@8 633 dateMap[ mfi.m_fileInfoB.lastModified() ] = 1;
joachim99@8 634 }
joachim99@8 635 if( mfi.m_bExistsInC )
joachim99@8 636 {
joachim99@8 637 mfi.m_bLinkC = mfi.m_fileInfoC.isSymLink();
joachim99@8 638 mfi.m_bDirC = mfi.m_fileInfoC.isDir();
joachim99@8 639 dateMap[ mfi.m_fileInfoC.lastModified() ] = 2;
joachim99@8 640 }
joachim99@8 641
joachim99@8 642 bool bError;
joachim99@8 643 QString eqStatus;
joachim99@8 644 if( mfi.m_bExistsInA && mfi.m_bExistsInB )
joachim99@8 645 {
joachim99@8 646 if( mfi.m_bDirA ) mfi.m_bEqualAB=true;
joachim99@8 647 else fastFileComparison( mfi.m_fileInfoA, mfi.m_fileInfoB, mfi.m_bEqualAB, bError, eqStatus );
joachim99@8 648 }
joachim99@8 649 if( mfi.m_bExistsInA && mfi.m_bExistsInC )
joachim99@8 650 {
joachim99@8 651 if( mfi.m_bDirA ) mfi.m_bEqualAC=true;
joachim99@8 652 else fastFileComparison( mfi.m_fileInfoA, mfi.m_fileInfoC, mfi.m_bEqualAC, bError, eqStatus );
joachim99@8 653 }
joachim99@8 654 if( mfi.m_bExistsInB && mfi.m_bExistsInC )
joachim99@8 655 {
joachim99@8 656 if (mfi.m_bEqualAB && mfi.m_bEqualAC)
joachim99@8 657 mfi.m_bEqualBC = true;
joachim99@8 658 else
joachim99@8 659 {
joachim99@8 660 if( mfi.m_bDirB ) mfi.m_bEqualBC=true;
joachim99@8 661 else fastFileComparison( mfi.m_fileInfoB, mfi.m_fileInfoC, mfi.m_bEqualBC, bError, eqStatus );
joachim99@8 662 }
joachim99@8 663 }
joachim99@8 664
joachim99@8 665 if (mfi.m_bLinkA!=mfi.m_bLinkB) mfi.m_bEqualAB=false;
joachim99@8 666 if (mfi.m_bLinkA!=mfi.m_bLinkC) mfi.m_bEqualAC=false;
joachim99@8 667 if (mfi.m_bLinkB!=mfi.m_bLinkC) mfi.m_bEqualBC=false;
joachim99@8 668
joachim99@8 669 if (mfi.m_bDirA!=mfi.m_bDirB) mfi.m_bEqualAB=false;
joachim99@8 670 if (mfi.m_bDirA!=mfi.m_bDirC) mfi.m_bEqualAC=false;
joachim99@8 671 if (mfi.m_bDirB!=mfi.m_bDirC) mfi.m_bEqualBC=false;
joachim99@8 672
joachim99@8 673 assert(eNew==0 && eMiddle==1 && eOld==2);
joachim99@8 674
joachim99@8 675 // The map automatically sorts the keys.
joachim99@8 676 int age = eNew;
joachim99@8 677 std::map<QDateTime,int>::reverse_iterator i;
joachim99@8 678 for( i=dateMap.rbegin(); i!=dateMap.rend(); ++i )
joachim99@8 679 {
joachim99@8 680 int n = i->second;
joachim99@8 681 if ( n==0 && mfi.m_ageA==eNotThere )
joachim99@8 682 {
joachim99@8 683 mfi.m_ageA = (e_Age)age; ++age;
joachim99@8 684 if ( mfi.m_bEqualAB ) { mfi.m_ageB = mfi.m_ageA; ++age; }
joachim99@8 685 if ( mfi.m_bEqualAC ) { mfi.m_ageC = mfi.m_ageA; ++age; }
joachim99@8 686 }
joachim99@8 687 else if ( n==1 && mfi.m_ageB==eNotThere )
joachim99@8 688 {
joachim99@8 689 mfi.m_ageB = (e_Age)age; ++age;
joachim99@8 690 if ( mfi.m_bEqualAB ) { mfi.m_ageA = mfi.m_ageB; ++age; }
joachim99@8 691 if ( mfi.m_bEqualBC ) { mfi.m_ageC = mfi.m_ageB; ++age; }
joachim99@8 692 }
joachim99@8 693 else if ( n==2 && mfi.m_ageC==eNotThere)
joachim99@8 694 {
joachim99@8 695 mfi.m_ageC = (e_Age)age; ++age;
joachim99@8 696 if ( mfi.m_bEqualAC ) { mfi.m_ageA = mfi.m_ageC; ++age; }
joachim99@8 697 if ( mfi.m_bEqualBC ) { mfi.m_ageB = mfi.m_ageC; ++age; }
joachim99@8 698 }
joachim99@8 699 }
joachim99@8 700
joachim99@8 701 // The checks below are necessary when the dates of the file are equal but the
joachim99@8 702 // files are not. One wouldn't expect this to happen, yet it happens sometimes.
joachim99@8 703 if ( mfi.m_bExistsInC && mfi.m_ageC==eNotThere )
joachim99@8 704 {
joachim99@8 705 mfi.m_ageC = (e_Age)age; ++age;
joachim99@8 706 mfi.m_bConflictingAges = true;
joachim99@8 707 }
joachim99@8 708 if ( mfi.m_bExistsInB && mfi.m_ageB==eNotThere )
joachim99@8 709 {
joachim99@8 710 mfi.m_ageB = (e_Age)age; ++age;
joachim99@8 711 mfi.m_bConflictingAges = true;
joachim99@8 712 }
joachim99@8 713 if ( mfi.m_bExistsInA && mfi.m_ageA==eNotThere )
joachim99@8 714 {
joachim99@8 715 mfi.m_ageA = (e_Age)age; ++age;
joachim99@8 716 mfi.m_bConflictingAges = true;
joachim99@8 717 }
joachim99@8 718
joachim99@8 719 if ( mfi.m_ageA != eOld && mfi.m_ageB != eOld && mfi.m_ageC != eOld )
joachim99@8 720 {
joachim99@8 721 if (mfi.m_ageA == eMiddle) mfi.m_ageA = eOld;
joachim99@8 722 if (mfi.m_ageB == eMiddle) mfi.m_ageB = eOld;
joachim99@8 723 if (mfi.m_ageC == eMiddle) mfi.m_ageC = eOld;
joachim99@8 724 }
joachim99@8 725 }
joachim99@8 726
joachim99@8 727 static QPixmap* s_pm_dir;
joachim99@8 728 static QPixmap* s_pm_file;
joachim99@8 729
joachim99@8 730 static void setOnePixmap( QListViewItem* pLVI, int col, e_Age eAge, bool bLink, bool bDir )
joachim99@8 731 {
joachim99@8 732 #include "xpm/equal.xpm"
joachim99@8 733 #include "xpm/not_equal.xpm"
joachim99@8 734 #include "xpm/not_everywhere.xpm"
joachim99@8 735 #include "xpm/not_there.xpm"
joachim99@8 736 #include "xpm/link_arrow.xpm"
joachim99@8 737
joachim99@8 738 static QPixmap pmLink( link_arrow );
joachim99@8 739
joachim99@8 740 static QPixmap pmDirLink( pixCombiner( *s_pm_dir, pmLink) );
joachim99@8 741 static QPixmap pmFileLink( pixCombiner( *s_pm_file, pmLink ) );
joachim99@8 742
joachim99@8 743 static QPixmap pmNotThere( not_there_pm );
joachim99@8 744
joachim99@8 745 static QPixmap pmNew( equal_pm );
joachim99@8 746 static QPixmap pmOld( not_equal_pm );
joachim99@8 747 static QPixmap pmMiddle( not_everywhere_pm );
joachim99@8 748
joachim99@8 749 static QPixmap pmNewLink( pixCombiner( pmNew, pmLink) );
joachim99@8 750 static QPixmap pmOldLink( pixCombiner( pmOld, pmLink) );
joachim99@8 751 static QPixmap pmMiddleLink( pixCombiner( pmMiddle, pmLink) );
joachim99@8 752
joachim99@8 753 static QPixmap pmNewDir( pixCombiner2( pmNew, *s_pm_dir) );
joachim99@8 754 static QPixmap pmMiddleDir( pixCombiner2( pmMiddle, *s_pm_dir) );
joachim99@8 755 static QPixmap pmOldDir( pixCombiner2( pmOld, *s_pm_dir) );
joachim99@8 756
joachim99@8 757 static QPixmap pmNewDirLink( pixCombiner( pmNewDir, pmLink) );
joachim99@8 758 static QPixmap pmMiddleDirLink( pixCombiner( pmMiddleDir, pmLink) );
joachim99@8 759 static QPixmap pmOldDirLink( pixCombiner( pmOldDir, pmLink) );
joachim99@8 760
joachim99@8 761 static QPixmap* ageToPm[]= { &pmNew, &pmMiddle, &pmOld, &pmNotThere, s_pm_file };
joachim99@8 762 static QPixmap* ageToPmLink[]= { &pmNewLink, &pmMiddleLink, &pmOldLink, &pmNotThere, &pmFileLink };
joachim99@8 763 static QPixmap* ageToPmDir[]= { &pmNewDir, &pmMiddleDir, &pmOldDir, &pmNotThere, s_pm_dir };
joachim99@8 764 static QPixmap* ageToPmDirLink[]={ &pmNewDirLink, &pmMiddleDirLink, &pmOldDirLink, &pmNotThere, &pmDirLink };
joachim99@8 765
joachim99@8 766 QPixmap** ppPm = bDir ? ( bLink ? ageToPmDirLink : ageToPmDir ):
joachim99@8 767 ( bLink ? ageToPmLink : ageToPm );
joachim99@8 768
joachim99@8 769 pLVI->setPixmap( col, *ppPm[eAge] );
joachim99@8 770 }
joachim99@8 771
joachim99@8 772 static void setPixmaps( MergeFileInfos& mfi, bool bCheckC )
joachim99@8 773 {
joachim99@8 774 setOnePixmap( mfi.m_pDMI, s_nameCol, eAgeEnd,
joachim99@8 775 mfi.m_bLinkA || mfi.m_bLinkB || mfi.m_bLinkC,
joachim99@8 776 mfi.m_bDirA || mfi.m_bDirB || mfi.m_bDirC
joachim99@8 777 );
joachim99@8 778
joachim99@8 779 if ( mfi.m_bDirA || mfi.m_bDirB || mfi.m_bDirC )
joachim99@8 780 {
joachim99@8 781 mfi.m_ageA=eNotThere;
joachim99@8 782 mfi.m_ageB=eNotThere;
joachim99@8 783 mfi.m_ageC=eNotThere;
joachim99@8 784 int age = eNew;
joachim99@8 785 if ( mfi.m_bExistsInC )
joachim99@8 786 {
joachim99@8 787 mfi.m_ageC = (e_Age)age;
joachim99@8 788 if (mfi.m_bEqualAC) mfi.m_ageA = (e_Age)age;
joachim99@8 789 if (mfi.m_bEqualBC) mfi.m_ageB = (e_Age)age;
joachim99@8 790 ++age;
joachim99@8 791 }
joachim99@8 792 if ( mfi.m_bExistsInB && mfi.m_ageB==eNotThere )
joachim99@8 793 {
joachim99@8 794 mfi.m_ageB = (e_Age)age;
joachim99@8 795 if (mfi.m_bEqualAB) mfi.m_ageA = (e_Age)age;
joachim99@8 796 ++age;
joachim99@8 797 }
joachim99@8 798 if ( mfi.m_bExistsInA && mfi.m_ageA==eNotThere )
joachim99@8 799 {
joachim99@8 800 mfi.m_ageA = (e_Age)age;
joachim99@8 801 }
joachim99@8 802 if ( mfi.m_ageA != eOld && mfi.m_ageB != eOld && mfi.m_ageC != eOld )
joachim99@8 803 {
joachim99@8 804 if (mfi.m_ageA == eMiddle) mfi.m_ageA = eOld;
joachim99@8 805 if (mfi.m_ageB == eMiddle) mfi.m_ageB = eOld;
joachim99@8 806 if (mfi.m_ageC == eMiddle) mfi.m_ageC = eOld;
joachim99@8 807 }
joachim99@8 808 }
joachim99@8 809
joachim99@8 810 setOnePixmap( mfi.m_pDMI, s_ACol, mfi.m_ageA, mfi.m_bLinkA, mfi.m_bDirA );
joachim99@8 811 setOnePixmap( mfi.m_pDMI, s_BCol, mfi.m_ageB, mfi.m_bLinkB, mfi.m_bDirB );
joachim99@8 812 if ( bCheckC )
joachim99@8 813 setOnePixmap( mfi.m_pDMI, s_CCol, mfi.m_ageC, mfi.m_bLinkC, mfi.m_bDirC );
joachim99@8 814 }
joachim99@8 815
joachim99@8 816 // Iterate through the complete tree. Start by specifying QListView::firstChild().
joachim99@8 817 static QListViewItem* treeIterator( QListViewItem* p, bool bVisitChildren=true )
joachim99@8 818 {
joachim99@8 819 if( p!=0 )
joachim99@8 820 {
joachim99@8 821 if ( bVisitChildren && p->firstChild() != 0 ) p = p->firstChild();
joachim99@8 822 else if ( p->nextSibling() !=0 ) p = p->nextSibling();
joachim99@8 823 else
joachim99@8 824 {
joachim99@8 825 p = p->parent();
joachim99@8 826 while ( p!=0 )
joachim99@8 827 {
joachim99@8 828 if( p->nextSibling()!=0 ) { p = p->nextSibling(); break; }
joachim99@8 829 else { p = p->parent(); }
joachim99@8 830 }
joachim99@8 831 }
joachim99@8 832 }
joachim99@8 833 return p;
joachim99@8 834 }
joachim99@8 835
joachim99@8 836 void DirectoryMergeWindow::prepareListView()
joachim99@8 837 {
joachim99@8 838 static bool bFirstTime = true;
joachim99@8 839 if (bFirstTime)
joachim99@8 840 {
joachim99@8 841 #include "xpm/file.xpm"
joachim99@8 842 #include "xpm/folder.xpm"
joachim99@8 843 s_pm_dir = new QPixmap( m_pIconLoader->loadIcon("folder", KIcon::Small ) );
joachim99@8 844 if (s_pm_dir->size()!=QSize(16,16))
joachim99@8 845 {
joachim99@8 846 delete s_pm_dir;
joachim99@8 847 s_pm_dir = new QPixmap( folder_pm );
joachim99@8 848 }
joachim99@8 849 s_pm_file= new QPixmap( file_pm );
joachim99@8 850 bFirstTime=false;
joachim99@8 851 }
joachim99@8 852
joachim99@8 853 clear();
joachim99@8 854
joachim99@8 855 setRootIsDecorated( true );
joachim99@8 856
joachim99@8 857 bool bCheckC = m_dirC.isValid();
joachim99@8 858
joachim99@8 859 std::map<QString, MergeFileInfos>::iterator j;
joachim99@8 860 int nrOfFiles = m_fileMergeMap.size();
joachim99@8 861 int currentIdx = 1;
joachim99@8 862 QTime t;
joachim99@8 863 t.start();
joachim99@8 864 for( j=m_fileMergeMap.begin(); j!=m_fileMergeMap.end(); ++j )
joachim99@8 865 {
joachim99@8 866 const QString& fileName = j->first;
joachim99@8 867 MergeFileInfos& mfi = j->second;
joachim99@8 868
joachim99@8 869 mfi.m_subPath = mfi.m_fileInfoA.exists() ? mfi.m_fileInfoA.filePath() :
joachim99@8 870 mfi.m_fileInfoB.exists() ? mfi.m_fileInfoB.filePath() :
joachim99@25 871 mfi.m_fileInfoC.exists() ? mfi.m_fileInfoC.filePath() :
joachim99@25 872 QString("");
joachim99@8 873
joachim99@8 874 g_pProgressDialog->setInformation(
joachim99@8 875 "Processing " + QString::number(currentIdx) +" / "+ QString::number(nrOfFiles)
joachim99@8 876 +"\n" + fileName, double(currentIdx) / nrOfFiles, false );
joachim99@8 877 if ( g_pProgressDialog->wasCancelled() ) break;
joachim99@8 878 ++currentIdx;
joachim99@8 879
joachim99@8 880
joachim99@8 881 // The comparisons and calculations for each file take place here.
joachim99@8 882 compareFilesAndCalcAges( mfi );
joachim99@8 883
joachim99@8 884 bool bEqual = bCheckC ? mfi.m_bEqualAB && mfi.m_bEqualAC : mfi.m_bEqualAB;
joachim99@8 885 bool bDir = mfi.m_bDirA || mfi.m_bDirB || mfi.m_bDirC;
joachim99@8 886
joachim99@8 887 if ( m_pOptions->m_bDmShowOnlyDeltas && !bDir && bEqual )
joachim99@8 888 continue;
joachim99@8 889
joachim99@8 890 // Get dirname from fileName: Search for "/" from end:
joachim99@8 891 int pos = fileName.findRev('/');
joachim99@8 892 QString dirPart;
joachim99@8 893 QString filePart;
joachim99@8 894 if (pos==-1)
joachim99@8 895 {
joachim99@8 896 // Top dir
joachim99@8 897 filePart = fileName;
joachim99@8 898 }
joachim99@8 899 else
joachim99@8 900 {
joachim99@8 901 dirPart = fileName.left(pos);
joachim99@8 902 filePart = fileName.mid(pos+1);
joachim99@8 903 }
joachim99@8 904
joachim99@8 905 if ( dirPart.isEmpty() ) // Top level
joachim99@8 906 {
joachim99@8 907 new DirMergeItem( this, filePart, &mfi );
joachim99@8 908 }
joachim99@8 909 else
joachim99@8 910 {
joachim99@8 911 MergeFileInfos& dirMfi = m_fileMergeMap[dirPart]; // parent
joachim99@8 912 assert(dirMfi.m_pDMI!=0);
joachim99@8 913 new DirMergeItem( dirMfi.m_pDMI, filePart, &mfi );
joachim99@8 914 mfi.m_pParent = &dirMfi;
joachim99@8 915
joachim99@8 916 if ( !bEqual ) // Set all parents to "not equal"
joachim99@8 917 {
joachim99@8 918 MergeFileInfos* p = mfi.m_pParent;
joachim99@8 919 while(p!=0)
joachim99@8 920 {
joachim99@8 921 bool bChange = false;
joachim99@8 922 if ( !mfi.m_bEqualAB && p->m_bEqualAB ){ p->m_bEqualAB = false; bChange=true; }
joachim99@8 923 if ( !mfi.m_bEqualAC && p->m_bEqualAC ){ p->m_bEqualAC = false; bChange=true; }
joachim99@8 924 if ( !mfi.m_bEqualBC && p->m_bEqualBC ){ p->m_bEqualBC = false; bChange=true; }
joachim99@8 925
joachim99@8 926 if ( bChange )
joachim99@8 927 setPixmaps( *p, bCheckC );
joachim99@8 928 else
joachim99@8 929 break;
joachim99@8 930
joachim99@8 931 p = p->m_pParent;
joachim99@8 932 }
joachim99@8 933 }
joachim99@8 934 }
joachim99@8 935
joachim99@8 936 setPixmaps( mfi, bCheckC );
joachim99@8 937 }
joachim99@8 938
joachim99@8 939 if ( m_pOptions->m_bDmShowOnlyDeltas )
joachim99@8 940 {
joachim99@8 941 // Remove all equals. (Search tree depth first)
joachim99@8 942 QListViewItem* p = firstChild();
joachim99@8 943 while( p!=0 && firstChild() != 0 )
joachim99@8 944 {
joachim99@8 945 QListViewItem* pParent = p->parent();
joachim99@8 946 QListViewItem* pNextSibling = p->nextSibling();
joachim99@8 947
joachim99@8 948 DirMergeItem* pDMI = static_cast<DirMergeItem*>(p);
joachim99@8 949 bool bDirEqual = bCheckC ? pDMI->m_pMFI->m_bEqualAB && pDMI->m_pMFI->m_bEqualAC
joachim99@8 950 : pDMI->m_pMFI->m_bEqualAB;
joachim99@8 951 if ( pDMI!=0 && pDMI->m_pMFI->m_bDirA && bDirEqual )
joachim99@8 952 {
joachim99@8 953 delete p;
joachim99@8 954 p=0;
joachim99@8 955 }
joachim99@8 956
joachim99@8 957 if ( p!=0 && p->firstChild() != 0 ) p = p->firstChild();
joachim99@8 958 else if ( pNextSibling!=0 ) p = pNextSibling;
joachim99@8 959 else
joachim99@8 960 {
joachim99@8 961 p=pParent;
joachim99@8 962 while ( p!=0 )
joachim99@8 963 {
joachim99@8 964 if( p->nextSibling()!=0 ) { p = p->nextSibling(); break; }
joachim99@8 965 else { p = p->parent(); }
joachim99@8 966 }
joachim99@8 967 }
joachim99@8 968 }
joachim99@8 969 }
joachim99@8 970 }
joachim99@8 971
joachim99@8 972 static bool conflictingFileTypes(MergeFileInfos& mfi)
joachim99@8 973 {
joachim99@8 974 // Now check if file/dir-types fit.
joachim99@8 975 if ( mfi.m_bLinkA || mfi.m_bLinkB || mfi.m_bLinkC )
joachim99@8 976 {
joachim99@8 977 if ( mfi.m_bExistsInA && ! mfi.m_bLinkA ||
joachim99@8 978 mfi.m_bExistsInB && ! mfi.m_bLinkB ||
joachim99@8 979 mfi.m_bExistsInC && ! mfi.m_bLinkC )
joachim99@8 980 {
joachim99@8 981 return true;
joachim99@8 982 }
joachim99@8 983 }
joachim99@8 984
joachim99@8 985 if ( mfi.m_bDirA || mfi.m_bDirB || mfi.m_bDirC )
joachim99@8 986 {
joachim99@8 987 if ( mfi.m_bExistsInA && ! mfi.m_bDirA ||
joachim99@8 988 mfi.m_bExistsInB && ! mfi.m_bDirB ||
joachim99@8 989 mfi.m_bExistsInC && ! mfi.m_bDirC )
joachim99@8 990 {
joachim99@8 991 return true;
joachim99@8 992 }
joachim99@8 993 }
joachim99@8 994 return false;
joachim99@8 995 }
joachim99@8 996
joachim99@8 997 void DirectoryMergeWindow::calcSuggestedOperation( MergeFileInfos& mfi, e_MergeOperation eDefaultMergeOp )
joachim99@8 998 {
joachim99@8 999 bool bCheckC = m_dirC.isValid();
joachim99@8 1000 bool bCopyNewer = m_pOptions->m_bDmCopyNewer;
joachim99@8 1001
joachim99@8 1002 if ( eDefaultMergeOp == eMergeABCToDest && !bCheckC ) { eDefaultMergeOp = eMergeABToDest; }
joachim99@8 1003 if ( eDefaultMergeOp == eMergeToAB && bCheckC ) { assert(false); }
joachim99@8 1004
joachim99@8 1005 if ( eDefaultMergeOp == eMergeToA || eDefaultMergeOp == eMergeToB ||
joachim99@8 1006 eDefaultMergeOp == eMergeABCToDest || eDefaultMergeOp == eMergeABToDest || eDefaultMergeOp == eMergeToAB )
joachim99@8 1007 {
joachim99@8 1008 if ( !bCheckC )
joachim99@8 1009 {
joachim99@8 1010 if ( mfi.m_bEqualAB )
joachim99@8 1011 {
joachim99@8 1012 mfi.setMergeOperation( eNoOperation ); // All is well, nothing to do.
joachim99@8 1013 }
joachim99@8 1014 else if ( mfi.m_bExistsInA && mfi.m_bExistsInB )
joachim99@8 1015 {
joachim99@8 1016 if ( !bCopyNewer || mfi.m_bDirA )
joachim99@8 1017 mfi.setMergeOperation( eDefaultMergeOp );
joachim99@8 1018 else if ( bCopyNewer && mfi.m_bConflictingAges )
joachim99@8 1019 {
joachim99@8 1020 mfi.setMergeOperation( eConflictingAges );
joachim99@8 1021 }
joachim99@8 1022 else
joachim99@8 1023 {
joachim99@8 1024 if ( mfi.m_ageA == eNew )
joachim99@8 1025 mfi.setMergeOperation( eDefaultMergeOp == eMergeToAB ? eCopyAToB : eCopyAToDest );
joachim99@8 1026 else
joachim99@8 1027 mfi.setMergeOperation( eDefaultMergeOp == eMergeToAB ? eCopyBToA : eCopyBToDest );
joachim99@8 1028 }
joachim99@8 1029 }
joachim99@8 1030 else if ( !mfi.m_bExistsInA && mfi.m_bExistsInB )
joachim99@8 1031 {
joachim99@8 1032 if ( eDefaultMergeOp==eMergeABToDest ) mfi.setMergeOperation( eCopyBToDest );
joachim99@8 1033 else if ( eDefaultMergeOp==eMergeToB ) mfi.setMergeOperation( eNoOperation );
joachim99@8 1034 else mfi.setMergeOperation( eCopyBToA );
joachim99@8 1035 }
joachim99@8 1036 else if ( mfi.m_bExistsInA && !mfi.m_bExistsInB )
joachim99@8 1037 {
joachim99@8 1038 if ( eDefaultMergeOp==eMergeABToDest ) mfi.setMergeOperation( eCopyAToDest );
joachim99@8 1039 else if ( eDefaultMergeOp==eMergeToA ) mfi.setMergeOperation( eNoOperation );
joachim99@8 1040 else mfi.setMergeOperation( eCopyAToB );
joachim99@8 1041 }
joachim99@8 1042 else //if ( !mfi.m_bExistsInA && !mfi.m_bExistsInB )
joachim99@8 1043 {
joachim99@8 1044 mfi.setMergeOperation( eNoOperation ); assert(false);
joachim99@8 1045 }
joachim99@8 1046 }
joachim99@8 1047 else
joachim99@8 1048 {
joachim99@8 1049 if ( mfi.m_bEqualAB && mfi.m_bEqualAC )
joachim99@8 1050 {
joachim99@8 1051 mfi.setMergeOperation( eCopyCToDest );
joachim99@8 1052 }
joachim99@8 1053 else if ( mfi.m_bExistsInA && mfi.m_bExistsInB && mfi.m_bExistsInC)
joachim99@8 1054 {
joachim99@8 1055 if ( mfi.m_bEqualAB )
joachim99@8 1056 mfi.setMergeOperation( eCopyCToDest );
joachim99@8 1057 else if ( mfi.m_bEqualAC )
joachim99@8 1058 mfi.setMergeOperation( eCopyBToDest );
joachim99@8 1059 else if ( mfi.m_bEqualBC )
joachim99@8 1060 mfi.setMergeOperation( eCopyCToDest );
joachim99@8 1061 else
joachim99@8 1062 mfi.setMergeOperation( eMergeABCToDest );
joachim99@8 1063 }
joachim99@8 1064 else if ( mfi.m_bExistsInA && mfi.m_bExistsInB && !mfi.m_bExistsInC )
joachim99@8 1065 {
joachim99@8 1066 if ( mfi.m_bEqualAB )
joachim99@8 1067 mfi.setMergeOperation( eDeleteFromDest );
joachim99@8 1068 else
joachim99@8 1069 mfi.setMergeOperation( eCopyBToDest );
joachim99@8 1070 }
joachim99@8 1071 else if ( mfi.m_bExistsInA && !mfi.m_bExistsInB && mfi.m_bExistsInC )
joachim99@8 1072 {
joachim99@8 1073 if ( mfi.m_bEqualAC )
joachim99@8 1074 mfi.setMergeOperation( eDeleteFromDest );
joachim99@8 1075 else
joachim99@8 1076 mfi.setMergeOperation( eCopyCToDest );
joachim99@8 1077 }
joachim99@8 1078 else if ( !mfi.m_bExistsInA && mfi.m_bExistsInB && mfi.m_bExistsInC )
joachim99@8 1079 {
joachim99@8 1080 if ( mfi.m_bEqualBC )
joachim99@8 1081 mfi.setMergeOperation( eCopyCToDest );
joachim99@8 1082 else
joachim99@8 1083 mfi.setMergeOperation( eMergeABCToDest );
joachim99@8 1084 }
joachim99@8 1085 else if ( !mfi.m_bExistsInA && !mfi.m_bExistsInB && mfi.m_bExistsInC )
joachim99@8 1086 {
joachim99@8 1087 mfi.setMergeOperation( eCopyCToDest );
joachim99@8 1088 }
joachim99@8 1089 else if ( !mfi.m_bExistsInA && mfi.m_bExistsInB && !mfi.m_bExistsInC )
joachim99@8 1090 {
joachim99@8 1091 mfi.setMergeOperation( eCopyBToDest );
joachim99@8 1092 }
joachim99@8 1093 else if ( mfi.m_bExistsInA && !mfi.m_bExistsInB && !mfi.m_bExistsInC)
joachim99@8 1094 {
joachim99@8 1095 mfi.setMergeOperation( eDeleteFromDest );
joachim99@8 1096 }
joachim99@8 1097 else //if ( !mfi.m_bExistsInA && !mfi.m_bExistsInB && !mfi.m_bExistsInC )
joachim99@8 1098 {
joachim99@8 1099 mfi.setMergeOperation( eNoOperation ); assert(false);
joachim99@8 1100 }
joachim99@8 1101 }
joachim99@8 1102
joachim99@8 1103 // Now check if file/dir-types fit.
joachim99@8 1104 if ( conflictingFileTypes(mfi) )
joachim99@8 1105 {
joachim99@8 1106 mfi.setMergeOperation( eConflictingFileTypes );
joachim99@8 1107 }
joachim99@8 1108 }
joachim99@8 1109 else
joachim99@8 1110 {
joachim99@8 1111 e_MergeOperation eMO = eDefaultMergeOp;
joachim99@8 1112 switch ( eDefaultMergeOp )
joachim99@8 1113 {
joachim99@8 1114 case eConflictingFileTypes:
joachim99@8 1115 case eConflictingAges:
joachim99@8 1116 case eDeleteA:
joachim99@8 1117 case eDeleteB:
joachim99@8 1118 case eDeleteAB:
joachim99@8 1119 case eDeleteFromDest:
joachim99@8 1120 case eNoOperation: break;
joachim99@8 1121 case eCopyAToB: if ( !mfi.m_bExistsInA ) { eMO = eDeleteB; } break;
joachim99@8 1122 case eCopyBToA: if ( !mfi.m_bExistsInB ) { eMO = eDeleteA; } break;
joachim99@8 1123 case eCopyAToDest: if ( !mfi.m_bExistsInA ) { eMO = eDeleteFromDest; } break;
joachim99@8 1124 case eCopyBToDest: if ( !mfi.m_bExistsInB ) { eMO = eDeleteFromDest; } break;
joachim99@8 1125 case eCopyCToDest: if ( !mfi.m_bExistsInC ) { eMO = eDeleteFromDest; } break;
joachim99@8 1126
joachim99@8 1127 case eMergeToA:
joachim99@8 1128 case eMergeToB:
joachim99@8 1129 case eMergeToAB:
joachim99@8 1130 case eMergeABCToDest:
joachim99@8 1131 case eMergeABToDest:
joachim99@8 1132 default:
joachim99@8 1133 assert(false);
joachim99@8 1134 }
joachim99@8 1135 mfi.setMergeOperation( eMO );
joachim99@8 1136 }
joachim99@8 1137 }
joachim99@8 1138
joachim99@8 1139 void DirectoryMergeWindow::onDoubleClick( QListViewItem* lvi )
joachim99@8 1140 {
joachim99@8 1141 if (lvi==0) return;
joachim99@8 1142
joachim99@8 1143 if ( m_bDirectoryMerge )
joachim99@8 1144 mergeCurrentFile();
joachim99@8 1145 else
joachim99@8 1146 compareCurrentFile();
joachim99@8 1147 }
joachim99@8 1148
joachim99@8 1149 void DirectoryMergeWindow::onSelectionChanged( QListViewItem* lvi )
joachim99@8 1150 {
joachim99@8 1151 if ( lvi==0 ) return;
joachim99@8 1152
joachim99@8 1153 DirMergeItem* pDMI = static_cast<DirMergeItem*>(lvi);
joachim99@8 1154
joachim99@8 1155 MergeFileInfos& mfi = *pDMI->m_pMFI;
joachim99@8 1156 assert( mfi.m_pDMI==pDMI );
joachim99@8 1157
joachim99@8 1158 m_pDirectoryMergeInfo->setInfo( m_dirA, m_dirB, m_dirC, m_dirDestInternal, mfi );
joachim99@8 1159 }
joachim99@8 1160
joachim99@8 1161 void DirectoryMergeWindow::onClick( QListViewItem* lvi, const QPoint& p, int c )
joachim99@8 1162 {
joachim99@8 1163 if ( lvi==0 ) return;
joachim99@8 1164
joachim99@8 1165 DirMergeItem* pDMI = static_cast<DirMergeItem*>(lvi);
joachim99@8 1166
joachim99@8 1167 MergeFileInfos& mfi = *pDMI->m_pMFI;
joachim99@8 1168 assert( mfi.m_pDMI==pDMI );
joachim99@8 1169
joachim99@8 1170 if ( c!=s_OpCol ) return;
joachim99@8 1171
joachim99@8 1172 bool bThreeDirs = m_dirC.isValid();
joachim99@8 1173
joachim99@8 1174 //bool bImmediate = (button==Qt::LeftButton);
joachim99@8 1175
joachim99@8 1176 KPopupMenu m(this);
joachim99@8 1177 //if (bImmediate ) m.insertItem("Immediate Mode", eTitleId );
joachim99@8 1178 //else m.insertItem("Postponed Mode", eTitleId );
joachim99@8 1179 //m.setItemEnabled ( eTitleId, false );
joachim99@8 1180 if ( bThreeDirs )
joachim99@8 1181 {
joachim99@8 1182 m.insertItem("Do nothing", eNoOperation );
joachim99@8 1183 int count=0;
joachim99@8 1184 if ( mfi.m_bExistsInA ) { m.insertItem("A", eCopyAToDest ); ++count; }
joachim99@8 1185 if ( mfi.m_bExistsInB ) { m.insertItem("B", eCopyBToDest ); ++count; }
joachim99@8 1186 if ( mfi.m_bExistsInC ) { m.insertItem("C", eCopyCToDest ); ++count; }
joachim99@8 1187 if ( !conflictingFileTypes(mfi) && count>1 ) m.insertItem("Merge", eMergeABCToDest );
joachim99@8 1188 m.insertItem("Delete (if exists)", eDeleteFromDest );
joachim99@8 1189 }
joachim99@8 1190 else if ( m_bSyncMode )
joachim99@8 1191 {
joachim99@8 1192 m.insertItem("Do nothing", eNoOperation );
joachim99@8 1193 if ( mfi.m_bExistsInA ) m.insertItem("Copy A to B", eCopyAToB );
joachim99@8 1194 if ( mfi.m_bExistsInB ) m.insertItem("Copy B to A", eCopyBToA );
joachim99@8 1195 if ( mfi.m_bExistsInA ) m.insertItem("Delete A", eDeleteA );
joachim99@8 1196 if ( mfi.m_bExistsInB ) m.insertItem("Delete B", eDeleteB );
joachim99@8 1197 if ( mfi.m_bExistsInA && mfi.m_bExistsInB )
joachim99@8 1198 {
joachim99@8 1199 m.insertItem("Delete A and B", eDeleteAB );
joachim99@8 1200 if ( !conflictingFileTypes(mfi))
joachim99@8 1201 {
joachim99@8 1202 m.insertItem("Merge to A", eMergeToA );
joachim99@8 1203 m.insertItem("Merge to B", eMergeToB );
joachim99@8 1204 m.insertItem("Merge to A and B", eMergeToAB );
joachim99@8 1205 }
joachim99@8 1206 }
joachim99@8 1207 }
joachim99@8 1208 else
joachim99@8 1209 {
joachim99@8 1210 m.insertItem("Do nothing", eNoOperation );
joachim99@8 1211 if ( mfi.m_bExistsInA ) m.insertItem("A", eCopyAToDest );
joachim99@8 1212 if ( mfi.m_bExistsInB ) m.insertItem("B", eCopyBToDest );
joachim99@8 1213 if ( mfi.m_bExistsInA && mfi.m_bExistsInB && !conflictingFileTypes(mfi) )
joachim99@8 1214 m.insertItem("Merge", eMergeABToDest );
joachim99@8 1215 m.insertItem("Delete (if exists)", eDeleteFromDest );
joachim99@8 1216 }
joachim99@8 1217
joachim99@8 1218 int result = m.exec( p );
joachim99@8 1219 if (result>=0 )
joachim99@8 1220 mfi.setMergeOperation( (e_MergeOperation)result );
joachim99@8 1221 }
joachim99@8 1222
joachim99@8 1223 // Since Qt 2.3.0 doesn't allow the specification of a compare operator, this trick emulates it.
joachim99@8 1224 #if QT_VERSION==230
joachim99@8 1225 #define DIRSORT(x) ( pMFI->m_bDirA ? " " : "" )+x
joachim99@8 1226 #else
joachim99@8 1227 #define DIRSORT(x) x
joachim99@8 1228 #endif
joachim99@8 1229
joachim99@8 1230 DirMergeItem::DirMergeItem( QListView* pParent, const QString& fileName, MergeFileInfos* pMFI )
joachim99@8 1231 : QListViewItem( pParent, DIRSORT( fileName ), "","","", "To do." )
joachim99@8 1232 {
joachim99@8 1233 pMFI->m_pDMI = this;
joachim99@8 1234 m_pMFI = pMFI;
joachim99@8 1235 }
joachim99@8 1236
joachim99@8 1237 DirMergeItem::DirMergeItem( DirMergeItem* pParent, const QString& fileName, MergeFileInfos* pMFI )
joachim99@8 1238 : QListViewItem( pParent, DIRSORT( fileName ), "","","", "To do." )
joachim99@8 1239 {
joachim99@8 1240 pMFI->m_pDMI = this;
joachim99@8 1241 m_pMFI = pMFI;
joachim99@8 1242 }
joachim99@8 1243
joachim99@8 1244 DirMergeItem::~DirMergeItem()
joachim99@8 1245 {
joachim99@8 1246 m_pMFI->m_pDMI = 0;
joachim99@8 1247 }
joachim99@8 1248
joachim99@8 1249 void MergeFileInfos::setMergeOperation( e_MergeOperation eMOp )
joachim99@8 1250 {
joachim99@8 1251 m_eMergeOperation = eMOp;
joachim99@8 1252 const char* s=0;
joachim99@8 1253 bool bDir = m_bDirA || m_bDirB || m_bDirC;
joachim99@8 1254 if( m_pDMI!=0 )
joachim99@8 1255 {
joachim99@8 1256 switch( m_eMergeOperation )
joachim99@8 1257 {
joachim99@8 1258 case eNoOperation: s=""; m_pDMI->setText(s_OpCol,""); break;
joachim99@8 1259 case eCopyAToB: s="Copy A to B"; break;
joachim99@8 1260 case eCopyBToA: s="Copy B to A"; break;
joachim99@8 1261 case eDeleteA: s="Delete A"; break;
joachim99@8 1262 case eDeleteB: s="Delete B"; break;
joachim99@8 1263 case eDeleteAB: s="Delete A and B"; break;
joachim99@8 1264 case eMergeToA: s="Merge to A"; break;
joachim99@8 1265 case eMergeToB: s="Merge to B"; break;
joachim99@8 1266 case eMergeToAB: s="Merge to A and B"; break;
joachim99@8 1267 case eCopyAToDest: s="A"; break;
joachim99@8 1268 case eCopyBToDest: s="B"; break;
joachim99@8 1269 case eCopyCToDest: s="C"; break;
joachim99@8 1270 case eDeleteFromDest: s="Delete (if exists)"; break;
joachim99@8 1271 case eMergeABCToDest: s= bDir ? "Merge" : "Merge (manual)"; break;
joachim99@8 1272 case eMergeABToDest: s= bDir ? "Merge" : "Merge (manual)"; break;
joachim99@8 1273 case eConflictingFileTypes: s="Error: Conflicting File Types"; break;
joachim99@8 1274 case eConflictingAges: s="Error: Dates are equal but files are not."; break;
joachim99@8 1275 default: assert(false); break;
joachim99@8 1276 }
joachim99@8 1277 m_pDMI->setText(s_OpCol,s);
joachim99@8 1278
joachim99@8 1279 e_MergeOperation eChildrenMergeOp = m_eMergeOperation;
joachim99@8 1280 if ( eChildrenMergeOp == eConflictingFileTypes ) eChildrenMergeOp = eMergeABCToDest;
joachim99@8 1281 QListViewItem* p = m_pDMI->firstChild();
joachim99@8 1282 while ( p!=0 )
joachim99@8 1283 {
joachim99@8 1284 DirMergeItem* pDMI = static_cast<DirMergeItem*>( p );
joachim99@8 1285 DirectoryMergeWindow* pDMW = static_cast<DirectoryMergeWindow*>( p->listView() );
joachim99@8 1286 pDMW->calcSuggestedOperation( *pDMI->m_pMFI, eChildrenMergeOp );
joachim99@8 1287 p = p->nextSibling();
joachim99@8 1288 }
joachim99@8 1289 }
joachim99@8 1290 }
joachim99@8 1291
joachim99@8 1292 void DirectoryMergeWindow::compareCurrentFile()
joachim99@8 1293 {
joachim99@8 1294 if (!canContinue()) return;
joachim99@8 1295
joachim99@8 1296 if ( m_bRealMergeStarted )
joachim99@8 1297 {
joachim99@8 1298 KMessageBox::sorry(this,"This operation is currently not possible.","KDiff3");
joachim99@8 1299 return;
joachim99@8 1300 }
joachim99@8 1301
joachim99@8 1302 DirMergeItem* pDMI = static_cast<DirMergeItem*>( selectedItem() );
joachim99@8 1303 if ( pDMI != 0 )
joachim99@8 1304 {
joachim99@8 1305 MergeFileInfos& mfi = *pDMI->m_pMFI;
joachim99@8 1306 if ( !(mfi.m_bDirA || mfi.m_bDirB || mfi.m_bDirC) )
joachim99@8 1307 {
joachim99@8 1308 emit startDiffMerge(
joachim99@8 1309 mfi.m_bExistsInA ? mfi.m_fileInfoA.absFilePath() : QString(""),
joachim99@8 1310 mfi.m_bExistsInB ? mfi.m_fileInfoB.absFilePath() : QString(""),
joachim99@8 1311 mfi.m_bExistsInC ? mfi.m_fileInfoC.absFilePath() : QString(""),
joachim99@8 1312 "",
joachim99@8 1313 "","",""
joachim99@8 1314 );
joachim99@8 1315 }
joachim99@8 1316 }
joachim99@8 1317 emit updateAvailabilities();
joachim99@8 1318 }
joachim99@8 1319
joachim99@8 1320 void DirectoryMergeWindow::mergeCurrentFile()
joachim99@8 1321 {
joachim99@8 1322 if (!canContinue()) return;
joachim99@8 1323
joachim99@8 1324 if ( m_bRealMergeStarted )
joachim99@8 1325 {
joachim99@8 1326 KMessageBox::sorry(this,"This operation is currently not possible because diff merge currently runs.","KDiff3");
joachim99@8 1327 return;
joachim99@8 1328 }
joachim99@8 1329
joachim99@8 1330 if ( isFileSelected() )
joachim99@8 1331 {
joachim99@8 1332 DirMergeItem* pDMI = static_cast<DirMergeItem*>( selectedItem() );
joachim99@8 1333 if ( pDMI != 0 )
joachim99@8 1334 {
joachim99@8 1335 MergeFileInfos& mfi = *pDMI->m_pMFI;
joachim99@8 1336 m_bSingleFileOperationStarted = true;
joachim99@8 1337 emit startDiffMerge(
joachim99@8 1338 mfi.m_bExistsInA ? mfi.m_fileInfoA.absFilePath() : QString(""),
joachim99@8 1339 mfi.m_bExistsInB ? mfi.m_fileInfoB.absFilePath() : QString(""),
joachim99@8 1340 mfi.m_bExistsInC ? mfi.m_fileInfoC.absFilePath() : QString(""),
joachim99@8 1341 fullNameDest(mfi),
joachim99@8 1342 "","",""
joachim99@8 1343 );
joachim99@8 1344 m_pCurrentItemForOperation = pDMI;
joachim99@8 1345 m_pCurrentItemForOperation->setText( s_OpStatusCol, "In progress ..." );
joachim99@8 1346 }
joachim99@8 1347 }
joachim99@8 1348 emit updateAvailabilities();
joachim99@8 1349 }
joachim99@8 1350
joachim99@8 1351
joachim99@8 1352 bool DirectoryMergeWindow::isFileSelected()
joachim99@8 1353 {
joachim99@8 1354 DirMergeItem* pDMI = static_cast<DirMergeItem*>( selectedItem() );
joachim99@8 1355 if ( pDMI != 0 )
joachim99@8 1356 {
joachim99@8 1357 MergeFileInfos& mfi = *pDMI->m_pMFI;
joachim99@8 1358 return ! (mfi.m_bDirA || mfi.m_bDirB || mfi.m_bDirC || conflictingFileTypes(mfi) );
joachim99@8 1359 }
joachim99@8 1360 return false;
joachim99@8 1361 }
joachim99@8 1362
joachim99@8 1363 void DirectoryMergeWindow::mergeResultSaved(const QString& fileName)
joachim99@8 1364 {
joachim99@8 1365 m_bSingleFileOperationStarted = false;
joachim99@8 1366 if ( m_pCurrentItemForOperation!=0 && m_pCurrentItemForOperation->m_pMFI==0 )
joachim99@8 1367 {
joachim99@8 1368 KMessageBox::error( this, "This should never happen: \n\nmergeResultSaved: m_pMFI=0\n\nIf you know how to reproduce this, please contact the program author.","Program Error" );
joachim99@8 1369 return;
joachim99@8 1370 }
joachim99@8 1371 if ( m_pCurrentItemForOperation!=0 && fileName == fullNameDest(*m_pCurrentItemForOperation->m_pMFI) )
joachim99@8 1372 {
joachim99@8 1373 if ( m_pCurrentItemForOperation->m_pMFI->m_eMergeOperation==eMergeToAB )
joachim99@8 1374 {
joachim99@8 1375 MergeFileInfos& mfi = *m_pCurrentItemForOperation->m_pMFI;
joachim99@8 1376 bool bSuccess = copyFLD( fullNameB(mfi), fullNameA(mfi) );
joachim99@8 1377 if (!bSuccess)
joachim99@8 1378 {
joachim99@8 1379 KMessageBox::error(this, i18n("An error occurred while copying.\n"), "KDiff3: Error" );
joachim99@8 1380 m_pStatusInfo->setCaption("KDiff3: Merge-Error");
joachim99@8 1381 m_pStatusInfo->show();
joachim99@8 1382 if ( m_pStatusInfo->firstChild()!=0 )
joachim99@8 1383 m_pStatusInfo->ensureItemVisible( m_pStatusInfo->last() );
joachim99@8 1384 m_bError = true;
joachim99@8 1385 m_pCurrentItemForOperation->setText( s_OpStatusCol, "Error." );
joachim99@8 1386 mfi.m_eMergeOperation = eCopyBToA;
joachim99@8 1387 return;
joachim99@8 1388 }
joachim99@8 1389 }
joachim99@8 1390 m_pCurrentItemForOperation->setText( s_OpStatusCol, "Done." );
joachim99@8 1391 m_pCurrentItemForOperation->m_pMFI->m_bOperationComplete = true;
joachim99@8 1392 }
joachim99@8 1393
joachim99@8 1394 emit updateAvailabilities();
joachim99@8 1395 }
joachim99@8 1396
joachim99@8 1397 bool DirectoryMergeWindow::canContinue()
joachim99@8 1398 {
joachim99@8 1399 bool bCanContinue=false;
joachim99@8 1400 checkIfCanContinue( &bCanContinue );
joachim99@8 1401 if ( bCanContinue && !m_bError )
joachim99@8 1402 {
joachim99@8 1403 if ( m_bRealMergeStarted && m_pCurrentItemForOperation!=0 && ! m_pCurrentItemForOperation->m_pMFI->m_bOperationComplete )
joachim99@8 1404 {
joachim99@8 1405 m_pCurrentItemForOperation->setText( s_OpStatusCol, "Not saved." );
joachim99@8 1406 m_pCurrentItemForOperation->m_pMFI->m_bOperationComplete = true;
joachim99@8 1407 }
joachim99@8 1408 }
joachim99@8 1409 return bCanContinue;
joachim99@8 1410 }
joachim99@8 1411
joachim99@8 1412 void DirectoryMergeWindow::mergeContinue()
joachim99@8 1413 {
joachim99@8 1414 if ( ! canContinue() ) return;
joachim99@8 1415
joachim99@8 1416 m_bSingleFileOperationStarted = false;
joachim99@8 1417
joachim99@8 1418 int nrOfItems = 0;
joachim99@8 1419 int nrOfCompletedItems = 0;
joachim99@8 1420 int nrOfCompletedSimItems = 0;
joachim99@8 1421
joachim99@8 1422 if ( !m_bSimulatedMergeStarted && !m_bRealMergeStarted )
joachim99@8 1423 {
joachim99@8 1424 // First check if an invalid merge operations exist.
joachim99@8 1425 for( QListViewItem* p=firstChild(); p!=0; p = treeIterator( p ) )
joachim99@8 1426 {
joachim99@8 1427 DirMergeItem* pDMI = static_cast<DirMergeItem*>(p);
joachim99@8 1428 if (pDMI!=0 && pDMI->m_pMFI->m_eMergeOperation == eConflictingFileTypes )
joachim99@8 1429 {
joachim99@8 1430 ensureItemVisible( pDMI );
joachim99@8 1431 setSelected( pDMI, true );
joachim99@8 1432 KMessageBox::error(this, i18n("The highlighted item has a different type in the different directories. Select what to do."), "Error");
joachim99@8 1433 return;
joachim99@8 1434 }
joachim99@8 1435 if (pDMI!=0 && pDMI->m_pMFI->m_eMergeOperation == eConflictingAges )
joachim99@8 1436 {
joachim99@8 1437 ensureItemVisible( pDMI );
joachim99@8 1438 setSelected( pDMI, true );
joachim99@8 1439 KMessageBox::error(this, i18n("The modification dates of the file are equal but the files are not. Select what to do."), "Error");
joachim99@8 1440 return;
joachim99@8 1441 }
joachim99@8 1442 ++nrOfItems;
joachim99@8 1443 if ( pDMI->m_pMFI->m_bSimOpComplete )
joachim99@8 1444 ++nrOfCompletedSimItems;
joachim99@8 1445 if ( pDMI->m_pMFI->m_bOperationComplete )
joachim99@8 1446 ++nrOfCompletedItems;
joachim99@8 1447 }
joachim99@8 1448
joachim99@8 1449 int status = KMessageBox::warningYesNoCancel(this,
joachim99@8 1450 i18n("The merge is about to begin.\n\n"
joachim99@8 1451 "Choose \"Do it\" if you have read the instructions and know what you are doing.\n"
joachim99@8 1452 "Choosing \"Simulate it\" will tell you what would happen.\n\n"
joachim99@8 1453 "Be aware that this program still has beta status "
joachim99@8 1454 "and there is NO WARRANTY whatsoever! Make backups of your vital data!"),
joachim99@8 1455 i18n("KDiff3: Starting the Merge"), i18n("Do it"), i18n("Simulate it") );
joachim99@8 1456 if (status==KMessageBox::Yes) m_bRealMergeStarted = true;
joachim99@8 1457 else if (status==KMessageBox::No ) m_bSimulatedMergeStarted = true;
joachim99@8 1458 else return;
joachim99@8 1459
joachim99@8 1460 m_pStatusInfo->hide();
joachim99@8 1461 m_pStatusInfo->clear();
joachim99@8 1462 }
joachim99@8 1463
joachim99@8 1464 bool bContinueWithCurrentItem = false;
joachim99@8 1465 bool bSkipItem = false;
joachim99@8 1466 if ( m_bError && m_pCurrentItemForOperation!=0 )
joachim99@8 1467 {
joachim99@8 1468 int status = KMessageBox::warningYesNoCancel(this,
joachim99@8 1469 i18n("There was an error in the last step.\n"
joachim99@8 1470 "Do you want to continue with the item that caused the error or do you want to skip this item?"),
joachim99@8 1471 i18n("KDiff3: Continue merge after an error"), i18n("Continue with last item"), i18n("Skip item") );
joachim99@8 1472 if (status==KMessageBox::Yes) bContinueWithCurrentItem = true;
joachim99@8 1473 else if (status==KMessageBox::No ) bSkipItem = true;
joachim99@8 1474 else return;
joachim99@8 1475 m_bError = false;
joachim99@8 1476 }
joachim99@8 1477
joachim99@8 1478 g_pProgressDialog->start();
joachim99@8 1479
joachim99@8 1480 bool bSuccess = true;
joachim99@8 1481 bool bSingleFileMerge = false;
joachim99@8 1482 bool bSim = m_bSimulatedMergeStarted;
joachim99@8 1483 while( bSuccess )
joachim99@8 1484 {
joachim99@8 1485 if ( m_pCurrentItemForOperation!=0 && !bContinueWithCurrentItem )
joachim99@8 1486 {
joachim99@8 1487 if ( bSim )
joachim99@8 1488 {
joachim99@8 1489 if( m_pCurrentItemForOperation->firstChild()==0 )
joachim99@8 1490 {
joachim99@8 1491 m_pCurrentItemForOperation->m_pMFI->m_bSimOpComplete = true;
joachim99@8 1492 }
joachim99@8 1493 }
joachim99@8 1494 else
joachim99@8 1495 {
joachim99@8 1496 if( m_pCurrentItemForOperation->firstChild()==0 )
joachim99@8 1497 {
joachim99@8 1498 if( !m_pCurrentItemForOperation->m_pMFI->m_bOperationComplete )
joachim99@8 1499 {
joachim99@8 1500 m_pCurrentItemForOperation->setText( s_OpStatusCol, bSkipItem ? "Skipped." : "Done." );
joachim99@8 1501 m_pCurrentItemForOperation->m_pMFI->m_bOperationComplete = true;
joachim99@8 1502 bSkipItem = false;
joachim99@8 1503 }
joachim99@8 1504 }
joachim99@8 1505 else
joachim99@8 1506 {
joachim99@8 1507 m_pCurrentItemForOperation->setText( s_OpStatusCol, "In progress ..." );
joachim99@8 1508 }
joachim99@8 1509 }
joachim99@8 1510 }
joachim99@8 1511
joachim99@8 1512 if ( m_pCurrentItemForOperation==0 )
joachim99@8 1513 {
joachim99@8 1514 m_pCurrentItemForOperation = static_cast<DirMergeItem*>( firstChild() );
joachim99@8 1515 }
joachim99@8 1516 else
joachim99@8 1517 {
joachim99@8 1518 if ( ! bContinueWithCurrentItem )
joachim99@8 1519 {
joachim99@8 1520 // Depth first
joachim99@8 1521 QListViewItem* pNextItem = m_pCurrentItemForOperation->firstChild();
joachim99@8 1522 QListViewItem* pCurrentItem = m_pCurrentItemForOperation;
joachim99@8 1523 while( pCurrentItem!=0 && pNextItem==0 )
joachim99@8 1524 {
joachim99@8 1525 // Find an item on this level that hasn't been operated yet. (Always start at beginning.)
joachim99@8 1526 if ( pCurrentItem->parent()==0 )
joachim99@8 1527 pNextItem = firstChild();
joachim99@8 1528 else
joachim99@8 1529 pNextItem = pCurrentItem->parent()->firstChild();
joachim99@8 1530
joachim99@8 1531 while( pNextItem!=0 && ( static_cast<DirMergeItem*>(pNextItem)->m_pMFI->m_bOperationComplete ||
joachim99@8 1532 ( bSim && static_cast<DirMergeItem*>(pNextItem)->m_pMFI->m_bSimOpComplete ) ) )
joachim99@8 1533 {
joachim99@8 1534 pNextItem = pNextItem->nextSibling();
joachim99@8 1535 }
joachim99@8 1536
joachim99@8 1537 if ( pNextItem == 0 )
joachim99@8 1538 {
joachim99@8 1539 pCurrentItem = pCurrentItem->parent();
joachim99@8 1540 if ( pCurrentItem!=0 )
joachim99@8 1541 {
joachim99@8 1542 if (bSim)
joachim99@8 1543 static_cast<DirMergeItem*>(pCurrentItem)->m_pMFI->m_bSimOpComplete = true;
joachim99@8 1544 else
joachim99@8 1545 {
joachim99@8 1546 pCurrentItem->setText( s_OpStatusCol, "Done." );
joachim99@8 1547 static_cast<DirMergeItem*>(pCurrentItem)->m_pMFI->m_bOperationComplete = true;
joachim99@8 1548 }
joachim99@8 1549 }
joachim99@8 1550 }
joachim99@8 1551 }
joachim99@8 1552 m_pCurrentItemForOperation = static_cast<DirMergeItem*>(pNextItem);
joachim99@8 1553 }
joachim99@8 1554 }
joachim99@8 1555
joachim99@8 1556 if( m_pCurrentItemForOperation !=0 &&
joachim99@8 1557 (bSim ? m_pCurrentItemForOperation->m_pMFI->m_bSimOpComplete :
joachim99@8 1558 m_pCurrentItemForOperation->m_pMFI->m_bOperationComplete ))
joachim99@8 1559 m_pCurrentItemForOperation = 0;
joachim99@8 1560
joachim99@8 1561 if ( m_pCurrentItemForOperation==0 )
joachim99@8 1562 {
joachim99@8 1563 if ( m_bRealMergeStarted )
joachim99@8 1564 {
joachim99@8 1565 KMessageBox::information( this, "Merge operation complete.", "The merge is complete." );
joachim99@8 1566 m_bRealMergeStarted = false;
joachim99@8 1567 m_pStatusInfo->setCaption("KDiff3: Merge complete.");
joachim99@8 1568 }
joachim99@8 1569 if ( m_bSimulatedMergeStarted )
joachim99@8 1570 {
joachim99@8 1571 m_bSimulatedMergeStarted = false;
joachim99@8 1572 for( QListViewItem* p=firstChild(); p!=0; p=treeIterator(p) )
joachim99@8 1573 {
joachim99@8 1574 static_cast<DirMergeItem*>(p)->m_pMFI->m_bSimOpComplete = false;
joachim99@8 1575 }
joachim99@8 1576 m_pStatusInfo->setCaption("KDiff3: Simulated merge complete: Check if you agree with the proposed operations.");
joachim99@8 1577 m_pStatusInfo->show();
joachim99@8 1578 }
joachim99@8 1579 g_pProgressDialog->hide();
joachim99@8 1580 return;
joachim99@8 1581 }
joachim99@8 1582
joachim99@8 1583 MergeFileInfos& mfi = *m_pCurrentItemForOperation->m_pMFI;
joachim99@8 1584 bool bCreateBackups = m_pOptions->m_bDmCreateBakFiles;
joachim99@8 1585
joachim99@8 1586 g_pProgressDialog->setInformation( mfi.m_subPath,
joachim99@8 1587 bSim ? double(nrOfCompletedSimItems)/nrOfItems : double(nrOfCompletedItems)/nrOfItems,
joachim99@8 1588 true
joachim99@8 1589 );
joachim99@8 1590 g_pProgressDialog->show();
joachim99@8 1591
joachim99@8 1592 // First decide destname
joachim99@8 1593 QString destName;
joachim99@8 1594 switch( mfi.m_eMergeOperation )
joachim99@8 1595 {
joachim99@8 1596 case eNoOperation: break;
joachim99@8 1597 case eMergeToAB: // let the user save in B. In mergeResultSaved() the file will be copied to A.
joachim99@8 1598 case eMergeToB:
joachim99@8 1599 case eDeleteB:
joachim99@8 1600 case eCopyAToB: destName = fullNameB(mfi); break;
joachim99@8 1601 case eMergeToA:
joachim99@8 1602 case eDeleteA:
joachim99@8 1603 case eCopyBToA: destName = fullNameA(mfi); break;
joachim99@8 1604 case eMergeABToDest:
joachim99@8 1605 case eMergeABCToDest:
joachim99@8 1606 case eCopyAToDest:
joachim99@8 1607 case eCopyBToDest:
joachim99@8 1608 case eCopyCToDest:
joachim99@8 1609 case eDeleteFromDest: destName = fullNameDest(mfi); break;
joachim99@8 1610 default:
joachim99@8 1611 KMessageBox::error( this, "Unknown merge operation.(This must never happen!)", "Error" );
joachim99@8 1612 assert(false);
joachim99@8 1613 }
joachim99@8 1614
joachim99@8 1615 bSuccess = false;
joachim99@8 1616 bSingleFileMerge = false;
joachim99@8 1617 switch( mfi.m_eMergeOperation )
joachim99@8 1618 {
joachim99@8 1619 case eNoOperation: bSuccess = true; break;
joachim99@8 1620 case eCopyAToDest:
joachim99@8 1621 case eCopyAToB: bSuccess = copyFLD( fullNameA(mfi), destName ); break;
joachim99@8 1622 case eCopyBToDest:
joachim99@8 1623 case eCopyBToA: bSuccess = copyFLD( fullNameB(mfi), destName ); break;
joachim99@8 1624 case eCopyCToDest: bSuccess = copyFLD( fullNameC(mfi), destName ); break;
joachim99@8 1625 case eDeleteFromDest:
joachim99@8 1626 case eDeleteA:
joachim99@8 1627 case eDeleteB: bSuccess = deleteFLD( destName, bCreateBackups ); break;
joachim99@8 1628 case eDeleteAB: bSuccess = deleteFLD( fullNameA(mfi), bCreateBackups ) &&
joachim99@8 1629 deleteFLD( fullNameB(mfi), bCreateBackups ); break;
joachim99@8 1630 case eMergeABToDest:
joachim99@8 1631 case eMergeToA:
joachim99@8 1632 case eMergeToAB:
joachim99@8 1633 case eMergeToB: bSuccess = mergeFLD( fullNameA(mfi), fullNameB(mfi), "",
joachim99@8 1634 destName, bSingleFileMerge );
joachim99@8 1635 break;
joachim99@8 1636 case eMergeABCToDest:bSuccess = mergeFLD(
joachim99@8 1637 mfi.m_bExistsInA ? fullNameA(mfi) : QString(""),
joachim99@8 1638 mfi.m_bExistsInB ? fullNameB(mfi) : QString(""),
joachim99@8 1639 mfi.m_bExistsInC ? fullNameC(mfi) : QString(""),
joachim99@8 1640 destName, bSingleFileMerge );
joachim99@8 1641 break;
joachim99@8 1642 default:
joachim99@8 1643 KMessageBox::error( this, "Unknown merge operation.", "Error" );
joachim99@8 1644 assert(false);
joachim99@8 1645 }
joachim99@8 1646 if ( bSuccess )
joachim99@8 1647 {
joachim99@8 1648 if(bSim) ++nrOfCompletedSimItems;
joachim99@8 1649 else ++nrOfCompletedItems;
joachim99@8 1650 bContinueWithCurrentItem = false;
joachim99@8 1651 }
joachim99@8 1652 } // end while
joachim99@8 1653
joachim99@8 1654 g_pProgressDialog->hide();
joachim99@8 1655
joachim99@8 1656 setCurrentItem( m_pCurrentItemForOperation );
joachim99@8 1657 ensureItemVisible( m_pCurrentItemForOperation );
joachim99@8 1658 if ( !bSuccess && !bSingleFileMerge )
joachim99@8 1659 {
joachim99@8 1660 KMessageBox::error(this, i18n("An error occurred. Press OK to see detailed information.\n"), "KDiff3: Error" );
joachim99@8 1661 m_pStatusInfo->setCaption("KDiff3: Merge-Error");
joachim99@8 1662 m_pStatusInfo->show();
joachim99@8 1663 if ( m_pStatusInfo->firstChild()!=0 )
joachim99@8 1664 m_pStatusInfo->ensureItemVisible( m_pStatusInfo->last() );
joachim99@8 1665 m_bError = true;
joachim99@8 1666 m_pCurrentItemForOperation->setText( s_OpStatusCol, "Error." );
joachim99@8 1667 }
joachim99@8 1668 else
joachim99@8 1669 {
joachim99@8 1670 m_bError = false;
joachim99@8 1671 }
joachim99@8 1672 emit updateAvailabilities();
joachim99@8 1673 }
joachim99@8 1674
joachim99@8 1675 void DirectoryMergeWindow::allowResizeEvents(bool bAllowResizeEvents )
joachim99@8 1676 {
joachim99@8 1677 m_bAllowResizeEvents = bAllowResizeEvents;
joachim99@8 1678 }
joachim99@8 1679
joachim99@8 1680 void DirectoryMergeWindow::resizeEvent( QResizeEvent* e )
joachim99@8 1681 {
joachim99@8 1682 if (m_bAllowResizeEvents)
joachim99@8 1683 QListView::resizeEvent(e);
joachim99@8 1684 }
joachim99@8 1685
joachim99@8 1686 bool DirectoryMergeWindow::deleteFLD( const QString& name, bool bCreateBackup )
joachim99@8 1687 {
joachim99@8 1688 FileAccess fi(name, true);
joachim99@8 1689 if ( !fi.exists() )
joachim99@8 1690 return true;
joachim99@8 1691
joachim99@8 1692 if ( bCreateBackup )
joachim99@8 1693 {
joachim99@8 1694 bool bSuccess = renameFLD( name, name+".orig" );
joachim99@8 1695 if (!bSuccess)
joachim99@8 1696 {
joachim99@8 1697 m_pStatusInfo->addText( "Error: While deleting "+name+": Creating backup failed." );
joachim99@8 1698 return false;
joachim99@8 1699 }
joachim99@8 1700 }
joachim99@8 1701 else
joachim99@8 1702 {
joachim99@8 1703 if ( fi.isDir() && !fi.isSymLink() )
joachim99@8 1704 m_pStatusInfo->addText("delete directory recursively( "+name+" )");
joachim99@8 1705 else
joachim99@8 1706 m_pStatusInfo->addText("delete( "+name+" )");
joachim99@8 1707
joachim99@8 1708 if ( m_bSimulatedMergeStarted )
joachim99@8 1709 {
joachim99@8 1710 return true;
joachim99@8 1711 }
joachim99@8 1712
joachim99@8 1713 if ( fi.isDir() && !fi.isSymLink() )// recursive directory delete only for real dirs, not symlinks
joachim99@8 1714 {
joachim99@8 1715 t_DirectoryList dirList;
joachim99@8 1716 bool bSuccess = fi.listDir( &dirList, false, true, "*", "", "", false, false ); // not recursive, find hidden files
joachim99@8 1717
joachim99@8 1718 if ( !bSuccess )
joachim99@8 1719 {
joachim99@8 1720 // No Permission to read directory or other error.
joachim99@8 1721 m_pStatusInfo->addText( "Error: delete dir operation failed while trying to read the directory." );
joachim99@8 1722 return false;
joachim99@8 1723 }
joachim99@8 1724
joachim99@8 1725 t_DirectoryList::iterator it; // create list iterator
joachim99@8 1726
joachim99@8 1727 for ( it=dirList.begin(); it!=dirList.end(); ++it ) // for each file...
joachim99@8 1728 {
joachim99@8 1729 FileAccess& fi2 = *it;
joachim99@8 1730 if ( fi2.fileName() == "." || fi2.fileName()==".." )
joachim99@8 1731 continue;
joachim99@8 1732 bSuccess = deleteFLD( fi2.absFilePath(), false );
joachim99@8 1733 if (!bSuccess) break;
joachim99@8 1734 }
joachim99@8 1735 if (bSuccess)
joachim99@8 1736 {
joachim99@8 1737 bSuccess = FileAccess::removeDir( name );
joachim99@8 1738 if ( !bSuccess )
joachim99@8 1739 {
joachim99@8 1740 m_pStatusInfo->addText( "Error: rmdir( "+name+" ) operation failed." );
joachim99@8 1741 return false;
joachim99@8 1742 }
joachim99@8 1743 }
joachim99@8 1744 }
joachim99@8 1745 else
joachim99@8 1746 {
joachim99@8 1747 bool bSuccess = FileAccess::removeFile( name );
joachim99@8 1748 if ( !bSuccess )
joachim99@8 1749 {
joachim99@8 1750 m_pStatusInfo->addText( "Error: delete operation failed." );
joachim99@8 1751 return false;
joachim99@8 1752 }
joachim99@8 1753 }
joachim99@8 1754 }
joachim99@8 1755 return true;
joachim99@8 1756 }
joachim99@8 1757
joachim99@8 1758 bool DirectoryMergeWindow::mergeFLD( const QString& nameA,const QString& nameB,const QString& nameC,const QString& nameDest, bool& bSingleFileMerge )
joachim99@8 1759 {
joachim99@8 1760 FileAccess fi(nameA);
joachim99@8 1761 if (fi.isDir())
joachim99@8 1762 {
joachim99@8 1763 return makeDir(nameDest);
joachim99@8 1764 }
joachim99@8 1765
joachim99@8 1766 // Make sure that the dir exists, into which we will save the file later.
joachim99@8 1767 int pos=nameDest.findRev('/');
joachim99@8 1768 if ( pos>0 )
joachim99@8 1769 {
joachim99@8 1770 QString parentName = nameDest.left(pos);
joachim99@8 1771 bool bSuccess = makeDir(parentName, true /*quiet*/);
joachim99@8 1772 if (!bSuccess)
joachim99@8 1773 return false;
joachim99@8 1774 }
joachim99@8 1775
joachim99@8 1776 m_pStatusInfo->addText("manual merge( "+nameA+ ", "+nameB+","+nameC+" -> " + nameDest +" )" );
joachim99@8 1777 if ( m_bSimulatedMergeStarted )
joachim99@8 1778 {
joachim99@8 1779 m_pStatusInfo->addText(" Note: After a manual merge the user should continue via F5." );
joachim99@8 1780 return true;
joachim99@8 1781 }
joachim99@8 1782
joachim99@8 1783 bSingleFileMerge = true;
joachim99@8 1784 m_pCurrentItemForOperation->setText( s_OpStatusCol, "In progress ..." );
joachim99@8 1785 ensureItemVisible( m_pCurrentItemForOperation );
joachim99@8 1786
joachim99@8 1787 emit startDiffMerge( nameA, nameB, nameC, nameDest, "","","" );
joachim99@8 1788
joachim99@8 1789 return false;
joachim99@8 1790 }
joachim99@8 1791
joachim99@8 1792 bool DirectoryMergeWindow::copyFLD( const QString& srcName, const QString& destName )
joachim99@8 1793 {
joachim99@8 1794 if ( srcName == destName )
joachim99@8 1795 return true;
joachim99@8 1796
joachim99@8 1797 if ( FileAccess(destName, true).exists() )
joachim99@8 1798 {
joachim99@8 1799 bool bSuccess = deleteFLD( destName, m_pOptions->m_bDmCreateBakFiles );
joachim99@8 1800 if ( !bSuccess )
joachim99@8 1801 {
joachim99@8 1802 m_pStatusInfo->addText("Error: copy( "+srcName+ " -> " + destName +" ) failed."
joachim99@8 1803 "Deleting existing destination failed.");
joachim99@8 1804 return false;
joachim99@8 1805 }
joachim99@8 1806 }
joachim99@8 1807
joachim99@8 1808 FileAccess fi( srcName );
joachim99@8 1809
joachim99@8 1810 if ( fi.isSymLink() && (fi.isDir() && !m_bFollowDirLinks || !fi.isDir() && !m_bFollowDirLinks) )
joachim99@8 1811 {
joachim99@8 1812 m_pStatusInfo->addText("copyLink( "+srcName+ " -> " + destName +" )");
joachim99@8 1813 #ifdef _WIN32
joachim99@8 1814 // What are links?
joachim99@8 1815 #else
joachim99@8 1816 if ( m_bSimulatedMergeStarted )
joachim99@8 1817 {
joachim99@8 1818 return true;
joachim99@8 1819 }
joachim99@8 1820 FileAccess destFi(destName);
joachim99@8 1821 if ( !destFi.isLocal() || !fi.isLocal() )
joachim99@8 1822 {
joachim99@8 1823 m_pStatusInfo->addText("Error: copyLink failed: Remote links are not yet supported.");
joachim99@8 1824 return false;
joachim99@8 1825 }
joachim99@8 1826 QString linkTarget = fi.readLink();
joachim99@8 1827 bool bSuccess = FileAccess::symLink( linkTarget, destName );
joachim99@8 1828 if (!bSuccess)
joachim99@8 1829 m_pStatusInfo->addText("Error: copyLink failed.");
joachim99@8 1830 return bSuccess;
joachim99@8 1831 #endif
joachim99@8 1832 }
joachim99@8 1833
joachim99@8 1834 if ( fi.isDir() )
joachim99@8 1835 {
joachim99@8 1836 bool bSuccess = makeDir( destName );
joachim99@8 1837 return bSuccess;
joachim99@8 1838 }
joachim99@8 1839
joachim99@8 1840 int pos=destName.findRev('/');
joachim99@8 1841 if ( pos>0 )
joachim99@8 1842 {
joachim99@8 1843 QString parentName = destName.left(pos);
joachim99@8 1844 bool bSuccess = makeDir(parentName, true /*quiet*/);
joachim99@8 1845 if (!bSuccess)
joachim99@8 1846 return false;
joachim99@8 1847 }
joachim99@8 1848
joachim99@8 1849 m_pStatusInfo->addText("copy( "+srcName+ " -> " + destName +" )");
joachim99@8 1850
joachim99@8 1851 if ( m_bSimulatedMergeStarted )
joachim99@8 1852 {
joachim99@8 1853 return true;
joachim99@8 1854 }
joachim99@8 1855
joachim99@8 1856 FileAccess faSrc ( srcName );
joachim99@8 1857 bool bSuccess = faSrc.copyFile( destName );
joachim99@8 1858 if (! bSuccess ) m_pStatusInfo->addText( faSrc.getStatusText() );
joachim99@8 1859 return bSuccess;
joachim99@8 1860 }
joachim99@8 1861
joachim99@8 1862 // Rename is not an operation that can be selected by the user.
joachim99@8 1863 // It will only be used to create backups.
joachim99@8 1864 // Hence it will delete an existing destination without making a backup (of the old backup.)
joachim99@8 1865 bool DirectoryMergeWindow::renameFLD( const QString& srcName, const QString& destName )
joachim99@8 1866 {
joachim99@8 1867 if ( srcName == destName )
joachim99@8 1868 return true;
joachim99@8 1869
joachim99@8 1870 if ( FileAccess(destName, true).exists() )
joachim99@8 1871 {
joachim99@8 1872 bool bSuccess = deleteFLD( destName, false /*no backup*/ );
joachim99@8 1873 if (!bSuccess)
joachim99@8 1874 {
joachim99@8 1875 m_pStatusInfo->addText( "Error during rename( "+srcName+" -> " + destName + " ): "
joachim99@8 1876 "Cannot delete existing destination." );
joachim99@8 1877 return false;
joachim99@8 1878 }
joachim99@8 1879 }
joachim99@8 1880
joachim99@8 1881 m_pStatusInfo->addText("rename( "+srcName+ " -> " + destName +" )");
joachim99@8 1882 if ( m_bSimulatedMergeStarted )
joachim99@8 1883 {
joachim99@8 1884 return true;
joachim99@8 1885 }
joachim99@8 1886
joachim99@8 1887 bool bSuccess = FileAccess( srcName ).rename( destName );
joachim99@8 1888 if (!bSuccess)
joachim99@8 1889 {
joachim99@8 1890 m_pStatusInfo->addText( "Error: Rename failed." );
joachim99@8 1891 return false;
joachim99@8 1892 }
joachim99@8 1893
joachim99@8 1894 return true;
joachim99@8 1895 }
joachim99@8 1896
joachim99@8 1897 bool DirectoryMergeWindow::makeDir( const QString& name, bool bQuiet )
joachim99@8 1898 {
joachim99@8 1899 FileAccess fi(name, true);
joachim99@8 1900 if( fi.exists() && fi.isDir() )
joachim99@8 1901 return true;
joachim99@8 1902
joachim99@8 1903 if( fi.exists() && !fi.isDir() )
joachim99@8 1904 {
joachim99@8 1905 bool bSuccess = deleteFLD( name, true );
joachim99@8 1906 if (!bSuccess)
joachim99@8 1907 {
joachim99@8 1908 m_pStatusInfo->addText( "Error during makeDir of "+name+
joachim99@8 1909 "Cannot delete existing file." );
joachim99@8 1910 return false;
joachim99@8 1911 }
joachim99@8 1912 }
joachim99@8 1913
joachim99@8 1914 int pos=name.findRev('/');
joachim99@8 1915 if ( pos>0 )
joachim99@8 1916 {
joachim99@8 1917 QString parentName = name.left(pos);
joachim99@8 1918 bool bSuccess = makeDir(parentName,true);
joachim99@8 1919 if (!bSuccess)
joachim99@8 1920 return false;
joachim99@8 1921 }
joachim99@8 1922
joachim99@8 1923 if ( ! bQuiet )
joachim99@8 1924 m_pStatusInfo->addText("makeDir( " + name + " )");
joachim99@8 1925
joachim99@8 1926 if ( m_bSimulatedMergeStarted )
joachim99@8 1927 {
joachim99@8 1928 return true;
joachim99@8 1929 }
joachim99@8 1930
joachim99@8 1931 bool bSuccess = FileAccess::makeDir( name );
joachim99@8 1932 if ( bSuccess == false )
joachim99@8 1933 {
joachim99@8 1934 m_pStatusInfo->addText( "Error while creating directory." );
joachim99@8 1935 return false;
joachim99@8 1936 }
joachim99@8 1937 return true;
joachim99@8 1938 }
joachim99@8 1939
joachim99@8 1940
joachim99@8 1941
joachim99@8 1942
joachim99@8 1943
joachim99@8 1944 DirectoryMergeInfo::DirectoryMergeInfo( QWidget* pParent )
joachim99@8 1945 : QFrame(pParent)
joachim99@8 1946 {
joachim99@8 1947 QVBoxLayout *topLayout = new QVBoxLayout( this );
joachim99@8 1948
joachim99@8 1949
joachim99@8 1950 QGridLayout *grid = new QGridLayout( topLayout );
joachim99@8 1951 grid->setColStretch(1,10);
joachim99@8 1952
joachim99@8 1953 int line=0;
joachim99@8 1954
joachim99@8 1955 m_pA = new QLabel("A",this); grid->addWidget( m_pA,line, 0 );
joachim99@8 1956 m_pInfoA = new QLabel(this); grid->addWidget( m_pInfoA,line,1 ); ++line;
joachim99@8 1957 m_pB = new QLabel("B",this); grid->addWidget( m_pB,line, 0 );
joachim99@8 1958 m_pInfoB = new QLabel(this); grid->addWidget( m_pInfoB,line,1 ); ++line;
joachim99@8 1959 m_pC = new QLabel("C",this); grid->addWidget( m_pC,line, 0 );
joachim99@8 1960 m_pInfoC = new QLabel(this); grid->addWidget( m_pInfoC,line,1 ); ++line;
joachim99@8 1961 m_pDest = new QLabel("Dest",this); grid->addWidget( m_pDest,line, 0 );
joachim99@8 1962 m_pInfoDest = new QLabel(this); grid->addWidget( m_pInfoDest,line,1 ); ++line;
joachim99@8 1963
joachim99@8 1964 m_pInfoList = new QListView(this); topLayout->addWidget( m_pInfoList );
joachim99@8 1965 m_pInfoList->addColumn("Dir");
joachim99@8 1966 m_pInfoList->addColumn("Type");
joachim99@8 1967 m_pInfoList->addColumn("Size");
joachim99@8 1968 m_pInfoList->addColumn("Attr");
joachim99@8 1969 m_pInfoList->addColumn("Last Modification");
joachim99@8 1970 m_pInfoList->addColumn("Link-Destination");
joachim99@8 1971 setMinimumSize( 100,100 );
joachim99@8 1972 }
joachim99@8 1973
joachim99@8 1974 static void addListViewItem( QListView* pListView, const QString& dir,
joachim99@8 1975 const QString& basePath, FileAccess& fi )
joachim99@8 1976 {
joachim99@8 1977 if ( basePath.isEmpty() )
joachim99@8 1978 {
joachim99@8 1979 return;
joachim99@8 1980 }
joachim99@8 1981 else
joachim99@8 1982 {
joachim99@8 1983 if ( fi.exists() )
joachim99@8 1984 {
joachim99@8 1985 #if QT_VERSION==230
joachim99@8 1986 QString dateString = fi.lastModified().toString();
joachim99@8 1987 #else
joachim99@8 1988 QString dateString = fi.lastModified().toString("yyyy-MM-dd hh:mm:ss");
joachim99@8 1989 #endif
joachim99@8 1990
joachim99@8 1991 new QListViewItem(
joachim99@8 1992 pListView,
joachim99@8 1993 dir,
joachim99@8 1994 QString( fi.isDir() ? "Dir" : "File" ) + (fi.isSymLink() ? "-Link" : ""),
joachim99@8 1995 QString::number(fi.size()),
joachim99@8 1996 QString(fi.isReadable() ? "r" : " ") + (fi.isWritable()?"w" : " ")
joachim99@8 1997 #ifdef _WIN32
joachim99@8 1998 /*Future: Use GetFileAttributes()*/,
joachim99@8 1999 #else
joachim99@8 2000 + (fi.isExecutable()?"x" : " "),
joachim99@8 2001 #endif
joachim99@8 2002 dateString,
joachim99@8 2003 QString(fi.isSymLink() ? (" -> " + fi.readLink()) : QString(""))
joachim99@8 2004 );
joachim99@8 2005 }
joachim99@8 2006 else
joachim99@8 2007 {
joachim99@8 2008 new QListViewItem(
joachim99@8 2009 pListView,
joachim99@8 2010 dir,
joachim99@8 2011 "not available",
joachim99@8 2012 "",
joachim99@8 2013 "",
joachim99@8 2014 "",
joachim99@8 2015 ""
joachim99@8 2016 );
joachim99@8 2017 }
joachim99@8 2018 }
joachim99@8 2019 }
joachim99@8 2020
joachim99@8 2021 void DirectoryMergeInfo::setInfo(
joachim99@8 2022 const FileAccess& dirA,
joachim99@8 2023 const FileAccess& dirB,
joachim99@8 2024 const FileAccess& dirC,
joachim99@8 2025 const FileAccess& dirDest,
joachim99@8 2026 MergeFileInfos& mfi )
joachim99@8 2027 {
joachim99@8 2028 bool bHideDest = false;
joachim99@8 2029 if ( dirA.absFilePath()==dirDest.absFilePath() )
joachim99@8 2030 {
joachim99@8 2031 m_pA->setText( "A (Dest): " ); bHideDest=true;
joachim99@8 2032 }
joachim99@8 2033 else
joachim99@8 2034 m_pA->setText( !dirC.isValid() ? "A: " : "A (Base): ");
joachim99@8 2035
joachim99@8 2036 m_pInfoA->setText( dirA.prettyAbsPath() );
joachim99@8 2037
joachim99@8 2038 if ( dirB.absFilePath()==dirDest.absFilePath() )
joachim99@8 2039 {
joachim99@8 2040 m_pB->setText( "B (Dest): " ); bHideDest=true;
joachim99@8 2041 }
joachim99@8 2042 else
joachim99@8 2043 m_pB->setText( "B: " );
joachim99@8 2044 m_pInfoB->setText( dirB.prettyAbsPath() );
joachim99@8 2045
joachim99@8 2046 if ( dirC.absFilePath()==dirDest.absFilePath() )
joachim99@8 2047 {
joachim99@8 2048 m_pC->setText( "C (Dest): " ); bHideDest=true;
joachim99@8 2049 }
joachim99@8 2050 else
joachim99@8 2051 m_pC->setText( "C: " );
joachim99@8 2052 m_pInfoC->setText( dirC.prettyAbsPath() );
joachim99@8 2053
joachim99@8 2054 m_pDest->setText( "Dest: " ); m_pInfoDest->setText( dirDest.prettyAbsPath() );
joachim99@8 2055
joachim99@8 2056 if (!dirC.isValid()) { m_pC->hide(); m_pInfoC->hide(); }
joachim99@8 2057 else { m_pC->show(); m_pInfoC->show(); }
joachim99@8 2058
joachim99@8 2059 if (!dirDest.isValid()||bHideDest) { m_pDest->hide(); m_pInfoDest->hide(); }
joachim99@8 2060 else { m_pDest->show(); m_pInfoDest->show(); }
joachim99@8 2061
joachim99@8 2062 m_pInfoList->clear();
joachim99@8 2063 addListViewItem( m_pInfoList, "A", dirA.prettyAbsPath(), mfi.m_fileInfoA );
joachim99@8 2064 addListViewItem( m_pInfoList, "B", dirB.prettyAbsPath(), mfi.m_fileInfoB );
joachim99@8 2065 addListViewItem( m_pInfoList, "C", dirC.prettyAbsPath(), mfi.m_fileInfoC );
joachim99@8 2066 if (!bHideDest)
joachim99@8 2067 {
joachim99@8 2068 FileAccess fiDest( dirDest.prettyAbsPath() + "/" + mfi.m_subPath, true );
joachim99@8 2069 addListViewItem( m_pInfoList, "Dest", dirDest.prettyAbsPath(), fiDest );
joachim99@8 2070 }
joachim99@8 2071 }
joachim99@8 2072
joachim99@8 2073 #include "directorymergewindow.moc"