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)");
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
te->clear();
00240
if (
extPart )
00241
extPart->
closeURL();
00242 }
00243
00244
00245
void DiffWidget::slotAppend(
const QString& str )
00246 {
00247
te->append( str );
00248 }
00249
00250
00251
void DiffWidget::slotAppend(
KIO::Job*,
const QByteArray& ba )
00252 {
00253
slotAppend(
QString( ba ) );
00254 }
00255
00256
void DiffWidget::populateExtPart()
00257 {
00258
if ( !
extPart )
00259
return;
00260
00261
bool ok =
false;
00262
int paragCount =
te->paragraphs();
00263
if (
extPart->
openStream(
"text/plain",
KURL() ) ) {
00264
for (
int i = 0; i < paragCount; ++i )
00265
extPart->
writeStream(
te->text( i ).local8Bit() );
00266 ok =
extPart->
closeStream();
00267 }
else {
00268
00269
delete tempFile;
00270
tempFile =
new KTempFile();
00271
tempFile->
setAutoDelete(
true );
00272
for (
int i = 0; i < paragCount; ++i )
00273 *(
tempFile->
textStream()) <<
te->text( i ) <<
endl;
00274
tempFile->
close();
00275 ok =
extPart->
openURL(
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
slotAppend( diff );
00292
slotFinished();
00293 }
00294
00295
void DiffWidget::openURL(
const KURL& url )
00296 {
00297
if (
job )
00298
job->
kill();
00299
00300
KIO::TransferJob*
job =
KIO::get( url );
00301
if ( !job )
00302
return;
00303
00304 connect( job, SIGNAL(
data(
KIO::Job *,
const QByteArray & )),
00305
this, SLOT(
slotAppend(
KIO::Job*,
const QByteArray& )) );
00306 connect( job, SIGNAL(result(
KIO::Job * )),
00307
this, SLOT(
slotFinished()) );
00308 }
00309
00310
void DiffWidget::contextMenuEvent(
QContextMenuEvent* )
00311 {
00312 QPopupMenu* popup =
new QPopupMenu(
this );
00313
00314
if ( !
te->isVisible() )
00315 popup->insertItem( i18n(
"Display &Raw Output"),
this, SLOT(
showTextEdit()) );
00316
00317 popup->exec( QCursor::pos() );
00318
delete popup;
00319 }
00320
00321
void DiffWidget::showExtPart()
00322 {
00323
setExtPartVisible(
true );
00324 }
00325
00326
void DiffWidget::showTextEdit()
00327 {
00328
setExtPartVisible(
false );
00329 }
00330
00331
#include "diffwidget.moc"