annotate kdiff3/src/directorymergewindow.cpp @ 51:c59d5a3a8ff3

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