23 #include <QtGui/QLayout>
24 #include <QtGui/QWidget>
27 #include <QPrintDialog>
28 #include <QPrintPreviewDialog>
30 #include <kaboutdata.h>
32 #include <kactioncollection.h>
33 #include <kapplication.h>
34 #include <kcomponentdata.h>
36 #include <kdeprintdialog.h>
37 #include <kfiledialog.h>
39 #include <kmessagebox.h>
40 #include <kstandardaction.h>
41 #include <kstandarddirs.h>
42 #include <kstandardshortcut.h>
43 #include <ktemporaryfile.h>
46 #include <kio/netaccess.h>
49 #include "diffmodel.h"
52 #include "diffsettings.h"
59 K_PLUGIN_FACTORY( KomparePartFactory, registerPlugin<KomparePart>(); )
60 K_EXPORT_PLUGIN( KomparePartFactory )
66 KParts::ReadWritePart(parent),
70 if( !m_viewSettings ) {
73 if( !m_diffSettings ) {
74 m_diffSettings =
new DiffSettings( 0 );
77 readProperties( KGlobal::config().data() );
79 m_view =
new KompareView ( m_viewSettings, parentWidget );
81 m_splitter = m_view->splitter();
84 m_modelList =
new Diff2::KompareModelList( m_diffSettings, m_splitter,
this,
"komparemodellist" , KParts::ReadWritePart::isReadWrite());
86 Q_FOREACH(
QAction* action, m_modelList->actionCollection()->actions())
88 actionCollection()->addAction(action->
objectName(), action);
90 connect( m_modelList, SIGNAL(status( Kompare::Status )),
91 this, SLOT(slotSetStatus( Kompare::Status )) );
92 connect( m_modelList, SIGNAL(setStatusBarModelInfo(
int,
int,
int,
int,
int )),
93 this, SIGNAL(setStatusBarModelInfo(
int,
int,
int,
int,
int )) );
94 connect( m_modelList, SIGNAL(error(
QString )),
95 this, SLOT(slotShowError(
QString )) );
96 connect( m_modelList, SIGNAL(applyAllDifferences(
bool )),
97 this, SLOT(updateActions()) );
98 connect( m_modelList, SIGNAL(applyDifference(
bool )),
99 this, SLOT(updateActions()) );
100 connect( m_modelList, SIGNAL(applyAllDifferences(
bool )),
101 this, SIGNAL(appliedChanged()) );
102 connect( m_modelList, SIGNAL(applyDifference(
bool )),
103 this, SIGNAL(appliedChanged()) );
104 connect( m_modelList, SIGNAL(updateActions()),
this, SLOT(updateActions()) );
107 connect( m_modelList, SIGNAL(modelsChanged(
const Diff2::DiffModelList*)),
108 this, SIGNAL(modelsChanged(
const Diff2::DiffModelList*)) );
110 connect( m_modelList, SIGNAL(setSelection(
const Diff2::DiffModel*,
const Diff2::Difference*)),
111 this, SIGNAL(setSelection(
const Diff2::DiffModel*,
const Diff2::Difference*)) );
112 connect(
this, SIGNAL(selectionChanged(
const Diff2::DiffModel*,
const Diff2::Difference*)),
113 m_modelList, SLOT(slotSelectionChanged(
const Diff2::DiffModel*,
const Diff2::Difference*)) );
115 connect( m_modelList, SIGNAL(setSelection(
const Diff2::Difference*)),
116 this, SIGNAL(setSelection(
const Diff2::Difference*)) );
117 connect(
this, SIGNAL(selectionChanged(
const Diff2::Difference*)),
118 m_modelList, SLOT(slotSelectionChanged(
const Diff2::Difference*)) );
120 connect( m_modelList, SIGNAL(applyDifference(
bool)),
121 this, SIGNAL(applyDifference(
bool)) );
122 connect( m_modelList, SIGNAL(applyAllDifferences(
bool)),
123 this, SIGNAL(applyAllDifferences(
bool)) );
124 connect( m_modelList, SIGNAL(applyDifference(
const Diff2::Difference*,
bool)),
125 this, SIGNAL(applyDifference(
const Diff2::Difference*,
bool)) );
126 connect( m_modelList, SIGNAL(diffString(
const QString&)),
127 this, SIGNAL(diffString(
const QString&)) );
129 connect(
this, SIGNAL(kompareInfo(Kompare::Info*)), m_modelList, SLOT(slotKompareInfo(Kompare::Info*)) );
132 connect( m_modelList, SIGNAL(setSelection(
const Diff2::DiffModel*,
const Diff2::Difference*)),
133 m_splitter, SLOT(slotSetSelection(
const Diff2::DiffModel*,
const Diff2::Difference*)) );
136 connect( m_modelList, SIGNAL(setSelection(
const Diff2::Difference*)),
137 m_splitter, SLOT(slotSetSelection(
const Diff2::Difference*)) );
138 connect( m_splitter, SIGNAL(selectionChanged(
const Diff2::Difference*)),
139 m_modelList, SLOT(slotSelectionChanged(
const Diff2::Difference*)) );
141 connect( m_modelList, SIGNAL(applyDifference(
bool)),
142 m_splitter, SLOT(slotApplyDifference(
bool)) );
143 connect( m_modelList, SIGNAL(applyAllDifferences(
bool)),
144 m_splitter, SLOT(slotApplyAllDifferences(
bool)) );
145 connect( m_modelList, SIGNAL(applyDifference(
const Diff2::Difference*,
bool)),
146 m_splitter, SLOT(slotApplyDifference(
const Diff2::Difference*,
bool)) );
147 connect(
this, SIGNAL(configChanged()), m_splitter, SIGNAL(configChanged()) );
152 setXMLFile(
"komparepartui.rc" );
156 setReadWrite(
true );
159 setModified(
false );
166 cleanUpTemporaryFiles();
169 void KomparePart::setupActions()
173 m_saveAll = actionCollection()->addAction(
"file_save_all",
this, SLOT(
saveAll()));
174 m_saveAll->setIcon(KIcon(
"document-save-all"));
175 m_saveAll->setText(i18n(
"Save &All"));
176 m_saveDiff = actionCollection()->addAction(
"file_save_diff",
this, SLOT(
saveDiff()));
177 m_saveDiff->setText(i18n(
"Save &Diff..."));
178 m_swap = actionCollection()->addAction(
"file_swap",
this, SLOT(
slotSwap()));
179 m_swap->setText(i18n(
"Swap Source with Destination"));
180 m_diffStats = actionCollection()->addAction(
"file_diffstats",
this, SLOT(
slotShowDiffstats()));
181 m_diffStats->setText(i18n(
"Show Statistics"));
182 m_diffRefresh = actionCollection()->addAction(
"file_refreshdiff",
this, SLOT(
slotRefreshDiff()));
183 m_diffRefresh->setIcon(KIcon(
"view-refresh"));
184 m_diffRefresh->setText(i18n(
"Refresh Diff"));
185 m_diffRefresh->setShortcut(KStandardShortcut::reload());
187 m_print = actionCollection()->addAction(KStandardAction::Print,
this, SLOT(
slotFilePrint() ));
188 m_printPreview = actionCollection()->addAction(KStandardAction::PrintPreview,
this, SLOT(
slotFilePrintPreview() ));
194 m_saveAll->setEnabled ( m_modelList->hasUnsavedChanges() );
195 m_saveDiff->setEnabled ( m_modelList->mode() == Kompare::ComparingFiles || m_modelList->mode() == Kompare::ComparingDirs );
196 m_swap->setEnabled ( m_modelList->mode() == Kompare::ComparingFiles || m_modelList->mode() == Kompare::ComparingDirs );
197 m_diffRefresh->setEnabled ( m_modelList->mode() == Kompare::ComparingFiles || m_modelList->mode() == Kompare::ComparingDirs );
198 m_diffStats->setEnabled ( m_modelList->modelCount() > 0 );
199 m_print->setEnabled ( m_modelList->modelCount() > 0 );
200 m_printPreview->setEnabled( m_modelList );
205 kDebug(8103) <<
"Encoding: " << encoding << endl;
206 m_modelList->setEncoding( encoding );
211 kDebug(8103) <<
"Url = " << url.url() << endl;
213 m_info.mode = Kompare::ShowingDiff;
216 fetchURL( url,
true );
220 if ( !m_info.localSource.isEmpty() )
222 kDebug(8103) <<
"Download succeeded " << endl;
223 result = m_modelList->openDiff( m_info.localSource );
230 kDebug(8103) <<
"Download failed !" << endl;
240 m_info.mode = Kompare::ShowingDiff;
244 if ( m_modelList->parseAndOpenDiff( diffOutput ) == 0 )
258 kDebug(8103) <<
"Not implemented yet. Filename is: " << diff3Url.prettyUrl() << endl;
265 kDebug(8103) <<
"Not implemented yet. diff3 output is: " << endl;
266 kDebug(8103) << diff3Output << endl;
270 bool KomparePart::exists(
const QString& url )
276 bool KomparePart::fetchURL(
const KUrl& url,
bool addToSource )
282 KTempDir* tmpDir = 0;
284 if ( !url.isLocalFile() )
287 KIO::NetAccess::stat( url, node, widget() );
290 if ( ! KIO::NetAccess::download( url, tempFileName, widget() ) )
292 slotShowError( i18n(
"<qt>The URL <b>%1</b> cannot be downloaded.</qt>", url.prettyUrl() ) );
299 tmpDir =
new KTempDir(KStandardDirs::locateLocal(
"tmp",
"kompare"));
300 tmpDir->setAutoRemove(
true );
301 if ( ! KIO::NetAccess::dircopy( url, KUrl( tmpDir->name() ), widget() ) )
303 slotShowError( i18n(
"<qt>The URL <b>%1</b> cannot be downloaded.</qt>", url.prettyUrl() ) );
310 tempFileName = tmpDir->name();
311 kDebug(8101) <<
"tempFileName = " << tempFileName << endl;
314 QDir dir( tempFileName );
315 QStringList entries = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot );
316 if ( entries.
size() == 1 )
318 if ( !tempFileName.endsWith(
'/' ) )
320 tempFileName += entries.
at( 0 );
325 kDebug(8101) <<
"Yikes, nothing downloaded?" << endl;
337 if ( exists( url.toLocalFile() ) )
338 tempFileName = url.toLocalFile();
341 slotShowError( i18n(
"<qt>The URL <b>%1</b> does not exist on your system.</qt>", url.prettyUrl() ) );
348 m_info.localSource = tempFileName;
349 m_info.sourceKTempDir = tmpDir;
353 m_info.localDestination = tempFileName;
354 m_info.destinationKTempDir = tmpDir;
360 void KomparePart::cleanUpTemporaryFiles()
362 kDebug(8101) <<
"Cleaning temporary files." << endl;
363 if ( !m_info.localSource.isEmpty() )
365 if ( m_info.sourceKTempDir == 0 )
366 KIO::NetAccess::removeTempFile( m_info.localSource );
369 delete m_info.sourceKTempDir;
370 m_info.sourceKTempDir = 0;
372 m_info.localSource =
"";
374 if ( !m_info.localDestination.isEmpty() )
376 if ( m_info.destinationKTempDir == 0 )
377 KIO::NetAccess::removeTempFile( m_info.localDestination );
380 delete m_info.destinationKTempDir;
381 m_info.destinationKTempDir = 0;
383 m_info.localDestination =
"";
393 m_info.source = source;
394 m_info.destination = destination;
398 fetchURL( source,
true );
399 fetchURL( destination,
false );
409 m_info.mode = Kompare::ComparingFileString;
411 m_info.source = sourceFile;
412 m_info.localDestination = destination;
414 fetchURL(sourceFile,
true);
424 m_info.mode = Kompare::ComparingStringFile;
426 m_info.localSource = source;
427 m_info.destination = destinationFile;
429 fetchURL(destinationFile,
false);
438 m_info.mode = Kompare::ComparingFiles;
440 m_info.source = sourceFile;
441 m_info.destination = destinationFile;
445 fetchURL( sourceFile,
true );
446 fetchURL( destinationFile,
false );
455 m_info.mode = Kompare::ComparingDirs;
457 m_info.source = sourceDirectory;
458 m_info.destination = destinationDirectory;
460 fetchURL( sourceDirectory,
true );
461 fetchURL( destinationDirectory,
false );
478 m_info.source = file;
479 m_info.destination = diffFile;
481 fetchURL( file,
true );
482 fetchURL( diffFile,
false );
483 m_info.mode = Kompare::BlendingFile;
493 m_info.destination = diffFile;
495 fetchURL( dir,
true );
496 fetchURL( diffFile,
false );
497 m_info.mode = Kompare::BlendingDir;
501 if ( !m_info.localSource.isEmpty() && !m_info.localDestination.isEmpty() )
503 m_modelList->openDirAndDiff();
521 bool result = m_modelList->saveAll();
530 KDialog dlg( widget() );
531 dlg.setObjectName(
"save_options" );
532 dlg.setModal(
true );
533 dlg.setWindowTitle( i18n(
"Diff Options") );
534 dlg.setButtons( KDialog::Ok|KDialog::Cancel );
537 m_info.localDestination,
538 m_diffSettings, &dlg );
539 dlg.setMainWidget( w );
540 dlg.setButtonGuiItem( KDialog::Ok, KStandardGuiItem::save() );
544 KSharedConfig::Ptr config = componentData().config();
550 KUrl url = KFileDialog::getSaveUrl( m_info.destination.url(),
551 i18n(
"*.diff *.dif *.patch|Patch Files"), widget(), i18n(
"Save .diff" ) );
552 if ( KIO::NetAccess::exists( url, KIO::NetAccess::DestinationSide, widget() ) )
554 int result = KMessageBox::warningYesNoCancel( widget(), i18n(
"The file exists or is write-protected; do you want to overwrite it?"), i18n(
"File Exists"), KGuiItem(i18n(
"Overwrite")), KGuiItem(i18n(
"Do Not Overwrite")) );
555 if ( result == KMessageBox::Cancel )
559 else if ( result == KMessageBox::No )
565 kDebug(8103) <<
"URL = " << url.prettyUrl() << endl;
566 kDebug(8103) <<
"Directory = " << w->
directory() << endl;
567 kDebug(8103) <<
"DiffSettings = " << m_diffSettings << endl;
569 m_modelList->saveDiff( url.url(), w->
directory(), m_diffSettings );
575 kDebug(8103) <<
"URL = " << url.prettyUrl() << endl;
576 kDebug(8103) <<
"Directory = " << w->
directory() << endl;
577 kDebug(8103) <<
"DiffSettings = " << m_diffSettings << endl;
579 m_modelList->saveDiff( url.url(), w->
directory(), m_diffSettings );
590 QPrintDialog* dlg = KdePrint::createPrintDialog( &printer, m_splitter );
592 if ( dlg->
exec() == QDialog::Accepted )
614 kDebug(8103) <<
"Now paint something..." << endl;
619 kDebug(8103) <<
"printer.width() = " << printer->
width() << endl;
620 kDebug(8103) <<
"widgetWidth.width() = " << widgetWidth.
width() << endl;
621 qreal factor = ((qreal)printer->
width())/((qreal)widgetWidth.
width());
623 kDebug(8103) <<
"factor = " << factor << endl;
625 p.
scale( factor, factor );
629 kDebug(8103) <<
"Done painting something..." << endl;
634 KAboutData *about =
new KAboutData(
"kompare", 0, ki18n(
"KomparePart"),
"4.0");
635 about->addAuthor(ki18n(
"John Firebaugh"), ki18n(
"Author"),
"jfirebaugh@kde.org");
636 about->addAuthor(ki18n(
"Otto Bruggeman"), ki18n(
"Author"),
"bruggie@gmail.com" );
637 about->addAuthor(ki18n(
"Kevin Kofler"), ki18n(
"Author"),
"kevin.kofler@chello.at" );
646 case Kompare::RunningDiff:
647 emit setStatusBarText( i18n(
"Running diff..." ) );
649 case Kompare::Parsing:
650 emit setStatusBarText( i18n(
"Parsing diff output..." ) );
652 case Kompare::FinishedParsing:
655 case Kompare::FinishedWritingDiff:
666 QString source = m_info.source.prettyUrl();
667 QString destination = m_info.destination.prettyUrl();
671 switch ( m_info.mode )
673 case Kompare::ComparingFiles :
674 case Kompare::ComparingDirs :
675 case Kompare::BlendingFile :
676 case Kompare::BlendingDir :
677 text = source +
" -- " + destination;
679 case Kompare::ShowingDiff :
686 emit setWindowCaption( text );
691 QString source = m_info.source.prettyUrl();
692 QString destination = m_info.destination.prettyUrl();
696 switch ( m_info.mode )
698 case Kompare::ComparingFiles :
699 text = i18n(
"Comparing file %1 with file %2" ,
703 case Kompare::ComparingDirs :
704 text = i18n(
"Comparing files in %1 with files in %2" ,
708 case Kompare::ShowingDiff :
709 text = i18n(
"Viewing diff output from %1", source );
711 case Kompare::BlendingFile :
712 text = i18n(
"Blending diff output from %1 into file %2" ,
716 case Kompare::BlendingDir :
717 text = i18n(
"Blending diff output from %1 into folder %2" ,
718 m_info.source.prettyUrl() ,
719 m_info.destination.prettyUrl() );
725 emit setStatusBarText( text );
730 if ( !m_info.localSource.isEmpty() && !m_info.localDestination.isEmpty() )
735 case Kompare::UnknownMode:
736 m_modelList->compare();
739 case Kompare::ComparingStringFile:
740 case Kompare::ComparingFileString:
741 case Kompare::ComparingFiles:
742 case Kompare::ComparingDirs:
743 m_modelList->compare(m_info.mode);
746 case Kompare::BlendingFile:
747 m_modelList->openFileAndDiff();
758 KMessageBox::error( widget(), error );
763 if ( m_modelList->hasUnsavedChanges() )
765 int query = KMessageBox::warningYesNoCancel
768 i18n(
"You have made changes to the destination file(s).\n"
769 "Would you like to save them?" ),
770 i18n(
"Save Changes?" ),
771 KStandardGuiItem::save(),
772 KStandardGuiItem::discard()
775 if ( query == KMessageBox::Yes )
776 m_modelList->saveAll();
778 if ( query == KMessageBox::Cancel )
783 m_info.swapSourceWithDestination();
794 if ( m_modelList->hasUnsavedChanges() )
796 int query = KMessageBox::warningYesNoCancel
799 i18n(
"You have made changes to the destination file(s).\n"
800 "Would you like to save them?" ),
801 i18n(
"Save Changes?" ),
802 KStandardGuiItem::save(),
803 KStandardGuiItem::discard()
806 if ( query == KMessageBox::Cancel )
809 if ( query == KMessageBox::Yes )
810 m_modelList->saveAll();
814 cleanUpTemporaryFiles();
815 fetchURL( m_info.source,
true );
816 fetchURL( m_info.destination,
false );
817 m_modelList->refresh();
832 oldFile = m_modelList->selectedModel() ? m_modelList->selectedModel()->sourceFile() :
QString(
"" );
833 newFile = m_modelList->selectedModel() ? m_modelList->selectedModel()->destinationFile() :
QString(
"" );
835 if ( m_modelList->selectedModel() )
837 switch( m_info.format ) {
838 case Kompare::Unified :
839 diffFormat = i18n(
"Unified" );
841 case Kompare::Context :
842 diffFormat = i18n(
"Context" );
845 diffFormat = i18n(
"RCS" );
848 diffFormat = i18n(
"Ed" );
850 case Kompare::Normal :
851 diffFormat = i18n(
"Normal" );
853 case Kompare::UnknownFormat :
855 diffFormat = i18n(
"Unknown" );
864 filesInDiff = m_modelList->modelCount();
866 noOfHunks = m_modelList->selectedModel() ? m_modelList->selectedModel()->hunkCount() : 0;
867 noOfDiffs = m_modelList->selectedModel() ? m_modelList->selectedModel()->differenceCount() : 0;
869 if ( m_modelList->modelCount() == 0 ) {
870 KMessageBox::information( 0L, i18n(
871 "No diff file, or no 2 files have been diffed. "
872 "Therefore no stats are available."),
873 i18n(
"Diff Statistics"),
QString(), 0 );
875 else if ( m_modelList->modelCount() == 1 ) {
876 KMessageBox::information( 0L, i18n(
883 "Number of hunks: %4\n"
884 "Number of differences: %5",
885 oldFile, newFile, diffFormat,
886 noOfHunks, noOfDiffs),
887 i18n(
"Diff Statistics"),
QString(), 0 );
889 KMessageBox::information( 0L, ki18n(
892 "Number of files in diff file: %1\n"
895 "Current old file: %3\n"
896 "Current new file: %4\n"
898 "Number of hunks: %5\n"
899 "Number of differences: %6")
900 .subs(filesInDiff).subs(diffFormat).subs(oldFile)
901 .subs(newFile).subs(noOfHunks).subs(noOfDiffs)
903 i18n(
"Diff Statistics"),
QString(), 0 );
909 if ( !m_modelList->hasUnsavedChanges() )
return true;
911 int query = KMessageBox::warningYesNoCancel
914 i18n(
"You have made changes to the destination file(s).\n"
915 "Would you like to save them?" ),
916 i18n(
"Save Changes?" ),
917 KStandardGuiItem::save(),
918 KStandardGuiItem::discard()
921 if( query == KMessageBox::Cancel )
924 if( query == KMessageBox::Yes )
925 return m_modelList->saveAll();
933 m_diffSettings->loadSettings( config );
941 m_diffSettings->saveSettings( config );
956 #include "kompare_part.moc"
static KAboutData * createAboutData()
virtual void setEncoding(const QString &encoding)
Reimplementing this because this one knows more about the real part then the interface.
void scale(qreal sx, qreal sy)
void compareAndUpdateAll()
const T & at(int i) const
virtual bool openDiff(const KUrl &diffUrl)
Open and parse the diff file at diffUrl.
virtual bool openFile()
This is the method that gets called when the file is opened, when using openURL( const KUrl& ) or in ...
void slotFilePrintPreview()
virtual void openFileAndDiff(const KUrl &file, const KUrl &diffFile)
This will show the file and the file with the diff applied.
virtual ~KomparePart()
Destructor.
virtual int readProperties(KConfig *config)
Warning this should be in class Part in KDE 4.0, not here ! Around that time the methods will disappe...
virtual void compareFiles(const KUrl &sourceFile, const KUrl &destinationFile)
Compare, with diff, source with destination.
void slotSetStatus(Kompare::Status status)
virtual void loadSettings(KConfig *config)
void optionsPreferences()
virtual void compareFileString(const KUrl &sourceFile, const QString &destination)
Compare a Source file to a custom Destination string.
virtual void compare(const KUrl &sourceFile, const KUrl &destinationFile)
Compare, with diff, source with destination.
virtual void compareStringFile(const QString &source, const KUrl &destinationFile)
Compare a custom Source string to a Destination file.
void slotPaintRequested(QPrinter *)
void setOrientation(Orientation orientation)
virtual void compare3Files(const KUrl &originalFile, const KUrl &changedFile1, const KUrl &changedFile2)
Compare, with diff3, originalFile with changedFile1 and changedFile2.
virtual bool queryClose()
Warning this should be in class ReadWritePart in KDE 4.0, not here ! Around that time the method will...
void slotShowError(QString error)
void slotFilePrint()
To enable printing, the part has the only interesting printable content so putting it here...
virtual void compareDirs(const KUrl &sourceDir, const KUrl &destinationDir)
Compare, with diff, source with destination.
virtual void saveSettings(KConfig *config)
void saveDiff()
Save the results of a comparison as a diff file.
virtual int saveProperties(KConfig *config)
virtual void openDirAndDiff(const KUrl &dir, const KUrl &diffFile)
This will show the directory and the directory with the diff applied.
bool begin(QPaintDevice *device)
bool saveAll()
Save all destinations.
void kompareInfo(Kompare::Info *info)
virtual bool openDiff3(const KUrl &diff3URL)
Open and parse the diff3 file at diff3Url.