00001
00002
00003
00004
00005
00006
00007
00008
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
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
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
00152 static bool init = false;
00153 if ( init )
00154 return;
00155 init = true;
00156
00157
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
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
00246 void DiffWidget::slotAppend( const QString& str )
00247 {
00248 te->append( str );
00249 }
00250
00251
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
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
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* )
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"