/*************************************************************************** * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "diffpart.h" #include "diffwidget.h" // yup, magic value for the popupmenu-id static const int POPUP_BASE = 130977; TQStringList KDiffTextEdit::extParts; TQStringList KDiffTextEdit::extPartsTranslated; KDiffTextEdit::KDiffTextEdit( TQWidget* parent, const char* name ): TQTextEdit( parent, name ) { TDEConfig* config = kapp->config(); config->setGroup( "Diff" ); _highlight = config->readBoolEntry( "Highlight", true ); searchExtParts(); } KDiffTextEdit::~KDiffTextEdit() { TDEConfig* config = kapp->config(); config->setGroup( "Diff" ); config->writeEntry( "Highlight", _highlight ); } TQPopupMenu* KDiffTextEdit::createPopupMenu() { return createPopupMenu( TQPoint() ); } TQPopupMenu* KDiffTextEdit::createPopupMenu( const TQPoint& p ) { TQPopupMenu* popup = TQTextEdit::createPopupMenu( p ); if ( !popup ) popup = new TQPopupMenu( this ); int i = 0; for ( TQStringList::Iterator it = extPartsTranslated.begin(); it != extPartsTranslated.end(); ++it ) { popup->insertItem( i18n( "Show in %1" ).arg( *it ), i + POPUP_BASE, i ); i++; } if ( !extPartsTranslated.isEmpty() ) popup->insertSeparator( i ); connect( popup, TQT_SIGNAL(activated(int)), this, TQT_SLOT(popupActivated(int)) ); popup->insertItem( SmallIconSet( "document-save-as" ), i18n( "&Save As..." ), this, TQT_SLOT(saveAs()), CTRL + Key_S, POPUP_BASE - 2, 0 ); popup->setItemEnabled( POPUP_BASE - 2, length() > 0 ); popup->insertSeparator( 1 ); popup->insertItem( i18n( "Highlight Syntax" ), this, TQT_SLOT(toggleSyntaxHighlight()), 0, POPUP_BASE - 1, 2 ); popup->setItemChecked( POPUP_BASE - 1, _highlight ); popup->insertSeparator( 3 ); popup->insertSeparator(); popup->insertItem( i18n("Hide view"), parent(), TQT_SLOT(hideView()) ); return popup; } void KDiffTextEdit::saveAs() { TQString fName = KFileDialog::getSaveFileName(); if ( fName.isEmpty() ) return; TQFile f( fName ); if ( f.open( IO_WriteOnly ) ) { TQTextStream stream( &f ); int pCount = paragraphs(); for ( int i = 0; i < pCount; ++i ) stream << text( i ) << "\n"; f.close(); } else { KMessageBox::sorry( 0, i18n("Unable to open file."), i18n("Diff Frontend") ); } } void KDiffTextEdit::toggleSyntaxHighlight() { _highlight = !_highlight; if ( _highlight ) applySyntaxHighlight(); else clearSyntaxHighlight(); } void KDiffTextEdit::applySyntaxHighlight() { // the diff has been loaded so we apply a simple highlighting static TQColor cAdded( 190, 190, 237); static TQColor cRemoved( 190, 237, 190 ); if ( !_highlight ) return; int paragCount = paragraphs(); for ( int i = 0; i < paragCount; ++i ) { TQString txt = text( i ); if ( txt.length() > 0 ) { if ( txt.startsWith( "+" ) || txt.startsWith( ">" ) ) { setParagraphBackgroundColor( i, cAdded ); } else if ( txt.startsWith( "-" ) || txt.startsWith( "<" ) ) { setParagraphBackgroundColor( i, cRemoved ); } } } } void KDiffTextEdit::clearSyntaxHighlight() { int paragCount = paragraphs(); for ( int i = 0; i < paragCount; ++i ) { clearParagraphBackground( i ); } } void KDiffTextEdit::searchExtParts() { // only execute once static bool init = false; if ( init ) return; init = true; // search all parts that can handle text/x-diff TDETrader::OfferList offers = TDETrader::self()->query("text/x-diff", "('KParts/ReadOnlyPart' in ServiceTypes) and ('text/x-diff' in ServiceTypes) and (DesktopEntryName != 'katepart')"); TDETrader::OfferList::const_iterator it; for ( it = offers.begin(); it != offers.end(); ++it ) { KService::Ptr ptr = (*it); extPartsTranslated << ptr->name(); extParts << ptr->desktopEntryName(); } return; } void KDiffTextEdit::popupActivated( int id ) { id -= POPUP_BASE; if ( id < 0 || id > (int)extParts.count() ) return; emit externalPartRequested( extParts[ id ] ); } DiffWidget::DiffWidget( DiffPart * part, TQWidget *parent, const char *name, WFlags f ): TQWidget( parent, name, f ), m_part( part ), tempFile( 0 ) { job = 0; extPart = 0; te = new KDiffTextEdit( this, "Main Diff Viewer" ); te->setReadOnly( true ); te->setTextFormat( TQTextEdit::PlainText ); // te->setMinimumSize( 300, 200 ); connect( te, TQT_SIGNAL(externalPartRequested(const TQString&)), this, TQT_SLOT(loadExtPart(const TQString&)) ); TQVBoxLayout* layout = new TQVBoxLayout( this ); layout->addWidget( te ); } DiffWidget::~DiffWidget() { m_part = 0; delete tempFile; } void DiffWidget::setExtPartVisible( bool visible ) { if ( !extPart || !extPart->widget() ) { te->show(); return; } if ( visible ) { te->hide(); extPart->widget()->show(); } else { te->show(); extPart->widget()->hide(); } } void DiffWidget::loadExtPart( const TQString& partName ) { if ( extPart ) { setExtPartVisible( false ); delete extPart; extPart = 0; } KService::Ptr extService = KService::serviceByDesktopName( partName ); if ( !extService ) return; extPart = KParts::ComponentFactory::createPartInstanceFromService( extService, this, 0, TQT_TQOBJECT(this), 0 ); if ( !extPart || !extPart->widget() ) return; layout()->add( extPart->widget() ); setExtPartVisible( true ); if ( te->paragraphs() > 0 ) populateExtPart(); } void DiffWidget::slotClear() { rawDiff = TQString(); te->clear(); if ( extPart ) extPart->closeURL(); } // internally for the TextEdit only! void DiffWidget::slotAppend( const TQString& str ) { te->append( str ); } // internally for the TextEdit only! void DiffWidget::slotAppend( TDEIO::Job*, const TQByteArray& ba ) { slotAppend( TQString( ba ) ); } void DiffWidget::populateExtPart() { if ( !extPart ) return; bool ok = false; int paragCount = te->paragraphs(); if ( extPart->openStream( "text/plain", KURL() ) ) { for ( int i = 0; i < paragCount; ++i ) extPart->writeStream( rawDiff.local8Bit() ); ok = extPart->closeStream(); } else { // workaround for parts that cannot handle streams delete tempFile; tempFile = new KTempFile(); tempFile->setAutoDelete( true ); *(tempFile->textStream()) << rawDiff.local8Bit() << endl; tempFile->close(); ok = extPart->openURL( KURL::fromPathOrURL( tempFile->name() ) ); } if ( !ok ) setExtPartVisible( false ); } // internally for the TextEdit only! void DiffWidget::slotFinished() { te->applySyntaxHighlight(); populateExtPart(); } void DiffWidget::setDiff( const TQString& diff ) { slotClear(); rawDiff = diff; slotAppend( diff ); slotFinished(); } void DiffWidget::openURL( const KURL& url ) { if ( job ) job->kill(); TDEIO::TransferJob* job = TDEIO::get( url ); if ( !job ) return; connect( job, TQT_SIGNAL(data( TDEIO::Job *, const TQByteArray & )), this, TQT_SLOT(slotAppend( TDEIO::Job*, const TQByteArray& )) ); connect( job, TQT_SIGNAL(result( TDEIO::Job * )), this, TQT_SLOT(slotFinished()) ); } void DiffWidget::contextMenuEvent( TQContextMenuEvent* /* e */ ) { TQPopupMenu* popup = new TQPopupMenu( this ); if ( !te->isVisible() ) { popup->insertItem( i18n("Display &Raw Output"), this, TQT_SLOT(showTextEdit()) ); popup->insertSeparator(); popup->insertItem( i18n("Hide view"), this, TQT_SLOT(hideView()) ); } popup->exec( TQCursor::pos() ); delete popup; } void DiffWidget::showExtPart() { setExtPartVisible( true ); } void DiffWidget::showTextEdit() { setExtPartVisible( false ); } void DiffWidget::hideView() { m_part->mainWindow()->setViewAvailable( this, false ); } #include "diffwidget.moc"