KDevelop API Documentation

diffwidget.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 <qlayout.h>
00013 #include <qtextedit.h>
00014 #include <qpopupmenu.h>
00015 #include <qcursor.h>
00016 #include <qfile.h>
00017 
00018 #include <kconfig.h>
00019 #include <kapplication.h>
00020 #include <klocale.h>
00021 #include <kservice.h>
00022 #include <ktempfile.h>
00023 #include <kpopupmenu.h>
00024 #include <kiconloader.h>
00025 #include <kfiledialog.h>
00026 #include <kmessagebox.h>
00027 
00028 #include <kparts/componentfactory.h>
00029 #include <kparts/part.h>
00030 
00031 #include <kio/jobclasses.h>
00032 #include <kio/job.h>
00033 
00034 #include "diffwidget.h"
00035 
00036 // yup, magic value for the popupmenu-id
00037 static const int POPUP_BASE = 130977;
00038 
00039 QStringList KDiffTextEdit::extParts;
00040 QStringList KDiffTextEdit::extPartsTranslated;
00041 
00042 KDiffTextEdit::KDiffTextEdit( QWidget* parent, const char* name ): QTextEdit( parent, name )
00043 {
00044   KConfig* config = kapp->config();
00045   config->setGroup( "Diff" );
00046   _highlight = config->readBoolEntry( "Highlight", true );
00047 
00048   searchExtParts();
00049 }
00050 
00051 KDiffTextEdit::~KDiffTextEdit()
00052 {
00053   KConfig* config = kapp->config();
00054 
00055   config->setGroup( "Diff" );
00056   config->writeEntry( "Highlight", _highlight );
00057 }
00058 
00059 QPopupMenu* KDiffTextEdit::createPopupMenu()
00060 {
00061   return createPopupMenu( QPoint() );
00062 }
00063 
00064 QPopupMenu* KDiffTextEdit::createPopupMenu( const QPoint& p )
00065 {
00066   QPopupMenu* popup = QTextEdit::createPopupMenu( p );
00067   if ( !popup )
00068     popup = new QPopupMenu( this );
00069 
00070   int i = 0;
00071 
00072   for ( QStringList::Iterator it = extPartsTranslated.begin(); it != extPartsTranslated.end(); ++it ) {
00073     popup->insertItem( i18n( "Show in %1" ).arg( *it ), i + POPUP_BASE, i );
00074     i++;
00075   }
00076   if ( !extPartsTranslated.isEmpty() )
00077     popup->insertSeparator( i );
00078   connect( popup, SIGNAL(activated(int)), this, SLOT(popupActivated(int)) );
00079 
00080   popup->insertItem( SmallIconSet( "filesaveas" ), i18n( "&Save As..." ), this, SLOT(saveAs()), CTRL + Key_S, POPUP_BASE - 2, 0 );
00081   popup->setItemEnabled( POPUP_BASE - 2, length() > 0 );
00082 
00083   popup->insertSeparator( 1 );
00084 
00085   popup->insertItem( i18n( "Highlight Syntax" ), this, SLOT(toggleSyntaxHighlight()), 0, POPUP_BASE - 1, 2 );
00086   popup->setItemChecked( POPUP_BASE - 1, _highlight );
00087   popup->insertSeparator( 3 );
00088 
00089   return popup;
00090 }
00091 
00092 void KDiffTextEdit::saveAs()
00093 {
00094   QString fName = KFileDialog::getSaveFileName();
00095   if ( fName.isEmpty() )
00096     return;
00097 
00098   QFile f( fName );
00099   if ( f.open( IO_WriteOnly ) ) {
00100     QTextStream stream( &f );
00101     int pCount = paragraphs();
00102     for ( int i = 0; i < pCount; ++i )
00103       stream << text( i ) << "\n";
00104     f.close();
00105   } else {
00106     KMessageBox::sorry( 0, i18n("Unable to open file."), i18n("Diff Frontend") );
00107   }
00108 }
00109 
00110 void KDiffTextEdit::toggleSyntaxHighlight()
00111 {
00112   _highlight = !_highlight;
00113   if ( _highlight )
00114     applySyntaxHighlight();
00115   else
00116     clearSyntaxHighlight();
00117 }
00118 
00119 void KDiffTextEdit::applySyntaxHighlight()
00120 {
00121   // the diff has been loaded so we apply a simple highlighting
00122   static QColor cAdded( 190, 190, 237);
00123   static QColor cRemoved( 190, 237, 190 );
00124 
00125   if ( !_highlight )
00126     return;
00127 
00128   int paragCount = paragraphs();
00129   for ( int i = 0; i < paragCount; ++i ) {
00130     QString txt = text( i );
00131     if ( txt.length() > 0 ) {
00132       if ( txt.startsWith( "+" ) || txt.startsWith( ">" ) ) {
00133         setParagraphBackgroundColor( i, cAdded );
00134       } else if ( txt.startsWith( "-" ) || txt.startsWith( "<" ) ) {
00135         setParagraphBackgroundColor( i, cRemoved );
00136       }
00137     }
00138   }
00139 }
00140 
00141 void KDiffTextEdit::clearSyntaxHighlight()
00142 {
00143   int paragCount = paragraphs();
00144   for ( int i = 0; i < paragCount; ++i ) {
00145     clearParagraphBackground( i );
00146   }
00147 }
00148  
00149 void KDiffTextEdit::searchExtParts()
00150 {
00151   // only execute once
00152   static bool init = false;
00153   if ( init )
00154     return;
00155   init = true;
00156 
00157   // search all parts that can handle text/x-diff
00158   KTrader::OfferList offers = KTrader::self()->query("text/x-diff", "('KParts/ReadOnlyPart' in ServiceTypes) and ('text/x-diff' in ServiceTypes) and (DesktopEntryName != 'katepart')");
00159   KTrader::OfferList::const_iterator it;
00160   for ( it = offers.begin(); it != offers.end(); ++it ) {
00161     KService::Ptr ptr = (*it);
00162     extPartsTranslated << ptr->name();
00163     extParts << ptr->desktopEntryName();
00164   }
00165   return;
00166 }
00167 
00168 void KDiffTextEdit::popupActivated( int id )
00169 {
00170   id -= POPUP_BASE;
00171   if ( id < 0 || id > (int)extParts.count() )
00172     return;
00173 
00174   emit externalPartRequested( extParts[ id ] );
00175 }
00176 
00177 DiffWidget::DiffWidget( QWidget *parent, const char *name, WFlags f ):
00178     QWidget( parent, name, f ), tempFile( 0 )
00179 {
00180   job = 0;
00181   extPart = 0;
00182 
00183   te = new KDiffTextEdit( this, "Main Diff Viewer" );
00184   te->setReadOnly( true );
00185   te->setTextFormat( QTextEdit::PlainText );
00186 //  te->setMinimumSize( 300, 200 );
00187   connect( te, SIGNAL(externalPartRequested(const QString&)), this, SLOT(loadExtPart(const QString&)) );
00188 
00189   QVBoxLayout* layout = new QVBoxLayout( this );
00190   layout->addWidget( te );
00191 }
00192 
00193 DiffWidget::~DiffWidget()
00194 {
00195     delete tempFile;
00196 }
00197 
00198 void DiffWidget::setExtPartVisible( bool visible )
00199 {
00200   if ( !extPart || !extPart->widget() ) {
00201     te->show();
00202     return;
00203   }
00204   if ( visible ) {
00205     te->hide();
00206     extPart->widget()->show();
00207   } else {
00208     te->show();
00209     extPart->widget()->hide();
00210   }
00211 }
00212 
00213 void DiffWidget::loadExtPart( const QString& partName )
00214 {
00215   if ( extPart ) {
00216     setExtPartVisible( false );
00217     delete extPart;
00218     extPart = 0;
00219   }
00220 
00221   KService::Ptr extService = KService::serviceByDesktopName( partName );
00222   if ( !extService )
00223     return;
00224 
00225   extPart = KParts::ComponentFactory::createPartInstanceFromService<KParts::ReadOnlyPart>( extService, this, 0, this, 0 );
00226   if ( !extPart || !extPart->widget() )
00227     return;
00228 
00229   layout()->add( extPart->widget() );
00230 
00231   setExtPartVisible( true );
00232 
00233   if ( te->paragraphs() > 0 )
00234     populateExtPart();
00235 }
00236 
00237 void DiffWidget::slotClear()
00238 {
00239   rawDiff = QString();
00240   te->clear();
00241   if ( extPart )
00242     extPart->closeURL();
00243 }
00244 
00245 // internally for the TextEdit only!
00246 void DiffWidget::slotAppend( const QString& str )
00247 {
00248   te->append( str );
00249 }
00250 
00251 // internally for the TextEdit only!
00252 void DiffWidget::slotAppend( KIO::Job*, const QByteArray& ba )
00253 {
00254   slotAppend( QString( ba ) );
00255 }
00256 
00257 void DiffWidget::populateExtPart()
00258 {
00259   if ( !extPart )
00260     return;
00261 
00262   bool ok = false;
00263   int paragCount = te->paragraphs();
00264   if ( extPart->openStream( "text/plain", KURL() ) ) {
00265     for ( int i = 0; i < paragCount; ++i )
00266       extPart->writeStream( rawDiff.local8Bit() );
00267     ok = extPart->closeStream();
00268   } else {
00269       // workaround for parts that cannot handle streams
00270       delete tempFile;
00271       tempFile = new KTempFile();
00272       tempFile->setAutoDelete( true );
00273         *(tempFile->textStream()) << rawDiff.local8Bit() << endl;
00274       tempFile->close();
00275       ok = extPart->openURL( KURL::fromPathOrURL( tempFile->name() ) );
00276   }
00277   if ( !ok )
00278     setExtPartVisible( false );
00279 }
00280 
00281 // internally for the TextEdit only!
00282 void DiffWidget::slotFinished()
00283 {
00284     te->applySyntaxHighlight();
00285     populateExtPart();
00286 }
00287 
00288 void DiffWidget::setDiff( const QString& diff )
00289 {
00290   slotClear();
00291   rawDiff = diff;
00292   slotAppend( diff );
00293   slotFinished();
00294 }
00295 
00296 void DiffWidget::openURL( const KURL& url )
00297 {
00298   if ( job )
00299     job->kill();
00300 
00301   KIO::TransferJob* job = KIO::get( url );
00302   if ( !job )
00303     return;
00304 
00305   connect( job, SIGNAL(data( KIO::Job *, const QByteArray & )),
00306            this, SLOT(slotAppend( KIO::Job*, const QByteArray& )) );
00307   connect( job, SIGNAL(result( KIO::Job * )),
00308            this, SLOT(slotFinished()) );
00309 }
00310 
00311 void DiffWidget::contextMenuEvent( QContextMenuEvent* /* e */ )
00312 {
00313   QPopupMenu* popup = new QPopupMenu( this );
00314 
00315   if ( !te->isVisible() )
00316     popup->insertItem( i18n("Display &Raw Output"), this, SLOT(showTextEdit()) );
00317 
00318   popup->exec( QCursor::pos() );
00319   delete popup;
00320 }
00321 
00322 void DiffWidget::showExtPart()
00323 {
00324   setExtPartVisible( true );
00325 }
00326 
00327 void DiffWidget::showTextEdit()
00328 {
00329   setExtPartVisible( false );
00330 }
00331 
00332 #include "diffwidget.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