1
/***************************************************************************
2
* Copyright (C) 2001 by Harald Fernengel *
5
* This program is free software; you can redistribute it and/or modify *
6
* it under the terms of the GNU General Public License as published by *
7
* the Free Software Foundation; either version 2 of the License, or *
8
* (at your option) any later version. *
10
***************************************************************************/
13
#include <qtextedit.h>
14
#include <qpopupmenu.h>
19
#include <kapplication.h>
22
#include <ktempfile.h>
23
#include <kpopupmenu.h>
24
#include <kiconloader.h>
25
#include <kfiledialog.h>
26
#include <kmessagebox.h>
28
#include <kparts/componentfactory.h>
29
#include <kparts/part.h>
31
#include <kio/jobclasses.h>
34
#include "diffwidget.h"
36
// yup, magic value for the popupmenu-id
37
static const int POPUP_BASE = 130977;
39
QStringList KDiffTextEdit::extParts;
40
QStringList KDiffTextEdit::extPartsTranslated;
42
KDiffTextEdit::KDiffTextEdit( QWidget* parent, const char* name ): QTextEdit( parent, name )
44
KConfig* config = kapp->config();
45
config->setGroup( "Diff" );
46
_highlight = config->readBoolEntry( "Highlight", true );
51
KDiffTextEdit::~KDiffTextEdit()
53
KConfig* config = kapp->config();
55
config->setGroup( "Diff" );
56
config->writeEntry( "Highlight", _highlight );
59
QPopupMenu* KDiffTextEdit::createPopupMenu()
61
return createPopupMenu( QPoint() );
64
QPopupMenu* KDiffTextEdit::createPopupMenu( const QPoint& p )
66
QPopupMenu* popup = QTextEdit::createPopupMenu( p );
68
popup = new QPopupMenu( this );
72
for ( QStringList::Iterator it = extPartsTranslated.begin(); it != extPartsTranslated.end(); ++it ) {
73
popup->insertItem( i18n( "Show in %1" ).arg( *it ), i + POPUP_BASE, i );
76
if ( !extPartsTranslated.isEmpty() )
77
popup->insertSeparator( i );
78
connect( popup, SIGNAL(activated(int)), this, SLOT(popupActivated(int)) );
80
popup->insertItem( SmallIconSet( "filesaveas" ), i18n( "&Save As..." ), this, SLOT(saveAs()), CTRL + Key_S, POPUP_BASE - 2, 0 );
81
popup->setItemEnabled( POPUP_BASE - 2, length() > 0 );
83
popup->insertSeparator( 1 );
85
popup->insertItem( i18n( "Highlight Syntax" ), this, SLOT(toggleSyntaxHighlight()), 0, POPUP_BASE - 1, 2 );
86
popup->setItemChecked( POPUP_BASE - 1, _highlight );
87
popup->insertSeparator( 3 );
92
void KDiffTextEdit::saveAs()
94
QString fName = KFileDialog::getSaveFileName();
95
if ( fName.isEmpty() )
99
if ( f.open( IO_WriteOnly ) ) {
100
QTextStream stream( &f );
101
int pCount = paragraphs();
102
for ( int i = 0; i < pCount; ++i )
103
stream << text( i ) << "\n";
106
KMessageBox::sorry( this, i18n("Unable to open file."), i18n("Diff Frontend") );
110
void KDiffTextEdit::toggleSyntaxHighlight()
112
_highlight = !_highlight;
114
applySyntaxHighlight();
116
clearSyntaxHighlight();
119
void KDiffTextEdit::applySyntaxHighlight()
121
// the diff has been loaded so we apply a simple highlighting
122
static QColor cAdded( 190, 190, 237);
123
static QColor cRemoved( 190, 237, 190 );
128
int paragCount = paragraphs();
129
for ( int i = 0; i < paragCount; ++i ) {
130
QString txt = text( i );
131
if ( txt.length() > 0 ) {
132
if ( txt.startsWith( "+" ) || txt.startsWith( ">" ) ) {
133
setParagraphBackgroundColor( i, cAdded );
134
} else if ( txt.startsWith( "-" ) || txt.startsWith( "<" ) ) {
135
setParagraphBackgroundColor( i, cRemoved );
141
void KDiffTextEdit::clearSyntaxHighlight()
143
int paragCount = paragraphs();
144
for ( int i = 0; i < paragCount; ++i ) {
145
clearParagraphBackground( i );
149
void KDiffTextEdit::searchExtParts()
152
static bool init = false;
157
// search all parts that can handle text/x-diff
158
KTrader::OfferList offers = KTrader::self()->query("text/x-diff", "('KParts/ReadOnlyPart' in ServiceTypes) and ('text/x-diff' in ServiceTypes)");
159
KTrader::OfferList::const_iterator it;
160
for ( it = offers.begin(); it != offers.end(); ++it ) {
161
KService::Ptr ptr = (*it);
162
extPartsTranslated << ptr->name();
163
extParts << ptr->desktopEntryName();
168
void KDiffTextEdit::popupActivated( int id )
171
if ( id < 0 || id > (int)extParts.count() )
174
emit externalPartRequested( extParts[ id ] );
177
DiffWidget::DiffWidget( QWidget *parent, const char *name, WFlags f ):
178
QWidget( parent, name, f ), tempFile( 0 )
183
te = new KDiffTextEdit( this, "Main Diff Viewer" );
184
te->setReadOnly( true );
185
te->setTextFormat( QTextEdit::PlainText );
186
// te->setMinimumSize( 300, 200 );
187
connect( te, SIGNAL(externalPartRequested(const QString&)), this, SLOT(loadExtPart(const QString&)) );
189
QVBoxLayout* layout = new QVBoxLayout( this );
190
layout->addWidget( te );
193
DiffWidget::~DiffWidget()
198
void DiffWidget::setExtPartVisible( bool visible )
200
if ( !extPart || !extPart->widget() ) {
206
extPart->widget()->show();
209
extPart->widget()->hide();
213
void DiffWidget::loadExtPart( const QString& partName )
216
setExtPartVisible( false );
221
KService::Ptr extService = KService::serviceByDesktopName( partName );
225
extPart = KParts::ComponentFactory::createPartInstanceFromService<KParts::ReadOnlyPart>( extService, this, 0, this, 0 );
226
if ( !extPart || !extPart->widget() )
229
layout()->add( extPart->widget() );
231
setExtPartVisible( true );
233
if ( te->paragraphs() > 0 )
237
void DiffWidget::slotClear()
244
// internally for the TextEdit only!
245
void DiffWidget::slotAppend( const QString& str )
250
// internally for the TextEdit only!
251
void DiffWidget::slotAppend( KIO::Job*, const QByteArray& ba )
253
slotAppend( QString( ba ) );
256
void DiffWidget::populateExtPart()
262
int paragCount = te->paragraphs();
263
if ( extPart->openStream( "text/plain", KURL() ) ) {
264
for ( int i = 0; i < paragCount; ++i )
265
extPart->writeStream( te->text( i ).local8Bit() );
266
ok = extPart->closeStream();
268
// workaround for parts that cannot handle streams
270
tempFile = new KTempFile();
271
tempFile->setAutoDelete( true );
272
for ( int i = 0; i < paragCount; ++i )
273
*(tempFile->textStream()) << te->text( i ) << endl;
275
ok = extPart->openURL( KURL( tempFile->name() ) );
278
setExtPartVisible( false );
281
// internally for the TextEdit only!
282
void DiffWidget::slotFinished()
284
te->applySyntaxHighlight();
288
void DiffWidget::setDiff( const QString& diff )
295
void DiffWidget::openURL( const KURL& url )
300
KIO::TransferJob* job = KIO::get( url );
304
connect( job, SIGNAL(data( KIO::Job *, const QByteArray & )),
305
this, SLOT(slotAppend( KIO::Job*, const QByteArray& )) );
306
connect( job, SIGNAL(result( KIO::Job * )),
307
this, SLOT(slotFinished()) );
310
void DiffWidget::contextMenuEvent( QContextMenuEvent* /* e */ )
312
QPopupMenu* popup = new QPopupMenu( this );
314
if ( !te->isVisible() )
315
popup->insertItem( i18n("Display &Raw Output"), this, SLOT(showTextEdit()) );
317
popup->exec( QCursor::pos() );
321
void DiffWidget::showExtPart()
323
setExtPartVisible( true );
326
void DiffWidget::showTextEdit()
328
setExtPartVisible( false );
331
#include "diffwidget.moc"