annotate kdiff3/src/directorymergewindow.cpp @ 58:8af4bb9d9a5a

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