/*************************************************************************** * Copyright (C) 2001 by Harald Fernengel * * harry@kdevelop.org * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "diffpart.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kdevcore.h" #include "kdevmainwindow.h" #include "kdevpartcontroller.h" #include "kdevplugininfo.h" #include "diffdlg.h" #include "diffwidget.h" static const KDevPluginInfo data("kdevdiff"); typedef KDevGenericFactory DiffFactory; K_EXPORT_COMPONENT_FACTORY( libkdevdiff, DiffFactory( data ) ) DiffPart::DiffPart(TQObject *parent, const char *name, const TQStringList &) : KDevDiffFrontend(&data, parent, name ? name : "DiffPart"), proc(0) { setInstance(DiffFactory::instance()); setXMLFile("kdevdiff.rc"); diffWidget = new DiffWidget(this, 0, "diffWidget"); diffWidget->setIcon( SmallIcon("edit-copy") ); TQString nm( i18n( "Diff" ) ); diffWidget->setCaption( i18n( "Diff Output" ) ); TQWhatsThis::add(diffWidget, i18n("Difference viewer

Shows output of the diff format. " "Can utilize every installed component that is able to show diff output. " "For example if you have Kompare installed, Difference Viewer can use its graphical diff view.")); mainWindow()->embedOutputView( diffWidget, nm, i18n("Output of the diff command") ); mainWindow()->setViewAvailable( diffWidget, false ); TDEAction *action = new TDEAction( i18n("Difference Viewer..."), 0, this, TQT_SLOT(slotExecDiff()), actionCollection(), "tools_diff" ); action->setToolTip(i18n("Difference viewer")); action->setWhatsThis(i18n("Difference viewer

Shows the contents of a patch file.")); connect( core(), TQT_SIGNAL(contextMenu(TQPopupMenu *, const Context *)), this, TQT_SLOT(contextMenu(TQPopupMenu *, const Context *)) ); } static bool urlIsEqual(const KURL &a, const KURL &b) { if (a.isLocalFile() && b.isLocalFile()) { struct stat aStat, bStat; if ((::stat(TQFile::encodeName(a.fileName()), &aStat) == 0) && (::stat(TQFile::encodeName(b.fileName()), &bStat) == 0)) { return (aStat.st_dev == bStat.st_dev) && (aStat.st_ino == bStat.st_ino); } } return a == b; } static KParts::ReadWritePart* partForURL(const KURL &url, KDevPartController* pc) { if ( !pc ) return 0; TQPtrListIterator it(*(pc->parts())); for ( ; it.current(); ++it) { KParts::ReadWritePart *rw_part = dynamic_cast(it.current()); if ( rw_part && dynamic_cast(it.current()) && urlIsEqual(url, rw_part->url()) ) return rw_part; } return 0; } void DiffPart::contextMenu( TQPopupMenu* popup, const Context* context ) { if ( context->hasType( Context::EditorContext ) ) { const EditorContext *eContext = static_cast(context); popupFile = eContext->url(); } else if ( context->hasType( Context::FileContext ) ) { const FileContext * fContext = static_cast( context ); popupFile.setPath( fContext->urls().first().fileName() ); //@fixme - assuming absolute path. is this correct? } else { return; } KParts::ReadWritePart* rw_part = partForURL( popupFile, partController() ); if ( !rw_part ) return; if ( partController()->documentState( rw_part->url() ) != Clean ) { int id = popup->insertItem( i18n( "Difference to Disk File" ), this, TQT_SLOT(localDiff()) ); popup->TQMenuData::setWhatsThis(id, i18n("Difference to disk file

Shows the difference between " "the file contents in this editor and the file contents on disk.")); } } DiffPart::~DiffPart() { if ( diffWidget ) mainWindow()->removeView( diffWidget ); delete proc; delete (DiffWidget*) diffWidget; } void DiffPart::localDiff() { KParts::ReadWritePart* rw_part = partForURL( popupFile, partController() ); if ( !rw_part ) return; KTextEditor::EditInterface* editIface = dynamic_cast(rw_part); if ( !editIface ) return; buffer = editIface->text().local8Bit(); resultBuffer = resultErr = TQString(); delete proc; proc = new TDEProcess(); *proc << "diff"; *proc << "-u" << popupFile.path() << "-"; proc->setWorkingDirectory( popupFile.directory() ); connect( proc, TQT_SIGNAL(processExited( TDEProcess* )), this, TQT_SLOT(processExited( TDEProcess* )) ); connect( proc, TQT_SIGNAL(receivedStdout( TDEProcess*, char*, int )), this, TQT_SLOT(receivedStdout( TDEProcess*, char*, int )) ); connect( proc, TQT_SIGNAL(receivedStderr( TDEProcess*, char*, int )), this, TQT_SLOT(receivedStderr( TDEProcess*, char*, int )) ); connect( proc, TQT_SIGNAL(wroteStdin( TDEProcess* )), this, TQT_SLOT(wroteStdin( TDEProcess* )) ); if ( !proc->start( TDEProcess::NotifyOnExit, TDEProcess::All ) ) { KMessageBox::error( 0, i18n( "Could not invoke the \"diff\" command." ) ); delete proc; proc = 0; return; } proc->writeStdin( buffer.data(), buffer.length() ); } void DiffPart::processExited( TDEProcess* p ) { // diff has exit status 0 and 1 for success if ( p->normalExit() && ( p->exitStatus() == 0 || p->exitStatus() == 1 ) ) { if ( resultBuffer.isEmpty() ) KMessageBox::information( 0, i18n("DiffPart: No differences found.") ); else showDiff( resultBuffer ); } else { KMessageBox::error( 0, i18n("Diff command failed (%1):\n").arg( p->exitStatus() ) + resultErr ); } resultBuffer = resultErr = TQString(); delete proc; proc = 0; } void DiffPart::receivedStdout( TDEProcess* /* p */, char* buf, int buflen ) { resultBuffer += TQString::fromLocal8Bit( buf, buflen ); } void DiffPart::receivedStderr( TDEProcess* /* p */, char* buf, int buflen ) { kdDebug(9033) << "received Stderr: " << TQString(TQString::fromLocal8Bit( buf, buflen )).ascii() << endl; resultErr += TQString::fromLocal8Bit( buf, buflen ); } void DiffPart::wroteStdin( TDEProcess* p ) { buffer = 0L; p->closeStdin(); } void DiffPart::openURL( const KURL& url ) { diffWidget->slotClear(); diffWidget->openURL( url ); mainWindow()->raiseView( diffWidget ); /* DiffDlg* diffDlg = new DiffDlg( 0, "diffDlg" ); diffDlg->openURL( url ); diffDlg->exec(); delete diffDlg; */ } void DiffPart::showDiff( const TQString& diff ) { diffWidget->slotClear(); diffWidget->setDiff( diff ); mainWindow()->setViewAvailable( diffWidget, true ); mainWindow()->raiseView( diffWidget ); /* DiffDlg* diffDlg = new DiffDlg( 0, "diffDlg" ); diffDlg->setDiff( diff ); diffDlg->exec(); delete diffDlg; */ } void DiffPart::slotExecDiff() { KURL url = KFileDialog::getOpenURL( TQString(), TQString(), 0, i18n("Please Select Patch File") ); if ( url.isEmpty() ) return; openURL( url ); } #include "diffpart.moc"