annotate kdiff3/src-QT4/directorymergewindow.cpp @ 96:9000a9763f6f

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