~ubuntu-branches/debian/sid/kdevelop/sid

« back to all changes in this revision

Viewing changes to vcs/cvsservice/diffwidget.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jeremy Lainé
  • Date: 2010-05-05 07:21:55 UTC
  • mfrom: (1.2.3 upstream) (5.1.2 squeeze)
  • Revision ID: james.westby@ubuntu.com-20100505072155-h78lx19pu04sbhtn
Tags: 4:4.0.0-2
* Upload to unstable (Closes: #579947, #481832).
* Acknowledge obsolete NMU fixes (Closes: #562410, #546961).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/***************************************************************************
2
 
 *   Copyright (C) 2001 by Harald Fernengel                                *
3
 
 *   harry@kdevelop.org                                                    *
4
 
 *                                                                         *
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.                                   *
9
 
 *                                                                         *
10
 
 ***************************************************************************/
11
 
 
12
 
#include <qlayout.h>
13
 
#include <qtextedit.h>
14
 
#include <qpopupmenu.h>
15
 
#include <qcursor.h>
16
 
#include <qfile.h>
17
 
 
18
 
#include <kconfig.h>
19
 
#include <kapplication.h>
20
 
#include <klocale.h>
21
 
#include <kservice.h>
22
 
#include <ktempfile.h>
23
 
#include <kpopupmenu.h>
24
 
#include <kiconloader.h>
25
 
#include <kfiledialog.h>
26
 
#include <kmessagebox.h>
27
 
 
28
 
#include <kparts/componentfactory.h>
29
 
#include <kparts/part.h>
30
 
 
31
 
#include <kio/jobclasses.h>
32
 
#include <kio/job.h>
33
 
 
34
 
#include "diffwidget.h"
35
 
 
36
 
// yup, magic value for the popupmenu-id
37
 
static const int POPUP_BASE = 130977;
38
 
 
39
 
QStringList KDiffTextEdit::extParts;
40
 
QStringList KDiffTextEdit::extPartsTranslated;
41
 
 
42
 
KDiffTextEdit::KDiffTextEdit( QWidget* parent, const char* name ): QTextEdit( parent, name )
43
 
{
44
 
  KConfig* config = kapp->config();
45
 
  config->setGroup( "Diff" );
46
 
  _highlight = config->readBoolEntry( "Highlight", true );
47
 
 
48
 
  searchExtParts();
49
 
}
50
 
 
51
 
KDiffTextEdit::~KDiffTextEdit()
52
 
{
53
 
  KConfig* config = kapp->config();
54
 
 
55
 
  config->setGroup( "Diff" );
56
 
  config->writeEntry( "Highlight", _highlight );
57
 
}
58
 
 
59
 
QPopupMenu* KDiffTextEdit::createPopupMenu()
60
 
{
61
 
  return createPopupMenu( QPoint() );
62
 
}
63
 
 
64
 
QPopupMenu* KDiffTextEdit::createPopupMenu( const QPoint& p )
65
 
{
66
 
  QPopupMenu* popup = QTextEdit::createPopupMenu( p );
67
 
  if ( !popup )
68
 
    popup = new QPopupMenu( this );
69
 
 
70
 
  int i = 0;
71
 
 
72
 
  for ( QStringList::Iterator it = extPartsTranslated.begin(); it != extPartsTranslated.end(); ++it ) {
73
 
    popup->insertItem( i18n( "Show in %1" ).arg( *it ), i + POPUP_BASE, i );
74
 
    i++;
75
 
  }
76
 
  if ( !extPartsTranslated.isEmpty() )
77
 
    popup->insertSeparator( i );
78
 
  connect( popup, SIGNAL(activated(int)), this, SLOT(popupActivated(int)) );
79
 
 
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 );
82
 
 
83
 
  popup->insertSeparator( 1 );
84
 
 
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 );
88
 
 
89
 
  return popup;
90
 
}
91
 
 
92
 
void KDiffTextEdit::saveAs()
93
 
{
94
 
  QString fName = KFileDialog::getSaveFileName();
95
 
  if ( fName.isEmpty() )
96
 
    return;
97
 
 
98
 
  QFile f( fName );
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";
104
 
    f.close();
105
 
  } else {
106
 
    KMessageBox::sorry( this, i18n("Unable to open file."), i18n("Diff Frontend") );
107
 
  }
108
 
}
109
 
 
110
 
void KDiffTextEdit::toggleSyntaxHighlight()
111
 
{
112
 
  _highlight = !_highlight;
113
 
  if ( _highlight )
114
 
    applySyntaxHighlight();
115
 
  else
116
 
    clearSyntaxHighlight();
117
 
}
118
 
 
119
 
void KDiffTextEdit::applySyntaxHighlight()
120
 
{
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 );
124
 
 
125
 
  if ( !_highlight )
126
 
    return;
127
 
 
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 );
136
 
      }
137
 
    }
138
 
  }
139
 
}
140
 
 
141
 
void KDiffTextEdit::clearSyntaxHighlight()
142
 
{
143
 
  int paragCount = paragraphs();
144
 
  for ( int i = 0; i < paragCount; ++i ) {
145
 
    clearParagraphBackground( i );
146
 
  }
147
 
}
148
 
 
149
 
void KDiffTextEdit::searchExtParts()
150
 
