2
#include <qclipboard.h>
3
#include <qapplication.h>
5
#include <kxmlguiclient.h>
7
#include <kstdaction.h>
8
#include <kstandarddirs.h>
10
#include <kpopupmenu.h>
11
#include <kiconloader.h>
12
#include <kmainwindow.h>
13
#include <khtmlview.h>
14
#include <khtml_settings.h>
17
#include <kdevmainwindow.h>
20
#include "kdevhtmlpart.h"
22
KDevHTMLPart::KDevHTMLPart()
23
: KHTMLPart(0L, 0L, 0L, "KDevHTMLPart", DefaultGUI )
25
setXMLFile(locate("data", "kdevelop/kdevhtml_partui.rc"), true);
27
connect(browserExtension(), SIGNAL(openURLRequestDelayed(const KURL &,const KParts::URLArgs &)),
28
this, SLOT(openURLRequest(const KURL &)) );
30
connect(this, SIGNAL(started(KIO::Job *)), this, SLOT(slotStarted(KIO::Job* )));
31
connect(this, SIGNAL(completed()), this, SLOT(slotCompleted()));
32
connect(this, SIGNAL(canceled(const QString &)), this, SLOT(slotCancelled(const QString &)));
34
KActionCollection * actions = actionCollection();// new KActionCollection( this );
35
reloadAction = new KAction( i18n( "Reload" ), "reload", 0,
36
this, SLOT( slotReload() ), actions, "doc_reload" );
37
reloadAction->setWhatsThis(i18n("<b>Reload</b><p>Reloads the current document."));
38
stopAction = new KAction( i18n( "Stop" ), "stop", 0,
39
this, SLOT( slotStop() ), actions, "doc_stop" );
40
stopAction->setWhatsThis(i18n("<b>Stop</b><p>Stops the loading of current document."));
41
duplicateAction = new KAction( i18n( "Duplicate Tab" ), "window_new", 0,
42
this, SLOT( slotDuplicate() ), actions, "doc_dup" );
43
duplicateAction->setWhatsThis(i18n("<b>Duplicate window</b><p>Opens current document in a new window."));
44
printAction = KStdAction::print(this, SLOT(slotPrint()), actions, "print_doc");
45
copyAction = KStdAction::copy(this, SLOT(slotCopy()), actions, "copy_doc_selection");
47
connect( this, SIGNAL(popupMenu(const QString &, const QPoint &)), this, SLOT(popup(const QString &, const QPoint &)));
48
connect(this, SIGNAL(selectionChanged()), this, SLOT(slotSelectionChanged()));
50
//BEGIN documentation history stuff
52
m_backAction = new KToolBarPopupAction(i18n("Back"), "back", 0,
53
this, SLOT(slotBack()),
54
actions, "browser_back");
55
m_backAction->setEnabled( false );
56
m_backAction->setToolTip(i18n("Back"));
57
m_backAction->setWhatsThis(i18n("<b>Back</b><p>Moves backwards one step in the <b>documentation</b> browsing history."));
59
connect(m_backAction->popupMenu(), SIGNAL(aboutToShow()),
60
this, SLOT(slotBackAboutToShow()));
61
connect(m_backAction->popupMenu(), SIGNAL(activated(int)),
62
this, SLOT(slotPopupActivated(int)));
64
m_forwardAction = new KToolBarPopupAction(i18n("Forward"), "forward", 0,
65
this, SLOT(slotForward()),
66
actions, "browser_forward");
67
m_forwardAction->setEnabled( false );
68
m_forwardAction->setToolTip(i18n("Forward"));
69
m_forwardAction->setWhatsThis(i18n("<b>Forward</b><p>Moves forward one step in the <b>documentation</b> browsing history."));
71
connect(m_forwardAction->popupMenu(), SIGNAL(aboutToShow()),
72
this, SLOT(slotForwardAboutToShow()));
73
connect(m_forwardAction->popupMenu(), SIGNAL(activated(int)),
74
this, SLOT(slotPopupActivated(int)));
77
m_Current = m_history.end();
78
//END documentation history stuff
81
KConfig *appConfig = KGlobal::config();
82
appConfig->setGroup("KHTMLPart");
83
setStandardFont(appConfig->readEntry("StandardFont",
84
settings()->stdFontName()));
85
setFixedFont(appConfig->readEntry("FixedFont",
86
settings()->fixedFontName()));
87
setZoomFactor(appConfig->readEntry("Zoom", "100").toInt());
90
void KDevHTMLPart::popup( const QString & url, const QPoint & p )
92
// KPopupMenu popup( i18n( "Documentation Viewer" ), this->widget() );
93
KPopupMenu popup(this->widget());
97
if (!url.isEmpty() && (m_options & CanOpenInNewWindow))
99
idNewWindow = popup.insertItem(SmallIcon("window_new"),i18n("Open in New Tab"));
100
popup.setWhatsThis(idNewWindow, i18n("<b>Open in new window</b><p>Opens current link in a new window."));
103
if (m_options & CanDuplicate)
105
duplicateAction->plug(&popup);
109
popup.insertSeparator();
111
m_backAction->plug( &popup );
112
m_forwardAction->plug( &popup );
113
reloadAction->plug(&popup);
114
// stopAction->plug(&popup);
115
popup.insertSeparator();
117
copyAction->plug( &popup );
118
popup.insertSeparator();
120
printAction->plug(&popup);
121
popup.insertSeparator();
123
KAction * incFontAction = this->action("incFontSizes");
124
KAction * decFontAction = this->action("decFontSizes");
125
if ( incFontAction && decFontAction )
127
incFontAction->plug( &popup );
128
decFontAction->plug( &popup );
129
popup.insertSeparator();
132
KAction *ac = action("setEncoding");
136
int r = popup.exec(p);
138
if (r == idNewWindow)
141
if (!KURL(url).path().startsWith("/"))
143
kdDebug() << "processing relative url: " << url << endl;
144
if (url.startsWith("#"))
146
kurl = KURL(KDevHTMLPart::url());
147
kurl.setRef(url.mid(1));
150
kurl = KURL(KDevHTMLPart::url().upURL().url(true)+url);
156
slotOpenInNewWindow(kurl);
160
void KDevHTMLPart::setContext(const QString &context)
166
QString KDevHTMLPart::context() const
172
// Note: this function is a copy of code in kdecore/kconfigbase.cpp ;)
173
static bool isUtf8(const char *buf) {
175
register unsigned char c;
178
#define F 0 /* character never appears in text */
179
#define T 1 /* character appears in plain ASCII text */
180
#define I 2 /* character appears in ISO-8859 text */
181
#define X 3 /* character appears in non-ISO extended ASCII (Mac, IBM PC) */
183
static const unsigned char text_chars[256] = {
184
/* BEL BS HT LF FF CR */
185
F, F, F, F, F, F, F, T, T, T, T, F, T, T, F, F, /* 0x0X */
187
F, F, F, F, F, F, F, F, F, F, F, T, F, F, F, F, /* 0x1X */
188
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x2X */
189
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x3X */
190
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x4X */
191
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x5X */
192
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x6X */
193
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, F, /* 0x7X */
195
X, X, X, X, X, T, X, X, X, X, X, X, X, X, X, X, /* 0x8X */
196
X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, /* 0x9X */
197
I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xaX */
198
I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xbX */
199
I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xcX */
200
I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xdX */
201
I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xeX */
202
I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I /* 0xfX */
206
for (i = 0; (c = buf[i]); i++) {
207
if ((c & 0x80) == 0) { /* 0xxxxxxx is plain ASCII */
209
* Even if the whole file is valid UTF-8 sequences,
210
* still reject it if it uses weird control characters.
213
if (text_chars[c] != T)
216
} else if ((c & 0x40) == 0) { /* 10xxxxxx never 1st byte */
218
} else { /* 11xxxxxx begins UTF-8 */
221
if ((c & 0x20) == 0) { /* 110xxxxx */
223
} else if ((c & 0x10) == 0) { /* 1110xxxx */
225
} else if ((c & 0x08) == 0) { /* 11110xxx */
227
} else if ((c & 0x04) == 0) { /* 111110xx */
229
} else if ((c & 0x02) == 0) { /* 1111110x */
234
for (n = 0; n < following; n++) {
239
if ((c & 0x80) == 0 || (c & 0x40))
246
return gotone; /* don't claim it's UTF-8 if it's all 7-bit */
253
QString KDevHTMLPart::resolveEnvVarsInURL(const QString& url)
255
// check for environment variables and make necessary translations
257
int nDollarPos = path.find( '$' );
259
// Note: the while loop below is a copy of code in kdecore/kconfigbase.cpp ;)
260
while( nDollarPos != -1 && nDollarPos+1 < static_cast<int>(path.length())) {
261
// there is at least one $
262
if( (path)[nDollarPos+1] == '(' ) {
263
uint nEndPos = nDollarPos+1;
264
// the next character is no $
265
while ( (nEndPos <= path.length()) && (path[nEndPos]!=')') )
268
QString cmd = path.mid( nDollarPos+2, nEndPos-nDollarPos-3 );
271
FILE *fs = popen(QFile::encodeName(cmd).data(), "r");
274
QTextStream ts(fs, IO_ReadOnly);
275
result = ts.read().stripWhiteSpace();
278
path.replace( nDollarPos, nEndPos-nDollarPos, result );
279
} else if( (path)[nDollarPos+1] != '$' ) {
280
uint nEndPos = nDollarPos+1;
281
// the next character is no $
283
if (path[nEndPos]=='{')
285
while ( (nEndPos <= path.length()) && (path[nEndPos]!='}') )
288
aVarName = path.mid( nDollarPos+2, nEndPos-nDollarPos-3 );
292
while ( nEndPos <= path.length() && (path[nEndPos].isNumber()
293
|| path[nEndPos].isLetter() || path[nEndPos]=='_' ) )
295
aVarName = path.mid( nDollarPos+1, nEndPos-nDollarPos-1 );
297
const char* pEnv = 0;
298
if (!aVarName.isEmpty())
299
pEnv = getenv( aVarName.ascii() );
301
// !!! Sergey A. Sukiyazov <corwin@micom.don.ru> !!!
302
// A environment variables may contain values in 8bit
303
// locale cpecified encoding or in UTF8 encoding.
305
path.replace( nDollarPos, nEndPos-nDollarPos, QString::fromUtf8(pEnv) );
307
path.replace( nDollarPos, nEndPos-nDollarPos, QString::fromLocal8Bit(pEnv) );
309
path.remove( nDollarPos, nEndPos-nDollarPos );
311
// remove one of the dollar signs
312
path.remove( nDollarPos, 1 );
315
nDollarPos = path.find( '$', nDollarPos );
321
bool KDevHTMLPart::openURL(const KURL &url)
323
QString path = resolveEnvVarsInURL(url.url());
326
bool retval = KHTMLPart::openURL(newUrl);
329
emit fileNameChanged(this);
336
m_backAction->setEnabled( m_Current != m_history.begin() );
337
m_forwardAction->setEnabled( m_Current != m_history.fromLast() );
342
void KDevHTMLPart::openURLRequest(const KURL &url)
347
void KDevHTMLPart::slotReload( )
352
void KDevHTMLPart::slotStop( )
357
void KDevHTMLPart::slotStarted( KIO::Job * )
359
stopAction->setEnabled(true);
362
void KDevHTMLPart::slotCompleted( )
364
stopAction->setEnabled(false);
367
void KDevHTMLPart::slotCancelled( const QString & /*errMsg*/ )
369
stopAction->setEnabled(false);
372
/*void KDevHTMLPart::slotDuplicate( )
374
PartController::getInstance()->showDocument(url(), true);
377
void KDevHTMLPart::slotPrint( )
382
void KDevHTMLPart::slotBack()
384
if ( m_Current != m_history.begin() )
388
openURL( (*m_Current).url );
393
void KDevHTMLPart::slotForward()
395
if ( m_Current != m_history.fromLast() )
399
openURL( (*m_Current).url );
404
void KDevHTMLPart::slotBackAboutToShow()
406
KPopupMenu *popup = m_backAction->popupMenu();
409
if ( m_Current == m_history.begin() ) return;
411
QValueList<DocumentationHistoryEntry>::Iterator it = m_Current;
417
if ( it == m_history.begin() )
419
popup->insertItem( (*it).url.url(), (*it).id );
423
popup->insertItem( (*it).url.url(), (*it).id );
429
void KDevHTMLPart::slotForwardAboutToShow()
431
KPopupMenu *popup = m_forwardAction->popupMenu();
434
if ( m_Current == m_history.fromLast() ) return;
436
QValueList<DocumentationHistoryEntry>::Iterator it = m_Current;
442
if ( it == m_history.fromLast() )
444
popup->insertItem( (*it).url.url(), (*it).id );
448
popup->insertItem( (*it).url.url(), (*it).id );
454
void KDevHTMLPart::slotPopupActivated( int id )
456
kdDebug(9000) << "id: " << id << endl;
458
QValueList<DocumentationHistoryEntry>::Iterator it = m_history.begin();
459
while( it != m_history.end() )
461
kdDebug(9000) << "(*it).id: " << (*it).id << endl;
462
if ( (*it).id == id )
466
openURL( (*m_Current).url );
474
void KDevHTMLPart::addHistoryEntry()
476
QValueList<DocumentationHistoryEntry>::Iterator it = m_Current;
478
// if We're not already the last entry, we truncate the list here before adding an entry
479
if ( it != m_history.end() && it != m_history.fromLast() )
481
m_history.erase( ++it, m_history.end() );
484
DocumentationHistoryEntry newEntry( url() );
486
// Only save the new entry if it is different from the last
487
if ( newEntry.url != (*m_Current).url )
489
m_history.append( newEntry );
490
m_Current = m_history.fromLast();
494
void KDevHTMLPart::slotCopy( )
496
QString text = selectedText();
497
text.replace( QChar( 0xa0 ), ' ' );
498
QClipboard *cb = QApplication::clipboard();
499
disconnect( cb, SIGNAL( selectionChanged() ), this, SLOT( slotClearSelection() ) );
501
connect( cb, SIGNAL( selectionChanged() ), this, SLOT( slotClearSelection() ) );
504
void KDevHTMLPart::slotSelectionChanged( )
506
if (selectedText().isEmpty())
507
copyAction->setEnabled(false);
509
copyAction->setEnabled(true);
512
#include "kdevhtmlpart.moc"