annotate kdiff3/src-QT4/directorymergewindow.cpp @ 77:1184fc843210

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