{
151
 
  // only execute once
152
 
  static bool init = false;
153
 
  if ( init )
154
 
    return;
155
 
  init = true;
156
 
 
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();
164
 
  }
165
 
  return;
166
 
}
167
 
 
168
 
void KDiffTextEdit::popupActivated( int id )
169
 
{
170
 
  id -= POPUP_BASE;
171
 
  if ( id < 0 || id > (int)extParts.count() )
172
 
    return;
173
 
 
174
 
  emit externalPartRequested( extParts[ id ] );
175
 
}
176
 
 
177
 
DiffWidget::DiffWidget( QWidget *parent, const char *name, WFlags f ):
178
 
    QWidget( parent, name, f ), tempFile( 0 )
179
 
{
180
 
  job = 0;
181
 
  extPart = 0;
182
 
 
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&)) );
188
 
 
189
 
  QVBoxLayout* layout = new QVBoxLayout( this );
190
 
  layout->addWidget( te );
191
 
}
192
 
 
193
 
DiffWidget::~DiffWidget()
194
 
{
195
 
    delete tempFile;
196
 
}
197
 
 
198
 
void DiffWidget::setExtPartVisible( bool visible )
199
 
{
200
 
  if ( !extPart || !extPart->widget() ) {
201
 
    te->show();
202
 
    return;
203
 
  }
204
 
  if ( visible ) {
205
 
    te->hide();
206
 
    extPart->widget()->show();
207
 
  } else {
208
 
    te->show();
209
 
    extPart->widget()->hide();
210
 
  }
211
 
}
212
 
 
213
 
void DiffWidget::loadExtPart( const QString& partName )
214
 
{
215
 
  if ( extPart ) {
216
 
    setExtPartVisible( false );
217
 
    delete extPart;
218
 
    extPart = 0;
219
 
  }
220
 
 
221
 
  KService::Ptr extService = KService::serviceByDesktopName( partName );
222
 
  if ( !extService )
223
 
    return;
224
 
 
225
 
  extPart = KParts::ComponentFactory::createPartInstanceFromService<KParts::ReadOnlyPart>( extService, this, 0, this, 0 );
226
 
  if ( !extPart || !extPart->widget() )
227
 
    return;
228
 
 
229
 
  layout()->add( extPart->widget() );
230
 
 
231
 
  setExtPartVisible( true );
232
 
 
233
 
  if ( te->paragraphs() > 0 )
234
 
    populateExtPart();
235
 
}
236
 
 
237
 
void DiffWidget::slotClear()
238
 
{
239
 
  te->clear();
240
 
  if ( extPart )
241
 
    extPart->closeURL();
242
 
}
243
 
 
244
 
// internally for the TextEdit only!
245
 
void DiffWidget::slotAppend( const QString& str )
246
 
{
247
 
  te->append( str );
248
 
}
249
 
 
250
 
// internally for the TextEdit only!
251
 
void DiffWidget::slotAppend( KIO::Job*, const QByteArray& ba )
252
 
{
253
 
  slotAppend( QString( ba ) );
254
 
}
255
 
 
256
 
void DiffWidget::populateExtPart()
257
 
{
258
 
  if ( !extPart )
259
 
    return;
260
 
 
261
 
  bool ok = false;
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();
267
 
  } else {
268
 
      // workaround for parts that cannot handle streams
269
 
      delete tempFile;
270
 
      tempFile = new KTempFile();
271
 
      tempFile->setAutoDelete( true );
272
 
      for ( int i = 0; i < paragCount; ++i )
273
 
        *(tempFile->textStream()) << te->text( i ) << endl;
274
 
      tempFile->close();
275
 
      ok = extPart->openURL( KURL( tempFile->name() ) );
276
 
  }
277
 
  if ( !ok )
278
 
    setExtPartVisible( false );
279
 
}
280
 
 
281
 
// internally for the TextEdit only!
282
 
void DiffWidget::slotFinished()
283
 
{
284
 
    te->applySyntaxHighlight();
285
 
    populateExtPart();
286
 
}
287
 
 
288
 
void DiffWidget::setDiff( const QString& diff )
289
 
{
290
 
  slotClear();
291
 
  slotAppend( diff );
292
 
  slotFinished();
293
 
}
294
 
 
295
 
void DiffWidget::openURL( const KURL& url )
296
 
{
297
 
  if ( job )
298
 
    job->kill();
299
 
 
300
 
  KIO::TransferJob* job = KIO::get( url );
301
 
  if ( !job )
302
 
    return;
303
 
 
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()) );
308
 
}
309
 
 
310
 
void DiffWidget::contextMenuEvent( QContextMenuEvent* /* e */ )
311
 
{
312
 
  QPopupMenu* popup = new QPopupMenu( this );
313
 
 
314
 
  if ( !te->isVisible() )
315
 
    popup->insertItem( i18n("Display &Raw Output"), this, SLOT(showTextEdit()) );
316
 
 
317
 
  popup->exec( QCursor::pos() );
318
 
  delete popup;
319
 
}
320
 
 
321
 
void DiffWidget::showExtPart()
322
 
{
323
 
  setExtPartVisible( true );
324
 
}
325
 
 
326
 
void DiffWidget::showTextEdit()
327
 
{
328
 
  setExtPartVisible( false );
329
 
}
330
 
 
331
 
#include "diffwidget.moc"