annotate kdiff3/src/directorymergewindow.cpp @ 57:023fbd76c1e3

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