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