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