comparison kdiff3/src/pdiff.cpp @ 8:86d21651c8db

KDiff3 version 0.9.70
author joachim99
date Mon, 06 Oct 2003 18:50:45 +0000
parents
children 675b2ed580b2
comparison
equal deleted inserted replaced
7:ff98a43bbfea 8:86d21651c8db
1 /***************************************************************************
2 kdiff.cpp - description
3 -------------------
4 begin : Mon Mär 18 20:04:50 CET 2002
5 copyright : (C) 2002 by Joachim Eibl
6 email : joachim.eibl@gmx.de
7 ***************************************************************************/
8
9 /***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18 /***************************************************************************
19 * $Log$
20 * Revision 1.1 2003/10/06 18:38:48 joachim99
21 * KDiff3 version 0.9.70
22 * *
23 ***************************************************************************/
24
25 #include "diff.h"
26 #include "directorymergewindow.h"
27
28 #include <iostream>
29 #include <algorithm>
30 #include <ctype.h>
31 #include <qaccel.h>
32
33 #include <kfiledialog.h>
34 #include <klocale.h>
35 #include <kmessagebox.h>
36 #include <kfontdialog.h>
37 #include <kstatusbar.h>
38 #include <kkeydialog.h>
39
40 #include <qclipboard.h>
41 #include <qscrollbar.h>
42 #include <qlayout.h>
43 #include <qsplitter.h>
44 #include <qlabel.h>
45 #include <qpushbutton.h>
46 #include <qlineedit.h>
47 #include <qcheckbox.h>
48 #include <qcombobox.h>
49 #include <qdir.h>
50 #include <qfile.h>
51 #include <qvbuttongroup.h>
52 #include <qradiobutton.h>
53 #include <qdragobject.h>
54 #include <assert.h>
55
56 #include "kdiff3.h"
57 #include "optiondialog.h"
58 #include "fileaccess.h"
59 #ifdef _WIN32
60 #include <windows.h>
61 #else
62 #include <unistd.h>
63 #endif
64
65 //using namespace std;
66
67 int g_tabSize = 8;
68 bool g_bIgnoreWhiteSpace = true;
69 bool g_bIgnoreTrivialMatches = true;
70
71
72 QString createTempFile( const LineData* p, int size, bool bIgnoreWhiteSpace, bool bIgnoreNumbers )
73 {
74 QString fileName = FileAccess::tempFileName();
75
76 QFile file( fileName );
77 bool bSuccess = file.open( IO_WriteOnly );
78 if ( !bSuccess ) return "";
79 for (int l=0; l<size; ++l)
80 {
81 // We don't want any white space in the diff output
82 QCString s( p[l].size+1 );
83 int is=0;
84 for(int j=0; j<p[l].size; ++j )
85 {
86 char c = p[l].pLine[j];
87 if ( !( bIgnoreWhiteSpace && isWhite( c ) ||
88 bIgnoreNumbers && (isdigit( c ) || c=='-' || c=='.' )
89 )
90 )
91 {
92 if ( c=='\0' ) // Replace zeros with something else.
93 s[is]=(char)0xFF;
94 else
95 s[is]=c;
96 ++is;
97 }
98 }
99 s[is]='\n';
100 ++is;
101 if( is != file.writeBlock( &s[0], is ) )
102 return "";
103 }
104 return fileName;
105 }
106
107 bool KDiff3App::runDiff( LineData* p1, int size1, LineData* p2, int size2, DiffList& diffList )
108 {
109 diffList.clear();
110 //QString errorString;
111
112 if ( m_pOptionDialog->m_bUseExternalDiff )
113 {
114 bool bSuccess=false;
115
116 bool bIgnoreWhiteSpace = m_pOptionDialog->m_bIgnoreWhiteSpace;
117 bool bIgnoreNumbers = m_pOptionDialog->m_bIgnoreNumbers;
118
119 // Create two temp files (Remove all white spaces and carriage returns here)
120 // (Make sure that no existing files are overwritten.)
121 g_pProgressDialog->setSubCurrent(0);
122 QString fileName1 = createTempFile( p1, size1, bIgnoreWhiteSpace, bIgnoreNumbers );
123 g_pProgressDialog->setSubCurrent(0.25);
124 QString fileName2 = createTempFile( p2, size2, bIgnoreWhiteSpace, bIgnoreNumbers );
125 g_pProgressDialog->setSubCurrent(0.5);
126 QString fileNameOut = FileAccess::tempFileName();
127
128 if ( !fileName1.isEmpty() && !fileName2.isEmpty() )
129 {
130 QString cmd;
131 #ifdef _WIN32
132 // Under Windows it's better to search for diff.exe
133 char buf[200];
134 int r= SearchPathA( 0, "diff.exe", 0, sizeof(buf), buf, 0 );
135
136 if (r!=0) { cmd = buf; }
137 #else
138 // under Un*x I assume that a diff command is in the PATH
139 cmd = "diff";
140 #endif
141 if ( !cmd.isEmpty() )
142 {
143 cmd += " -a "; // -a = treat all files as text
144 if ( m_pOptionDialog->m_bTryHard )
145 cmd += "--minimal ";
146 //if ( m_pOptionDialog->m_bIgnoreWhiteSpace ) This I do myself, see below
147 // cmd += "--ignore-all-space ";
148 cmd += fileName1+" "+fileName2+" >"+fileNameOut;
149 // Run diff
150 //int status1 = ::system( 0 ); // ==0 if shell not found
151 int status = ::system( cmd.ascii() );
152 #ifdef WEXITSTATUS
153 status = WEXITSTATUS(status);
154 #endif
155 //if (status<0)
156 //{
157 // errorString = strerror( errno );
158 //}
159 bSuccess = status>=0 && status!=127;
160 }
161 }
162
163 g_pProgressDialog->setSubCurrent(0.75);
164
165 int currentLine1 = 0;
166 int currentLine2 = 0;
167 if ( bSuccess )
168 {
169 // Parse the output and create the difflist
170 QFile f( fileNameOut );
171 bSuccess = f.open(IO_ReadOnly);
172 if (bSuccess)
173 {
174 const QByteArray buf = f.readAll();
175 unsigned int bufSize=buf.size();
176 unsigned int pos=0;
177 for(pos=0;pos<bufSize;++pos)
178 {
179 unsigned int lineStart = pos;
180 // Find end of line
181 while( buf.at(pos)!='\n' && pos<bufSize )
182 ++pos;
183
184 // parse it
185 char c = buf.at(lineStart);
186 if ( c == '>' || c == '-' || c=='<' )
187 continue; // Not interested in the data
188 else
189 {
190 QCString line( &buf.at(lineStart), pos-lineStart+1 );
191 int pa = line.find('a'); // add
192 int pc = line.find('c'); // change
193 int pd = line.find('d'); // delete
194 int p = pa>0 ? pa : (pc > 0 ? pc : pd);
195 if (p<0) break; // Unexpected error
196 QCString left = line.left(p);
197 QCString right = line.mid(p+1);
198 int pcommaleft = left.find(',');
199 int pcommaright = right.find(',');
200 int l1top=-1, l1bottom=-1, l2top=-1, l2bottom=-1;
201 if (pcommaleft>0)
202 {
203 l1top = left.left(pcommaleft).toInt();
204 l1bottom = left.mid(pcommaleft+1).toInt();
205 }
206 else
207 {
208 l1top = left.toInt();
209 l1bottom = l1top;
210 }
211 if (pcommaright>0)
212 {
213 l2top = right.left(pcommaright).toInt();
214 l2bottom = right.mid(pcommaright+1).toInt();
215 }
216 else
217 {
218 l2top = right.toInt();
219 l2bottom = l2top;
220 }
221
222 Diff d(0,0,0);
223
224 if ( pa>0 )
225 {
226 d.nofEquals = l1top - currentLine1;
227 d.diff1 = 0;
228 d.diff2 = l2bottom - l2top + 1;
229 assert( d.nofEquals == l2top - 1 - currentLine2 );
230 }
231 else if ( pd>0 )
232 {
233 d.nofEquals = l2top - currentLine2;
234 d.diff1 = l1bottom - l1top + 1;
235 d.diff2 = 0;
236 assert( d.nofEquals == l1top - 1 - currentLine1 );
237 }
238 else if ( pc>0 )
239 {
240 d.nofEquals = l1top - 1 - currentLine1;
241 d.diff1 = l1bottom - l1top + 1;
242 d.diff2 = l2bottom - l2top + 1;
243 assert( d.nofEquals == l2top - 1 - currentLine2 );
244 }
245 else
246 assert(false);
247
248 currentLine1 += d.nofEquals + d.diff1;
249 currentLine2 += d.nofEquals + d.diff2;
250 diffList.push_back(d);
251 }
252 }
253 if (size1-currentLine1==size2-currentLine2 )
254 {
255 Diff d( size1-currentLine1,0,0);
256 diffList.push_back(d);
257 currentLine1=size1;
258 currentLine2=size2;
259 }
260
261 if ( currentLine1 == size1 && currentLine2 == size2 )
262 bSuccess = true;
263 }
264 }
265 if ( currentLine1==0 && currentLine2==0 )
266 {
267 Diff d( 0, size1, size2 );
268 diffList.push_back(d);
269 }
270
271 FileAccess::removeFile( fileName1 );
272 FileAccess::removeFile( fileName2 );
273 FileAccess::removeFile( fileNameOut );
274 g_pProgressDialog->setSubCurrent(1.0);
275
276 if ( !bSuccess )
277 {
278 KMessageBox::sorry(this,
279 i18n("Running the external diff failed.\n"
280 "Check if the diff works, if the program can write in the temp folder or if the disk is full.\n"
281 "The external diff option will be disabled now and the internal diff will be used."),
282 i18n("KDiff3 Warning"));
283 m_pOptionDialog->m_bUseExternalDiff = false;
284 }
285 }
286
287 if ( ! m_pOptionDialog->m_bUseExternalDiff )
288 {
289 g_pProgressDialog->setSubCurrent(0.0);
290 if ( size1>0 && p1!=0 && p1->occurances==0 )
291 {
292 prepareOccurances( p1, size1 );
293 }
294 g_pProgressDialog->setSubCurrent(0.25);
295
296 if ( size2>0 && p2!=0 && p2->occurances==0 )
297 {
298 prepareOccurances( p2, size2 );
299 }
300 g_pProgressDialog->setSubCurrent(0.5);
301
302 calcDiff( p1, size1, p2, size2, diffList, 2, m_pOptionDialog->m_maxSearchLength );
303
304 g_pProgressDialog->setSubCurrent(1.0);
305 }
306 return true;
307 }
308
309
310 void KDiff3App::init( bool bAuto )
311 {
312 bool bPreserveCarriageReturn = m_pOptionDialog->m_bPreserveCarriageReturn;
313
314 bool bVisibleMergeResultWindow = ! m_outputFilename.isEmpty();
315 if ( bVisibleMergeResultWindow )
316 {
317 bPreserveCarriageReturn = false;
318 }
319
320 g_bIgnoreWhiteSpace = m_pOptionDialog->m_bIgnoreWhiteSpace;
321 g_bIgnoreTrivialMatches = m_pOptionDialog->m_bIgnoreTrivialMatches;
322
323 m_diff3LineList.clear();
324
325 bool bUseLineMatchingPP = !m_pOptionDialog->m_LineMatchingPreProcessorCmd.isEmpty();
326 bool bUpCase = m_pOptionDialog->m_bUpCase;
327
328 if (m_pDiffTextWindow1) m_pDiffTextWindow1->setPaintingAllowed( false );
329 if (m_pDiffTextWindow2) m_pDiffTextWindow2->setPaintingAllowed( false );
330 if (m_pDiffTextWindow3) m_pDiffTextWindow3->setPaintingAllowed( false );
331 if (m_pOverview) m_pOverview->setPaintingAllowed( false );
332
333
334 if( m_sd3.isEmpty() )
335 g_pProgressDialog->setMaximum( 4 ); // Read 2 files, 1 comparison, 1 finediff
336 else
337 g_pProgressDialog->setMaximum( 9 ); // Read 3 files, 3 comparisons, 3 finediffs
338
339 g_pProgressDialog->start();
340
341 // First get all input data.
342 g_pProgressDialog->setInformation(i18n("Loading A"));
343 m_sd1.readPPFile( bPreserveCarriageReturn, m_pOptionDialog->m_PreProcessorCmd, bUpCase );
344 m_sdlm1.readLMPPFile( &m_sd1, m_pOptionDialog->m_LineMatchingPreProcessorCmd, bUpCase );
345 g_pProgressDialog->step();
346
347 g_pProgressDialog->setInformation(i18n("Loading B"));
348 m_sd2.readPPFile( bPreserveCarriageReturn, m_pOptionDialog->m_PreProcessorCmd, bUpCase );
349 m_sdlm2.readLMPPFile( &m_sd2, m_pOptionDialog->m_LineMatchingPreProcessorCmd, bUpCase );
350 g_pProgressDialog->step();
351
352 m_sd3.m_bIsText = true;
353 int maxSearchLength = m_pOptionDialog->m_maxSearchLength;
354 m_totalDiffStatus.reset();
355 // Run the diff.
356 if ( m_sd3.isEmpty() )
357 {
358 m_totalDiffStatus.bBinaryAEqB = (m_sd1.m_size!=0 && m_sd1.m_size==m_sd2.m_size && memcmp(m_sd1.m_pBuf,m_sd2.m_pBuf,m_sd1.m_size)==0);
359 g_pProgressDialog->setInformation(i18n("Diff: A <-> B"));
360 if ( !bUseLineMatchingPP )
361 runDiff( &m_sd1.m_v[0], m_sd1.m_vSize, &m_sd2.m_v[0], m_sd2.m_vSize, m_diffList12 );
362 else
363 runDiff( &m_sdlm1.m_v[0], m_sdlm1.m_vSize, &m_sdlm2.m_v[0], m_sdlm2.m_vSize, m_diffList12 );
364
365 g_pProgressDialog->step();
366
367 g_pProgressDialog->setInformation(i18n("Linediff: A <-> B"));
368 calcDiff3LineListUsingAB( &m_diffList12, m_diff3LineList );
369 fineDiff( m_diff3LineList, 1, &m_sd1.m_v[0], &m_sd2.m_v[0], maxSearchLength, m_totalDiffStatus.bTextAEqB );
370 if ( m_sd1.m_size==0 ) m_totalDiffStatus.bTextAEqB=false;
371
372 g_pProgressDialog->step();
373 }
374 else
375 {
376 g_pProgressDialog->setInformation(i18n("Loading C"));
377 m_sd3.readPPFile( bPreserveCarriageReturn, m_pOptionDialog->m_PreProcessorCmd, bUpCase );
378 m_sdlm3.readLMPPFile( &m_sd3, m_pOptionDialog->m_LineMatchingPreProcessorCmd, bUpCase );
379 g_pProgressDialog->step();
380
381 m_totalDiffStatus.bBinaryAEqB = (m_sd1.m_size!=0 && m_sd1.m_size==m_sd2.m_size && memcmp(m_sd1.m_pBuf,m_sd2.m_pBuf,m_sd1.m_size)==0);
382 m_totalDiffStatus.bBinaryAEqC = (m_sd1.m_size!=0 && m_sd1.m_size==m_sd3.m_size && memcmp(m_sd1.m_pBuf,m_sd3.m_pBuf,m_sd1.m_size)==0);
383 m_totalDiffStatus.bBinaryBEqC = (m_sd3.m_size!=0 && m_sd3.m_size==m_sd2.m_size && memcmp(m_sd3.m_pBuf,m_sd2.m_pBuf,m_sd3.m_size)==0);
384
385 if ( !bUseLineMatchingPP )
386 {
387 g_pProgressDialog->setInformation(i18n("Diff: A <-> B"));
388 runDiff( &m_sd1.m_v[0], m_sd1.m_vSize, &m_sd2.m_v[0], m_sd2.m_vSize, m_diffList12 );
389 g_pProgressDialog->step();
390 g_pProgressDialog->setInformation(i18n("Diff: B <-> C"));
391 runDiff( &m_sd2.m_v[0], m_sd2.m_vSize, &m_sd3.m_v[0], m_sd3.m_vSize, m_diffList23 );
392 g_pProgressDialog->step();
393 g_pProgressDialog->setInformation(i18n("Diff: A <-> C"));
394 runDiff( &m_sd1.m_v[0], m_sd1.m_vSize, &m_sd3.m_v[0], m_sd3.m_vSize, m_diffList13 );
395 g_pProgressDialog->step();
396 }
397 else
398 {
399 g_pProgressDialog->setInformation(i18n("Diff: A <-> B"));
400 runDiff( &m_sdlm1.m_v[0], m_sd1.m_vSize, &m_sdlm2.m_v[0], m_sd2.m_vSize, m_diffList12 );
401 g_pProgressDialog->step();
402 g_pProgressDialog->setInformation(i18n("Diff: B <-> C"));
403 runDiff( &m_sdlm2.m_v[0], m_sd2.m_vSize, &m_sdlm3.m_v[0], m_sd3.m_vSize, m_diffList23 );
404 g_pProgressDialog->step();
405 g_pProgressDialog->setInformation(i18n("Diff: A <-> C"));
406 runDiff( &m_sdlm1.m_v[0], m_sd1.m_vSize, &m_sdlm3.m_v[0], m_sd3.m_vSize, m_diffList13 );
407 g_pProgressDialog->step();
408 }
409
410 calcDiff3LineListUsingAB( &m_diffList12, m_diff3LineList );
411 calcDiff3LineListUsingAC( &m_diffList13, m_diff3LineList );
412 calcDiff3LineListTrim( m_diff3LineList, &m_sd1.m_v[0], &m_sd2.m_v[0], &m_sd3.m_v[0] );
413
414 calcDiff3LineListUsingBC( &m_diffList23, m_diff3LineList );
415 calcDiff3LineListTrim( m_diff3LineList, &m_sd1.m_v[0], &m_sd2.m_v[0], &m_sd3.m_v[0] );
416 debugLineCheck( m_diff3LineList, m_sd1.m_vSize, 1 );
417 debugLineCheck( m_diff3LineList, m_sd2.m_vSize, 2 );
418 debugLineCheck( m_diff3LineList, m_sd3.m_vSize, 3 );
419
420 g_pProgressDialog->setInformation(i18n("Linediff: A <-> B"));
421 fineDiff( m_diff3LineList, 1, &m_sd1.m_v[0], &m_sd2.m_v[0], maxSearchLength, m_totalDiffStatus.bTextAEqB );
422 g_pProgressDialog->step();
423 g_pProgressDialog->setInformation(i18n("Linediff: B <-> C"));
424 fineDiff( m_diff3LineList, 2, &m_sd2.m_v[0], &m_sd3.m_v[0], maxSearchLength, m_totalDiffStatus.bTextBEqC );
425 g_pProgressDialog->step();
426 g_pProgressDialog->setInformation(i18n("Linediff: A <-> C"));
427 fineDiff( m_diff3LineList, 3, &m_sd3.m_v[0], &m_sd1.m_v[0], maxSearchLength, m_totalDiffStatus.bTextAEqC );
428 g_pProgressDialog->step();
429 if ( m_sd1.m_size==0 ) { m_totalDiffStatus.bTextAEqB=false; m_totalDiffStatus.bTextAEqC=false; }
430 if ( m_sd2.m_size==0 ) { m_totalDiffStatus.bTextAEqB=false; m_totalDiffStatus.bTextBEqC=false; }
431 }
432 calcWhiteDiff3Lines( m_diff3LineList, &m_sd1.m_v[0], &m_sd2.m_v[0], &m_sd3.m_v[0] );
433 calcDiff3LineVector( m_diff3LineList, m_diff3LineVector );
434
435 // Calc needed lines for display
436 m_neededLines = m_diff3LineList.size();
437
438 m_pDirectoryMergeWindow->allowResizeEvents(false);
439 initView();
440 m_pDirectoryMergeWindow->allowResizeEvents(true);
441
442 m_bTripleDiff = ! m_sd3.isEmpty();
443
444 m_pDiffTextWindow1->init( m_sd1.getAliasName(),
445 &m_sd1.m_v[0], m_sd1.m_vSize, &m_diff3LineVector, 1, m_bTripleDiff );
446 m_pDiffTextWindow2->init( m_sd2.getAliasName(),
447 &m_sd2.m_v[0], m_sd2.m_vSize, &m_diff3LineVector, 2, m_bTripleDiff );
448 m_pDiffTextWindow3->init( m_sd3.getAliasName(),
449 &m_sd3.m_v[0], m_sd3.m_vSize, &m_diff3LineVector, 3, m_bTripleDiff );
450
451 if (m_bTripleDiff) m_pDiffTextWindow3->show();
452 else m_pDiffTextWindow3->hide();
453
454 m_bOutputModified = bVisibleMergeResultWindow;
455
456 m_pMergeResultWindow->init(
457 &m_sd1.m_v[0],
458 &m_sd2.m_v[0],
459 m_bTripleDiff ? &m_sd3.m_v[0] : 0,
460 &m_diff3LineList,
461 &m_totalDiffStatus,
462 m_outputFilename.isEmpty() ? QString("unnamed.txt") : m_outputFilename
463 );
464
465 m_pOverview->init(&m_diff3LineList, m_bTripleDiff );
466 m_pDiffVScrollBar->setValue( 0 );
467 m_pHScrollBar->setValue( 0 );
468
469 g_pProgressDialog->hide();
470 m_pDiffTextWindow1->setPaintingAllowed( true );
471 m_pDiffTextWindow2->setPaintingAllowed( true );
472 m_pDiffTextWindow3->setPaintingAllowed( true );
473 m_pOverview->setPaintingAllowed( true );
474
475 if ( !bVisibleMergeResultWindow )
476 m_pMergeWindowFrame->hide();
477 else
478 m_pMergeWindowFrame->show();
479
480 // Calc max width for display
481 m_maxWidth = max2( m_pDiffTextWindow1->getNofColumns(), m_pDiffTextWindow2->getNofColumns() );
482 m_maxWidth = max2( m_maxWidth, m_pDiffTextWindow3->getNofColumns() );
483 m_maxWidth += 5;
484
485 if ( bVisibleMergeResultWindow && !bAuto )
486 m_pMergeResultWindow->showNrOfConflicts();
487 else if ( !bAuto )
488 {
489 QString totalInfo;
490 if ( m_totalDiffStatus.bBinaryAEqB && m_totalDiffStatus.bBinaryAEqC )
491 totalInfo += i18n("All input files are binary equal.");
492 else if ( m_totalDiffStatus.bTextAEqB && m_totalDiffStatus.bTextAEqC )
493 totalInfo += i18n("All input files contain the same text.");
494 else {
495 if ( m_totalDiffStatus.bBinaryAEqB ) totalInfo += i18n("Files A and B are binary equal.\n");
496 else if ( m_totalDiffStatus.bTextAEqB ) totalInfo += i18n("Files A and B have equal text. \n");
497 if ( m_totalDiffStatus.bBinaryAEqC ) totalInfo += i18n("Files A and C are binary equal.\n");
498 else if ( m_totalDiffStatus.bTextAEqC ) totalInfo += i18n("Files A and C have equal text. \n");
499 if ( m_totalDiffStatus.bBinaryBEqC ) totalInfo += i18n("Files B and C are binary equal.\n");
500 else if ( m_totalDiffStatus.bTextBEqC ) totalInfo += i18n("Files B and C have equal text. \n");
501 }
502
503 if ( !totalInfo.isEmpty() )
504 KMessageBox::information( this, totalInfo );
505 }
506
507 if ( bVisibleMergeResultWindow && (!m_sd1.m_bIsText || !m_sd2.m_bIsText || !m_sd3.m_bIsText) )
508 {
509 KMessageBox::information( this, i18n(
510 "Some inputfiles don't seem to be pure textfiles.\n"
511 "Note that the KDiff3-merge was not meant for binary data.\n"
512 "Continue at your own risk.") );
513 /* QDialog d(this);
514 QVBoxLayout* l = new QVBoxLayout(&d);
515 QVButtonGroup* bg = new QVButtonGroup(i18n("Some file(s) don't seem to be text files:"),&d);
516 l->addWidget(bg);
517 new QRadioButton("A: " + m_sd1.getAliasName(), bg);
518 new QRadioButton("B: " + m_sd2.getAliasName(), bg);
519 if (!m_sd3.isEmpty()) new QRadioButton("C: " + m_sd3.getAliasName(), bg);
520 bg->setButton(0);
521 QHBoxLayout* hbl = new QHBoxLayout(l);
522 QPushButton* pSaveButton = new QPushButton( i18n("Save Selection"), &d );
523 connect( pSaveButton, SIGNAL(clicked()), &d, SLOT(accept()));
524 hbl->addWidget( pSaveButton );
525 QPushButton* pProceedButton = new QPushButton( i18n("Proceed with text-merge"), &d );
526 connect( pProceedButton, SIGNAL(clicked()), &d, SLOT(reject()));
527 hbl->addWidget( pProceedButton );
528
529 int result = d.exec();
530 if( result == QDialog::Accepted )
531 {
532 if ( bg->find(0)->isOn() ) saveBuffer( m_sd1.m_pBuf, m_sd1.m_size, m_outputFilename );
533 else if ( bg->find(1)->isOn() ) saveBuffer( m_sd2.m_pBuf, m_sd2.m_size, m_outputFilename );
534 else saveBuffer( m_sd3.m_pBuf, m_sd3.m_size, m_outputFilename );
535 }*/
536 }
537
538 QTimer::singleShot( 10, this, SLOT(slotAfterFirstPaint()) );
539 }
540
541
542 void KDiff3App::resizeDiffTextWindow(int newWidth, int newHeight)
543 {
544 m_DTWHeight = newHeight;
545 m_pDiffVScrollBar->setRange(0, max2(0, m_neededLines+1 - newHeight) );
546 m_pDiffVScrollBar->setPageStep( newHeight );
547 m_pOverview->setRange( m_pDiffVScrollBar->value(), m_pDiffVScrollBar->pageStep() );
548
549 // The second window has a somewhat inverse width
550
551 m_pHScrollBar->setRange(0, max2(0, m_maxWidth - newWidth) );
552 m_pHScrollBar->setPageStep( newWidth );
553 }
554
555 void KDiff3App::resizeMergeResultWindow()
556 {
557 MergeResultWindow* p = m_pMergeResultWindow;
558 m_pMergeVScrollBar->setRange(0, max2(0, p->getNofLines() - p->getNofVisibleLines()) );
559 m_pMergeVScrollBar->setPageStep( p->getNofVisibleLines() );
560
561 // The second window has a somewhat inverse width
562 // m_pHScrollBar->setRange(0, max2(0, m_maxWidth - newWidth) );
563 // m_pHScrollBar->setPageStep( newWidth );
564 }
565
566 void KDiff3App::scrollDiffTextWindow( int deltaX, int deltaY )
567 {
568 if ( deltaY!= 0 )
569 {
570 m_pDiffVScrollBar->setValue( m_pDiffVScrollBar->value() + deltaY );
571 m_pOverview->setRange( m_pDiffVScrollBar->value(), m_pDiffVScrollBar->pageStep() );
572 }
573 if ( deltaX!= 0)
574 m_pHScrollBar->setValue( m_pHScrollBar->value() + deltaX );
575 }
576
577 void KDiff3App::scrollMergeResultWindow( int deltaX, int deltaY )
578 {
579 if ( deltaY!= 0 )
580 m_pMergeVScrollBar->setValue( m_pMergeVScrollBar->value() + deltaY );
581 if ( deltaX!= 0)
582 m_pHScrollBar->setValue( m_pHScrollBar->value() + deltaX );
583 }
584
585 void KDiff3App::setDiff3Line( int line )
586 {
587 m_pDiffVScrollBar->setValue( line );
588 }
589
590 void KDiff3App::sourceMask( int srcMask, int enabledMask )
591 {
592 chooseA->setChecked( (srcMask & 1) != 0 );
593 chooseB->setChecked( (srcMask & 2) != 0 );
594 chooseC->setChecked( (srcMask & 4) != 0 );
595 chooseA->setEnabled( (enabledMask & 1) != 0 );
596 chooseB->setEnabled( (enabledMask & 2) != 0 );
597 chooseC->setEnabled( (enabledMask & 4) != 0 );
598 }
599
600
601
602 // Function uses setMinSize( sizeHint ) before adding the widget.
603 // void addWidget(QBoxLayout* layout, QWidget* widget);
604 template <class W, class L>
605 void addWidget( L* layout, W* widget)
606 {
607 QSize s = widget->sizeHint();
608 widget->setMinimumSize( QSize(max2(s.width(),0),max2(s.height(),0) ) );
609 layout->addWidget( widget );
610 }
611
612 void KDiff3App::initView()
613 {
614 // set the main widget here
615 QValueList<int> oldHeights;
616 if ( m_pDirectoryMergeSplitter->isVisible() )
617 {
618 oldHeights = m_pMainSplitter->sizes();
619 }
620
621 if ( m_pMainWidget != 0 )
622 {
623 return;
624 //delete m_pMainWidget;
625 }
626 m_pMainWidget = new QFrame(m_pMainSplitter);
627 m_pMainWidget->setFrameStyle( QFrame::Panel | QFrame::Sunken );
628 m_pMainWidget->setLineWidth(1);
629
630
631 QVBoxLayout* pVLayout = new QVBoxLayout(m_pMainWidget);
632
633 QSplitter* pVSplitter = new QSplitter( m_pMainWidget );
634 pVSplitter->setOrientation( Vertical );
635 pVLayout->addWidget( pVSplitter );
636
637 QWidget* pDiffWindowFrame = new QFrame( pVSplitter );
638 QHBoxLayout* pDiffHLayout = new QHBoxLayout( pDiffWindowFrame );
639
640 m_pDiffWindowSplitter = new QSplitter( pDiffWindowFrame );
641 m_pDiffWindowSplitter->setOrientation( m_pOptionDialog->m_bHorizDiffWindowSplitting ? Horizontal : Vertical );
642 pDiffHLayout->addWidget( m_pDiffWindowSplitter );
643
644 m_pOverview = new Overview( pDiffWindowFrame, m_pOptionDialog );
645 pDiffHLayout->addWidget(m_pOverview);
646 connect( m_pOverview, SIGNAL(setLine(int)), this, SLOT(setDiff3Line(int)) );
647 //connect( m_pOverview, SIGNAL(afterFirstPaint()), this, SLOT(slotAfterFirstPaint()));
648
649 m_pDiffVScrollBar = new QScrollBar( Vertical, pDiffWindowFrame );
650 pDiffHLayout->addWidget( m_pDiffVScrollBar );
651
652 m_pDiffTextWindow1 = new DiffTextWindow( m_pDiffWindowSplitter, statusBar(), m_pOptionDialog );
653 m_pDiffTextWindow2 = new DiffTextWindow( m_pDiffWindowSplitter, statusBar(), m_pOptionDialog );
654 m_pDiffTextWindow3 = new DiffTextWindow( m_pDiffWindowSplitter, statusBar(), m_pOptionDialog );
655
656 // Merge window
657 m_pMergeWindowFrame = new QFrame( pVSplitter );
658 QHBoxLayout* pMergeHLayout = new QHBoxLayout( m_pMergeWindowFrame );
659
660 m_pMergeResultWindow = new MergeResultWindow( m_pMergeWindowFrame, m_pOptionDialog );
661 pMergeHLayout->addWidget( m_pMergeResultWindow );
662
663 m_pMergeVScrollBar = new QScrollBar( Vertical, m_pMergeWindowFrame );
664 pMergeHLayout->addWidget( m_pMergeVScrollBar );
665
666 autoAdvance->setEnabled(true);
667
668 QValueList<int> sizes = pVSplitter->sizes();
669 int total = sizes[0] + sizes[1];
670 sizes[0]=total/2; sizes[1]=total/2;
671 pVSplitter->setSizes( sizes );
672
673 m_pMergeResultWindow->installEventFilter( this ); // for Cut/Copy/Paste-shortcuts
674
675 QHBoxLayout* pHScrollBarLayout = new QHBoxLayout( pVLayout );
676 m_pHScrollBar = new QScrollBar( Horizontal, m_pMainWidget );
677 pHScrollBarLayout->addWidget( m_pHScrollBar );
678 m_pCornerWidget = new QWidget( m_pMainWidget );
679 pHScrollBarLayout->addWidget( m_pCornerWidget );
680
681
682 connect( m_pDiffVScrollBar, SIGNAL(valueChanged(int)), m_pOverview, SLOT(setFirstLine(int)));
683 connect( m_pDiffVScrollBar, SIGNAL(valueChanged(int)), m_pDiffTextWindow1, SLOT(setFirstLine(int)));
684 connect( m_pHScrollBar, SIGNAL(valueChanged(int)), m_pDiffTextWindow1, SLOT(setFirstColumn(int)));
685 connect( m_pDiffTextWindow1, SIGNAL(newSelection()), this, SLOT(slotSelectionStart()));
686 connect( m_pDiffTextWindow1, SIGNAL(selectionEnd()), this, SLOT(slotSelectionEnd()));
687 connect( m_pDiffTextWindow1, SIGNAL(scroll(int,int)), this, SLOT(scrollDiffTextWindow(int,int)));
688 m_pDiffTextWindow1->installEventFilter( this );
689
690 connect( m_pDiffVScrollBar, SIGNAL(valueChanged(int)), m_pDiffTextWindow2, SLOT(setFirstLine(int)));
691 connect( m_pHScrollBar, SIGNAL(valueChanged(int)), m_pDiffTextWindow2, SLOT(setFirstColumn(int)));
692 connect( m_pDiffTextWindow2, SIGNAL(newSelection()), this, SLOT(slotSelectionStart()));
693 connect( m_pDiffTextWindow2, SIGNAL(selectionEnd()), this, SLOT(slotSelectionEnd()));
694 connect( m_pDiffTextWindow2, SIGNAL(scroll(int,int)), this, SLOT(scrollDiffTextWindow(int,int)));
695 m_pDiffTextWindow2->installEventFilter( this );
696
697 connect( m_pDiffVScrollBar, SIGNAL(valueChanged(int)), m_pDiffTextWindow3, SLOT(setFirstLine(int)));
698 connect( m_pHScrollBar, SIGNAL(valueChanged(int)), m_pDiffTextWindow3, SLOT(setFirstColumn(int)));
699 connect( m_pDiffTextWindow3, SIGNAL(newSelection()), this, SLOT(slotSelectionStart()));
700 connect( m_pDiffTextWindow3, SIGNAL(selectionEnd()), this, SLOT(slotSelectionEnd()));
701 connect( m_pDiffTextWindow3, SIGNAL(scroll(int,int)), this, SLOT(scrollDiffTextWindow(int,int)));
702 m_pDiffTextWindow3->installEventFilter( this );
703
704 MergeResultWindow* p = m_pMergeResultWindow;
705 connect( m_pMergeVScrollBar, SIGNAL(valueChanged(int)), p, SLOT(setFirstLine(int)));
706
707 connect( m_pHScrollBar, SIGNAL(valueChanged(int)), p, SLOT(setFirstColumn(int)));
708 connect( p, SIGNAL(scroll(int,int)), this, SLOT(scrollMergeResultWindow(int,int)));
709 connect( p, SIGNAL(sourceMask(int,int)), this, SLOT(sourceMask(int,int)));
710 connect( p, SIGNAL( resizeSignal() ),this, SLOT(resizeMergeResultWindow()));
711 connect( p, SIGNAL( selectionEnd() ), this, SLOT( slotSelectionEnd() ) );
712 connect( p, SIGNAL( newSelection() ), this, SLOT( slotSelectionStart() ) );
713 connect( p, SIGNAL( modified() ), this, SLOT( slotOutputModified() ) );
714 connect( p, SIGNAL( updateAvailabilities() ), this, SLOT( slotUpdateAvailabilities() ) );
715 connect( p, SIGNAL( showPopupMenu(const QPoint&) ), this, SLOT(showPopupMenu(const QPoint&)));
716 sourceMask(0,0);
717
718
719 connect( p, SIGNAL(setFastSelectorRange(int,int)), m_pDiffTextWindow1, SLOT(setFastSelectorRange(int,int)));
720 connect( p, SIGNAL(setFastSelectorRange(int,int)), m_pDiffTextWindow2, SLOT(setFastSelectorRange(int,int)));
721 connect( p, SIGNAL(setFastSelectorRange(int,int)), m_pDiffTextWindow3, SLOT(setFastSelectorRange(int,int)));
722 connect(m_pDiffTextWindow1, SIGNAL(setFastSelectorLine(int)), p, SLOT(slotSetFastSelectorLine(int)));
723 connect(m_pDiffTextWindow2, SIGNAL(setFastSelectorLine(int)), p, SLOT(slotSetFastSelectorLine(int)));
724 connect(m_pDiffTextWindow3, SIGNAL(setFastSelectorLine(int)), p, SLOT(slotSetFastSelectorLine(int)));
725
726 connect( m_pDiffTextWindow1, SIGNAL( resizeSignal(int,int) ),this, SLOT(resizeDiffTextWindow(int,int)));
727
728 m_pDiffTextWindow1->setFocus();
729 m_pMainWidget->setMinimumSize(50,50);
730 if ( m_pDirectoryMergeSplitter->isVisible() )
731 {
732 if (oldHeights.count() < 2)
733 oldHeights.append(0);
734 if (oldHeights[1]==0) // Distribute the available space evenly between the two widgets.
735 {
736 oldHeights[1] = oldHeights[0]/2;
737 oldHeights[0] -= oldHeights[1];
738 }
739 m_pMainSplitter->setSizes( oldHeights );
740 }
741 m_pCornerWidget->setFixedSize( m_pDiffVScrollBar->width(), m_pHScrollBar->height() );
742 //show();
743 m_pMainWidget->show();
744 showWindowA->setChecked( true );
745 showWindowB->setChecked( true );
746 showWindowC->setChecked( true );
747 }
748
749 void KDiff3App::slotAfterFirstPaint()
750 {
751 int newHeight = m_pDiffTextWindow1->getNofVisibleLines();
752 int newWidth = m_pDiffTextWindow1->getNofVisibleColumns();
753 m_DTWHeight = newHeight;
754 m_pDiffVScrollBar->setRange(0, max2(0, m_neededLines+1 - newHeight) );
755 m_pDiffVScrollBar->setPageStep( newHeight );
756 m_pOverview->setRange( m_pDiffVScrollBar->value(), m_pDiffVScrollBar->pageStep() );
757
758 // The second window has a somewhat inverse width
759 m_pHScrollBar->setRange(0, max2(0, m_maxWidth - newWidth) );
760 m_pHScrollBar->setPageStep( newWidth );
761
762 m_pMergeResultWindow->slotGoTop();
763
764 if (m_pCornerWidget)
765 m_pCornerWidget->setFixedSize( m_pDiffVScrollBar->width(), m_pHScrollBar->height() );
766
767 slotUpdateAvailabilities();
768 }
769
770 void KDiff3App::resizeEvent(QResizeEvent* e)
771 {
772 QSplitter::resizeEvent(e);
773 if (m_pCornerWidget)
774 m_pCornerWidget->setFixedSize( m_pDiffVScrollBar->width(), m_pHScrollBar->height() );
775 }
776
777
778 bool KDiff3App::eventFilter( QObject* o, QEvent* e )
779 {
780 if( o == m_pMergeResultWindow )
781 {
782 if ( e->type() == QEvent::KeyPress )
783 { // key press
784 QKeyEvent *k = (QKeyEvent*)e;
785 if (k->key()==Qt::Key_Insert && (k->state() & Qt::ControlButton)!=0 )
786 {
787 slotEditCopy();
788 return true;
789 }
790 if (k->key()==Qt::Key_Insert && (k->state() & Qt::ShiftButton)!=0 )
791 {
792 slotEditPaste();
793 return true;
794 }
795 if (k->key()==Qt::Key_Delete && (k->state() & Qt::ShiftButton)!=0 )
796 {
797 slotEditCut();
798 return true;
799 }
800 }
801 return QSplitter::eventFilter( o, e ); // standard event processing
802 }
803
804 if ( e->type() == QEvent::KeyPress ) // key press
805 {
806 QKeyEvent *k = (QKeyEvent*)e;
807
808 bool bCtrl = (k->state() & Qt::ControlButton) != 0;
809 if (k->key()==Qt::Key_Insert && bCtrl )
810 {
811 slotEditCopy();
812 return true;
813 }
814 if (k->key()==Qt::Key_Insert && (k->state() & Qt::ShiftButton)!=0 )
815 {
816 slotEditPaste();
817 return true;
818 }
819 int deltaX=0;
820 int deltaY=0;
821 int pageSize = m_DTWHeight;
822 switch( k->key() )
823 {
824 case Key_Down: ++deltaY; break;
825 case Key_Up: --deltaY; break;
826 case Key_PageDown: if (!bCtrl) deltaY+=pageSize; break;
827 case Key_PageUp: if (!bCtrl) deltaY-=pageSize; break;
828 case Key_Left: --deltaX; break;
829 case Key_Right: ++deltaX; break;
830 case Key_Home: if ( bCtrl ) m_pDiffVScrollBar->setValue( 0 );
831 else m_pHScrollBar->setValue( 0 );
832 break;
833 case Key_End: if ( bCtrl ) m_pDiffVScrollBar->setValue( m_pDiffVScrollBar->maxValue() );
834 else m_pHScrollBar->setValue( m_pHScrollBar->maxValue() );
835 break;
836 default: break;
837 }
838
839 scrollDiffTextWindow( deltaX, deltaY );
840
841 return true; // eat event
842 }
843 else if (e->type() == QEvent::Wheel ) { // wheel event
844 QWheelEvent *w = (QWheelEvent*)e;
845 w->accept();
846
847 int deltaX=0;
848
849 int d=w->delta();
850 int deltaY = -d/120 * QApplication::wheelScrollLines();
851
852 scrollDiffTextWindow( deltaX, deltaY );
853 return true;
854 }
855 else if (e->type() == QEvent::Drop )
856 {
857 QDropEvent* pDropEvent = static_cast<QDropEvent*>(e);
858 pDropEvent->accept();
859
860 if ( QUriDrag::canDecode(pDropEvent) )
861 {
862 #ifdef KREPLACEMENTS_H
863 QStringList stringList;
864 QUriDrag::decodeLocalFiles( pDropEvent, stringList );
865 if ( canContinue() && !stringList.isEmpty() )
866 {
867 raise();
868 QString filename = stringList.first();
869 if ( o == m_pDiffTextWindow1 ) m_sd1.setFilename( filename );
870 else if ( o == m_pDiffTextWindow2 ) m_sd2.setFilename( filename );
871 else if ( o == m_pDiffTextWindow3 ) m_sd3.setFilename( filename );
872 init();
873 }
874 #else
875 KURL::List urlList;
876 KURLDrag::decode( pDropEvent, urlList );
877 if ( canContinue() && !urlList.isEmpty() )
878 {
879 raise();
880 FileAccess fa( urlList.first().url() );
881 if ( o == m_pDiffTextWindow1 ) m_sd1.setFileAccess( fa );
882 else if ( o == m_pDiffTextWindow2 ) m_sd2.setFileAccess( fa );
883 else if ( o == m_pDiffTextWindow3 ) m_sd3.setFileAccess( fa );
884 init();
885 }
886 #endif
887 }
888 else if ( QTextDrag::canDecode(pDropEvent) )
889 {
890 QString text;
891 bool bDecodeSuccess = QTextDrag::decode( pDropEvent, text );
892 if ( bDecodeSuccess && canContinue() )
893 {
894 raise();
895 bool bUpCase = m_pOptionDialog->m_bUpCase;
896 if ( o == m_pDiffTextWindow1 ) m_sd1.setData(text, bUpCase);
897 else if ( o == m_pDiffTextWindow2 ) m_sd2.setData(text, bUpCase);
898 else if ( o == m_pDiffTextWindow3 ) m_sd3.setData(text, bUpCase);
899 init();
900 }
901 }
902
903 return true;
904 }
905 return QSplitter::eventFilter( o, e ); // standard event processing
906 }
907
908
909
910 OpenDialog::OpenDialog(
911 QWidget* pParent, const QString& n1, const QString& n2, const QString& n3,
912 bool bMerge, const QString& outputName, const char* slotConfigure, OptionDialog* pOptions )
913 : QDialog( pParent, "OpenDialog", true /*modal*/ )
914 {
915 m_pOptions = pOptions;
916
917 QVBoxLayout* v = new QVBoxLayout( this, 5 );
918 QGridLayout* h = new QGridLayout( v, 5, 4, 5 );
919 h->setColStretch( 1, 10 );
920
921 QLabel* label = new QLabel( "A (Base):", this );
922
923 m_lineA = new QComboBox( true, this );
924 m_lineA->insertStringList( m_pOptions->m_recentAFiles );
925 m_lineA->setEditText( KURL(n1).prettyURL() );
926 m_lineA->setMinimumSize( 200, m_lineA->size().height() );
927 QPushButton * button = new QPushButton( "File...", this );
928 connect( button, SIGNAL(clicked()), this, SLOT( selectFileA() ) );
929 QPushButton * button2 = new QPushButton( "Dir...", this );
930 connect( button2, SIGNAL(clicked()), this, SLOT( selectDirA() ) );
931
932 h->addWidget( label, 0, 0 );
933 h->addWidget( m_lineA, 0, 1 );
934 h->addWidget( button, 0, 2 );
935 h->addWidget( button2, 0, 3 );
936
937 label = new QLabel( "B:", this );
938 m_lineB = new QComboBox( true, this );
939 m_lineB->insertStringList( m_pOptions->m_recentBFiles );
940 m_lineB->setEditText( KURL(n2).prettyURL() );
941 m_lineB->setMinimumSize( 200, m_lineB->size().height() );
942 button = new QPushButton( "File...", this );
943 connect( button, SIGNAL(clicked()), this, SLOT( selectFileB() ) );
944 button2 = new QPushButton( "Dir...", this );
945 connect( button2, SIGNAL(clicked()), this, SLOT( selectDirB() ) );
946
947 h->addWidget( label, 1, 0 );
948 h->addWidget( m_lineB, 1, 1 );
949 h->addWidget( button, 1, 2 );
950 h->addWidget( button2, 1, 3 );
951
952 label = new QLabel( "C (Optional):", this );
953 m_lineC= new QComboBox( true, this );
954 m_lineC->insertStringList( m_pOptions->m_recentCFiles );
955 m_lineC->setEditText( KURL(n3).prettyURL() );
956 m_lineC->setMinimumSize( 200, m_lineC->size().height() );
957 button = new QPushButton( "File...", this );
958 connect( button, SIGNAL(clicked()), this, SLOT( selectFileC() ) );
959 button2 = new QPushButton( "Dir...", this );
960 connect( button2, SIGNAL(clicked()), this, SLOT( selectDirC() ) );
961
962 h->addWidget( label, 2, 0 );
963 h->addWidget( m_lineC, 2, 1 );
964 h->addWidget( button, 2, 2 );
965 h->addWidget( button2, 2, 3 );
966
967 m_pMerge = new QCheckBox( "Merge", this );
968 h->addWidget( m_pMerge, 3, 0 );
969
970 label = new QLabel( "Output (Optional):", this );
971 m_lineOut = new QComboBox( true, this );
972 m_lineOut->insertStringList( m_pOptions->m_recentOutputFiles );
973 m_lineOut->setEditText( KURL(outputName).prettyURL() );
974 m_lineOut->setMinimumSize( 200, m_lineOut->size().height() );
975 button = new QPushButton( "File...", this );
976 connect( button, SIGNAL(clicked()), this, SLOT( selectOutputName() ) );
977 button2 = new QPushButton( "Dir...", this );
978 connect( button2, SIGNAL(clicked()), this, SLOT( selectOutputDir() ) );
979 connect( m_pMerge, SIGNAL(stateChanged(int)), this, SLOT(internalSlot(int)) );
980 connect( this, SIGNAL(internalSignal(bool)), m_lineOut, SLOT(setEnabled(bool)) );
981 connect( this, SIGNAL(internalSignal(bool)), button, SLOT(setEnabled(bool)) );
982 connect( this, SIGNAL(internalSignal(bool)), button2, SLOT(setEnabled(bool)) );
983
984 m_pMerge->setChecked( !bMerge );
985 m_pMerge->setChecked( bMerge );
986 // m_lineOutput->setEnabled( bMerge );
987
988 // button->setEnabled( bMerge );
989
990 h->addWidget( label, 4, 0 );
991 h->addWidget( m_lineOut, 4, 1 );
992 h->addWidget( button, 4, 2 );
993 h->addWidget( button2, 4, 3 );
994
995 h->addColSpacing( 1, 200 );
996
997 QHBoxLayout* l = new QHBoxLayout( v, 5 );
998 button = new QPushButton( "Ok", this );
999 button->setDefault( true );
1000 connect( button, SIGNAL(clicked()), this, SLOT( accept() ) );
1001 l->addWidget( button );
1002
1003 button = new QPushButton( "Cancel", this );
1004 connect( button, SIGNAL(clicked()), this, SLOT( reject() ) );
1005 l->addWidget( button );
1006
1007 button = new QPushButton( "Configure...", this );
1008 connect( button, SIGNAL(clicked()), pParent, slotConfigure );
1009 l->addWidget( button );
1010
1011 QSize sh = sizeHint();
1012 setFixedHeight( sh.height() );
1013 }
1014
1015 void OpenDialog::selectURL( QComboBox* pLine, bool bDir, int i, bool bSave )
1016 {
1017 QString current = pLine->currentText();
1018 if (current.isEmpty() && i>3 ){ current = m_lineC->currentText(); }
1019 if (current.isEmpty() ){ current = m_lineB->currentText(); }
1020 if (current.isEmpty() ){ current = m_lineA->currentText(); }
1021 KURL newURL = bDir ? KFileDialog::getExistingURL( current, this)
1022 : bSave ? KFileDialog::getSaveURL( current, 0, this)
1023 : KFileDialog::getOpenURL( current, 0, this);
1024 if ( !newURL.isEmpty() )
1025 {
1026 pLine->setEditText( newURL.url() );
1027 }
1028 // newURL won't be modified if nothing was selected.
1029 }
1030
1031 void OpenDialog::selectFileA() { selectURL( m_lineA, false, 1, false ); }
1032 void OpenDialog::selectFileB() { selectURL( m_lineB, false, 2, false ); }
1033 void OpenDialog::selectFileC() { selectURL( m_lineC, false, 3, false ); }
1034 void OpenDialog::selectOutputName(){ selectURL( m_lineOut, false, 4, true ); }
1035 void OpenDialog::selectDirA() { selectURL( m_lineA, true, 1, false ); }
1036 void OpenDialog::selectDirB() { selectURL( m_lineB, true, 2, false ); }
1037 void OpenDialog::selectDirC() { selectURL( m_lineC, true, 3, false ); }
1038 void OpenDialog::selectOutputDir() { selectURL( m_lineOut, true, 4, true ); }
1039
1040 void OpenDialog::internalSlot(int i)
1041 {
1042 emit internalSignal(i!=0);
1043 }
1044
1045 void OpenDialog::accept()
1046 {
1047 unsigned int maxNofRecentFiles = 10;
1048
1049 QString s = m_lineA->currentText();
1050 s = KURL::fromPathOrURL(s).prettyURL();
1051 QStringList* sl = &m_pOptions->m_recentAFiles;
1052 // If an item exist, remove it from the list and reinsert it at the beginning.
1053 sl->remove(s);
1054 if ( !s.isEmpty() ) sl->prepend( s );
1055 if (sl->count()>maxNofRecentFiles) sl->erase( sl->at(maxNofRecentFiles), sl->end() );
1056
1057 s = m_lineB->currentText();
1058 s = KURL::fromPathOrURL(s).prettyURL();
1059 sl = &m_pOptions->m_recentBFiles;
1060 sl->remove(s);
1061 if ( !s.isEmpty() ) sl->prepend( s );
1062 if (sl->count()>maxNofRecentFiles) sl->erase( sl->at(maxNofRecentFiles), sl->end() );
1063
1064 s = m_lineC->currentText();
1065 s = KURL::fromPathOrURL(s).prettyURL();
1066 sl = &m_pOptions->m_recentCFiles;
1067 sl->remove(s);
1068 if ( !s.isEmpty() ) sl->prepend( s );
1069 if (sl->count()>maxNofRecentFiles) sl->erase( sl->at(maxNofRecentFiles), sl->end() );
1070
1071 s = m_lineOut->currentText();
1072 s = KURL::fromPathOrURL(s).prettyURL();
1073 sl = &m_pOptions->m_recentOutputFiles;
1074 sl->remove(s);
1075 if ( !s.isEmpty() ) sl->prepend( s );
1076 if (sl->count()>maxNofRecentFiles) sl->erase( sl->at(maxNofRecentFiles), sl->end() );
1077
1078 QDialog::accept();
1079 }
1080
1081 void KDiff3App::slotFileOpen()
1082 {
1083 if ( !canContinue() ) return;
1084
1085 if ( m_pDirectoryMergeWindow->isDirectoryMergeInProgress() )
1086 {
1087 int result = KMessageBox::warningYesNo(this,
1088 i18n("You are currently doing a directory merge. Are you sure, you want to abort?"),
1089 i18n("Warning"), i18n("Yes - Abort"), i18n("No - Continue merging") );
1090 if ( result!=KMessageBox::Yes )
1091 return;
1092 }
1093
1094
1095 slotStatusMsg(i18n("Opening files..."));
1096
1097 for(;;)
1098 {
1099 OpenDialog d(this,
1100 m_sd1.m_bPreserve ? QString("") : m_sd1.getAliasName(),
1101 m_sd2.m_bPreserve ? QString("") : m_sd2.getAliasName(),
1102 m_sd3.m_bPreserve ? QString("") : m_sd3.getAliasName(),
1103 !m_outputFilename.isEmpty(),
1104 m_bDefaultFilename ? QString("") : m_outputFilename,
1105 SLOT(slotConfigure()), m_pOptionDialog );
1106 int status = d.exec();
1107 if ( status == QDialog::Accepted )
1108 {
1109 m_sd1.setFilename( d.m_lineA->currentText() );
1110 m_sd2.setFilename( d.m_lineB->currentText() );
1111 m_sd3.setFilename( d.m_lineC->currentText() );
1112
1113 if( d.m_pMerge->isChecked() )
1114 {
1115 if ( d.m_lineOut->currentText().isEmpty() )
1116 {
1117 m_outputFilename = "unnamed.txt";
1118 m_bDefaultFilename = true;
1119 }
1120 else
1121 {
1122 m_outputFilename = d.m_lineOut->currentText();
1123 m_bDefaultFilename = false;
1124 }
1125 }
1126 else
1127 m_outputFilename = "";
1128
1129 m_bDirCompare = improveFilenames();
1130 if ( m_bDirCompare )
1131 {
1132 m_pDirectoryMergeSplitter->show();
1133 if ( m_pMainWidget!=0 )
1134 {
1135 m_pMainWidget->hide();
1136 }
1137 break;
1138 }
1139 else
1140 {
1141 m_pDirectoryMergeSplitter->hide();
1142 init();
1143
1144 if ( ! m_sd1.isEmpty() && m_sd1.m_pBuf==0 ||
1145 ! m_sd2.isEmpty() && m_sd2.m_pBuf==0 ||
1146 ! m_sd3.isEmpty() && m_sd3.m_pBuf==0 )
1147 {
1148 QString text( i18n("Opening of these files failed:") );
1149 text += "\n\n";
1150 if ( ! m_sd1.isEmpty() && m_sd1.m_pBuf==0 )
1151 text += " - " + m_sd1.getAliasName() + "\n";
1152 if ( ! m_sd2.isEmpty() && m_sd2.m_pBuf==0 )
1153 text += " - " + m_sd2.getAliasName() + "\n";
1154 if ( ! m_sd3.isEmpty() && m_sd3.m_pBuf==0 )
1155 text += " - " + m_sd3.getAliasName() + "\n";
1156
1157 KMessageBox::sorry( this, text, i18n("File open error") );
1158 continue;
1159 }
1160 }
1161 }
1162 break;
1163 }
1164
1165 slotUpdateAvailabilities();
1166 slotStatusMsg(i18n("Ready."));
1167 }
1168
1169 void KDiff3App::slotFileOpen2(QString fn1, QString fn2, QString fn3, QString ofn,
1170 QString an1, QString an2, QString an3 )
1171 {
1172 if ( !canContinue() ) return;
1173
1174 slotStatusMsg(i18n("Opening files..."));
1175
1176 m_sd1.setFilename( fn1 );
1177 m_sd2.setFilename( fn2 );
1178 m_sd3.setFilename( fn3 );
1179
1180 m_sd1.setAliasName( an1 );
1181 m_sd2.setAliasName( an2 );
1182 m_sd3.setAliasName( an3 );
1183
1184 if ( ! ofn.isEmpty() )
1185 {
1186 m_outputFilename = ofn;
1187 m_bDefaultFilename = false;
1188 }
1189 else
1190 {
1191 m_outputFilename = "";
1192 m_bDefaultFilename = true;
1193 }
1194
1195 bool bDirCompare = improveFilenames(); // Using local bDirCompare is intended, because
1196 // this method is called from the directory-merge-window.
1197
1198 if( bDirCompare )
1199 {
1200 }
1201 else
1202 {
1203 init();
1204
1205 if ( ! m_sd1.isEmpty() && m_sd1.m_pBuf==0 ||
1206 ! m_sd2.isEmpty() && m_sd2.m_pBuf==0 ||
1207 ! m_sd3.isEmpty() && m_sd3.m_pBuf==0 )
1208 {
1209 QString text( i18n("Opening of these files failed:") );
1210 text += "\n\n";
1211 if ( ! m_sd1.isEmpty() && m_sd1.m_pBuf==0 )
1212 text += " - " + m_sd1.getAliasName() + "\n";
1213 if ( ! m_sd2.isEmpty() && m_sd2.m_pBuf==0 )
1214 text += " - " + m_sd2.getAliasName() + "\n";
1215 if ( ! m_sd3.isEmpty() && m_sd3.m_pBuf==0 )
1216 text += " - " + m_sd3.getAliasName() + "\n";
1217
1218 KMessageBox::sorry( this, text, i18n("File open error") );
1219 }
1220 else
1221 {
1222 if ( m_pDirectoryMergeWindow!=0 && m_pDirectoryMergeWindow->isVisible() && ! dirShowBoth->isChecked() )
1223 {
1224 slotDirViewToggle();
1225 }
1226 }
1227 }
1228 slotStatusMsg(i18n("Ready."));
1229 }
1230
1231 void KDiff3App::slotEditCut()
1232 {
1233 slotStatusMsg(i18n("Cutting selection..."));
1234
1235 QString s;
1236 if ( m_pMergeResultWindow!=0 )
1237 {
1238 s = m_pMergeResultWindow->getSelection();
1239 m_pMergeResultWindow->deleteSelection();
1240
1241 m_pMergeResultWindow->update();
1242 }
1243
1244 if ( !s.isNull() )
1245 {
1246 QApplication::clipboard()->setText( s );
1247 }
1248
1249 slotStatusMsg(i18n("Ready."));
1250 }
1251
1252 void KDiff3App::slotEditCopy()
1253 {
1254 slotStatusMsg(i18n("Copying selection to clipboard..."));
1255 QString s;
1256 if ( m_pDiffTextWindow1!=0 ) s = m_pDiffTextWindow1->getSelection();
1257 if ( s.isNull() && m_pDiffTextWindow2!=0 ) s = m_pDiffTextWindow2->getSelection();
1258 if ( s.isNull() && m_pDiffTextWindow3!=0 ) s = m_pDiffTextWindow3->getSelection();
1259 if ( s.isNull() && m_pMergeResultWindow!=0 ) s = m_pMergeResultWindow->getSelection();
1260 if ( !s.isNull() )
1261 {
1262 QApplication::clipboard()->setText( s );
1263 }
1264
1265 slotStatusMsg(i18n("Ready."));
1266 }
1267
1268 void KDiff3App::slotEditPaste()
1269 {
1270 slotStatusMsg(i18n("Inserting clipboard contents..."));
1271
1272 if ( m_pMergeResultWindow!=0 && m_pMergeResultWindow->isVisible() )
1273 {
1274 m_pMergeResultWindow->pasteClipboard();
1275 }
1276 else if ( canContinue() )
1277 {
1278 bool bUpCase = m_pOptionDialog->m_bUpCase;
1279 if ( m_pDiffTextWindow1->hasFocus() )
1280 {
1281 m_sd1.setData( QApplication::clipboard()->text(), bUpCase );
1282 init();
1283 }
1284 else if ( m_pDiffTextWindow2->hasFocus() )
1285 {
1286 m_sd2.setData( QApplication::clipboard()->text(), bUpCase );
1287 init();
1288 }
1289 else if ( m_pDiffTextWindow3->hasFocus() )
1290 {
1291 m_sd3.setData( QApplication::clipboard()->text(), bUpCase );
1292 init();
1293 }
1294 }
1295
1296 slotStatusMsg(i18n("Ready."));
1297 }
1298
1299
1300 void KDiff3App::slotGoCurrent()
1301 {
1302 if (m_pMergeResultWindow) m_pMergeResultWindow->slotGoCurrent();
1303 }
1304 void KDiff3App::slotGoTop()
1305 {
1306 if (m_pMergeResultWindow) m_pMergeResultWindow->slotGoTop();
1307 }
1308 void KDiff3App::slotGoBottom()
1309 {
1310 if (m_pMergeResultWindow) m_pMergeResultWindow->slotGoBottom();
1311 }
1312 void KDiff3App::slotGoPrevUnsolvedConflict()
1313 {
1314 if (m_pMergeResultWindow) m_pMergeResultWindow->slotGoPrevUnsolvedConflict();
1315 }
1316 void KDiff3App::slotGoNextUnsolvedConflict()
1317 {
1318 m_bTimerBlock = false;
1319 if (m_pMergeResultWindow) m_pMergeResultWindow->slotGoNextUnsolvedConflict();
1320 }
1321 void KDiff3App::slotGoPrevConflict()
1322 {
1323 if (m_pMergeResultWindow) m_pMergeResultWindow->slotGoPrevConflict();
1324 }
1325 void KDiff3App::slotGoNextConflict()
1326 {
1327 m_bTimerBlock = false;
1328 if (m_pMergeResultWindow) m_pMergeResultWindow->slotGoNextConflict();
1329 }
1330 void KDiff3App::slotGoPrevDelta()
1331 {
1332 if (m_pMergeResultWindow) m_pMergeResultWindow->slotGoPrevDelta();
1333 }
1334 void KDiff3App::slotGoNextDelta()
1335 {
1336 if (m_pMergeResultWindow) m_pMergeResultWindow->slotGoNextDelta();
1337 }
1338 void KDiff3App::slotChooseA()
1339 {
1340 if (m_pMergeResultWindow && ! m_bTimerBlock )
1341 {
1342 m_pMergeResultWindow->slotChooseA();
1343 if ( autoAdvance->isChecked() )
1344 {
1345 m_bTimerBlock = true;
1346 QTimer::singleShot( m_pOptionDialog->m_autoAdvanceDelay, this, SLOT( slotGoNextUnsolvedConflict() ) );
1347 }
1348 }
1349 }
1350 void KDiff3App::slotChooseB()
1351 {
1352 if ( m_pMergeResultWindow && ! m_bTimerBlock )
1353 {
1354 m_pMergeResultWindow->slotChooseB();
1355 if ( autoAdvance->isChecked() )
1356 {
1357 m_bTimerBlock = true;
1358 QTimer::singleShot( m_pOptionDialog->m_autoAdvanceDelay, this, SLOT( slotGoNextUnsolvedConflict() ) );
1359 }
1360 }
1361 }
1362 void KDiff3App::slotChooseC()
1363 {
1364 if ( m_pMergeResultWindow && ! m_bTimerBlock )
1365 {
1366 m_pMergeResultWindow->slotChooseC();
1367 if ( autoAdvance->isChecked() )
1368 {
1369 m_bTimerBlock = true;
1370 QTimer::singleShot( m_pOptionDialog->m_autoAdvanceDelay, this, SLOT( slotGoNextUnsolvedConflict() ) );
1371 }
1372 }
1373 }
1374 void KDiff3App::slotChooseAEverywhere()
1375 {
1376 if (m_pMergeResultWindow )
1377 {
1378 slotGoTop();
1379 m_pMergeResultWindow->slotChooseAEverywhere();
1380 }
1381 }
1382 void KDiff3App::slotChooseBEverywhere()
1383 {
1384 if (m_pMergeResultWindow )
1385 {
1386 slotGoTop();
1387 m_pMergeResultWindow->slotChooseBEverywhere();
1388 }
1389 }
1390
1391 void KDiff3App::slotChooseCEverywhere()
1392 {
1393 if (m_pMergeResultWindow )
1394 {
1395 slotGoTop();
1396 m_pMergeResultWindow->slotChooseCEverywhere();
1397 }
1398 }
1399
1400 void KDiff3App::slotAutoSolve()
1401 {
1402 if (m_pMergeResultWindow )
1403 {
1404 slotGoTop();
1405 m_pMergeResultWindow->slotAutoSolve();
1406 // m_pMergeWindowFrame->show(); incompatible with bPreserveCarriageReturn
1407 m_pMergeResultWindow->showNrOfConflicts();
1408 slotUpdateAvailabilities();
1409 }
1410 }
1411
1412 void KDiff3App::slotUnsolve()
1413 {
1414 if (m_pMergeResultWindow )
1415 {
1416 slotGoTop();
1417 m_pMergeResultWindow->slotUnsolve();
1418 }
1419 }
1420
1421
1422 void KDiff3App::slotConfigure()
1423 {
1424 m_pOptionDialog->setState();
1425 m_pOptionDialog->incInitialSize ( QSize(0,40) );
1426 m_pOptionDialog->exec();
1427 slotRefresh();
1428 }
1429
1430 void KDiff3App::slotConfigureKeys()
1431 {
1432 KKeyDialog::configure(actionCollection(), this);
1433 }
1434
1435 void KDiff3App::slotRefresh()
1436 {
1437 g_tabSize = m_pOptionDialog->m_tabSize;
1438 if (m_pDiffTextWindow1!=0) m_pDiffTextWindow1->update();
1439 if (m_pDiffTextWindow2!=0) m_pDiffTextWindow2->update();
1440 if (m_pDiffTextWindow3!=0) m_pDiffTextWindow3->update();
1441 if (m_pMergeResultWindow!=0) m_pMergeResultWindow->update();
1442
1443 autoAdvance->setChecked( m_pOptionDialog->m_bAutoAdvance );
1444 showWhiteSpace->setChecked( m_pOptionDialog->m_bShowWhiteSpace );
1445 showLineNumbers->setChecked( m_pOptionDialog->m_bShowLineNumbers );
1446
1447 if ( m_pDiffWindowSplitter!=0 )
1448 {
1449 m_pDiffWindowSplitter->setOrientation( m_pOptionDialog->m_bHorizDiffWindowSplitting ? Horizontal : Vertical );
1450 }
1451 }
1452
1453 void KDiff3App::slotSelectionStart()
1454 {
1455 //editCopy->setEnabled( false );
1456 //editCut->setEnabled( false );
1457
1458 const QObject* s = sender();
1459 if (m_pDiffTextWindow1 && s!=m_pDiffTextWindow1) m_pDiffTextWindow1->resetSelection();
1460 if (m_pDiffTextWindow2 && s!=m_pDiffTextWindow2) m_pDiffTextWindow2->resetSelection();
1461 if (m_pDiffTextWindow3 && s!=m_pDiffTextWindow3) m_pDiffTextWindow3->resetSelection();
1462 if (m_pMergeResultWindow && s!=m_pMergeResultWindow) m_pMergeResultWindow->resetSelection();
1463 }
1464
1465 void KDiff3App::slotSelectionEnd()
1466 {
1467 //const QObject* s = sender();
1468 //editCopy->setEnabled(true);
1469 //editCut->setEnabled( s==m_pMergeResultWindow );
1470 if ( m_pOptionDialog->m_bAutoCopySelection )
1471 {
1472 slotEditCopy();
1473 }
1474 }
1475
1476 void KDiff3App::slotClipboardChanged()
1477 {
1478 QString s = QApplication::clipboard()->text();
1479 //editPaste->setEnabled(!s.isEmpty());
1480 }
1481
1482 void KDiff3App::slotOutputModified()
1483 {
1484 if ( !m_bOutputModified )
1485 {
1486 m_bOutputModified=true;
1487 slotUpdateAvailabilities();
1488 }
1489 }
1490
1491 void KDiff3App::slotAutoAdvanceToggled()
1492 {
1493 m_pOptionDialog->m_bAutoAdvance = autoAdvance->isChecked();
1494 }
1495
1496 void KDiff3App::slotShowWhiteSpaceToggled()
1497 {
1498 m_pOptionDialog->m_bShowWhiteSpace = showWhiteSpace->isChecked();
1499 if ( m_pDiffTextWindow1!=0 )
1500 m_pDiffTextWindow1->update();
1501 if ( m_pDiffTextWindow2!=0 )
1502 m_pDiffTextWindow2->update();
1503 if ( m_pDiffTextWindow3!=0 )
1504 m_pDiffTextWindow3->update();
1505 }
1506
1507 void KDiff3App::slotShowLineNumbersToggled()
1508 {
1509 m_pOptionDialog->m_bShowLineNumbers = showLineNumbers->isChecked();
1510 if ( m_pDiffTextWindow1!=0 )
1511 m_pDiffTextWindow1->update();
1512 if ( m_pDiffTextWindow2!=0 )
1513 m_pDiffTextWindow2->update();
1514 if ( m_pDiffTextWindow3!=0 )
1515 m_pDiffTextWindow3->update();
1516 }
1517
1518 /// Return true for directory compare, else false
1519 bool KDiff3App::improveFilenames()
1520 {
1521 FileAccess f1(m_sd1.getFilename());
1522 FileAccess f2(m_sd2.getFilename());
1523 FileAccess f3(m_sd3.getFilename());
1524 FileAccess f4(m_outputFilename);
1525
1526 if ( f1.isFile() && f1.exists() )
1527 {
1528 if ( f2.isDir() )
1529 {
1530 f2.addPath( f1.fileName() );
1531 if ( f2.isFile() && f2.exists() )
1532 m_sd2.setFileAccess( f2 );
1533 }
1534 if ( f3.isDir() )
1535 {
1536 f3.addPath( f1.fileName() );
1537 if ( f3.isFile() && f3.exists() )
1538 m_sd3.setFileAccess( f3 );
1539 }
1540 if ( f4.isDir() )
1541 {
1542 f4.addPath( f1.fileName() );
1543 if ( f4.isFile() && f4.exists() )
1544 m_outputFilename = f4.absFilePath();
1545 }
1546 }
1547 else if ( f1.isDir() )
1548 {
1549 FileAccess destDir;
1550 if (!m_bDefaultFilename) destDir = f4;
1551 m_pDirectoryMergeSplitter->show();
1552 m_pDirectoryMergeWindow->init(
1553 f1, f2, f3,
1554 destDir, // Destdirname
1555 !m_outputFilename.isEmpty()
1556 );
1557
1558 if (m_pMainWidget!=0) m_pMainWidget->hide();
1559 m_sd1.reset();
1560 if (m_pDiffTextWindow1!=0) m_pDiffTextWindow1->init(0,0,0,0,1,false);
1561 m_sd2.reset();
1562 if (m_pDiffTextWindow2!=0) m_pDiffTextWindow2->init(0,0,0,0,2,false);
1563 m_sd3.reset();
1564 if (m_pDiffTextWindow3!=0) m_pDiffTextWindow3->init(0,0,0,0,3,false);
1565 slotUpdateAvailabilities();
1566 return true;
1567 }
1568 return false;
1569 }
1570
1571 void KDiff3App::slotReload()
1572 {
1573 if ( !canContinue() ) return;
1574
1575 init();
1576 }
1577
1578 bool KDiff3App::canContinue()
1579 {
1580 // First test if anything must be saved.
1581 if(m_bOutputModified)
1582 {
1583 int result = KMessageBox::warningYesNoCancel(this,
1584 i18n("The merge result hasn't been saved."),
1585 i18n("Warning"), i18n("Save and continue"), i18n("Continue without saving") );
1586 if ( result==KMessageBox::Cancel )
1587 return false;
1588 else if ( result==KMessageBox::Yes )
1589 {
1590 slotFileSave();
1591 if ( m_bOutputModified )
1592 {
1593 KMessageBox::sorry(this, i18n("Saving the merge result failed."), i18n("Warning") );
1594 return false;
1595 }
1596 }
1597 }
1598
1599 m_bOutputModified = false;
1600 return true;
1601 }
1602
1603 void KDiff3App::slotCheckIfCanContinue( bool* pbContinue )
1604 {
1605 if (pbContinue!=0) *pbContinue = canContinue();
1606 }
1607
1608
1609 void KDiff3App::slotDirShowBoth()
1610 {
1611 if( dirShowBoth->isChecked() )
1612 {
1613 if ( m_bDirCompare )
1614 m_pDirectoryMergeSplitter->show();
1615 else
1616 m_pDirectoryMergeSplitter->hide();
1617
1618 if ( m_pMainWidget!=0 )
1619 m_pMainWidget->show();
1620 }
1621 else
1622 {
1623 if ( m_pMainWidget!=0 )
1624 {
1625 m_pMainWidget->show();
1626 m_pDirectoryMergeSplitter->hide();
1627 }
1628 else if ( m_bDirCompare )
1629 {
1630 m_pDirectoryMergeSplitter->show();
1631 }
1632 }
1633
1634 slotUpdateAvailabilities();
1635 }
1636
1637
1638 void KDiff3App::slotDirViewToggle()
1639 {
1640 if ( m_bDirCompare )
1641 {
1642 if( ! m_pDirectoryMergeSplitter->isVisible() )
1643 {
1644 m_pDirectoryMergeSplitter->show();
1645 if (m_pMainWidget!=0)
1646 m_pMainWidget->hide();
1647 }
1648 else
1649 {
1650 if (m_pMainWidget!=0)
1651 {
1652 m_pDirectoryMergeSplitter->hide();
1653 m_pMainWidget->show();
1654 }
1655 }
1656 }
1657 slotUpdateAvailabilities();
1658 }
1659
1660 void KDiff3App::slotShowWindowAToggled()
1661 {
1662 if ( m_pDiffTextWindow1!=0 )
1663 {
1664 if ( showWindowA->isChecked() ) m_pDiffTextWindow1->show();
1665 else m_pDiffTextWindow1->hide();
1666 slotUpdateAvailabilities();
1667 }
1668 }
1669
1670 void KDiff3App::slotShowWindowBToggled()
1671 {
1672 if ( m_pDiffTextWindow2!=0 )
1673 {
1674 if ( showWindowB->isChecked() ) m_pDiffTextWindow2->show();
1675 else m_pDiffTextWindow2->hide();
1676 slotUpdateAvailabilities();
1677 }
1678 }
1679
1680 void KDiff3App::slotShowWindowCToggled()
1681 {
1682 if ( m_pDiffTextWindow3!=0 )
1683 {
1684 if ( showWindowC->isChecked() ) m_pDiffTextWindow3->show();
1685 else m_pDiffTextWindow3->hide();
1686 slotUpdateAvailabilities();
1687 }
1688 }
1689
1690 void KDiff3App::slotEditFind()
1691 {
1692 m_pFindDialog->currentLine = 0;
1693 m_pFindDialog->currentPos = 0;
1694 m_pFindDialog->currentWindow = 1;
1695
1696 if ( QDialog::Accepted == m_pFindDialog->exec() )
1697 {
1698 slotEditFindNext();
1699 }
1700 }
1701
1702 void KDiff3App::slotEditFindNext()
1703 {
1704 QCString s = m_pFindDialog->m_pSearchString->text().utf8();
1705 if ( s.isEmpty() )
1706 {
1707 slotEditFind();
1708 return;
1709 }
1710
1711 bool bDirDown = true;
1712 bool bCaseSensitive = m_pFindDialog->m_pCaseSensitive->isChecked();
1713
1714 int d3vLine = m_pFindDialog->currentLine;
1715 int posInLine = m_pFindDialog->currentPos;
1716 if ( m_pFindDialog->currentWindow == 1 )
1717 {
1718 if ( m_pFindDialog->m_pSearchInA->isChecked() && m_pDiffTextWindow1!=0 &&
1719 m_pDiffTextWindow1->findString( s, d3vLine, posInLine, bDirDown, bCaseSensitive ) )
1720 {
1721 m_pDiffTextWindow1->setSelection( d3vLine, posInLine, d3vLine, posInLine+s.length() );
1722 m_pDiffVScrollBar->setValue(d3vLine-m_pDiffVScrollBar->pageStep()/2);
1723 m_pHScrollBar->setValue( max2( 0, posInLine+(int)s.length()-m_pHScrollBar->pageStep()) );
1724 m_pFindDialog->currentLine = d3vLine;
1725 m_pFindDialog->currentPos = posInLine + 1;
1726 return;
1727 }
1728 m_pFindDialog->currentWindow = 2;
1729 m_pFindDialog->currentLine = 0;
1730 m_pFindDialog->currentPos = 0;
1731 }
1732
1733 d3vLine = m_pFindDialog->currentLine;
1734 posInLine = m_pFindDialog->currentPos;
1735 if ( m_pFindDialog->currentWindow == 2 )
1736 {
1737 if ( m_pFindDialog->m_pSearchInB->isChecked() && m_pDiffTextWindow2!=0 &&
1738 m_pDiffTextWindow2->findString( s, d3vLine, posInLine, bDirDown, bCaseSensitive ) )
1739 {
1740 m_pDiffTextWindow2->setSelection( d3vLine, posInLine, d3vLine, posInLine+s.length() );
1741 m_pDiffVScrollBar->setValue(d3vLine-m_pDiffVScrollBar->pageStep()/2);
1742 m_pHScrollBar->setValue( max2( 0, posInLine+(int)s.length()-m_pHScrollBar->pageStep()) );
1743 m_pFindDialog->currentLine = d3vLine;
1744 m_pFindDialog->currentPos = posInLine + 1;
1745 return;
1746 }
1747 m_pFindDialog->currentWindow = 3;
1748 m_pFindDialog->currentLine = 0;
1749 m_pFindDialog->currentPos = 0;
1750 }
1751
1752 d3vLine = m_pFindDialog->currentLine;
1753 posInLine = m_pFindDialog->currentPos;
1754 if ( m_pFindDialog->currentWindow == 3 )
1755 {
1756 if ( m_pFindDialog->m_pSearchInC->isChecked() && m_pDiffTextWindow3!=0 &&
1757 m_pDiffTextWindow3->findString( s, d3vLine, posInLine, bDirDown, bCaseSensitive ) )
1758 {
1759 m_pDiffTextWindow3->setSelection( d3vLine, posInLine, d3vLine, posInLine+s.length() );
1760 m_pDiffVScrollBar->setValue(d3vLine-m_pDiffVScrollBar->pageStep()/2);
1761 m_pHScrollBar->setValue( max2( 0, posInLine+(int)s.length()-m_pHScrollBar->pageStep()) );
1762 m_pFindDialog->currentLine = d3vLine;
1763 m_pFindDialog->currentPos = posInLine + 1;
1764 return;
1765 }
1766 m_pFindDialog->currentWindow = 4;
1767 m_pFindDialog->currentLine = 0;
1768 m_pFindDialog->currentPos = 0;
1769 }
1770
1771 d3vLine = m_pFindDialog->currentLine;
1772 posInLine = m_pFindDialog->currentPos;
1773 if ( m_pFindDialog->currentWindow == 4 )
1774 {
1775 if ( m_pFindDialog->m_pSearchInOutput->isChecked() && m_pMergeResultWindow!=0 && m_pMergeResultWindow->isVisible() &&
1776 m_pMergeResultWindow->findString( s, d3vLine, posInLine, bDirDown, bCaseSensitive ) )
1777 {
1778 m_pMergeResultWindow->setSelection( d3vLine, posInLine, d3vLine, posInLine+s.length() );
1779 m_pMergeVScrollBar->setValue(d3vLine - m_pMergeVScrollBar->pageStep()/2);
1780 m_pHScrollBar->setValue( max2( 0, posInLine+(int)s.length()-m_pHScrollBar->pageStep()) );
1781 m_pFindDialog->currentLine = d3vLine;
1782 m_pFindDialog->currentPos = posInLine + 1;
1783 return;
1784 }
1785 m_pFindDialog->currentWindow = 5;
1786 m_pFindDialog->currentLine = 0;
1787 m_pFindDialog->currentPos = 0;
1788 }
1789
1790 KMessageBox::information(this,i18n("Search Complete."),i18n("KDiff3: Search Complete."));
1791 m_pFindDialog->currentWindow = 1;
1792 m_pFindDialog->currentLine = 0;
1793 m_pFindDialog->currentPos = 0;
1794 }
1795
1796 void KDiff3App::slotMergeCurrentFile()
1797 {
1798 if ( m_bDirCompare && m_pDirectoryMergeWindow->isVisible() && m_pDirectoryMergeWindow->isFileSelected() )
1799 {
1800 m_pDirectoryMergeWindow->mergeCurrentFile();
1801 }
1802 else if ( m_pMainWidget != 0 && m_pMainWidget->isVisible() )
1803 {
1804 if ( !canContinue() ) return;
1805 if ( m_outputFilename.isEmpty() )
1806 {
1807 if ( !m_sd3.isEmpty() && !m_sd3.m_bPreserve )
1808 {
1809 m_outputFilename = m_sd3.getFilename();
1810 }
1811 else if ( !m_sd2.isEmpty() && !m_sd2.m_bPreserve )
1812 {
1813 m_outputFilename = m_sd2.getFilename();
1814 }
1815 else if ( !m_sd1.isEmpty() && !m_sd1.m_bPreserve )
1816 {
1817 m_outputFilename = m_sd1.getFilename();
1818 }
1819 else
1820 {
1821 m_outputFilename = "unnamed.txt";
1822 m_bDefaultFilename = true;
1823 }
1824 }
1825 init();
1826 }
1827 }
1828
1829 void KDiff3App::slotWinFocusNext()
1830 {
1831 QWidget* focus = qApp->focusWidget();
1832 if ( focus == m_pDirectoryMergeWindow && m_pDirectoryMergeWindow->isVisible() && ! dirShowBoth->isChecked() )
1833 {
1834 slotDirViewToggle();
1835 }
1836
1837 std::list<QWidget*> visibleWidgetList;
1838 if ( m_pDiffTextWindow1->isVisible() ) visibleWidgetList.push_back(m_pDiffTextWindow1);
1839 if ( m_pDiffTextWindow2->isVisible() ) visibleWidgetList.push_back(m_pDiffTextWindow2);
1840 if ( m_pDiffTextWindow3->isVisible() ) visibleWidgetList.push_back(m_pDiffTextWindow3);
1841 if ( m_pMergeResultWindow->isVisible() ) visibleWidgetList.push_back(m_pMergeResultWindow);
1842 if ( m_bDirCompare /*m_pDirectoryMergeWindow->isVisible()*/ ) visibleWidgetList.push_back(m_pDirectoryMergeWindow);
1843 //if ( m_pDirectoryMergeInfo->isVisible() ) visibleWidgetList.push_back(m_pDirectoryMergeInfo->getInfoList());
1844
1845 std::list<QWidget*>::iterator i = std::find( visibleWidgetList.begin(), visibleWidgetList.end(), focus);
1846 ++i;
1847 if ( i==visibleWidgetList.end() ) ++i; // if at end goto begin of list
1848 if ( i!=visibleWidgetList.end() )
1849 {
1850 if ( *i == m_pDirectoryMergeWindow && ! dirShowBoth->isChecked() )
1851 {
1852 slotDirViewToggle();
1853 }
1854 (*i)->setFocus();
1855 }
1856 }
1857
1858 void KDiff3App::slotWinFocusPrev()
1859 {
1860 QWidget* focus = qApp->focusWidget();
1861 if ( focus == m_pDirectoryMergeWindow && m_pDirectoryMergeWindow->isVisible() && ! dirShowBoth->isChecked() )
1862 {
1863 slotDirViewToggle();
1864 }
1865
1866 std::list<QWidget*> visibleWidgetList;
1867 if ( m_pDiffTextWindow1->isVisible() ) visibleWidgetList.push_back(m_pDiffTextWindow1);
1868 if ( m_pDiffTextWindow2->isVisible() ) visibleWidgetList.push_back(m_pDiffTextWindow2);
1869 if ( m_pDiffTextWindow3->isVisible() ) visibleWidgetList.push_back(m_pDiffTextWindow3);
1870 if ( m_pMergeResultWindow->isVisible() ) visibleWidgetList.push_back(m_pMergeResultWindow);
1871 if (m_bDirCompare /* m_pDirectoryMergeWindow->isVisible() */ ) visibleWidgetList.push_back(m_pDirectoryMergeWindow);
1872 //if ( m_pDirectoryMergeInfo->isVisible() ) visibleWidgetList.push_back(m_pDirectoryMergeInfo->getInfoList());
1873
1874 std::list<QWidget*>::iterator i = std::find( visibleWidgetList.begin(), visibleWidgetList.end(), focus);
1875 --i;
1876 if ( i==visibleWidgetList.end() ) --i;
1877 if ( i!=visibleWidgetList.end() )
1878 {
1879 if ( *i == m_pDirectoryMergeWindow && ! dirShowBoth->isChecked() )
1880 {
1881 slotDirViewToggle();
1882 }
1883 (*i)->setFocus();
1884 }
1885 }
1886
1887 void KDiff3App::slotWinToggleSplitterOrientation()
1888 {
1889 if ( m_pDiffWindowSplitter!=0 )
1890 {
1891 m_pDiffWindowSplitter->setOrientation(
1892 m_pDiffWindowSplitter->orientation()==Vertical ? Horizontal : Vertical
1893 );
1894 }
1895 }
1896
1897 void KDiff3App::slotUpdateAvailabilities()
1898 {
1899 bool bTextDataAvailable = (m_sd1.m_pBuf != 0 || m_sd2.m_pBuf != 0 || m_sd3.m_pBuf != 0 );
1900 if( dirShowBoth->isChecked() )
1901 {
1902 if ( m_bDirCompare )
1903 m_pDirectoryMergeSplitter->show();
1904 else
1905 m_pDirectoryMergeSplitter->hide();
1906
1907 if ( m_pMainWidget!=0 && !m_pMainWidget->isVisible() &&
1908 bTextDataAvailable
1909 )
1910 m_pMainWidget->show();
1911 }
1912
1913 bool bDiffWindowVisible = m_pMainWidget != 0 && m_pMainWidget->isVisible();
1914 bool bMergeEditorVisible = m_pMergeWindowFrame !=0 && m_pMergeWindowFrame->isVisible();
1915
1916 dirStartOperation->setEnabled( m_bDirCompare );
1917 dirFoldAll->setEnabled( m_bDirCompare );
1918 dirUnfoldAll->setEnabled( m_bDirCompare );
1919
1920 dirCompareCurrent->setEnabled( m_bDirCompare && m_pDirectoryMergeWindow->isVisible() && m_pDirectoryMergeWindow->isFileSelected() );
1921
1922 dirMergeCurrent->setEnabled( m_bDirCompare && m_pDirectoryMergeWindow->isVisible() && m_pDirectoryMergeWindow->isFileSelected()
1923 || bDiffWindowVisible );
1924
1925 dirShowBoth->setEnabled( m_bDirCompare );
1926
1927 dirRescan->setEnabled( m_bDirCompare );
1928
1929 dirViewToggle->setEnabled(
1930 m_bDirCompare &&
1931 (!m_pDirectoryMergeSplitter->isVisible() && m_pMainWidget!=0 && m_pMainWidget->isVisible() ||
1932 m_pDirectoryMergeSplitter->isVisible() && m_pMainWidget!=0 && !m_pMainWidget->isVisible() && bTextDataAvailable )
1933 );
1934
1935 dirAutoChoiceEverywhere->setEnabled( m_bDirCompare && m_pDirectoryMergeWindow->isVisible() );
1936 dirDoNothingEverywhere->setEnabled( m_bDirCompare && m_pDirectoryMergeWindow->isVisible() );
1937 dirChooseAEverywhere->setEnabled( m_bDirCompare && m_pDirectoryMergeWindow->isVisible() );
1938 dirChooseBEverywhere->setEnabled( m_bDirCompare && m_pDirectoryMergeWindow->isVisible() );
1939 dirChooseCEverywhere->setEnabled( m_bDirCompare && m_pDirectoryMergeWindow->isVisible() );
1940
1941 showWhiteSpace->setEnabled( bDiffWindowVisible );
1942 autoAdvance->setEnabled( bMergeEditorVisible );
1943 autoSolve->setEnabled( bMergeEditorVisible && m_bTripleDiff );
1944 unsolve->setEnabled( bMergeEditorVisible );
1945 chooseA->setEnabled( bMergeEditorVisible );
1946 chooseB->setEnabled( bMergeEditorVisible );
1947 chooseC->setEnabled( bMergeEditorVisible && m_bTripleDiff );
1948 chooseAEverywhere->setEnabled( bMergeEditorVisible );
1949 chooseBEverywhere->setEnabled( bMergeEditorVisible );
1950 chooseCEverywhere->setEnabled( bMergeEditorVisible && m_bTripleDiff );
1951 showWindowA->setEnabled( bDiffWindowVisible && ( m_pDiffTextWindow2->isVisible() || m_pDiffTextWindow3->isVisible() ) );
1952 showWindowB->setEnabled( bDiffWindowVisible && ( m_pDiffTextWindow1->isVisible() || m_pDiffTextWindow3->isVisible() ));
1953 showWindowC->setEnabled( bDiffWindowVisible && m_bTripleDiff && ( m_pDiffTextWindow1->isVisible() || m_pDiffTextWindow2->isVisible() ) );
1954 editFind->setEnabled( bDiffWindowVisible );
1955 editFindNext->setEnabled( bDiffWindowVisible );
1956 m_pFindDialog->m_pSearchInC->setEnabled( m_bTripleDiff );
1957 m_pFindDialog->m_pSearchInOutput->setEnabled( bMergeEditorVisible );
1958
1959 bool bSavable = bMergeEditorVisible && m_pMergeResultWindow->getNrOfUnsolvedConflicts()==0;
1960 fileSave->setEnabled( m_bOutputModified && bSavable );
1961 fileSaveAs->setEnabled( bSavable );
1962
1963 goTop->setEnabled( bDiffWindowVisible && m_pMergeResultWindow->isDeltaAboveCurrent() );
1964 goBottom->setEnabled( bDiffWindowVisible && m_pMergeResultWindow->isDeltaBelowCurrent() );
1965 goCurrent->setEnabled( bDiffWindowVisible );
1966 goPrevUnsolvedConflict->setEnabled( bMergeEditorVisible && m_pMergeResultWindow->isUnsolvedConflictAboveCurrent() );
1967 goNextUnsolvedConflict->setEnabled( bMergeEditorVisible && m_pMergeResultWindow->isUnsolvedConflictBelowCurrent() );
1968 goPrevConflict->setEnabled( bDiffWindowVisible && m_pMergeResultWindow->isConflictAboveCurrent() );
1969 goNextConflict->setEnabled( bDiffWindowVisible && m_pMergeResultWindow->isConflictBelowCurrent() );
1970 goPrevDelta->setEnabled( bDiffWindowVisible && m_pMergeResultWindow->isDeltaAboveCurrent() );
1971 goNextDelta->setEnabled( bDiffWindowVisible && m_pMergeResultWindow->isDeltaBelowCurrent() );
1972
1973 winToggleSplitOrientation->setEnabled( bDiffWindowVisible && m_pDiffWindowSplitter!=0 );
1974 }