KDevelop API Documentation

diffpart.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2001 by Harald Fernengel                                *
00003  *   harry@kdevelop.org                                                    *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU General Public License as published by  *
00007  *   the Free Software Foundation; either version 2 of the License, or     *
00008  *   (at your option) any later version.                                   *
00009  *                                                                         *
00010  ***************************************************************************/
00011 
00012 #include <sys/stat.h>
00013 
00014 #include <qwhatsthis.h>
00015 #include <qpopupmenu.h>
00016 
00017 #include <klocale.h>
00018 #include <kdevgenericfactory.h>
00019 #include <kaction.h>
00020 #include <kfiledialog.h>
00021 #include <kprocess.h>
00022 #include <kio/jobclasses.h>
00023 #include <kio/job.h>
00024 #include <kparts/part.h>
00025 #include <ktexteditor/editinterface.h>
00026 #include <kmessagebox.h>
00027 #include <kdebug.h>
00028 #include <kiconloader.h>
00029 
00030 #include "kdevcore.h"
00031 #include "kdevmainwindow.h"
00032 #include "kdevpartcontroller.h"
00033 
00034 #include "diffpart.h"
00035 #include "diffdlg.h"
00036 #include "diffwidget.h"
00037 
00038 static const KAboutData data("kdevdiff", I18N_NOOP("Difference Viewer"), "1.0");
00039 
00040 typedef KDevGenericFactory<DiffPart> DiffFactory;
00041 K_EXPORT_COMPONENT_FACTORY( libkdevdiff, DiffFactory( &data ) )
00042 
00043 DiffPart::DiffPart(QObject *parent, const char *name, const QStringList &)
00044     : KDevDiffFrontend("Diff", "diff", parent, name ? name : "DiffPart"), proc(0)
00045 {
00046   setInstance(DiffFactory::instance());
00047   setXMLFile("kdevdiff.rc");
00048 
00049   diffWidget = new DiffWidget();
00050   diffWidget->setIcon( SmallIcon("editcopy") );
00051   QString nm( i18n( "Diff" ) );
00052   diffWidget->setCaption( i18n( "Diff Output" ) );
00053   QWhatsThis::add(diffWidget, i18n("<b>Difference viewer</b><p>Shows output of the diff format. "
00054     "Can utilize every installed component that is able to show diff output. "
00055     "For example if you have Kompare installed, Difference Viewer can use its graphical diff view."));
00056   mainWindow()->embedOutputView( diffWidget, nm, i18n("Output of the diff command") );
00057 
00058   KAction *action = new KAction( i18n("Difference Viewer..."), 0,
00059            this, SLOT(slotExecDiff()),
00060            actionCollection(), "tools_diff" );
00061   action->setToolTip(i18n("Difference viewer"));
00062   action->setWhatsThis(i18n("<b>Difference viewer</b><p>Shows the contents of a patch file."));
00063 
00064   connect( core(), SIGNAL(contextMenu(QPopupMenu *, const Context *)),
00065            this, SLOT(contextMenu(QPopupMenu *, const Context *)) );
00066 }
00067 
00068 static bool urlIsEqual(const KURL &a, const KURL &b)
00069 {
00070   if (a.isLocalFile() && b.isLocalFile())
00071   {
00072     struct stat aStat, bStat;
00073 
00074     if ((::stat(QFile::encodeName(a.fileName()), &aStat) == 0)
00075         && (::stat(QFile::encodeName(b.fileName()), &bStat) == 0))
00076     {
00077       return (aStat.st_dev == bStat.st_dev) && (aStat.st_ino == bStat.st_ino);
00078     }
00079   }
00080 
00081   return a == b;
00082 }
00083 
00084 static KParts::ReadWritePart* partForURL(const KURL &url, KDevPartController* pc)
00085 {
00086   if ( !pc )
00087     return 0;
00088   QPtrListIterator<KParts::Part> it(*(pc->parts()));
00089   for ( ; it.current(); ++it)
00090   {
00091     KParts::ReadWritePart *rw_part = dynamic_cast<KParts::ReadWritePart*>(it.current());
00092     if ( rw_part && dynamic_cast<KTextEditor::EditInterface*>(it.current()) && urlIsEqual(url, rw_part->url()) )
00093       return rw_part;
00094   }
00095 
00096   return 0;
00097 }
00098 
00099 void DiffPart::contextMenu( QPopupMenu* popup, const Context* context )
00100 {
00101     if ( context->hasType( Context::EditorContext ) )
00102     {
00103         const EditorContext *eContext = static_cast<const EditorContext*>(context);
00104         popupFile = eContext->url();
00105     }
00106     else if ( context->hasType( Context::FileContext ) )
00107     {
00108         const FileContext * fContext = static_cast<const FileContext*>( context );
00109         popupFile.setPath( fContext->fileName() );  //@fixme - assuming absolute path. is this correct?
00110     }
00111     else
00112     {
00113         return;
00114     }
00115 
00116     KParts::ReadWritePart* rw_part = partForURL( popupFile, partController() );
00117     if ( !rw_part ) return;
00118     
00119     if ( partController()->documentState( rw_part->url() ) != Clean )
00120     {
00121         int id = popup->insertItem( i18n( "Difference to Disk File" ),
00122                             this, SLOT(localDiff()) );
00123         popup->setWhatsThis(id, i18n("<b>Difference to disk file</b><p>Shows the difference between "
00124             "the file contents in this editor and the file contents on disk."));
00125     }
00126 }
00127 
00128 DiffPart::~DiffPart()
00129 {
00130   if ( diffWidget )
00131     mainWindow()->removeView( diffWidget );
00132 
00133   delete proc;
00134   delete (DiffWidget*) diffWidget;
00135 }
00136 
00137 void DiffPart::localDiff()
00138 {
00139   KParts::ReadWritePart* rw_part = partForURL( popupFile, partController() );
00140   if ( !rw_part )
00141     return;
00142 
00143   KTextEditor::EditInterface* editIface = dynamic_cast<KTextEditor::EditInterface*>(rw_part);
00144   if ( !editIface )
00145     return;
00146   buffer = editIface->text().local8Bit();
00147   resultBuffer = resultErr = QString::null;
00148 
00149   delete proc;
00150   proc = new KProcess();
00151 
00152   *proc << "diff";
00153   *proc << "-u" << popupFile.path() << "-";
00154   proc->setWorkingDirectory( popupFile.directory() );
00155 
00156   connect( proc, SIGNAL(processExited( KProcess* )),
00157            this, SLOT(processExited( KProcess* )) );
00158   connect( proc, SIGNAL(receivedStdout( KProcess*, char*, int )),
00159            this, SLOT(receivedStdout( KProcess*, char*, int )) );
00160   connect( proc, SIGNAL(receivedStderr( KProcess*, char*, int )),
00161            this, SLOT(receivedStderr( KProcess*, char*, int )) );
00162   connect( proc, SIGNAL(wroteStdin( KProcess* )),
00163            this, SLOT(wroteStdin( KProcess* )) );
00164 
00165   if ( !proc->start( KProcess::NotifyOnExit, KProcess::All ) ) {
00166     KMessageBox::error( 0, i18n( "Could not invoke the \"diff\" command." ) );
00167     delete proc;
00168     proc = 0;
00169     return;
00170   }
00171   proc->writeStdin( buffer.data(), buffer.length() );
00172 }
00173 
00174 void DiffPart::processExited( KProcess* p )
00175 {
00176   // diff has exit status 0 and 1 for success
00177   if ( p->normalExit() && ( p->exitStatus() == 0 || p->exitStatus() == 1 ) ) {
00178     if ( resultBuffer.isEmpty() )
00179       KMessageBox::information( 0, i18n("DiffPart: No differences found.") );
00180     else
00181       showDiff( resultBuffer );
00182   } else {
00183     KMessageBox::error( 0, i18n("Diff command failed (%1):\n").arg( p->exitStatus() ) + resultErr );
00184   }
00185   resultBuffer = resultErr = QString::null;
00186   delete proc;
00187   proc = 0;
00188 }
00189 
00190 void DiffPart::receivedStdout( KProcess* /* p */, char* buf, int buflen )
00191 {
00192   resultBuffer += QString::fromLocal8Bit( buf, buflen );
00193 }
00194 
00195 void DiffPart::receivedStderr( KProcess* /* p */, char* buf, int buflen )
00196 {
00197   kdDebug(9033) << "received Stderr: " << QString::fromLocal8Bit( buf, buflen ) << endl;
00198   resultErr += QString::fromLocal8Bit( buf, buflen );
00199 }
00200 
00201 void DiffPart::wroteStdin( KProcess* p )
00202 {
00203   buffer = 0L;
00204   p->closeStdin();
00205 }
00206 
00207 void DiffPart::openURL( const KURL& url )
00208 {
00209   diffWidget->slotClear();
00210   diffWidget->openURL( url );
00211   mainWindow()->raiseView( diffWidget );
00212 /*
00213   DiffDlg* diffDlg = new DiffDlg( 0, "diffDlg" );
00214 
00215   diffDlg->openURL( url );
00216   diffDlg->exec();
00217   delete diffDlg;
00218 */
00219 }
00220 
00221 void DiffPart::showDiff( const QString& diff )
00222 {
00223   diffWidget->slotClear();
00224   diffWidget->setDiff( diff );
00225   mainWindow()->raiseView( diffWidget );
00226 /*
00227   DiffDlg* diffDlg = new DiffDlg( 0, "diffDlg" );
00228 
00229   diffDlg->setDiff( diff );
00230   diffDlg->exec();
00231   delete diffDlg;
00232 */
00233 }
00234 
00235 void DiffPart::slotExecDiff()
00236 {
00237   KURL url = KFileDialog::getOpenURL( QString::null, QString::null, 0, i18n("Please Select Patch File") );
00238 
00239   if ( url.isEmpty() )
00240     return;
00241 
00242   openURL( url );
00243 }
00244 
00245 #include "diffpart.moc"
KDE Logo
This file is part of the documentation for KDevelop Version 3.1.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Feb 22 09:22:38 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003